+
webgoat-container
4.0.0
@@ -9,111 +10,44 @@
org.owasp.webgoat
webgoat-parent
- 7.2-SNAPSHOT
+ 7.1-SNAPSHOT
-
-
- run-integration-tests
-
- false
-
- run-integration
- true
-
-
-
-
-
- org.apache.tomcat.maven
- tomcat7-maven-plugin
- 2.3-SNAPSHOT
-
- local_tomcat
- http://localhost:8080/manager
- /WebGoat
- exec
- true
- true
- ${project.basedir}/src/main/webapp/WEB-INF/context.xml
-
-
-
- org.owasp.webgoat
- webgoat-container
- ${project.version}
-
-
-
-
- tomcat-run
-
- exec-war-only
-
- package
-
-
- tomcat-startup
- pre-integration-test
-
- run-war-only
-
-
- 8888
- true
-
-
-
-
- tomcat-shutdown
- post-integration-test
-
- shutdown
-
-
-
-
-
- org.apache.maven.plugins
- maven-failsafe-plugin
- ${maven-failsafe-plugin.version}
-
-
- file:${project.basedir}/src/test/resources/log4j-silent.properties
-
-
-
-
-
- integration-test
- verify
-
-
-
-
-
-
-
-
+
+ org.owasp.webgoat.WebGoat
+
- ${basedir}/src/main/java
+ src/main/java
- ${basedir}/src/main/resources
+ src/main/resources
+ true
+
+ **/application.properties
+
+
+
+ src/main/resources
- org.apache.maven.plugins
- maven-compiler-plugin
- ${maven-compiler-plugin.version}
+ com.spotify
+ docker-maven-plugin
+ 0.4.10
- 1.7
- 1.7
- ISO-8859-1
+ webgoat/${project.artifactId}
+ src/main/docker
+
+
+ /
+ ${project.build.directory}
+ ${project.build.finalName}.war
+
+
@@ -130,26 +64,6 @@
-
- org.apache.maven.plugins
- maven-war-plugin
- ${maven-war-plugin.version}
-
-
- false
-
-
- true
-
-
- ${project.name}
- ${project.version}
- ${build.number}
-
-
-
-
org.codehaus.mojo
build-helper-maven-plugin
@@ -172,34 +86,25 @@
- org.apache.tomcat.maven
- tomcat7-maven-plugin
- 2.3-SNAPSHOT
+ org.apache.maven.plugins
+ maven-resources-plugin
+ 2.6
- local_tomcat
- http://localhost:8080/manager/text
- /WebGoat
- exec
- true
- true
- ${project.basedir}/src/main/webapp/WEB-INF/context.xml
+
+ @
+
+ false
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ ${maven-compiler-plugin.version}
+
+ 1.8
+ 1.8
+ ISO-8859-1
-
-
- org.owasp.webgoat
- webgoat-container
- ${project.version}
-
-
-
-
- tomcat-run
-
- exec-war-only
-
- package
-
-
org.apache.maven.plugins
@@ -211,32 +116,102 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+ org.thymeleaf.extra
+ thymeleaf-extras-springsecurity4
+
+
+ org.asciidoctor
+ asciidoctorj
+
+
+ org.jruby
+ jruby-complete
+
+
+ true
+
+
+
+
+
+
+
+
+
+
+ maven-clean-plugin
+
+
+
+ ${project.basedir}/src/main/resources/plugin_lessons
+
+ **/*.jar
+ **/*.pom
+
+
+
+ ${user.home}/.webgoat/
+
+ **/*.jar
+ **/org/**
+ **/plugin/**
+
+
+
+
+
+
+
+ org.projectlombok
+ lombok
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+
+
+
+
+ com.fasterxml.jackson.dataformat
+ jackson-dataformat-yaml
+
+
+ org.asciidoctor
+ asciidoctorj
+ 1.5.4
+
+
+ javax.servlet
+ jstl
+
+
+ org.springframework.boot
+ spring-boot-starter-security
+
+
+ org.springframework.boot
+ spring-boot-starter-thymeleaf
+
+
+ org.thymeleaf.extras
+ thymeleaf-extras-springsecurity4
+ 2.1.2.RELEASE
+
javax.activation
activation
@@ -267,52 +242,6 @@
axis-ant
${axis-ant.version}
-
- org.apache.commons
- commons-lang3
- ${commons-lang3.version}
-
-
- commons-io
- commons-io
- ${commons-io.version}
-
-
- commons-collections
- commons-collections
- ${commons-collections.version}
-
-
- commons-digester
- commons-digester
- ${commons-digester.version}
-
-
- xml-apis
- xml-apis
-
-
-
-
- commons-logging
- commons-logging
- ${commons-logging.version}
-
-
- org.slf4j
- jcl-over-slf4j
- ${jcl-over-slf4j.version}
-
-
- commons-discovery
- commons-discovery
- ${commons-discovery.version}
-
-
- javax.mail
- javax.mail-api
- ${mail-api.version}
-
hsqldb
hsqldb
@@ -323,92 +252,11 @@
wsdl4j
${wsdl4j.version}
-
- java2html
- j2h
- ${j2h.version}
-
-
- ecs
- ecs
- ${ecs.version}
-
javax.transaction
javax.transaction-api
${javax.transaction-api.version}
-
- net.sourceforge.jtds
- jtds
- ${jtds.version}
-
-
- org.apache.tomcat
- tomcat-catalina
- ${tomcat-catalina.version}
- provided
-
-
-
-
-
-
-
- javax
- javaee-api
- ${javaee-api.version}
- provided
-
-
-
- org.springframework
- spring-core
- ${org.springframework.version}
-
-
- org.springframework
- spring-aop
- ${org.springframework.version}
-
-
-
-
- com.fasterxml.jackson.core
- jackson-core
- ${jackson-core.version}
-
-
- com.fasterxml.jackson.core
- jackson-databind
- ${jackson-databind.version}
-
-
-
-
- org.springframework
- spring-webmvc
- ${org.springframework.version}
- jar
-
-
-
- org.springframework.security
- spring-security-core
- ${spring.security.version}
-
-
-
- org.springframework.security
- spring-security-config
- ${spring.security.version}
-
-
-
- org.springframework.security
- spring-security-web
- ${spring.security.version}
-
@@ -422,59 +270,19 @@
guava
${guava.version}
-
-
- javax.servlet
- jstl
- ${jstl.version}
+ com.spotify
+ docker-maven-plugin
+ 0.4.10
-
- taglibs
- standard
- ${standard.version}
-
-
-
- log4j
- log4j
- ${log4j.version}
-
-
- javax.jms
- jms
-
-
- com.sun.jdmk
- jmxtools
-
-
- com.sun.jmx
- jmxri
-
-
-
-
- org.apache.tiles
- tiles-core
- ${tiles.version}
- jar
-
-
- org.slf4j
- slf4j-api
- ${slf4j-api.version}
- jar
-
-
- org.slf4j
- slf4j-log4j12
- ${slf4j-log4j12.version}
- jar
-
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
junit
junit
@@ -492,13 +300,9 @@
${sauce_junit.version}
test
-
-
-
-
-
+
diff --git a/webgoat-container/src/main/docker/Dockerfile b/webgoat-container/src/main/docker/Dockerfile
new file mode 100644
index 000000000..a33389017
--- /dev/null
+++ b/webgoat-container/src/main/docker/Dockerfile
@@ -0,0 +1,6 @@
+FROM frolvlad/alpine-oraclejdk8:slim
+VOLUME /tmp
+RUN cd /root; mkdir -p .webgoat
+ADD webgoat-container-8.0-SNAPSHOT.war webgoat.jar
+RUN sh -c 'touch /webgoat.jar'
+ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/webgoat.jar"]
\ No newline at end of file
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/AsciiDoctorTemplateResolver.java b/webgoat-container/src/main/java/org/owasp/webgoat/AsciiDoctorTemplateResolver.java
new file mode 100644
index 000000000..1a2a8c38c
--- /dev/null
+++ b/webgoat-container/src/main/java/org/owasp/webgoat/AsciiDoctorTemplateResolver.java
@@ -0,0 +1,108 @@
+
+/**
+ *************************************************************************************************
+ * This file is part of WebGoat, an Open Web Application Security Project utility. For details,
+ * please see http://www.owasp.org/
+ *
+ * Copyright (c) 2002 - 20014 Bruce Mayhew
+ *
+ * This program is free software; you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program; if
+ * not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Getting Source ==============
+ *
+ * Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
+ * projects.
+ *
+ *
+ * @author WebGoat
+ * @since December 12, 2015
+ * @version $Id: $Id
+ */
+package org.owasp.webgoat;
+
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import org.asciidoctor.Asciidoctor;
+import org.thymeleaf.TemplateProcessingParameters;
+import org.thymeleaf.resourceresolver.IResourceResolver;
+import org.thymeleaf.templateresolver.TemplateResolver;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.StringWriter;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Optional;
+
+import static org.asciidoctor.Asciidoctor.Factory.create;
+
+/**
+ * Thymeleaf resolver for AsciiDoc used in the lesson, can be used as follows inside a lesson file:
+ *
+ *
+ *
+ *
+ */
+public class AsciiDoctorTemplateResolver extends TemplateResolver {
+
+ private static final Asciidoctor asciidoctor = create();
+ private static final String PREFIX = "doc:";
+ private final File pluginTargetDirectory;
+
+ public AsciiDoctorTemplateResolver(File pluginTargetDirectory) {
+ this.pluginTargetDirectory = pluginTargetDirectory;
+ setResourceResolver(new AdocResourceResolver());
+ setResolvablePatterns(Sets.newHashSet(PREFIX + "*"));
+ }
+
+ @Override
+ protected String computeResourceName(TemplateProcessingParameters params) {
+ String templateName = params.getTemplateName();
+ return templateName.substring(PREFIX.length());
+ }
+
+ private class AdocResourceResolver implements IResourceResolver {
+
+ @Override
+ public InputStream getResourceAsStream(TemplateProcessingParameters params, String resourceName) {
+ try {
+ Optional adocFile = find(pluginTargetDirectory.toPath(), resourceName);
+ if (adocFile.isPresent()) {
+ try (FileReader reader = new FileReader(adocFile.get().toFile())) {
+ StringWriter writer = new StringWriter();
+ asciidoctor.convert(reader, writer, Maps.newHashMap());
+ return new ByteArrayInputStream(writer.getBuffer().toString().getBytes());
+ }
+ }
+ return new ByteArrayInputStream(new byte[0]);
+ } catch (IOException e) {
+ //no html yet
+ return new ByteArrayInputStream(new byte[0]);
+ }
+ }
+
+ private Optional find(Path path, String resourceName) throws IOException {
+ return Files.walk(path)
+ .filter(Files::isRegularFile)
+ .filter(p -> p.toString().endsWith(resourceName)).findFirst();
+ }
+
+ @Override
+ public String getName() {
+ return "adocResourceResolver";
+ }
+ }
+}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/Catcher.java b/webgoat-container/src/main/java/org/owasp/webgoat/Catcher.java
deleted file mode 100644
index 074c61c91..000000000
--- a/webgoat-container/src/main/java/org/owasp/webgoat/Catcher.java
+++ /dev/null
@@ -1,120 +0,0 @@
-
-package org.owasp.webgoat;
-
-import java.io.IOException;
-import java.util.Enumeration;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import org.owasp.webgoat.lessons.AbstractLesson;
-import org.owasp.webgoat.session.Course;
-import org.owasp.webgoat.session.WebSession;
-
-
-/**
- *************************************************************************************************
- *
- *
- * This file is part of WebGoat, an Open Web Application Security Project utility. For details,
- * please see http://www.owasp.org/
- *
- * Copyright (c) 2002 - 20014 Bruce Mayhew
- *
- * This program is free software; you can redistribute it and/or modify it under the terms of the
- * GNU General Public License as published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
- * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with this program; if
- * not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- *
- * Getting Source ==============
- *
- * Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
- * projects.
- *
- * @author Bruce Mayhew WebGoat
- * @since March 13, 2007
- * @version $Id: $Id
- */
-public class Catcher extends HammerHead
-{
-
- /**
- *
- */
- private static final long serialVersionUID = 7441856110845727651L;
-
- /**
- * Description of the Field
- */
- public final static String START_SOURCE_SKIP = "START_OMIT_SOURCE";
-
- /** Constant END_SOURCE_SKIP="END_OMIT_SOURCE"
*/
- public final static String END_SOURCE_SKIP = "END_OMIT_SOURCE";
-
- /** Constant PROPERTY="PROPERTY"
*/
- public static final String PROPERTY = "PROPERTY";
-
- /** Constant EMPTY_STRING=""
*/
- public static final String EMPTY_STRING = "";
-
- /**
- * {@inheritDoc}
- *
- * Description of the Method
- * @exception IOException
- * Description of the Exception
- * @exception ServletException
- * Description of the Exception
- */
- public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
- {
- try
- {
- // System.out.println( "Entering doPost: " );
- // System.out.println( " - request " + request);
- // System.out.println( " - principle: " + request.getUserPrincipal() );
- // setCacheHeaders(response, 0);
- WebSession session = (WebSession) request.getSession(true).getAttribute(WebSession.SESSION);
- session.update(request, response, this.getServletName()); // FIXME: Too much in this
- // call.
-
- int scr = session.getCurrentScreen();
- Course course = session.getCourse();
- AbstractLesson lesson = course.getLesson(session, scr, AbstractLesson.USER_ROLE);
-
- log(request, lesson.getClass().getName() + " | " + session.getParser().toString());
-
- String property = new String(session.getParser().getStringParameter(PROPERTY, EMPTY_STRING));
-
- // if the PROPERTY parameter is available - write all the parameters to the
- // property file. No other control parameters are supported at this time.
- if (!property.equals(EMPTY_STRING))
- {
- Enumeration e = session.getParser().getParameterNames();
-
- while (e.hasMoreElements())
- {
- String name = (String) e.nextElement();
- String value = session.getParser().getParameterValues(name)[0];
- lesson.getLessonTracker(session).getLessonProperties().setProperty(name, value);
- }
- }
- lesson.getLessonTracker(session).store(session, lesson);
-
- // BDM MC
-// WEB-173 - removed for testing, as plugin architecture would not allow this
-// if ( request.getParameter("Deleter") != null ){org.owasp.webgoat.lessons.BlindScript.StaticDeleter();}
-
- } catch (Throwable t)
- {
- t.printStackTrace();
- log("ERROR: " + t);
- }
- }
-}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/HammerHead.java b/webgoat-container/src/main/java/org/owasp/webgoat/HammerHead.java
index d870a8a49..e2a09ab3a 100644
--- a/webgoat-container/src/main/java/org/owasp/webgoat/HammerHead.java
+++ b/webgoat-container/src/main/java/org/owasp/webgoat/HammerHead.java
@@ -1,442 +1,59 @@
package org.owasp.webgoat;
-import org.owasp.webgoat.lessons.AbstractLesson;
-import org.owasp.webgoat.lessons.WelcomeScreen;
-import org.owasp.webgoat.lessons.admin.WelcomeAdminScreen;
import org.owasp.webgoat.session.Course;
-import org.owasp.webgoat.session.ErrorScreen;
-import org.owasp.webgoat.session.Screen;
-import org.owasp.webgoat.session.UserTracker;
-import org.owasp.webgoat.session.WebSession;
-import org.owasp.webgoat.session.WebgoatContext;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.servlet.ServletContext;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpSession;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.net.URL;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.Locale;
-import java.util.TimeZone;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.servlet.ModelAndView;
/**
* *************************************************************************************************
- *
- *
+ *
+ *
* This file is part of WebGoat, an Open Web Application Security Project
* utility. For details, please see http://www.owasp.org/
- *
+ *
* Copyright (c) 2002 - 20014 Bruce Mayhew
- *
+ *
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option) any later
* version.
- *
+ *
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
- *
+ *
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place - Suite 330, Boston, MA 02111-1307, USA.
- *
+ *
* Getting Source ==============
- *
+ *
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository
* for free software projects.
*
- * @author Jeff Williams Aspect
- * Security
- * @author Bruce Mayhew WebGoat
- * @since October 28, 2003
+ * @author Jeff Williams
+ * @author Bruce Mayhew
+ * @author Nanne Baars
* @version $Id: $Id
+ * @since October 28, 2003
*/
-public class HammerHead extends HttpServlet {
+@Controller
+public class HammerHead {
- final Logger logger = LoggerFactory.getLogger(HammerHead.class);
+ private final Course course;
-
- /**
- *
- */
- private static final long serialVersionUID = 645640331343188020L;
-
- /**
- * Description of the Field
- */
- protected static SimpleDateFormat httpDateFormat;
-
- /**
- * Set the session timeout to be 2 days
- */
- private final static int sessionTimeoutSeconds = 60 * 60 * 24 * 2;
-
- // private final static int sessionTimeoutSeconds = 1;
- /**
- * Properties file path
- */
- public static String propertiesPath = null;
-
- /**
- * provides convenience methods for getting setup information from the
- * ServletContext
- */
- private WebgoatContext webgoatContext = null;
-
- /**
- * {@inheritDoc}
- *
- * Description of the Method
- * @exception IOException Description of the Exception
- * @exception ServletException Description of the Exception
- */
- @Override
- public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
- doPost(request, response);
+ public HammerHead(Course course) {
+ this.course = course;
}
/**
- * {@inheritDoc}
- *
- * Description of the Method
- * @exception IOException Description of the Exception
- * @exception ServletException Description of the Exception
+ * Entry point for WebGoat, redirects to the first lesson found within the course.
*/
- @Override
- public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
- Screen screen = null;
-
- WebSession mySession = null;
- try {
- logger.debug("Entering doPost");
- logger.debug("request: " + request);
- logger.debug("principle: " + request.getUserPrincipal());
- // setCacheHeaders(response, 0);
- ServletContext context = getServletContext();
-
- // FIXME: If a response is written by updateSession(), do not
- // call makeScreen() and writeScreen()
- mySession = updateSession(request, response, context);
-
- if (response.isCommitted()) {
- logger.debug("Response already committed, exiting");
- return;
- }
-
- if ("true".equals(request.getParameter("start")) || request.getQueryString() == null) {
- logger.warn("Redirecting to first lesson");
- response.sendRedirect("start.mvc" + mySession.getCourse().getFirstLesson().getLink());
- return;
- }
-
- // Note: For the lesson to track the status, we need to update
- // the lesson tracker object
- // from the screen.createContent() method. The create content is
- // the only point
- // where the lesson "knows" what has happened. To track it at a
- // latter point would
- // require the lesson to have memory.
- screen = makeScreen(mySession);
- // This calls the lesson's
- // handleRequest()
- if (response.isCommitted()) {
- return;
- }
-
- // perform lesson-specific tracking activities
- if (screen instanceof AbstractLesson) {
- AbstractLesson lesson = (AbstractLesson) screen;
-
- // we do not count the initial display of the lesson screen as a visit
- if ("GET".equals(request.getMethod())) {
- String uri = request.getRequestURI() + "?" + request.getQueryString();
- if (!uri.endsWith(lesson.getLink())) {
- screen.getLessonTracker(mySession).incrementNumVisits();
- }
- } else if ("POST".equals(request.getMethod())
- && mySession.getPreviousScreen() == mySession.getCurrentScreen()) {
- screen.getLessonTracker(mySession).incrementNumVisits();
- }
- }
-
- // log the access to this screen for this user
- UserTracker userTracker = UserTracker.instance();
- userTracker.update(mySession, screen);
- log(request, screen.getClass().getName() + " | " + mySession.getParser().toString());
-
- // Redirect the request to our View servlet
- String userAgent = request.getHeader("user-agent");
- String clientBrowser = "Not known!";
- if (userAgent != null) {
- clientBrowser = userAgent;
- }
- request.setAttribute("client.browser", clientBrowser);
- // removed - this is being done in updateSession call
- //request.getSession().setAttribute(WebSession.SESSION, mySession);
- // not sure why this is being set in the session?
- //request.getSession().setAttribute(WebSession.COURSE, mySession.getCourse());
- String viewPage = getViewPage(mySession);
- logger.debug("Forwarding to view: " + viewPage);
- logger.debug("Screen: " + screen);
- request.getRequestDispatcher(viewPage).forward(request, response);
- } catch (Throwable t) {
- logger.error("Error handling request", t); screen = new ErrorScreen(mySession, t);
- } finally {
- try {
- if (screen instanceof ErrorScreen) {
- this.writeScreen(mySession, screen, response);
- }
- } catch (Throwable thr) {
- logger.error("Could not write error screen", thr);
- }
- WebSession.returnConnection(mySession);
- logger.debug("Leaving doPost: ");
- }
- }
-
- private String getViewPage(WebSession webSession) {
- // now always display the lesson content
- String page = "/lesson_content.jsp";
- //page = "/main.jsp";
- return page;
- }
-
- /**
- * Description of the Method
- *
- * @param date Description of the Parameter
- * @return RFC 1123 http date format
- */
- protected static String formatHttpDate(Date date) {
- synchronized (httpDateFormat) {
- return httpDateFormat.format(date);
- }
- }
-
- /**
- * {@inheritDoc}
- *
- * Return information about this servlet
- */
- @Override
- public String getServletInfo() {
- return "WebGoat is sponsored by Aspect Security.";
- }
-
- /**
- * {@inheritDoc}
- *
- * Return properties path
- */
- @Override
- public void init() throws ServletException {
- logger.info("Initializing main webgoat servlet");
- httpDateFormat = new SimpleDateFormat("EEE, dd MMM yyyyy HH:mm:ss z", Locale.US);
- httpDateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
- propertiesPath = getServletContext().getRealPath("/WEB-INF/webgoat.properties");
- webgoatContext = new WebgoatContext(this);
- URL runningStandalone = Thread.currentThread().getContextClassLoader().getResource("standalone.properties");
- if (runningStandalone == null) {
- logger.info("Browse to http://localhost:8080/WebGoat and happy hacking!");
- }
- }
-
- /**
- * Description of the Method
- *
- * @param request Description of the Parameter
- * @param message Description of the Parameter
- */
- public void log(HttpServletRequest request, String message) {
- String output = new Date() + " | " + request.getRemoteHost() + ":" + request.getRemoteAddr() + " | " + message;
- log(output);
- logger.debug(output);
- }
-
- /*
- * public List getLessons(Category category, String role) { Course course =
- * mySession.getCourse(); // May need to clone the List before returning it. //return new
- * ArrayList(course.getLessons(category, role)); return course.getLessons(category, role); }
- */
- /**
- * Description of the Method
- *
- * @param s Description of the Parameter
- * @return Description of the Return Value
- */
- protected Screen makeScreen(WebSession s) {
- Screen screen = null;
- int scr = s.getCurrentScreen();
- Course course = s.getCourse();
-
- if (s.isUser() || s.isChallenge()) {
- if (scr == WebSession.WELCOME) {
- screen = new WelcomeScreen(s);
- } else {
- AbstractLesson lesson = course.getLesson(s, scr, AbstractLesson.USER_ROLE);
- if (lesson == null && s.isHackedAdmin()) {
- // If admin was hacked, let the user see some of the
- // admin screens
- lesson = course.getLesson(s, scr, AbstractLesson.HACKED_ADMIN_ROLE);
- }
-
- if (lesson != null) {
- screen = lesson;
-
- // We need to do some bookkeeping for the hackable admin
- // interface.
- // This is the only place we can tell if the user
- // successfully hacked the hackable
- // admin and has actually accessed an admin screen. You
- // need BOTH pieces of information
- // in order to satisfy the remote admin lesson.
- s.setHasHackableAdmin(screen.getRole());
-
- lesson.handleRequest(s);
- s.setCurrentMenu(lesson.getCategory().getRanking());
- } else {
- screen = new ErrorScreen(s, "Invalid screen requested. Try: http://localhost/WebGoat/attack");
- }
- }
- } else if (s.isAdmin()) {
- if (scr == WebSession.WELCOME) {
- screen = new WelcomeAdminScreen(s);
- } else {
- // Admin can see all roles.
- // FIXME: should be able to pass a list of roles.
- AbstractLesson lesson = course.getLesson(s, scr, AbstractLesson.ADMIN_ROLE);
- if (lesson == null) {
- lesson = course.getLesson(s, scr, AbstractLesson.HACKED_ADMIN_ROLE);
- }
- if (lesson == null) {
- lesson = course.getLesson(s, scr, AbstractLesson.USER_ROLE);
- }
-
- if (lesson != null) {
- screen = lesson;
-
- // We need to do some bookkeeping for the hackable admin
- // interface.
- // This is the only place we can tell if the user
- // successfully hacked the hackable
- // admin and has actually accessed an admin screen. You
- // need BOTH pieces of information
- // in order to satisfy the remote admin lesson.
- s.setHasHackableAdmin(screen.getRole());
-
- lesson.handleRequest(s);
- s.setCurrentMenu(lesson.getCategory().getRanking());
- } else {
- screen = new ErrorScreen(s,
- "Invalid screen requested. Try Setting Admin to false or Try: http://localhost/WebGoat/attack");
- }
- }
- }
-
- return (screen);
- }
-
- /**
- * This method sets the required expiration headers in the response for a
- * given RunData object. This method attempts to set all relevant headers,
- * both for HTTP 1.0 and HTTP 1.1.
- *
- * @param response The new cacheHeaders value
- * @param expiry The new cacheHeaders value
- */
- protected static void setCacheHeaders(HttpServletResponse response, int expiry) {
- if (expiry == 0) {
- response.setHeader("Pragma", "no-cache");
- response.setHeader("Cache-Control", "no-cache");
- response.setHeader("Expires", formatHttpDate(new Date()));
- } else {
- Date expiryDate = new Date(System.currentTimeMillis() + expiry);
- response.setHeader("Expires", formatHttpDate(expiryDate));
- }
- }
-
- /**
- * Description of the Method
- *
- * @param request Description of the Parameter
- * @param response Description of the Parameter
- * @param context Description of the Parameter
- * @return Description of the Return Value
- * @throws java.io.IOException if any.
- */
- protected WebSession updateSession(HttpServletRequest request, HttpServletResponse response, ServletContext context)
- throws IOException {
- HttpSession hs;
- // session should already be created by spring security
- hs = request.getSession(false);
-
- logger.debug("HH Entering Session_id: " + hs.getId());
- // dumpSession( hs );
- // Get our session object out of the HTTP session
- WebSession session = null;
- Object o = hs.getAttribute(WebSession.SESSION);
-
- if ((o != null) && o instanceof WebSession) {
- session = (WebSession) o;
- hs.setAttribute(WebSession.COURSE, session.getCourse());
- } else {
- // Create new custom session and save it in the HTTP session
- logger.warn("HH Creating new WebSession");
- session = new WebSession(webgoatContext, context);
- // Ensure splash screen shows on any restart
- // rlawson - removed this since we show splash screen at login now
- //hs.removeAttribute(WELCOMED);
- hs.setAttribute(WebSession.SESSION, session);
- // reset timeout
- hs.setMaxInactiveInterval(sessionTimeoutSeconds);
- }
-
- session.update(request, response, this.getServletName());
- // update last attack request info (cookies, parms)
- // this is so the REST services can have access to them via the session
- session.updateLastAttackRequestInfo(request);
-
- // to authenticate
- logger.debug("HH Leaving Session_id: " + hs.getId());
- //dumpSession( hs );
- return (session);
- }
-
- /**
- * Description of the Method
- *
- * @param s Description of the Parameter
- * @param screen a {@link org.owasp.webgoat.session.Screen} object.
- * @param screen a {@link org.owasp.webgoat.session.Screen} object.
- * @param response Description of the Parameter
- * @exception IOException Description of the Exception
- * @throws java.io.IOException if any.
- */
- protected void writeScreen(WebSession s, Screen screen, HttpServletResponse response) throws IOException {
- response.setContentType("text/html");
-
- PrintWriter out = response.getWriter();
-
- if (s == null) {
- screen = new ErrorScreen(s, "Page to display was null");
- }
-
- // set the content-length of the response.
- // Trying to avoid chunked-encoding. (Aspect required)
- response.setContentLength(screen.getContentLength());
- response.setHeader("Content-Length", screen.getContentLength() + "");
-
- screen.output(out);
- out.flush();
- out.close();
+ @RequestMapping(path = "/attack", method = {RequestMethod.GET, RequestMethod.POST})
+ public ModelAndView attack() {
+ return new ModelAndView("redirect:" + "start.mvc" + course.getFirstLesson().getLink());
}
}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/LessonSource.java b/webgoat-container/src/main/java/org/owasp/webgoat/LessonSource.java
deleted file mode 100644
index 0b03e30ba..000000000
--- a/webgoat-container/src/main/java/org/owasp/webgoat/LessonSource.java
+++ /dev/null
@@ -1,191 +0,0 @@
-package org.owasp.webgoat;
-
-import java.io.IOException;
-import java.io.PrintWriter;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import org.owasp.webgoat.lessons.AbstractLesson;
-import org.owasp.webgoat.session.Course;
-import org.owasp.webgoat.session.WebSession;
-
-/**
- * *************************************************************************************************
- *
- *
- * This file is part of WebGoat, an Open Web Application Security Project
- * utility. For details, please see http://www.owasp.org/
- *
- * Copyright (c) 2002 - 20014 Bruce Mayhew
- *
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License as published by the Free Software
- * Foundation; either version 2 of the License, or (at your option) any later
- * version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * Getting Source ==============
- *
- * Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository
- * for free software projects.
- *
- * @author Bruce Mayhew WebGoat
- * @since October 28, 2003
- * @version $Id: $Id
- */
-public class LessonSource extends HammerHead {
-
- /**
- *
- */
- private static final long serialVersionUID = 2588430536196446145L;
-
- /**
- * Description of the Field
- */
- public final static String START_SOURCE_SKIP = "START_OMIT_SOURCE";
-
- /** Constant END_SOURCE_SKIP="END_OMIT_SOURCE"
*/
- public final static String END_SOURCE_SKIP = "END_OMIT_SOURCE";
-
- /**
- * {@inheritDoc}
- *
- * Description of the Method
- * @exception IOException Description of the Exception
- * @exception ServletException Description of the Exception
- */
- public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
- String source = null;
-
- try {
- // System.out.println( "Entering doPost: " );
- // System.out.println( " - request " + request);
- // System.out.println( " - principle: " + request.getUserPrincipal()
- // );
- // setCacheHeaders(response, 0);
- WebSession session = (WebSession) request.getSession(true).getAttribute(WebSession.SESSION);
- // FIXME: Too much in this call.
- session.update(request, response, this.getServletName());
-
- boolean showSolution = session.getParser().getBooleanParameter("solution", false);
- boolean showSource = session.getParser().getBooleanParameter("source", false);
- if (showSolution) {
-
- // Get the Java solution of the lesson.
- source = getSolution(session);
-
- int scr = session.getCurrentScreen();
- Course course = session.getCourse();
- AbstractLesson lesson = course.getLesson(session, scr, AbstractLesson.USER_ROLE);
- lesson.getLessonTracker(session).setViewedSolution(true);
-
- } else if (showSource) {
-
- // Get the Java source of the lesson. FIXME: Not needed
- source = getSource(session);
-
- int scr = session.getCurrentScreen();
- Course course = session.getCourse();
- AbstractLesson lesson = course.getLesson(session, scr, AbstractLesson.USER_ROLE);
- lesson.getLessonTracker(session).setViewedSource(true);
- }
- } catch (Throwable t) {
- t.printStackTrace();
- log("ERROR: " + t);
- } finally {
- try {
- this.writeSource(source, response);
- } catch (Throwable thr) {
- thr.printStackTrace();
- log(request, "Could not write error screen: " + thr.getMessage());
- }
- // System.out.println( "Leaving doPost: " );
-
- }
- }
-
- /**
- * Description of the Method
- *
- * @param s Description of the Parameter
- * @return Description of the Return Value
- */
- protected String getSource(WebSession s) {
-
- String source = null;
- int scr = s.getCurrentScreen();
- Course course = s.getCourse();
-
- if (s.isUser() || s.isChallenge()) {
-
- AbstractLesson lesson = course.getLesson(s, scr, AbstractLesson.USER_ROLE);
-
- if (lesson != null) {
- source = lesson.getSource(s);
- }
- }
- if (source == null) {
- return "Source code is not available. Contact "
- + s.getWebgoatContext().getFeedbackAddressHTML();
- }
- return (source.replaceAll("(?s)" + START_SOURCE_SKIP + ".*" + END_SOURCE_SKIP,
- "Code Section Deliberately Omitted"));
- }
-
- /**
- *
getSolution.
- *
- * @param s a {@link org.owasp.webgoat.session.WebSession} object.
- * @return a {@link java.lang.String} object.
- */
- protected String getSolution(WebSession s) {
-
- String source = null;
- int scr = s.getCurrentScreen();
- Course course = s.getCourse();
-
- if (s.isUser() || s.isChallenge()) {
-
- AbstractLesson lesson = course.getLesson(s, scr, AbstractLesson.USER_ROLE);
-
- if (lesson != null) {
- source = lesson.getSolution(s);
- }
- }
- if (source == null) {
- return "Solution is not available. Contact "
- + s.getWebgoatContext().getFeedbackAddressHTML();
- }
- return (source);
- }
-
- /**
- * Description of the Method
- *
- * @param s Description of the Parameter
- * @param response Description of the Parameter
- * @exception IOException Description of the Exception
- * @throws java.io.IOException if any.
- */
- protected void writeSource(String s, HttpServletResponse response) throws IOException {
- response.setContentType("text/html");
-
- PrintWriter out = response.getWriter();
-
- if (s == null) {
- s = new String();
- }
-
- out.print(s);
- out.close();
- }
-}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/LessonTemplateResolver.java b/webgoat-container/src/main/java/org/owasp/webgoat/LessonTemplateResolver.java
new file mode 100644
index 000000000..dd23861fc
--- /dev/null
+++ b/webgoat-container/src/main/java/org/owasp/webgoat/LessonTemplateResolver.java
@@ -0,0 +1,91 @@
+/**
+ *************************************************************************************************
+ *
+ *
+ * This file is part of WebGoat, an Open Web Application Security Project utility. For details,
+ * please see http://www.owasp.org/
+ *
+ * Copyright (c) 2002 - 20014 Bruce Mayhew
+ *
+ * This program is free software; you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program; if
+ * not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Getting Source ==============
+ *
+ * Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
+ * projects.
+ *
+ * @author WebGoat
+ * @since October 28, 2003
+ * @version $Id: $Id
+ */
+package org.owasp.webgoat;
+
+import com.google.common.collect.Sets;
+import com.google.common.io.Files;
+import org.thymeleaf.TemplateProcessingParameters;
+import org.thymeleaf.resourceresolver.IResourceResolver;
+import org.thymeleaf.templateresolver.TemplateResolver;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * Dynamically resolve a lesson. In the html file this can be invoked as:
+ *
+ *
+ *
+ *
+ *
+ * Thymeleaf will invoke this resolver based on the prefix and this implementqtion will resolve the html in the plugins directory
+ */
+public class LessonTemplateResolver extends TemplateResolver {
+
+ private final static String PREFIX = "lesson:";
+ private final File pluginTargetDirectory;
+
+ public LessonTemplateResolver(File pluginTargetDirectory) {
+ this.pluginTargetDirectory = pluginTargetDirectory;
+ setResourceResolver(new LessonResourceResolver());
+ setResolvablePatterns(Sets.newHashSet(PREFIX + "*"));
+ }
+
+ @Override
+ protected String computeResourceName(TemplateProcessingParameters params) {
+ String templateName = params.getTemplateName();
+ return templateName.substring(PREFIX.length());
+ }
+
+ private class LessonResourceResolver implements IResourceResolver {
+
+ @Override
+ public InputStream getResourceAsStream(TemplateProcessingParameters params, String resourceName) {
+ File lesson = new File(pluginTargetDirectory, "/plugin/" + resourceName + "/html/" + resourceName + ".html");
+ if (lesson != null) {
+ try {
+ return new ByteArrayInputStream(Files.toByteArray(lesson));
+ } catch (IOException e) {
+ //no html yet
+ return new ByteArrayInputStream(new byte[0]);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public String getName() {
+ return "lessonResourceResolver";
+ }
+ }
+}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/MvcConfiguration.java b/webgoat-container/src/main/java/org/owasp/webgoat/MvcConfiguration.java
new file mode 100644
index 000000000..02ab81b6d
--- /dev/null
+++ b/webgoat-container/src/main/java/org/owasp/webgoat/MvcConfiguration.java
@@ -0,0 +1,124 @@
+/**
+ *************************************************************************************************
+ *
+ *
+ * This file is part of WebGoat, an Open Web Application Security Project utility. For details,
+ * please see http://www.owasp.org/
+ *
+ * Copyright (c) 2002 - 20014 Bruce Mayhew
+ *
+ * This program is free software; you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program; if
+ * not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Getting Source ==============
+ *
+ * Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
+ * projects.
+ *
+ * @author WebGoat
+ * @since October 28, 2003
+ * @version $Id: $Id
+ */
+package org.owasp.webgoat;
+
+import com.google.common.collect.Sets;
+import org.owasp.webgoat.session.Course;
+import org.owasp.webgoat.session.LabelDebugger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
+import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
+import org.thymeleaf.extras.springsecurity4.dialect.SpringSecurityDialect;
+import org.thymeleaf.spring4.SpringTemplateEngine;
+import org.thymeleaf.spring4.templateresolver.SpringResourceTemplateResolver;
+import org.thymeleaf.templateresolver.TemplateResolver;
+
+import java.io.File;
+
+/**
+ * Configuration for Spring MVC
+ */
+@Configuration
+public class MvcConfiguration extends WebMvcConfigurerAdapter {
+
+ @Autowired
+ @Qualifier("pluginTargetDirectory")
+ private File pluginTargetDirectory;
+
+ @Override
+ public void addViewControllers(ViewControllerRegistry registry) {
+ registry.addViewController("/login").setViewName("login");
+ registry.addViewController("/lesson_content").setViewName("lesson_content");
+ registry.addViewController("/start.mvc").setViewName("main_new");
+ }
+
+ @Bean
+ public TemplateResolver springThymeleafTemplateResolver(ApplicationContext applicationContext) {
+ SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();
+ resolver.setPrefix("classpath:/templates/");
+ resolver.setSuffix(".html");
+ resolver.setOrder(1);
+ resolver.setApplicationContext(applicationContext);
+ return resolver;
+ }
+
+ @Bean
+ public LessonTemplateResolver lessonTemplateResolver() {
+ LessonTemplateResolver resolver = new LessonTemplateResolver(pluginTargetDirectory);
+ resolver.setOrder(2);
+ resolver.setCacheable(false);
+ return resolver;
+ }
+
+ @Bean
+ public AsciiDoctorTemplateResolver asciiDoctorTemplateResolver() {
+ AsciiDoctorTemplateResolver resolver = new AsciiDoctorTemplateResolver(pluginTargetDirectory);
+ resolver.setCacheable(true);
+ resolver.setOrder(3);
+ return resolver;
+ }
+
+ @Bean
+ public SpringTemplateEngine thymeleafTemplateEngine(TemplateResolver springThymeleafTemplateResolver,
+ LessonTemplateResolver lessonTemplateResolver,
+ AsciiDoctorTemplateResolver asciiDoctorTemplateResolver) {
+ SpringTemplateEngine engine = new SpringTemplateEngine();
+ engine.addDialect(new SpringSecurityDialect());
+ engine.setTemplateResolvers(
+ Sets.newHashSet(springThymeleafTemplateResolver, lessonTemplateResolver, asciiDoctorTemplateResolver));
+ return engine;
+ }
+
+ /**
+ * This way we expose the plugins target directory as a resource within the web application.
+ *
+ * @param registry
+ */
+ @Override
+ public void addResourceHandlers(ResourceHandlerRegistry registry) {
+ registry.addResourceHandler("/plugin_lessons/**").addResourceLocations("file:///" + pluginTargetDirectory.toString() + "/");
+ }
+
+ @Bean
+ public HammerHead hammerHead(Course course) {
+ return new HammerHead(course);
+ }
+
+ @Bean
+ public LabelDebugger labelDebugger() {
+ return new LabelDebugger();
+ }
+}
\ No newline at end of file
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/WebGoat.java b/webgoat-container/src/main/java/org/owasp/webgoat/WebGoat.java
new file mode 100644
index 000000000..edaf68ce5
--- /dev/null
+++ b/webgoat-container/src/main/java/org/owasp/webgoat/WebGoat.java
@@ -0,0 +1,116 @@
+/**
+ * ************************************************************************************************
+ *
+ *
+ * This file is part of WebGoat, an Open Web Application Security Project utility. For details,
+ * please see http://www.owasp.org/
+ *
+ * Copyright (c) 2002 - 20014 Bruce Mayhew
+ *
+ * This program is free software; you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program; if
+ * not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Getting Source ==============
+ *
+ * Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
+ * projects.
+ *
+ * @author WebGoat
+ * @version $Id: $Id
+ * @since October 28, 2003
+ */
+package org.owasp.webgoat;
+
+import lombok.SneakyThrows;
+import lombok.extern.slf4j.Slf4j;
+import org.owasp.webgoat.plugins.Plugin;
+import org.owasp.webgoat.plugins.PluginClassLoader;
+import org.owasp.webgoat.plugins.PluginEndpointPublisher;
+import org.owasp.webgoat.plugins.PluginsLoader;
+import org.owasp.webgoat.session.Course;
+import org.owasp.webgoat.session.UserTracker;
+import org.owasp.webgoat.session.WebSession;
+import org.owasp.webgoat.session.WebgoatContext;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.boot.web.support.SpringBootServletInitializer;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Scope;
+import org.springframework.context.annotation.ScopedProxyMode;
+
+import java.io.File;
+import java.util.List;
+
+@SpringBootApplication
+@Slf4j
+public class WebGoat extends SpringBootServletInitializer {
+
+ @Override
+ protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
+ return application.sources(WebGoat.class);
+ }
+
+ public static void main(String[] args) throws Exception {
+ SpringApplication.run(WebGoat.class, args);
+ }
+
+ @Bean(name = "pluginTargetDirectory")
+ public File pluginTargetDirectory(@Value("${webgoat.user.directory}") final String webgoatHome) {
+ return new File(webgoatHome);
+ }
+
+ @Bean
+ public PluginClassLoader pluginClassLoader() {
+ return new PluginClassLoader(PluginClassLoader.class.getClassLoader());
+ }
+
+ @Bean
+ public PluginsLoader pluginsLoader(@Qualifier("pluginTargetDirectory") File pluginTargetDirectory, PluginClassLoader classLoader) {
+ return new PluginsLoader(pluginTargetDirectory, classLoader);
+ }
+
+ @Bean
+ @Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
+ public WebSession webSession(WebgoatContext webgoatContext) {
+ return new WebSession(webgoatContext);
+ }
+
+ @Bean
+ public Course course(PluginsLoader pluginsLoader, PluginEndpointPublisher pluginEndpointPublisher) {
+ Course course = new Course();
+ List plugins = pluginsLoader.loadPlugins();
+ if (plugins.isEmpty()) {
+ log.error("No lessons found if you downloaded an official release of WebGoat please take the time to");
+ log.error("create a new issue at https://github.com/WebGoat/WebGoat/issues/new");
+ log.error("For developers run 'mvn package' first from the root directory.");
+ log.error("Stopping WebGoat...");
+ System.exit(1); //we always run standalone
+ }
+ course.createLessonsFromPlugins(plugins);
+ plugins.forEach(p -> pluginEndpointPublisher.publish(p));
+
+ return course;
+ }
+
+ @Bean
+ @Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
+ @SneakyThrows
+ public UserTracker userTracker(@Value("${webgoat.user.directory}") final String webgoatHome, WebSession webSession) {
+ UserTracker userTracker = new UserTracker(webgoatHome, webSession.getUserName());
+ userTracker.load();
+ return userTracker;
+ }
+
+}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/WebSecurityConfig.java b/webgoat-container/src/main/java/org/owasp/webgoat/WebSecurityConfig.java
new file mode 100644
index 000000000..51a9eecbf
--- /dev/null
+++ b/webgoat-container/src/main/java/org/owasp/webgoat/WebSecurityConfig.java
@@ -0,0 +1,92 @@
+
+/**
+ *************************************************************************************************
+ * This file is part of WebGoat, an Open Web Application Security Project utility. For details,
+ * please see http://www.owasp.org/
+ *
+ * Copyright (c) 2002 - 20014 Bruce Mayhew
+ *
+ * This program is free software; you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program; if
+ * not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Getting Source ==============
+ *
+ * Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
+ * projects.
+ *
+ *
+ * @author WebGoat
+ * @since December 12, 2015
+ * @version $Id: $Id
+ */
+package org.owasp.webgoat;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.builders.WebSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
+import org.springframework.security.core.userdetails.UserDetailsService;
+
+/**
+ * Security configuration for WebGoat.
+ */
+@Configuration
+@EnableWebSecurity
+public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
+ @Override
+ protected void configure(HttpSecurity http) throws Exception {
+ ExpressionUrlAuthorizationConfigurer.ExpressionInterceptUrlRegistry security = http
+ .authorizeRequests()
+ .antMatchers("/css/**", "/images/**", "/js/**", "fonts/**", "/plugins/**").permitAll()
+ .antMatchers("/servlet/AdminServlet/**").hasAnyRole("WEBGOAT_ADMIN", "SERVER_ADMIN") //
+ .antMatchers("/JavaSource/**").hasRole("SERVER_ADMIN") //
+ .anyRequest().hasAnyRole("WEBGOAT_USER", "WEBGOAT_ADMIN", "SERVER_ADMIN");
+ security.and()
+ .formLogin()
+ .loginPage("/login")
+ .defaultSuccessUrl("/welcome.mvc", true)
+ .usernameParameter("username")
+ .passwordParameter("password")
+ .permitAll();
+ security.and()
+ .logout()
+ .permitAll();
+ security.and().csrf().disable();
+
+ http.headers().cacheControl().disable();
+ }
+
+ //// TODO: 11/18/2016 make this a little bit more configurabe last part at least
+ @Override
+ public void configure(WebSecurity web) throws Exception {
+ web.ignoring().antMatchers("/plugin_lessons/**", "/XXE/**");
+ }
+
+ @Autowired
+ public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
+ auth.inMemoryAuthentication()
+ .withUser("guest").password("guest").roles("WEBGOAT_USER").and() //
+ .withUser("webgoat").password("webgoat").roles("WEBGOAT_ADMIN").and() //
+ .withUser("server").password("server").roles("SERVER_ADMIN");
+ }
+
+ @Bean
+ @Override
+ public UserDetailsService userDetailsServiceBean() throws Exception {
+ return super.userDetailsServiceBean();
+ }
+}
\ No newline at end of file
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/application/Application.java b/webgoat-container/src/main/java/org/owasp/webgoat/application/Application.java
deleted file mode 100644
index 7ad64dbb5..000000000
--- a/webgoat-container/src/main/java/org/owasp/webgoat/application/Application.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * To change this license header, choose License Headers in Project Properties.
- * To change this template file, choose Tools | Templates
- * and open the template in the editor.
- */
-package org.owasp.webgoat.application;
-
-import org.apache.commons.lang3.StringUtils;
-import org.apache.commons.lang3.builder.ToStringBuilder;
-
-/**
- * Singleton which is created on context startup
- *
- * @author rlawson
- * @version $Id: $Id
- */
-public class Application {
-
- private static final Application INSTANCE = new Application();
-
- private Application() {
-
- }
-
- /**
- * getInstance.
- *
- * @return a {@link org.owasp.webgoat.application.Application} object.
- */
- public static final Application getInstance() {
- return INSTANCE;
- }
-
- private String version = "SNAPSHOT";
- private String build = "local";
- private String name = "WebGoat";
-
- /**
- * Getter for the field version
.
- *
- * @return the version
- */
- public String getVersion() {
- return version;
- }
-
- /**
- * Setter for the field version
.
- *
- * @param version the version to set
- */
- public void setVersion(String version) {
- if (StringUtils.isNotBlank(version)) {
- this.version = version;
- }
- }
-
- /**
- * Getter for the field build
.
- *
- * @return the build
- */
- public String getBuild() {
- return build;
- }
-
- /**
- * Setter for the field build
.
- *
- * @param build the build to set
- */
- public void setBuild(String build) {
- if (StringUtils.isNotBlank(build)) {
- this.build = build;
- }
- }
-
- /**
- * Getter for the field name
.
- *
- * @return the name
- */
- public String getName() {
- return name;
- }
-
- /**
- * Setter for the field name
.
- *
- * @param name the name to set
- */
- public void setName(String name) {
- if (StringUtils.isNotBlank(name)) {
- this.name = name;
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public String toString() {
- return new ToStringBuilder(this).
- append("name", name).
- append("version", version).
- append("build", build).
- toString();
- }
-}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/application/WebGoatServletListener.java b/webgoat-container/src/main/java/org/owasp/webgoat/application/WebGoatServletListener.java
deleted file mode 100644
index 7999387e0..000000000
--- a/webgoat-container/src/main/java/org/owasp/webgoat/application/WebGoatServletListener.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * To change this license header, choose License Headers in Project Properties.
- * To change this template file, choose Tools | Templates
- * and open the template in the editor.
- */
-package org.owasp.webgoat.application;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.file.Paths;
-import java.sql.Driver;
-import java.sql.DriverManager;
-import java.sql.SQLException;
-import java.util.Enumeration;
-import java.util.Set;
-import java.util.jar.Attributes;
-import java.util.jar.Manifest;
-
-import javax.servlet.ServletContext;
-import javax.servlet.ServletContextEvent;
-import javax.servlet.ServletContextListener;
-import javax.servlet.ServletRegistration;
-
-import org.owasp.webgoat.HammerHead;
-import org.owasp.webgoat.lessons.LessonServletMapping;
-import org.owasp.webgoat.plugins.PluginsLoader;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.config.BeanDefinition;
-import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
-import org.springframework.core.type.filter.AnnotationTypeFilter;
-
-/**
- * Web application lifecycle listener.
- *
- * @author rlawson
- * @version $Id: $Id
- */
-public class WebGoatServletListener implements ServletContextListener {
-
- private static final Logger logger = LoggerFactory.getLogger(HammerHead.class);
-
- /** {@inheritDoc} */
- @Override
- public void contextInitialized(ServletContextEvent sce) {
- ServletContext context = sce.getServletContext();
- context.log("WebGoat is starting");
- setApplicationVariables(context);
- context.log("Adding extra mappings for lessions");
-
- loadPlugins(sce);
- loadServlets(sce);
- }
-
- private void loadServlets(ServletContextEvent sce) {
- final ServletContext servletContext = sce.getServletContext();
- ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(
- false);
- provider.addIncludeFilter(new AnnotationTypeFilter(LessonServletMapping.class));
- Set candidateComponents = provider.findCandidateComponents("org.owasp.webgoat");
- try {
- for (BeanDefinition beanDefinition : candidateComponents) {
- Class controllerClass = Class.forName(beanDefinition.getBeanClassName());
- LessonServletMapping pathAnnotation = (LessonServletMapping) controllerClass.getAnnotation(LessonServletMapping.class);
- final ServletRegistration.Dynamic dynamic = servletContext.addServlet(controllerClass.getSimpleName(), controllerClass);
- dynamic.addMapping(pathAnnotation.path());
- }
- } catch (Exception e) {
- logger.error("Error", e);
- }
- }
-
- private void loadPlugins(ServletContextEvent sce) {
- String pluginPath = sce.getServletContext().getRealPath("plugin_lessons");
- String targetPath = sce.getServletContext().getRealPath("plugin_extracted");
- new PluginsLoader(Paths.get(pluginPath), Paths.get(targetPath)).loadPlugins();
- }
-
- /** {@inheritDoc} */
- @Override
- public void contextDestroyed(ServletContextEvent sce) {
- ServletContext context = sce.getServletContext();
- context.log("WebGoat is stopping");
-
- // Unregister JDBC drivers in this context's ClassLoader:
- // Get the webapp's ClassLoader
- ClassLoader cl = Thread.currentThread().getContextClassLoader();
- // Loop through all drivers
- Enumeration drivers = DriverManager.getDrivers();
- while (drivers.hasMoreElements()) {
- java.sql.Driver driver = drivers.nextElement();
- if (driver.getClass().getClassLoader() == cl) {
- // This driver was registered by the webapp's ClassLoader, so deregister it:
- try {
- context.log("Unregister JDBC driver {}");
- DriverManager.deregisterDriver(driver);
- } catch (SQLException ex) {
- context.log("Error unregistering JDBC driver {}");
- }
- } else {
- // driver was not registered by the webapp's ClassLoader and may be in use elsewhere
- context.log("Not unregistering JDBC driver {} as it does not belong to this webapp's ClassLoader");
- }
- }
- }
-
- private void setApplicationVariables(ServletContext context) {
- Application app = Application.getInstance();
- try {
- InputStream inputStream = context.getResourceAsStream("/META-INF/MANIFEST.MF");
- Manifest manifest = new Manifest(inputStream);
- Attributes attr = manifest.getMainAttributes();
- String name = attr.getValue("Specification-Title");
- String version = attr.getValue("Specification-Version");
- String build = attr.getValue("Implementation-Version");
- app.setName(name);
- app.setVersion(version);
- app.setBuild(build);
- } catch (IOException ioe) {
- context.log("Error setting application variables", ioe);
- }
- }
-}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/controller/About.java b/webgoat-container/src/main/java/org/owasp/webgoat/controller/About.java
deleted file mode 100644
index 094d9285f..000000000
--- a/webgoat-container/src/main/java/org/owasp/webgoat/controller/About.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * To change this license header, choose License Headers in Project Properties.
- * To change this template file, choose Tools | Templates
- * and open the template in the editor.
- */
-package org.owasp.webgoat.controller;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpSession;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.servlet.ModelAndView;
-
-/**
- * About class.
- *
- * @author rlawson
- * @version $Id: $Id
- */
-@Controller
-public class About {
-
- final Logger logger = LoggerFactory.getLogger(About.class);
- private static final String WELCOMED = "welcomed";
-
- /**
- * welcome.
- *
- * @param request a {@link javax.servlet.http.HttpServletRequest} object.
- * @param error a {@link java.lang.String} object.
- * @param logout a {@link java.lang.String} object.
- * @return a {@link org.springframework.web.servlet.ModelAndView} object.
- */
- @RequestMapping(value = "about.mvc", method = RequestMethod.GET)
- public ModelAndView welcome(HttpServletRequest request,
- @RequestParam(value = "error", required = false) String error,
- @RequestParam(value = "logout", required = false) String logout) {
-
- // set the welcome attribute
- // this is so the attack servlet does not also
- // send them to the welcome page
- HttpSession session = request.getSession();
- if (session.getAttribute(WELCOMED) == null) {
- session.setAttribute(WELCOMED, "true");
- }
-
- //go ahead and send them to webgoat (skip the welcome page)
- ModelAndView model = new ModelAndView();
- //model.setViewName("welcome");
- //model.setViewName("main_new");
- model.setViewName("about");
- return model;
- }
-
-}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/controller/Login.java b/webgoat-container/src/main/java/org/owasp/webgoat/controller/Login.java
deleted file mode 100644
index 6f9021f19..000000000
--- a/webgoat-container/src/main/java/org/owasp/webgoat/controller/Login.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * To change this license header, choose License Headers in Project Properties.
- * To change this template file, choose Tools | Templates
- * and open the template in the editor.
- */
-package org.owasp.webgoat.controller;
-
-import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.servlet.ModelAndView;
-
-/**
- * Login class.
- *
- * @author rlawson
- * @version $Id: $Id
- */
-@Controller
-public class Login {
-
- /**
- * login.
- *
- * @param error a {@link java.lang.String} object.
- * @param logout a {@link java.lang.String} object.
- * @return a {@link org.springframework.web.servlet.ModelAndView} object.
- */
- @RequestMapping(value = "login.mvc", method = RequestMethod.GET)
- public ModelAndView login(
- @RequestParam(value = "error", required = false) String error,
- @RequestParam(value = "logout", required = false) String logout) {
-
- ModelAndView model = new ModelAndView();
- if (error != null) {
- model.addObject("error", "Invalid username and password!");
- }
-
- if (logout != null) {
- model.addObject("msg", "You've been logged out successfully.");
- }
- model.setViewName("login");
-
- return model;
-
- }
-}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/controller/Logout.java b/webgoat-container/src/main/java/org/owasp/webgoat/controller/Logout.java
deleted file mode 100644
index 92e236a1c..000000000
--- a/webgoat-container/src/main/java/org/owasp/webgoat/controller/Logout.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * To change this license header, choose License Headers in Project Properties.
- * To change this template file, choose Tools | Templates
- * and open the template in the editor.
- */
-package org.owasp.webgoat.controller;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.servlet.ModelAndView;
-
-/**
- * Logout class.
- *
- * @author rlawson
- * @version $Id: $Id
- */
-@Controller
-public class Logout {
-
- final Logger logger = LoggerFactory.getLogger(Logout.class);
-
- /**
- * logout.
- *
- * @param error a {@link java.lang.String} object.
- * @param logout a {@link java.lang.String} object.
- * @return a {@link org.springframework.web.servlet.ModelAndView} object.
- */
- @RequestMapping(value = "logout.mvc", method = RequestMethod.GET)
- public ModelAndView logout(
- @RequestParam(value = "error", required = false) String error,
- @RequestParam(value = "logout", required = false) String logout) {
-
- logger.info("Logging user out");
-
- ModelAndView model = new ModelAndView();
- if (error != null) {
- model.addObject("error", "Invalid username and password!");
- }
-
- if (logout != null) {
- model.addObject("msg", "You've been logged out successfully.");
- }
- model.setViewName("logout");
-
- return model;
-
- }
-}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/controller/Start.java b/webgoat-container/src/main/java/org/owasp/webgoat/controller/Start.java
deleted file mode 100644
index 300209a9d..000000000
--- a/webgoat-container/src/main/java/org/owasp/webgoat/controller/Start.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * To change this license header, choose License Headers in Project Properties.
- * To change this template file, choose Tools | Templates
- * and open the template in the editor.
- */
-package org.owasp.webgoat.controller;
-
-import java.util.Collection;
-import javax.servlet.ServletContext;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpSession;
-import org.apache.commons.lang3.StringUtils;
-import org.owasp.webgoat.application.Application;
-import org.owasp.webgoat.session.WebSession;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.core.GrantedAuthority;
-import org.springframework.security.core.context.SecurityContextHolder;
-import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.servlet.ModelAndView;
-
-/**
- * Start class.
- *
- * @author rlawson
- * @version $Id: $Id
- */
-@Controller
-public class Start {
-
- final Logger logger = LoggerFactory.getLogger(Start.class);
-
- private static final String WELCOMED = "welcomed";
-
- @Autowired
- private ServletContext servletContext;
-
- /**
- * start.
- *
- * @param request a {@link javax.servlet.http.HttpServletRequest} object.
- * @param error a {@link java.lang.String} object.
- * @param logout a {@link java.lang.String} object.
- * @return a {@link org.springframework.web.servlet.ModelAndView} object.
- */
- @RequestMapping(value = "start.mvc", method = {RequestMethod.GET, RequestMethod.POST})
- public ModelAndView start(HttpServletRequest request,
- @RequestParam(value = "error", required = false) String error,
- @RequestParam(value = "logout", required = false) String logout) {
-
- ModelAndView model = new ModelAndView();
- // make sure session is set up correctly
- // if not redirect user to login
- if (checkWebSession(request.getSession()) == false) {
- model.setViewName("redirect:/login.mvc");
- return model;
- }
- String role = getRole();
- String user = request.getUserPrincipal().getName();
- model.addObject("role", role);
- model.addObject("user", user);
-
- String contactEmail = servletContext.getInitParameter("email");
- model.addObject("contactEmail", contactEmail);
- String emailList = servletContext.getInitParameter("emaillist");
- model.addObject("emailList", emailList);
-
- Application app = Application.getInstance();
- logger.info("Setting application properties: " + app);
- model.addObject("version", app.getVersion());
- model.addObject("build", app.getBuild());
-
- // if everything ok then go to webgoat UI
- model.setViewName("main_new");
- return model;
- }
-
- private String getRole() {
- Collection authorities = (Collection) SecurityContextHolder.getContext().getAuthentication().getAuthorities();
- String role = "N/A";
- for (GrantedAuthority authority : authorities) {
- authority.getAuthority();
- role = authority.getAuthority();
- role = StringUtils.lowerCase(role);
- role = StringUtils.remove(role, "role_");
- break;
- }
- return role;
- }
-
- /**
- * checkWebSession.
- *
- * @param session a {@link javax.servlet.http.HttpSession} object.
- * @return a boolean.
- */
- public boolean checkWebSession(HttpSession session) {
- Object o = session.getAttribute(WebSession.SESSION);
- if (o == null) {
- logger.error("No valid WebSession object found, has session timed out? [" + session.getId() + "]");
- return false;
- }
- if (!(o instanceof WebSession)) {
- logger.error("Invalid WebSession object found, this is probably a bug! [" + o.getClass() + " | " + session.getId() + "]");
- return false;
- }
- return true;
- }
-}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/controller/StartLesson.java b/webgoat-container/src/main/java/org/owasp/webgoat/controller/StartLesson.java
new file mode 100644
index 000000000..6af1770f3
--- /dev/null
+++ b/webgoat-container/src/main/java/org/owasp/webgoat/controller/StartLesson.java
@@ -0,0 +1,93 @@
+/**
+ * ************************************************************************************************
+ *
+ *
+ * This file is part of WebGoat, an Open Web Application Security Project utility. For details,
+ * please see http://www.owasp.org/
+ *
+ * Copyright (c) 2002 - 20014 Bruce Mayhew
+ *
+ * This program is free software; you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program; if
+ * not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Getting Source ==============
+ *
+ * Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
+ * projects.
+ *
+ * @author WebGoat
+ * @version $Id: $Id
+ * @since October 28, 2003
+ */
+package org.owasp.webgoat.controller;
+
+import org.owasp.webgoat.lessons.AbstractLesson;
+import org.owasp.webgoat.session.Course;
+import org.owasp.webgoat.session.WebSession;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.context.SecurityContext;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.servlet.ModelAndView;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.List;
+import java.util.Optional;
+
+
+@Controller
+public class StartLesson {
+
+ private final WebSession ws;
+ private final Course course;
+
+ public StartLesson(final WebSession ws, final Course course) {
+ this.ws = ws;
+ this.course = course;
+ }
+
+ /**
+ *
start.
+ *
+ * @return a {@link ModelAndView} object.
+ */
+ @RequestMapping(path = "startlesson.mvc", method = {RequestMethod.GET, RequestMethod.POST})
+ public ModelAndView start() {
+ ModelAndView model = new ModelAndView();
+
+ model.addObject("course", course);
+ model.addObject("lesson", ws.getCurrentLesson());
+ model.setViewName("lesson_content");
+ return model;
+ }
+
+ @RequestMapping(value = {"*.lesson"}, produces = "text/html")
+ public ModelAndView lessonPage(HttpServletRequest request) {
+ // I will set here the thymeleaf fragment location based on the resource requested.
+ ModelAndView model = new ModelAndView();
+ SecurityContext context = SecurityContextHolder.getContext(); //TODO this should work with the security roles of Spring
+ GrantedAuthority authority = context.getAuthentication().getAuthorities().iterator().next();
+ String path = request.getServletPath(); // we now got /a/b/c/AccessControlMatrix.lesson
+ String lessonName = path.substring(path.lastIndexOf('/') + 1, path.indexOf(".lesson"));
+ List lessons = course.getLessons();
+ Optional lesson = lessons.stream()
+ .filter(l -> l.getId().equals(lessonName))
+ .findFirst();
+ ws.setCurrentLesson(lesson.get());
+ model.setViewName("lesson_content");
+ model.addObject("lesson", lesson.get());
+ return model;
+ }
+
+}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/controller/Welcome.java b/webgoat-container/src/main/java/org/owasp/webgoat/controller/Welcome.java
index 050b0a79f..546b1f992 100644
--- a/webgoat-container/src/main/java/org/owasp/webgoat/controller/Welcome.java
+++ b/webgoat-container/src/main/java/org/owasp/webgoat/controller/Welcome.java
@@ -1,20 +1,43 @@
-/*
- * To change this license header, choose License Headers in Project Properties.
- * To change this template file, choose Tools | Templates
- * and open the template in the editor.
+/**
+ *************************************************************************************************
+ *
+ *
+ * This file is part of WebGoat, an Open Web Application Security Project utility. For details,
+ * please see http://www.owasp.org/
+ *
+ * Copyright (c) 2002 - 20014 Bruce Mayhew
+ *
+ * This program is free software; you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program; if
+ * not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Getting Source ==============
+ *
+ * Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
+ * projects.
+ *
+ * @author WebGoat
+ * @since October 28, 2003
+ * @version $Id: $Id
*/
package org.owasp.webgoat.controller;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpSession;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+
/**
* Welcome class.
*
@@ -23,22 +46,17 @@ import org.springframework.web.servlet.ModelAndView;
*/
@Controller
public class Welcome {
-
- final Logger logger = LoggerFactory.getLogger(Welcome.class);
+
private static final String WELCOMED = "welcomed";
/**
* welcome.
*
* @param request a {@link javax.servlet.http.HttpServletRequest} object.
- * @param error a {@link java.lang.String} object.
- * @param logout a {@link java.lang.String} object.
* @return a {@link org.springframework.web.servlet.ModelAndView} object.
*/
- @RequestMapping(value = "welcome.mvc", method = RequestMethod.GET)
- public ModelAndView welcome(HttpServletRequest request,
- @RequestParam(value = "error", required = false) String error,
- @RequestParam(value = "logout", required = false) String logout) {
+ @RequestMapping(path = "welcome.mvc", method = RequestMethod.GET)
+ public ModelAndView welcome(HttpServletRequest request) {
// set the welcome attribute
// this is so the attack servlet does not also
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/util/LabelManager.java b/webgoat-container/src/main/java/org/owasp/webgoat/i18n/LabelManager.java
similarity index 98%
rename from webgoat-container/src/main/java/org/owasp/webgoat/util/LabelManager.java
rename to webgoat-container/src/main/java/org/owasp/webgoat/i18n/LabelManager.java
index a0f42adc9..21990bf6e 100644
--- a/webgoat-container/src/main/java/org/owasp/webgoat/util/LabelManager.java
+++ b/webgoat-container/src/main/java/org/owasp/webgoat/i18n/LabelManager.java
@@ -1,5 +1,5 @@
-package org.owasp.webgoat.util;
+package org.owasp.webgoat.i18n;
import java.util.Locale;
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/util/LabelManagerImpl.java b/webgoat-container/src/main/java/org/owasp/webgoat/i18n/LabelManagerImpl.java
similarity index 81%
rename from webgoat-container/src/main/java/org/owasp/webgoat/util/LabelManagerImpl.java
rename to webgoat-container/src/main/java/org/owasp/webgoat/i18n/LabelManagerImpl.java
index f98b1a981..0e3ed00c4 100644
--- a/webgoat-container/src/main/java/org/owasp/webgoat/util/LabelManagerImpl.java
+++ b/webgoat-container/src/main/java/org/owasp/webgoat/i18n/LabelManagerImpl.java
@@ -1,8 +1,7 @@
-package org.owasp.webgoat.util;
+package org.owasp.webgoat.i18n;
import org.owasp.webgoat.session.LabelDebugger;
-import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.io.Serializable;
@@ -38,30 +37,22 @@ import java.util.Locale;
* @version $Id: $Id
* @author dm
*/
-@Component("labelManager")
+@Component
public class LabelManagerImpl implements LabelManager, Serializable
{
private static final long serialVersionUID = 1L;
- @Autowired
- private transient LabelProvider labelProvider;
- @Autowired
+ private LabelProvider labelProvider;
private LabelDebugger labelDebugger;
-
- /** Locale mapped with current session. */
private Locale locale = new Locale(LabelProvider.DEFAULT_LANGUAGE);
- /**
- * Constructor for LabelManagerImpl.
- */
- protected LabelManagerImpl() {}
-
/**
* Constructor for LabelManagerImpl.
*
- * @param labelProvider a {@link org.owasp.webgoat.util.LabelProvider} object.
+ * @param labelProvider a {@link LabelProvider} object.
*/
- protected LabelManagerImpl(LabelProvider labelProvider) {
+ protected LabelManagerImpl(LabelProvider labelProvider, LabelDebugger labelDebugger) {
+ this.labelDebugger = labelDebugger;
this.labelProvider = labelProvider;
}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/util/LabelProvider.java b/webgoat-container/src/main/java/org/owasp/webgoat/i18n/LabelProvider.java
similarity index 98%
rename from webgoat-container/src/main/java/org/owasp/webgoat/util/LabelProvider.java
rename to webgoat-container/src/main/java/org/owasp/webgoat/i18n/LabelProvider.java
index 674699c01..c1fa62ae0 100644
--- a/webgoat-container/src/main/java/org/owasp/webgoat/util/LabelProvider.java
+++ b/webgoat-container/src/main/java/org/owasp/webgoat/i18n/LabelProvider.java
@@ -1,5 +1,5 @@
-package org.owasp.webgoat.util;
+package org.owasp.webgoat.i18n;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.core.io.Resource;
@@ -7,7 +7,6 @@ import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.UrlResource;
import org.springframework.stereotype.Component;
-import javax.inject.Singleton;
import java.net.MalformedURLException;
import java.nio.file.Path;
import java.util.Arrays;
@@ -47,7 +46,6 @@ import java.util.Locale;
* @author dm
*/
@Component
-@Singleton
public class LabelProvider {
/** Constant DEFAULT_LANGUAGE="Locale.ENGLISH.getLanguage()"
*/
public final static String DEFAULT_LANGUAGE = Locale.ENGLISH.getLanguage();
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/AbstractLesson.java b/webgoat-container/src/main/java/org/owasp/webgoat/lessons/AbstractLesson.java
index b209a88cf..4648c0335 100644
--- a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/AbstractLesson.java
+++ b/webgoat-container/src/main/java/org/owasp/webgoat/lessons/AbstractLesson.java
@@ -1,45 +1,15 @@
package org.owasp.webgoat.lessons;
-import org.apache.ecs.Element;
-import org.apache.ecs.ElementContainer;
-import org.apache.ecs.StringElement;
-import org.apache.ecs.html.Body;
-import org.apache.ecs.html.Form;
-import org.apache.ecs.html.Head;
-import org.apache.ecs.html.Html;
-import org.apache.ecs.html.IMG;
-import org.apache.ecs.html.PRE;
-import org.apache.ecs.html.Title;
-import org.owasp.webgoat.session.ParameterNotFoundException;
+import lombok.Getter;
+import lombok.Setter;
import org.owasp.webgoat.session.Screen;
-import org.owasp.webgoat.session.WebSession;
-import org.owasp.webgoat.session.WebgoatContext;
-import org.owasp.webgoat.session.WebgoatProperties;
-import org.owasp.webgoat.util.BeanProvider;
-import org.owasp.webgoat.util.LabelManager;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import java.io.BufferedReader;
-import java.io.FileNotFoundException;
-import java.io.FileReader;
-import java.io.InputStreamReader;
-import java.io.StringReader;
-import java.net.HttpURLConnection;
-import java.net.URL;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Statement;
-import java.util.HashMap;
-import java.util.LinkedList;
import java.util.List;
-import java.util.Map;
-
-import static java.lang.Math.abs;
/**
* ************************************************************************************************
*
+ *
* This file is part of WebGoat, an Open Web Application Security Project utility. For details,
* please see http://www.owasp.org/
*
@@ -68,66 +38,24 @@ import static java.lang.Math.abs;
*/
public abstract class AbstractLesson extends Screen implements Comparable {
- private static final Logger logger = LoggerFactory.getLogger(AbstractLesson.class);
-
- /**
- * Description of the Field
- */
- public final static String ADMIN_ROLE = "admin";
-
- /**
- * Constant CHALLENGE_ROLE="challenge"
- */
- public final static String CHALLENGE_ROLE = "challenge";
-
- /**
- * Description of the Field
- */
- public final static String HACKED_ADMIN_ROLE = "hacked_admin";
-
- /**
- * Description of the Field
- */
- public final static String USER_ROLE = "user";
-
private static int count = 1;
private Integer id = null;
- final static IMG nextGrey = new IMG("images/right16.gif").setAlt("Next").setBorder(0).setHspace(0).setVspace(0);
-
- final static IMG previousGrey = new IMG("images/left14.gif").setAlt("Previous").setBorder(0).setHspace(0)
- .setVspace(0);
-
private Integer ranking;
- private Category category;
-
- private boolean hidden;
-
- private String sourceFileName;
-
- private Map lessonPlanFileName = new HashMap();
-
- private String lessonSolutionFileName;
-
- private WebgoatContext webgoatContext;
-
- private LinkedList availableLanguages = new LinkedList();
-
- private String defaultLanguage = "en";
-
- private LabelManager labelManager = null;
+ @Setter
+ @Getter
+ private List> assignments;
/**
* Constructor for the Lesson object
*/
public AbstractLesson() {
- //based on the class name derive an id so the screenId is fixed, should not give clashes based on
- //the fact we use the classname and the size is limited
- id = abs(this.getClass().getSimpleName().hashCode());
+ id = new Integer(++count);
}
+
/**
* getName.
*
@@ -147,46 +75,6 @@ public abstract class AbstractLesson extends Screen implements ComparableSetter for the field hidden
.
- *
- * @param hidden a boolean.
- */
- public void setHidden(boolean hidden) {
- this.hidden = hidden;
- }
-
- /**
- * update.
- *
- * @param properties a {@link org.owasp.webgoat.session.WebgoatProperties} object.
- */
- public void update(WebgoatProperties properties) {
- String className = getClass().getName();
- className = className.substring(className.lastIndexOf(".") + 1);
- setRanking(new Integer(properties.getIntProperty("lesson." + className + ".ranking", getDefaultRanking()
- .intValue())));
- String categoryRankingKey = "category." + getDefaultCategory().getName() + ".ranking";
- // System.out.println("Category ranking key: " + categoryRankingKey);
- Category tempCategory = Category.getCategory(getDefaultCategory().getName());
- tempCategory.setRanking(new Integer(properties.getIntProperty(categoryRankingKey, getDefaultCategory()
- .getRanking().intValue())));
- category = tempCategory;
- setHidden(properties.getBooleanProperty("lesson." + className + ".hidden", getDefaultHidden()));
- // System.out.println(className + " in " + tempCategory.getName() + "
- // (Category Ranking: " + tempCategory.getRanking() + " Lesson ranking:
- // " + getRanking() + ", hidden:" + hidden +")");
- }
-
- /**
- * isCompleted.
- *
- * @param s a {@link org.owasp.webgoat.session.WebSession} object.
- * @return a boolean.
- */
- public boolean isCompleted(WebSession s) {
- return getLessonTracker(s, this).getCompleted();
- }
/**
* {@inheritDoc}
@@ -212,7 +100,7 @@ public abstract class AbstractLesson extends Screen implements ComparablegetHints.
*
- * @param s a {@link org.owasp.webgoat.session.WebSession} object.
* @return a {@link java.util.List} object.
*/
- protected abstract List getHints(WebSession s);
-
- // @TODO we need to restrict access at the service layer
- // rather than passing session object around
-
- /**
- * getHintsPublic.
- *
- * @param s a {@link org.owasp.webgoat.session.WebSession} object.
- * @return a {@link java.util.List} object.
- */
- public List getHintsPublic(WebSession s) {
- List hints = getHints(s);
- return hints;
- }
-
- /**
- * Fill in a minor hint that will help people who basically get it, but are
- * stuck on somthing silly.
- *
- * @param s The users WebSession
- * @param hintNumber a int.
- * @return The hint1 value
- */
- public String getHint(WebSession s, int hintNumber) {
- return "Hint: " + getHints(s).get(hintNumber);
- }
-
- /**
- * Gets the instructions attribute of the AbstractLesson object
- *
- * @param s a {@link org.owasp.webgoat.session.WebSession} object.
- * @return The instructions value
- */
- public abstract String getInstructions(WebSession s);
-
- /**
- * Gets the lessonPlan attribute of the Lesson object
- *
- * @return The lessonPlan value
- */
- public String getLessonName() {
- return this.getClass().getSimpleName();
- }
+ public abstract List getHints();
/**
* Gets the title attribute of the HelloScreen object
@@ -421,36 +154,6 @@ public abstract class AbstractLesson extends Screen implements ComparablegetHtml_DELETE_ME.
- *
- * @param s a {@link org.owasp.webgoat.session.WebSession} object.
- * @return a {@link java.lang.String} object.
- */
- public String getHtml_DELETE_ME(WebSession s) {
- String html = null;
-
- // FIXME: This doesn't work for the labs since they do not implement
- // createContent().
- String rawHtml = createContent(s).toString();
- // System.out.println("Getting raw html content: " +
- // rawHtml.substring(0, Math.min(rawHtml.length(), 100)));
- html = convertMetachars(AbstractLesson.readFromFile(new BufferedReader(new StringReader(rawHtml)), true));
- // System.out.println("Getting encoded html content: " +
- // html.substring(0, Math.min(html.length(), 100)));
-
- return html;
- }
-
- /**
- * getSource.
- *
- * @param s a {@link org.owasp.webgoat.session.WebSession} object.
- * @return a {@link java.lang.String} object.
- */
- public String getSource(WebSession s) {
- String source = null;
- String src = null;
-
- try {
- // System.out.println("Loading source file: " +
- // getSourceFileName());
- src = convertMetacharsJavaCode(readFromFile(new BufferedReader(new FileReader(getSourceFileName())), true));
-
- // TODO: For styled line numbers and better memory efficiency,
- // use a custom FilterReader
- // that performs the convertMetacharsJavaCode() transform plus
- // optionally adds a styled
- // line number. Wouldn't color syntax be great too?
- } catch (Exception e) {
- s.setMessage("Could not find source file");
- src = ("Could not find the source file or source file does not exist. "
- + "Send this message to: " + s.getWebgoatContext()
- .getFeedbackAddress() + " ");
- }
-
- Html html = new Html();
-
- Head head = new Head();
- head.addElement(new Title(getSourceFileName()));
-
- Body body = new Body();
- body.addElement(new StringElement(src));
-
- html.addElement(head);
- html.addElement(body);
-
- source = html.toString();
-
- return source;
- }
-
- /**
- * getRawSource.
- *
- * @param s a {@link org.owasp.webgoat.session.WebSession} object.
- * @return a {@link java.lang.String} object.
- */
- public String getRawSource(WebSession s) {
- String src;
-
- try {
- logger.debug("Loading source file: " + getSourceFileName());
- src = readFromFile(new BufferedReader(new FileReader(getSourceFileName())), false);
-
- } catch (FileNotFoundException e) {
- s.setMessage("Could not find source file");
- src = ("Could not find the source file or source file does not exist. "
- + "Send this message to: " + s.getWebgoatContext()
- .getFeedbackAddress() + " ");
- }
-
- return src;
- }
-
- /**
- * getSolution.
- *
- * @param s a {@link org.owasp.webgoat.session.WebSession} object.
- * @return a {@link java.lang.String} object.
- */
- public String getSolution(WebSession s) {
- String src = null;
-
- try {
- // System.out.println("Solution: " + getLessonSolutionFileName());
- src = readFromFile(new BufferedReader(new FileReader(getLessonSolutionFileName())), false);
- } catch (Exception e) {
- logger.error("Could not find solution for {}", getLessonSolutionFileName());
- s.setMessage("Could not find the solution file");
- src = ("Could not find the solution file or solution file does not exist. "
- + "Send this message to: " + s.getWebgoatContext()
- .getFeedbackAddress() + " ");
- }
-
- // Solutions are html files
- return src;
- }
-
/**
* Returns the default "path" portion of a lesson's URL.
*
+ *
* Legacy webgoat lesson links are of the form
* "attack?Screen=Xmenu=Ystage=Z". This method returns the path portion of
* the url, i.e., "attack" in the string above.
@@ -630,7 +190,7 @@ public abstract class AbstractLesson extends Screen implements Comparable
- * Unlike getLink() this method does not require rendering the output of
- * the request to the link in order to execute the servlet's method with
- * conventional HTTP query parameters.
- *
- * @return a {@link java.lang.String} object.
- */
- public String getServletLink() {
- StringBuffer link = new StringBuffer("attack");
-
- return link
- .append("?Screen=").append(getScreenId())
- .append("&menu=").append(getCategory().getRanking()).toString();
- }
-
- /**
- * Get the link to the jsp page used to render this screen.
- *
- * @param s a {@link org.owasp.webgoat.session.WebSession} object.
- * @return a {@link java.lang.String} object.
- */
- public String getPage(WebSession s) {
- return null;
- }
-
- /**
- * Get the link to the jsp template page used to render this screen.
- *
- * @param s a {@link org.owasp.webgoat.session.WebSession} object.
- * @return a {@link java.lang.String} object.
- */
- public String getTemplatePage(WebSession s) {
- return null;
- }
-
- /**
- * getCurrentAction.
- *
- * @param s a {@link org.owasp.webgoat.session.WebSession} object.
- * @return a {@link java.lang.String} object.
- */
- public abstract String getCurrentAction(WebSession s);
-
- /**
- * Initiates lesson restart functionality
- */
- public abstract void restartLesson();
-
-
- /**
- * setCurrentAction.
- *
- * @param s a {@link org.owasp.webgoat.session.WebSession} object.
- * @param lessonScreen a {@link java.lang.String} object.
- */
- public abstract void setCurrentAction(WebSession s, String lessonScreen);
-
- /**
- * Override this method to implement accesss control in a lesson.
- *
- * @param s a {@link org.owasp.webgoat.session.WebSession} object.
- * @param functionId a {@link java.lang.String} object.
- * @param employeeId a int.
- * @return a boolean.
- */
- public boolean isAuthorized(WebSession s, int employeeId, String functionId) {
- return false;
- }
-
- /**
- * Override this method to implement accesss control in a lesson.
- *
- * @param s a {@link org.owasp.webgoat.session.WebSession} object.
- * @param functionId a {@link java.lang.String} object.
- * @param role a {@link java.lang.String} object.
- * @return a boolean.
- */
- public boolean isAuthorized(WebSession s, String role, String functionId) {
- logger.info("Checking if " + role + " authorized for: " + functionId);
- boolean authorized = false;
- try {
- String query = "SELECT * FROM auth WHERE role = '" + role + "' and functionid = '" + functionId + "'";
- try {
- Statement answer_statement = WebSession.getConnection(s)
- .createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
- ResultSet answer_results = answer_statement.executeQuery(query);
- authorized = answer_results.first();
- logger.info("authorized: " + authorized);
- } catch (SQLException sqle) {
- s.setMessage("Error authorizing");
- logger.error("Error authorizing", sqle);
- }
- } catch (Exception e) {
- s.setMessage("Error authorizing");
- logger.error("Error authorizing", e);
- }
- return authorized;
- }
-
- /**
- * getUserId.
- *
- * @param s a {@link org.owasp.webgoat.session.WebSession} object.
- * @return a int.
- * @throws org.owasp.webgoat.session.ParameterNotFoundException if any.
- */
- public int getUserId(WebSession s) throws ParameterNotFoundException {
- return -1;
- }
-
- /**
- * getUserName.
- *
- * @param s a {@link org.owasp.webgoat.session.WebSession} object.
- * @return a {@link java.lang.String} object.
- * @throws org.owasp.webgoat.session.ParameterNotFoundException if any.
- */
- public String getUserName(WebSession s) throws ParameterNotFoundException {
- return null;
- }
-
- /**
- * Description of the Method
- *
- * @param windowName Description of the Parameter
- * @return Description of the Return Value
- */
- public static String makeWindowScript(String windowName) {
- // FIXME: make this string static
- StringBuffer script = new StringBuffer();
- script.append("\n");
-
- return script.toString();
- }
-
- /**
- * Simply reads a url into an Element for display. CAUTION: you might want
- * to tinker with any non-https links (href)
- *
- * @param url Description of the Parameter
- * @return Description of the Return Value
- */
- public static Element readFromURL(String url) {
- ElementContainer ec = new ElementContainer();
-
- try {
- URL u = new URL(url);
- HttpURLConnection huc = (HttpURLConnection) u.openConnection();
- BufferedReader reader = new BufferedReader(new InputStreamReader(huc.getInputStream()));
- String line;
-
- while ((line = reader.readLine()) != null) {
- ec.addElement(new StringElement(line));
- }
-
- reader.close();
- } catch (Exception e) {
- System.out.println(e);
- e.printStackTrace();
- }
-
- return (ec);
- }
-
- /**
- * Description of the Method
- *
- * @param reader Description of the Parameter
- * @param numbers Description of the Parameter
- * @param methodName Description of the Parameter
- * @return Description of the Return Value
- */
- public static Element readMethodFromFile(BufferedReader reader, String methodName, boolean numbers) {
- PRE pre = new PRE().addElement(getFileMethod(reader, methodName, numbers));
-
- return (pre);
- }
-
- /**
- * Description of the Method
- *
- * @param s Description of the Parameter
- */
- public void handleRequest(WebSession s) {
- // call createContent first so messages will go somewhere
- Form form = new Form(getFormAction(), Form.POST).setName("form").setEncType("");
- form.addElement(createContent(s));
- setContent(form);
- s.getRequest().getRequestURL();
- }
-
- /**
- * getFormAction.
- *
- * @return a {@link java.lang.String} object.
- */
- public String getFormAction() {
- return getLink();
+ return String.format("%s%s.lesson", getPath(), getId());
}
/**
@@ -893,115 +218,5 @@ public abstract class AbstractLesson extends Screen implements ComparableGetter for the field defaultLanguage
.
- *
- * @return a {@link java.lang.String} object.
- */
- public String getDefaultLanguage() {
- return this.defaultLanguage;
- }
-
- /**
- * Getter for the field lessonPlanFileName
.
- *
- * @param lang a {@link java.lang.String} object.
- * @return a {@link java.lang.String} object.
- */
- public String getLessonPlanFileName(String lang) {
- String ret = lessonPlanFileName.get(lang);
- if (ret == null) {
- ret = lessonPlanFileName.get(getDefaultLanguage());
- }
- return ret;
- }
-
- /**
- * Setter for the field lessonPlanFileName
.
- *
- * @param lang a {@link java.lang.String} object.
- * @param lessonPlanFileName a {@link java.lang.String} object.
- */
- public void setLessonPlanFileName(String lang, String lessonPlanFileName) {
- this.lessonPlanFileName.put(lang, lessonPlanFileName);
- this.availableLanguages.add(lang);
- }
-
- /**
- * Getter for the field availableLanguages
.
- *
- * @return a {@link java.util.List} object.
- */
- public List getAvailableLanguages() {
- return this.availableLanguages;
- }
-
- /**
- * Getter for the field lessonSolutionFileName
.
- *
- * @return a {@link java.lang.String} object.
- */
- public String getLessonSolutionFileName() {
- return lessonSolutionFileName;
- }
-
- /**
- * Setter for the field lessonSolutionFileName
.
- *
- * @param lessonSolutionFileName a {@link java.lang.String} object.
- */
- public void setLessonSolutionFileName(String lessonSolutionFileName) {
- this.lessonSolutionFileName = lessonSolutionFileName;
- }
-
- /**
- * Getter for the field sourceFileName
.
- *
- * @return a {@link java.lang.String} object.
- */
- public String getSourceFileName() {
- return sourceFileName;
- }
-
- /**
- * Setter for the field sourceFileName
.
- *
- * @param sourceFileName a {@link java.lang.String} object.
- */
- public void setSourceFileName(String sourceFileName) {
- logger.debug("Setting source file of lesson " + this + " to: " + sourceFileName);
- this.sourceFileName = sourceFileName;
- }
-
- /**
- * Getter for the field webgoatContext
.
- *
- * @return a {@link org.owasp.webgoat.session.WebgoatContext} object.
- */
- public WebgoatContext getWebgoatContext() {
- return webgoatContext;
- }
-
- /**
- * Setter for the field webgoatContext
.
- *
- * @param webgoatContext a {@link org.owasp.webgoat.session.WebgoatContext} object.
- */
- public void setWebgoatContext(WebgoatContext webgoatContext) {
- this.webgoatContext = webgoatContext;
- }
-
- /**
- * Getter for the field labelManager
.
- *
- * @return a {@link org.owasp.webgoat.util.LabelManager} object.
- */
- protected LabelManager getLabelManager() {
- if (labelManager == null) {
- labelManager = BeanProvider.getBean("labelManager", LabelManager.class);
- }
- return labelManager;
- }
-
-
+ public abstract String getId();
}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/Assignment.java b/webgoat-container/src/main/java/org/owasp/webgoat/lessons/Assignment.java
new file mode 100644
index 000000000..0189a7884
--- /dev/null
+++ b/webgoat-container/src/main/java/org/owasp/webgoat/lessons/Assignment.java
@@ -0,0 +1,65 @@
+/**
+ * ************************************************************************************************
+ * This file is part of WebGoat, an Open Web Application Security Project utility. For details,
+ * please see http://www.owasp.org/
+ *
+ * Copyright (c) 2002 - 20014 Bruce Mayhew
+ *
+ * This program is free software; you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program; if
+ * not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Getting Source ==============
+ *
+ * Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
+ * projects.
+ *
+ */
+package org.owasp.webgoat.lessons;
+
+import org.owasp.webgoat.lessons.model.AttackResult;
+import org.owasp.webgoat.session.UserTracker;
+import org.owasp.webgoat.session.WebSession;
+import org.springframework.beans.factory.annotation.Autowired;
+
+/**
+ * Each lesson can define an endpoint which can support the lesson. So for example if you create a lesson which uses JavaScript and
+ * needs to call out to the server to fetch data you can define an endpoint in that lesson. WebGoat will pick up this endpoint and
+ * Spring will publish it.
+ *
+ * Extend this class and implement the met
+ *
+ * Note: each subclass should declare this annotation otherwise the WebGoat framework cannot find your endpoint.
+ */
+public abstract class Assignment extends Endpoint {
+
+ @Autowired
+ private UserTracker userTracker;
+ @Autowired
+ private WebSession webSession;
+
+
+ //// TODO: 11/13/2016 events better fit?
+ protected AttackResult trackProgress(AttackResult attackResult) {
+ if (attackResult.assignmentSolved()) {
+ userTracker.assignmentSolved(webSession.getCurrentLesson(), this);
+ } else {
+ userTracker.assignmentFailed(webSession.getCurrentLesson());
+ }
+ return attackResult;
+ }
+
+ protected WebSession getWebSession() {
+ return webSession;
+ }
+
+
+}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/Category.java b/webgoat-container/src/main/java/org/owasp/webgoat/lessons/Category.java
index 66b3ee276..ea6a3cbb4 100644
--- a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/Category.java
+++ b/webgoat-container/src/main/java/org/owasp/webgoat/lessons/Category.java
@@ -1,220 +1,76 @@
package org.owasp.webgoat.lessons;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
+import lombok.Getter;
/**
* *************************************************************************************************
- *
- *
+ *
+ *
* This file is part of WebGoat, an Open Web Application Security Project
* utility. For details, please see http://www.owasp.org/
- *
+ *
* Copyright (c) 2002 - 20014 Bruce Mayhew
- *
+ *
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option) any later
* version.
- *
+ *
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
- *
+ *
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place - Suite 330, Boston, MA 02111-1307, USA.
- *
+ *
* Getting Source ==============
- *
+ *
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository
* for free software projects.
*
* @author Bruce Mayhew WebGoat
- * @since October 28, 2003
* @version $Id: $Id
+ * @since October 28, 2003
*/
-public class Category implements Comparable {
+public enum Category {
- /** Constant INTRODUCTION
*/
- public final static Category INTRODUCTION = new Category("Introduction", new Integer(5));
-
- /** Constant GENERAL
*/
- public final static Category GENERAL = new Category("General", new Integer(100));
-
- /** Constant ACCESS_CONTROL
*/
- public final static Category ACCESS_CONTROL = new Category("Access Control Flaws", new Integer(200));
-
- /** Constant AJAX_SECURITY
*/
- public final static Category AJAX_SECURITY = new Category("AJAX Security", new Integer(400));
-
- /** Constant AUTHENTICATION
*/
- public final static Category AUTHENTICATION = new Category("Authentication Flaws", new Integer(500));
-
- /** Constant BUFFER_OVERFLOW
*/
- public final static Category BUFFER_OVERFLOW = new Category("Buffer Overflows", new Integer(600));
-
- /** Constant CODE_QUALITY
*/
- public final static Category CODE_QUALITY = new Category("Code Quality", new Integer(700));
-
- /** Constant CONCURRENCY
*/
- public final static Category CONCURRENCY = new Category("Concurrency", new Integer(800));
-
- /** Constant XSS
*/
- public final static Category XSS = new Category("Cross-Site Scripting (XSS)", new Integer(900));
-
- /** Constant ERROR_HANDLING
*/
- public final static Category ERROR_HANDLING = new Category("Improper Error Handling", new Integer(1000));
-
- /** Constant INJECTION
*/
- public final static Category INJECTION = new Category("Injection Flaws", new Integer(1100));
-
- /** Constant DOS
*/
- public final static Category DOS = new Category("Denial of Service", new Integer(1200));
-
- /** Constant INSECURE_COMMUNICATION
*/
- public final static Category INSECURE_COMMUNICATION = new Category("Insecure Communication", new Integer(1300));
-
- /** Constant INSECURE_CONFIGURATION
*/
- public final static Category INSECURE_CONFIGURATION = new Category("Insecure Configuration", new Integer(1400));
-
- /** Constant INSECURE_STORAGE
*/
- public final static Category INSECURE_STORAGE = new Category("Insecure Storage", new Integer(1500));
-
- /** Constant MALICIOUS_EXECUTION
*/
- public final static Category MALICIOUS_EXECUTION = new Category("Malicious Execution", new Integer(1600));
-
- /** Constant PARAMETER_TAMPERING
*/
- public final static Category PARAMETER_TAMPERING = new Category("Parameter Tampering", new Integer(1700));
-
- /** Constant SESSION_MANAGEMENT
*/
- public final static Category SESSION_MANAGEMENT = new Category("Session Management Flaws", new Integer(1800));
-
- /** Constant WEB_SERVICES
*/
- public final static Category WEB_SERVICES = new Category("Web Services", new Integer(1900));
-
- /** Constant ADMIN_FUNCTIONS
*/
- public final static Category ADMIN_FUNCTIONS = new Category("Admin Functions", new Integer(2000));
-
- /** Constant CHALLENGE
*/
- public final static Category CHALLENGE = new Category("Challenge", new Integer(3000));
-
- private static final List categories = new ArrayList();
-
- private String category;
+ INTRODUCTION("Introduction", new Integer(5)),
+ GENERAL("General", new Integer(100)),
+ ACCESS_CONTROL("Access Control Flaws", new Integer(200)),
+ AJAX_SECURITY("AJAX Security", new Integer(400)),
+ AUTHENTICATION("Authentication Flaws", new Integer(500)),
+ BUFFER_OVERFLOW("Buffer Overflows", new Integer(600)),
+ CODE_QUALITY("Code Quality", new Integer(700)),
+ CONCURRENCY("Concurrency", new Integer(800)),
+ XSS("Cross-Site Scripting (XSS)", new Integer(900)),
+ ERROR_HANDLING("Improper Error Handling", new Integer(1000)),
+ INJECTION("Injection Flaws", new Integer(1100)),
+ DOS("Denial of Service", new Integer(1200)),
+ INSECURE_COMMUNICATION("Insecure Communication", new Integer(1300)),
+ INSECURE_CONFIGURATION("Insecure Configuration", new Integer(1400)),
+ INSECURE_STORAGE("Insecure Storage", new Integer(1500)),
+ MALICIOUS_EXECUTION("Malicious Execution", new Integer(1600)),
+ PARAMETER_TAMPERING("Parameter Tampering", new Integer(1700)),
+ SESSION_MANAGEMENT("Session Management Flaws", new Integer(1800)),
+ WEB_SERVICES("Web Services", new Integer(1900)),
+ ADMIN_FUNCTIONS("Admin Functions", new Integer(2000)),
+ CHALLENGE("Challenge", new Integer(3000));
+ @Getter
+ private String name;
+ @Getter
private Integer ranking;
- static {
- categories.add(INTRODUCTION);
- categories.add(PARAMETER_TAMPERING);
- categories.add(ACCESS_CONTROL);
- categories.add(AUTHENTICATION);
- categories.add(SESSION_MANAGEMENT);
- categories.add(XSS);
- categories.add(BUFFER_OVERFLOW);
- categories.add(INJECTION);
- categories.add(MALICIOUS_EXECUTION);
- categories.add(ERROR_HANDLING);
- categories.add(INSECURE_STORAGE);
- categories.add(DOS);
- categories.add(INSECURE_CONFIGURATION);
- categories.add(WEB_SERVICES);
- categories.add(AJAX_SECURITY);
- categories.add(ADMIN_FUNCTIONS);
- categories.add(GENERAL);
- categories.add(CODE_QUALITY);
- categories.add(CONCURRENCY);
- categories.add(INSECURE_COMMUNICATION);
- categories.add(CHALLENGE);
- }
-
- /**
- * addCategory.
- *
- * @param c a {@link org.owasp.webgoat.lessons.Category} object.
- */
- public static synchronized void addCategory(Category c) {
- categories.add(c);
- }
-
- /**
- * Getter for the field category
.
- *
- * @param name a {@link java.lang.String} object.
- * @return a {@link org.owasp.webgoat.lessons.Category} object.
- */
- public static synchronized Category getCategory(String name) {
- Iterator it = categories.iterator();
- while (it.hasNext()) {
- Category c = it.next();
- if (c.getName().equals(name)) {
- return c;
- }
- }
- return null;
- }
-
- /**
- * Constructor for Category.
- *
- * @param category a {@link java.lang.String} object.
- * @param ranking a {@link java.lang.Integer} object.
- */
- public Category(String category, Integer ranking) {
- this.category = category;
+ Category(String name, Integer ranking) {
+ this.name = name;
this.ranking = ranking;
}
- /** {@inheritDoc} */
- @Override
- public int compareTo(Object obj) {
- int value = 1;
-
- if (obj instanceof Category) {
- value = this.getRanking().compareTo(((Category) obj).getRanking());
- }
-
- return value;
- }
-
/**
- * Getter for the field ranking
.
- *
- * @return a {@link java.lang.Integer} object.
+ * {@inheritDoc}
*/
- public Integer getRanking() {
- return ranking;
- }
-
- /**
- * Setter for the field ranking
.
- *
- * @param ranking a {@link java.lang.Integer} object.
- * @return a {@link java.lang.Integer} object.
- */
- public Integer setRanking(Integer ranking) {
- return this.ranking = ranking;
- }
-
- /**
- * getName.
- *
- * @return a {@link java.lang.String} object.
- */
- public String getName() {
- return category;
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean equals(Object obj) {
- return (obj instanceof Category) && getName().equals(((Category) obj).getName());
- }
-
- /** {@inheritDoc} */
@Override
public String toString() {
return getName();
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/Endpoint.java b/webgoat-container/src/main/java/org/owasp/webgoat/lessons/Endpoint.java
new file mode 100644
index 000000000..18e33f4ef
--- /dev/null
+++ b/webgoat-container/src/main/java/org/owasp/webgoat/lessons/Endpoint.java
@@ -0,0 +1,70 @@
+package org.owasp.webgoat.lessons;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoint;
+
+import java.io.File;
+
+/**
+ * ************************************************************************************************
+ * This file is part of WebGoat, an Open Web Application Security Project utility. For details,
+ * please see http://www.owasp.org/
+ *
+ * Copyright (c) 2002 - 20014 Bruce Mayhew
+ *
+ * This program is free software; you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program; if
+ * not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Getting Source ==============
+ *
+ * Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
+ * projects.
+ *
+ *
+ * @author nbaars
+ * @version $Id: $Id
+ * @since November 13, 2016
+ */
+public abstract class Endpoint implements MvcEndpoint {
+
+ @Autowired
+ @Qualifier("pluginTargetDirectory")
+ private File pluginDirectory;
+
+ /**
+ * The directory of the plugin directory in which the lessons resides, so if you want to access the lesson 'ClientSideFiltering' you will
+ * need to:
+ *
+ *
+ * File lessonDirectory = new File(getPluginDirectory(), "ClientSideFiltering");
+ *
+ *
+ * The directory structure of the lesson is exactly the same as the directory structure in the plugins project.
+ *
+ * @return the top level
+ */
+ protected File getPluginDirectory() {
+ return new File(this.pluginDirectory, "plugin");
+ }
+
+
+ @Override
+ public final boolean isSensitive() {
+ return false;
+ }
+
+ @Override
+ public final Class extends org.springframework.boot.actuate.endpoint.Endpoint> getEndpointType() {
+ return null;
+ }
+}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/LessonAdapter.java b/webgoat-container/src/main/java/org/owasp/webgoat/lessons/LessonAdapter.java
index ef9f0f7fd..70d0fdf52 100644
--- a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/LessonAdapter.java
+++ b/webgoat-container/src/main/java/org/owasp/webgoat/lessons/LessonAdapter.java
@@ -1,26 +1,3 @@
-package org.owasp.webgoat.lessons;
-
-import com.google.common.base.Joiner;
-import org.apache.commons.io.IOUtils;
-import org.apache.ecs.Element;
-import org.apache.ecs.ElementContainer;
-import org.apache.ecs.StringElement;
-import org.apache.ecs.html.Center;
-import org.apache.ecs.html.H3;
-import org.apache.ecs.html.P;
-import org.apache.ecs.html.PRE;
-import org.apache.ecs.html.TD;
-import org.apache.ecs.html.TR;
-import org.apache.ecs.html.Table;
-import org.owasp.webgoat.session.WebSession;
-
-import java.io.BufferedReader;
-import java.io.FileReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.List;
-
/**
*************************************************************************************************
*
@@ -51,59 +28,11 @@ import java.util.List;
* @since October 28, 2003
* @version $Id: $Id
*/
+package org.owasp.webgoat.lessons;
+
+//// TODO: 11/8/2016 remove
public abstract class LessonAdapter extends AbstractLesson {
- /**
- * {@inheritDoc}
- *
- * Description of the Method
- */
- protected Element createContent(WebSession s) {
- // Mark this lesson as completed.
- makeSuccess(s);
-
- ElementContainer ec = new ElementContainer();
-
- ec.addElement(new Center().addElement(new H3().addElement(new StringElement(
- "Detailed Lesson Creation Instructions."))));
- ec.addElement(new P());
- ec
- .addElement(new StringElement(
- "Lesson are simple to create and very little coding is required. "
- + "In fact, most lessons can be created by following the easy to use instructions by going to the WebGoat wiki page "
- + "WebGoat Wiki Page "
- + "If you would prefer, send your lesson ideas to "
- + getWebgoatContext().getFeedbackAddressHTML())
- + " Note: you will need to register at "
- + "the following link to use the feedback tool: "
- + "List Registration "
- + "Finally, OWASP has a slack channel. You can register at the following link: "
- + "OWASP Slack Channel ");
-
- try (InputStream is = Thread.currentThread().getContextClassLoader()
- .getResourceAsStream("New Lesson Instructions.txt")) {
- if (is != null) {
- PRE pre = new PRE();
- pre.addElement(Joiner.on("\n").join(IOUtils.readLines(is)));
- ec.addElement(pre);
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
- return (ec);
- }
-
- /**
- * Gets the category attribute of the LessonAdapter object. The default
- * category is "General" Only override this method if you wish to create a
- * new category or if you wish this lesson to reside within a category other
- * the "General"
- *
- * @return The category value
- */
- protected Category getDefaultCategory() {
- return Category.GENERAL;
- }
/**
*
getDefaultHidden.
@@ -133,29 +62,6 @@ public abstract class LessonAdapter extends AbstractLesson {
return DEFAULT_RANKING;
}
- /**
- * {@inheritDoc}
- *
- * Gets the hintCount attribute of the LessonAdapter object
- */
- public int getHintCount(WebSession s) {
- return getHints(s).size();
- }
-
- /**
- * {@inheritDoc}
- *
- * Fill in a minor hint that will help people who basically get it, but are
- * stuck on somthing silly. Hints will be returned to the user in the order
- * they appear below. The user must click on the "next hint" button before
- * the hint will be displayed.
- */
- protected List getHints(WebSession s) {
- List hints = new ArrayList();
- hints.add("There are no hints defined.");
- return hints;
- }
-
/**
* provide a default submitMethod of lesson does not implement
*
@@ -165,44 +71,6 @@ public abstract class LessonAdapter extends AbstractLesson {
return "GET";
}
- /**
- * {@inheritDoc}
- *
- * Gets the instructions attribute of the LessonAdapter object. Instructions
- * will rendered as html and will appear below the control area and above
- * the actual lesson area. Instructions should provide the user with the
- * general setup and goal of the lesson.
- */
- public String getInstructions(WebSession s) {
- StringBuffer buff = new StringBuffer();
- String lang = s.getCurrrentLanguage();
- try {
- String fileName = getLessonPlanFileName(lang);
- if (fileName != null) {
- BufferedReader in = new BufferedReader(new FileReader(fileName));
- String line = null;
- boolean startAppending = false;
- while ((line = in.readLine()) != null) {
- if (line.indexOf("") != -1) {
- startAppending = true;
- continue;
- }
- if (line.indexOf("") != -1) {
- startAppending = false;
- continue;
- }
- if (startAppending) {
- buff.append(line + "\n");
- }
- }
- }
- } catch (Exception e) {
- }
-
- return buff.toString();
-
- }
-
/**
* Fill in a descriptive title for this lesson. The title of the lesson.
* This will appear above the control area at the top of the page. This
@@ -214,66 +82,5 @@ public abstract class LessonAdapter extends AbstractLesson {
return "Untitled Lesson " + getScreenId();
}
- /** {@inheritDoc} */
- public String getCurrentAction(WebSession s) {
- return s.getLessonSession(this).getCurrentLessonScreen();
- }
-
- /** {@inheritDoc} */
- public void setCurrentAction(WebSession s, String lessonScreen) {
- s.getLessonSession(this).setCurrentLessonScreen(lessonScreen);
- }
-
- /**
- * getSessionAttribute.
- *
- * @param s a {@link org.owasp.webgoat.session.WebSession} object.
- * @param key a {@link java.lang.String} object.
- * @return a {@link java.lang.Object} object.
- */
- public Object getSessionAttribute(WebSession s, String key) {
- return s.getRequest().getSession().getAttribute(key);
- }
-
- /**
- * setSessionAttribute.
- *
- * @param s a {@link org.owasp.webgoat.session.WebSession} object.
- * @param key a {@link java.lang.String} object.
- * @param value a {@link java.lang.Object} object.
- */
- public void setSessionAttribute(WebSession s, String key, Object value) {
- s.getRequest().getSession().setAttribute(key, value);
- }
-
- /**
- * Description of the Method
- *
- * @param s Description of the Parameter
- * @return Description of the Return Value
- */
- protected Element makeSuccess(WebSession s) {
- getLessonTracker(s).setCompleted(true);
-
- //s.setMessage(getLabelManager().get("LessonCompleted"));
-
- return (null);
- }
-
- /**
- * Gets the credits attribute of the AbstractLesson object
- *
- * @return The credits value
- * @param text a {@link java.lang.String} object.
- * @param e a {@link org.apache.ecs.Element} object.
- */
- protected Element getCustomCredits(String text, Element e) {
- Table t = new Table().setCellSpacing(0).setCellPadding(0).setBorder(0).setWidth("90%").setAlign("RIGHT");
- TR tr = new TR();
- tr.addElement(new TD(text).setVAlign("MIDDLE").setAlign("RIGHT").setWidth("100%"));
- tr.addElement(new TD(e).setVAlign("MIDDLE").setAlign("RIGHT"));
- t.addElement(tr);
- return t;
- }
}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/LessonServletMapping.java b/webgoat-container/src/main/java/org/owasp/webgoat/lessons/NewLesson.java
similarity index 69%
rename from webgoat-container/src/main/java/org/owasp/webgoat/lessons/LessonServletMapping.java
rename to webgoat-container/src/main/java/org/owasp/webgoat/lessons/NewLesson.java
index 9cc6737d8..c0a10e9d4 100644
--- a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/LessonServletMapping.java
+++ b/webgoat-container/src/main/java/org/owasp/webgoat/lessons/NewLesson.java
@@ -1,10 +1,9 @@
package org.owasp.webgoat.lessons;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
+import java.util.List;
/**
- *************************************************************************************************
+ * ************************************************************************************************
* This file is part of WebGoat, an Open Web Application Security Project utility. For details,
* please see http://www.owasp.org/
*
@@ -28,14 +27,26 @@ import java.lang.annotation.RetentionPolicy;
* projects.
*
*
- * @author Nanne Baars
- * @since December 12, 2015
+ * @author WebGoat
* @version $Id: $Id
+ * @since October 12, 2016
*/
-@Retention(RetentionPolicy.RUNTIME)
-public @interface LessonServletMapping {
+public abstract class NewLesson extends LessonAdapter {
+
+
+
+ @Override
+ public abstract Category getDefaultCategory();
+
+ public abstract List getHints();
+
+ @Override
+ public abstract Integer getDefaultRanking();
+
+ @Override
+ public abstract String getTitle();
+
+ @Override
+ public abstract String getId();
- String path();
}
-
-
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/RandomLessonAdapter.java b/webgoat-container/src/main/java/org/owasp/webgoat/lessons/RandomLessonAdapter.java
deleted file mode 100644
index e4a815f1c..000000000
--- a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/RandomLessonAdapter.java
+++ /dev/null
@@ -1,143 +0,0 @@
-
-package org.owasp.webgoat.lessons;
-
-import org.owasp.webgoat.session.CreateDB;
-import org.owasp.webgoat.session.DatabaseUtilities;
-import org.owasp.webgoat.session.LessonTracker;
-import org.owasp.webgoat.session.RandomLessonTracker;
-import org.owasp.webgoat.session.WebSession;
-
-import java.sql.Connection;
-import java.sql.SQLException;
-
-
-/**
- * Abstract RandomLessonAdapter class.
- *
- * @version $Id: $Id
- * @author dm
- */
-public abstract class RandomLessonAdapter extends LessonAdapter
-{
-
- /**
- * getStages.
- *
- * @return an array of {@link java.lang.String} objects.
- */
- public abstract String[] getStages();
-
- /**
- * setStage.
- *
- * @param s a {@link org.owasp.webgoat.session.WebSession} object.
- * @param stage a {@link java.lang.String} object.
- * @param stage a {@link java.lang.String} object.
- */
- public void setStage(WebSession s, String stage)
- {
- getLessonTracker(s).setStage(stage);
- try
- {
- Connection connection = DatabaseUtilities.getConnection(s);
-
- CreateDB db = new CreateDB();
- db.makeDB(connection);
- System.out.println("Successfully refreshed the database.");
-
- } catch (SQLException sqle)
- {
- System.out.println("Error refreshing the database!");
- sqle.printStackTrace();
- }
- }
-
- /**
- * getStage.
- *
- * @param s a {@link org.owasp.webgoat.session.WebSession} object.
- * @return a {@link java.lang.String} object.
- */
- public String getStage(WebSession s)
- {
- return getLessonTracker(s).getStage();
- }
-
- /**
- * setStageComplete.
- *
- * @param s a {@link org.owasp.webgoat.session.WebSession} object.
- * @param stage a {@link java.lang.String} object.
- * @param stage a {@link java.lang.String} object.
- */
- public void setStageComplete(WebSession s, String stage)
- {
- RandomLessonTracker lt = getLessonTracker(s);
- lt.setStageComplete(stage, true);
- if (lt.getCompleted())
- {
- //s.setMessage("Congratulations, you have completed this lab");
- }
- else
- {
- s.setMessage("You have completed Stage " + (lt.getStageNumber(stage) + 1) + ": " + stage + ".");
- if (!stage.equals(lt.getStage()))
- s.setMessage(" Welcome to Stage " + (lt.getStageNumber(lt.getStage()) + 1) + ": " + lt.getStage());
- }
- try
- {
- Connection connection = DatabaseUtilities.getConnection(s);
-
- CreateDB db = new CreateDB();
- db.makeDB(connection);
- System.out.println("Successfully refreshed the database.");
-
- } catch (SQLException sqle)
- {
- System.out.println("Error refreshing the database!");
- sqle.printStackTrace();
- }
- }
-
- /**
- * isStageComplete.
- *
- * @param s a {@link org.owasp.webgoat.session.WebSession} object.
- * @param stage a {@link java.lang.String} object.
- * @param stage a {@link java.lang.String} object.
- * @return a boolean.
- */
- public boolean isStageComplete(WebSession s, String stage)
- {
- return getLessonTracker(s).hasCompleted(stage);
- }
-
- /** {@inheritDoc} */
- @Override
- public RandomLessonTracker getLessonTracker(WebSession s)
- {
- return (RandomLessonTracker) super.getLessonTracker(s);
- }
-
- /** {@inheritDoc} */
- @Override
- public RandomLessonTracker getLessonTracker(WebSession s, AbstractLesson lesson)
- {
- return (RandomLessonTracker) super.getLessonTracker(s, lesson);
- }
-
- /** {@inheritDoc} */
- @Override
- public RandomLessonTracker getLessonTracker(WebSession s, String userNameOverride)
- {
- return (RandomLessonTracker) super.getLessonTracker(s, userNameOverride);
- }
-
- /** {@inheritDoc} */
- @Override
- public LessonTracker createLessonTracker()
- {
- return new RandomLessonTracker(getStages());
- }
-
-}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/SequentialLessonAdapter.java b/webgoat-container/src/main/java/org/owasp/webgoat/lessons/SequentialLessonAdapter.java
deleted file mode 100644
index 1053d212e..000000000
--- a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/SequentialLessonAdapter.java
+++ /dev/null
@@ -1,214 +0,0 @@
-
-package org.owasp.webgoat.lessons;
-
-import org.apache.ecs.Element;
-import org.apache.ecs.ElementContainer;
-import org.apache.ecs.StringElement;
-import org.owasp.webgoat.session.LessonTracker;
-import org.owasp.webgoat.session.SequentialLessonTracker;
-import org.owasp.webgoat.session.WebSession;
-
-
-/**
- * Abstract SequentialLessonAdapter class.
- *
- * @version $Id: $Id
- * @author dm
- */
-public abstract class SequentialLessonAdapter extends LessonAdapter
-{
-
- /**
- * setStage.
- *
- * @param s a {@link org.owasp.webgoat.session.WebSession} object.
- * @param stage a int.
- * @param stage a int.
- */
- public void setStage(WebSession s, int stage)
- {
- // System.out.println("Changed to stage " + stage);
- getLessonTracker(s).setStage(stage);
- }
-
- /*
- * By default returns 1 stage. (non-Javadoc)
- */
- /**
- * getStageCount.
- *
- * @return a int.
- */
- public int getStageCount()
- {
- return 1;
- }
-
- /**
- * getStage.
- *
- * @param s a {@link org.owasp.webgoat.session.WebSession} object.
- * @return a int.
- */
- public int getStage(WebSession s)
- {
- int stage = getLessonTracker(s).getStage();
-
- // System.out.println("In stage " + stage);
- return stage;
- }
-
- /** {@inheritDoc} */
- @Override
- public SequentialLessonTracker getLessonTracker(WebSession s)
- {
- return (SequentialLessonTracker) super.getLessonTracker(s);
- }
-
- /** {@inheritDoc} */
- @Override
- public SequentialLessonTracker getLessonTracker(WebSession s, AbstractLesson lesson)
- {
- return (SequentialLessonTracker) super.getLessonTracker(s, lesson);
- }
-
- /** {@inheritDoc} */
- @Override
- public SequentialLessonTracker getLessonTracker(WebSession s, String userNameOverride)
- {
- return (SequentialLessonTracker) super.getLessonTracker(s, userNameOverride);
- }
-
- /** {@inheritDoc} */
- @Override
- public LessonTracker createLessonTracker()
- {
- return new SequentialLessonTracker();
- }
-
- /**
- * createStagedContent.
- *
- * @param s a {@link org.owasp.webgoat.session.WebSession} object.
- * @return a {@link org.apache.ecs.Element} object.
- */
- protected Element createStagedContent(WebSession s)
- {
- try
- {
- int stage = getLessonTracker(s).getStage();
- // int stage = Integer.parseInt(
- // getLessonTracker(s).getLessonProperties().getProperty(WebSession.STAGE,"1"));
-
- switch (stage)
- {
- case 1:
- return (doStage1(s));
- case 2:
- return (doStage2(s));
- case 3:
- return (doStage3(s));
- case 4:
- return (doStage4(s));
- case 5:
- return (doStage5(s));
- case 6:
- return (doStage6(s));
- default:
- throw new Exception("Invalid stage");
- }
- } catch (Exception e)
- {
- s.setMessage("Error generating " + this.getClass().getName());
- // System.out.println(e);
- e.printStackTrace();
- }
-
- return (new StringElement(""));
- }
-
- /**
- * doStage1.
- *
- * @param s a {@link org.owasp.webgoat.session.WebSession} object.
- * @return a {@link org.apache.ecs.Element} object.
- * @throws java.lang.Exception if any.
- */
- protected Element doStage1(WebSession s) throws Exception
- {
- ElementContainer ec = new ElementContainer();
- ec.addElement("Stage 1 Stub");
- return ec;
- }
-
- /**
- * doStage2.
- *
- * @param s a {@link org.owasp.webgoat.session.WebSession} object.
- * @return a {@link org.apache.ecs.Element} object.
- * @throws java.lang.Exception if any.
- */
- protected Element doStage2(WebSession s) throws Exception
- {
- ElementContainer ec = new ElementContainer();
- ec.addElement("Stage 2 Stub");
- return ec;
- }
-
- /**
- * doStage3.
- *
- * @param s a {@link org.owasp.webgoat.session.WebSession} object.
- * @return a {@link org.apache.ecs.Element} object.
- * @throws java.lang.Exception if any.
- */
- protected Element doStage3(WebSession s) throws Exception
- {
- ElementContainer ec = new ElementContainer();
- ec.addElement("Stage 3 Stub");
- return ec;
- }
-
- /**
- * doStage4.
- *
- * @param s a {@link org.owasp.webgoat.session.WebSession} object.
- * @return a {@link org.apache.ecs.Element} object.
- * @throws java.lang.Exception if any.
- */
- protected Element doStage4(WebSession s) throws Exception
- {
- ElementContainer ec = new ElementContainer();
- ec.addElement("Stage 4 Stub");
- return ec;
- }
-
- /**
- * doStage5.
- *
- * @param s a {@link org.owasp.webgoat.session.WebSession} object.
- * @return a {@link org.apache.ecs.Element} object.
- * @throws java.lang.Exception if any.
- */
- protected Element doStage5(WebSession s) throws Exception
- {
- ElementContainer ec = new ElementContainer();
- ec.addElement("Stage 5 Stub");
- return ec;
- }
-
- /**
- * doStage6.
- *
- * @param s a {@link org.owasp.webgoat.session.WebSession} object.
- * @return a {@link org.apache.ecs.Element} object.
- * @throws java.lang.Exception if any.
- */
- protected Element doStage6(WebSession s) throws Exception
- {
- ElementContainer ec = new ElementContainer();
- ec.addElement("Stage 6 Stub");
- return ec;
- }
-
-}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/WelcomeScreen.java b/webgoat-container/src/main/java/org/owasp/webgoat/lessons/WelcomeScreen.java
deleted file mode 100644
index d9ac9328e..000000000
--- a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/WelcomeScreen.java
+++ /dev/null
@@ -1,159 +0,0 @@
-
-package org.owasp.webgoat.lessons;
-
-import org.apache.ecs.Element;
-import org.apache.ecs.ElementContainer;
-import org.apache.ecs.HtmlColor;
-import org.apache.ecs.StringElement;
-import org.apache.ecs.html.Center;
-import org.apache.ecs.html.Form;
-import org.apache.ecs.html.TD;
-import org.apache.ecs.html.TR;
-import org.apache.ecs.html.Table;
-import org.owasp.webgoat.session.*;
-
-
-/**
- *************************************************************************************************
- *
- *
- * This file is part of WebGoat, an Open Web Application Security Project utility. For details,
- * please see http://www.owasp.org/
- *
- * Copyright (c) 2002 - 20014 Bruce Mayhew
- *
- * This program is free software; you can redistribute it and/or modify it under the terms of the
- * GNU General Public License as published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
- * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with this program; if
- * not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- *
- * Getting Source ==============
- *
- * Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
- * projects.
- *
- * @author Jeff Williams Aspect Security
- * @since October 28, 2003
- * @version $Id: $Id
- */
-public class WelcomeScreen extends Screen
-{
-
- /**
- * Constructor for the WelcomeScreen object
- *
- * @param s
- * Description of the Parameter
- */
- public WelcomeScreen(WebSession s)
- {
- setup(s);
- }
-
- /**
- * Constructor for the WelcomeScreen object
- */
- public WelcomeScreen()
- {
- }
-
- /**
- * setup.
- *
- * @param s a {@link org.owasp.webgoat.session.WebSession} object.
- */
- public void setup(WebSession s)
- {
- // call createContent first so messages will go somewhere
-
- Form form = new Form("attack", Form.POST).setName("form").setEncType("");
-
- form.addElement(wrapForm(s));
-
- TD lowerright = new TD().setHeight("100%").setVAlign("top").setAlign("left").addElement(form);
- TR row = new TR().addElement(lowerright);
- Table layout = new Table().setBgColor(HtmlColor.WHITE).setCellSpacing(0).setCellPadding(0).setBorder(0);
-
- layout.addElement(row);
-
- setContent(layout);
- }
-
- /**
- * wrapForm.
- *
- * @param s a {@link org.owasp.webgoat.session.WebSession} object.
- * @return a {@link org.apache.ecs.Element} object.
- */
- protected Element wrapForm(WebSession s)
- {
- if (s == null) { return new StringElement("Invalid Session"); }
-
- Table container = new Table().setWidth("100%").setCellSpacing(10).setCellPadding(0).setBorder(0);
-
- // CreateContent can generate error messages so you MUST call it before makeMessages()
- Element content = createContent(s);
- container.addElement(new TR().addElement(new TD().setColSpan(2).setVAlign("TOP").addElement(makeMessages(s))));
- container.addElement(new TR().addElement(new TD().setColSpan(2).addElement(content)));
- container.addElement(new TR());
-
- return (container);
- }
-
- /**
- * {@inheritDoc}
- *
- * Description of the Method
- */
- protected Element createContent(WebSession s)
- {
- ElementContainer ec = new ElementContainer();
- Element b = ECSFactory.makeButton("Start the Course!");
- ec.addElement(new Center(b));
-
- return (ec);
- }
-
- /**
- * Gets the instructions attribute of the WelcomeScreen object
- *
- * @return The instructions value
- */
- protected String getInstructions()
- {
- String instructions = "Enter your name and learn how HTTP really works!";
-
- return (instructions);
- }
-
- /**
- * Gets the title attribute of the WelcomeScreen object
- *
- * @return The title value
- */
- public String getTitle()
- {
- return ("Welcome to the Penetration Testing Course");
- }
-
- /*
- * (non-Javadoc)
- * @see session.Screen#getRole()
- */
- /**
- * getRole.
- *
- * @return a {@link java.lang.String} object.
- */
- public String getRole()
- {
- return AbstractLesson.USER_ROLE;
- }
-}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/admin/AdminScreen.java b/webgoat-container/src/main/java/org/owasp/webgoat/lessons/admin/AdminScreen.java
deleted file mode 100644
index ea1cbb175..000000000
--- a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/admin/AdminScreen.java
+++ /dev/null
@@ -1,109 +0,0 @@
-
-package org.owasp.webgoat.lessons.admin;
-
-import org.owasp.webgoat.lessons.AbstractLesson;
-import org.owasp.webgoat.session.Screen;
-import org.owasp.webgoat.session.WebSession;
-
-
-/**
- *************************************************************************************************
- *
- *
- * This file is part of WebGoat, an Open Web Application Security Project utility. For details,
- * please see http://www.owasp.org/
- *
- * Copyright (c) 2002 - 20014 Bruce Mayhew
- *
- * This program is free software; you can redistribute it and/or modify it under the terms of the
- * GNU General Public License as published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
- * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with this program; if
- * not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- *
- * Getting Source ==============
- *
- * Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
- * projects.
- *
- * @author Jeff Williams Aspect Security
- * @since October 28, 2003
- * @version $Id: $Id
- */
-public abstract class AdminScreen extends Screen
-{
-
- /**
- * Description of the Field
- */
- protected String query = null;
-
- /**
- * Constructor for the AdminScreen object
- *
- * @param s
- * Description of the Parameter
- * @param q
- * Description of the Parameter
- */
- public AdminScreen(WebSession s, String q)
- {
- setQuery(q);
-
- // setupAdmin(s); FIXME: what was this supposed to do?
- }
-
- /**
- * Constructor for the AdminScreen object
- *
- * @param s
- * Description of the Parameter
- */
- public AdminScreen(WebSession s)
- {
- }
-
- /**
- * Constructor for the AdminScreen object
- */
- public AdminScreen()
- {
- }
-
- /**
- * Gets the title attribute of the AdminScreen object
- *
- * @return The title value
- */
- public String getTitle()
- {
- return ("Admin Information");
- }
-
- /**
- * getRole.
- *
- * @return a {@link java.lang.String} object.
- */
- public String getRole()
- {
- return AbstractLesson.ADMIN_ROLE;
- }
-
- /**
- * Sets the query attribute of the AdminScreen object
- *
- * @param q
- * The new query value
- */
- public void setQuery(String q)
- {
- query = q;
- }
-}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/admin/MenuToLessonMapperScreen.java b/webgoat-container/src/main/java/org/owasp/webgoat/lessons/admin/MenuToLessonMapperScreen.java
deleted file mode 100644
index 5a5085ef5..000000000
--- a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/admin/MenuToLessonMapperScreen.java
+++ /dev/null
@@ -1,162 +0,0 @@
-
-package org.owasp.webgoat.lessons.admin;
-
-import org.apache.ecs.Element;
-import org.apache.ecs.ElementContainer;
-import org.apache.ecs.StringElement;
-import org.apache.ecs.html.BR;
-import org.apache.ecs.html.TD;
-import org.apache.ecs.html.TH;
-import org.apache.ecs.html.TR;
-import org.apache.ecs.html.Table;
-import org.owasp.webgoat.lessons.AbstractLesson;
-import org.owasp.webgoat.lessons.Category;
-import org.owasp.webgoat.lessons.LessonAdapter;
-import org.owasp.webgoat.session.WebSession;
-
-import java.net.URL;
-
-import static org.springframework.util.StringUtils.getFilename;
-import static org.springframework.util.StringUtils.stripFilenameExtension;
-
-
-/**
- *************************************************************************************************
- *
- *
- * This file is part of WebGoat, an Open Web Application Security Project utility. For details,
- * please see http://www.owasp.org/
- *
- * Copyright (c) 2002 - 20014 Bruce Mayhew
- *
- * This program is free software; you can redistribute it and/or modify it under the terms of the
- * GNU General Public License as published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
- * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with this program; if
- * not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- *
- * Getting Source ==============
- *
- * Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
- * projects.
- *
- * @author Bruce Mayhew WebGoat
- * @since October 28, 2003
- * @version $Id: $Id
- */
-public class MenuToLessonMapperScreen extends LessonAdapter
-{
-
- /**
- * {@inheritDoc}
- *
- * Description of the Method
- */
- protected Element createContent(WebSession s)
- {
- ElementContainer ec = new ElementContainer();
- ec.addElement(new StringElement("This page describes an overview of all the lessons and maps the lesson to the WebGoat-Lessons project"));
- ec.addElement(new BR());
- ec.addElement(new BR());
- ec.addElement(makeMenuToLessonMapping(s));
-
- return ec;
- }
-
- /**
- * Gets the category attribute of the UserAdminScreen object
- *
- * @return The category value
- */
- protected Category getDefaultCategory()
- {
- return Category.ADMIN_FUNCTIONS;
- }
-
- private final static Integer DEFAULT_RANKING = new Integer(1000);
-
- /**
- * getDefaultRanking.
- *
- * @return a {@link java.lang.Integer} object.
- */
- protected Integer getDefaultRanking()
- {
- return DEFAULT_RANKING;
- }
-
- /**
- * Gets the role attribute of the UserAdminScreen object
- *
- * @return The role value
- */
- public String getRole()
- {
- return ADMIN_ROLE;
- }
-
- /**
- * Gets the title attribute of the UserAdminScreen object
- *
- * @return The title value
- */
- public String getTitle()
- {
- return ("Lesson information");
- }
-
- /**
- * Description of the Method
- *
- * @param s
- * Description of the Parameter
- * @return Description of the Return Value
- */
- public Element makeMenuToLessonMapping(WebSession s)
- {
- ElementContainer ec = new ElementContainer();
- Table t = new Table().setCellSpacing(0).setCellPadding(2).setBorder(1);
- t.addElement(makeHeaderRow());
-
- for (AbstractLesson lesson : s.getCourse().getLessons(s, AbstractLesson.USER_ROLE)) {
- TR tr = new TR();
- tr.addElement(new TD().addElement(lesson.getName()));
-
- URL jarLocation = lesson.getClass().getProtectionDomain().getCodeSource().getLocation();
- String projectName = removeVersion(stripFilenameExtension(getFilename(jarLocation.getFile())));
- tr.addElement(new TD().addElement(projectName));
-
- tr.addElement(new TD().addElement(lesson.getClass().getName() + ".java"));
- t.addElement(tr);
- }
- ec.addElement(t);
- return (ec);
- }
-
- //Remove version number and last '-'
- private static String removeVersion(String s) {
- return s.replaceAll("[^a-z\\-]", "").replaceAll("-$", "");
- }
-
- /**
- * Description of the Method
- *
- * @return Description of the Return Value
- */
- private TR makeHeaderRow()
- {
- TR tr = new TR();
-
- tr.addElement(new TH("Lesson menu item"));
- tr.addElement(new TH("Lesson project"));
- tr.addElement(new TH("Lesson source class"));
-
- return tr;
- }
-}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/admin/ProductsAdminScreen.java b/webgoat-container/src/main/java/org/owasp/webgoat/lessons/admin/ProductsAdminScreen.java
deleted file mode 100644
index 43b74795d..000000000
--- a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/admin/ProductsAdminScreen.java
+++ /dev/null
@@ -1,124 +0,0 @@
-
-package org.owasp.webgoat.lessons.admin;
-
-import java.sql.Connection;
-import java.sql.ResultSet;
-import java.sql.ResultSetMetaData;
-import java.sql.Statement;
-import org.apache.ecs.Element;
-import org.apache.ecs.ElementContainer;
-import org.owasp.webgoat.lessons.Category;
-import org.owasp.webgoat.lessons.LessonAdapter;
-import org.owasp.webgoat.session.DatabaseUtilities;
-import org.owasp.webgoat.session.WebSession;
-
-
-/**
- *************************************************************************************************
- *
- *
- * This file is part of WebGoat, an Open Web Application Security Project utility. For details,
- * please see http://www.owasp.org/
- *
- * Copyright (c) 2002 - 20014 Bruce Mayhew
- *
- * This program is free software; you can redistribute it and/or modify it under the terms of the
- * GNU General Public License as published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
- * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with this program; if
- * not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- *
- * Getting Source ==============
- *
- * Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
- * projects.
- *
- * @author Jeff Williams Aspect Security
- * @since October 28, 2003
- * @version $Id: $Id
- */
-public class ProductsAdminScreen extends LessonAdapter
-{
-
- private final static String QUERY = "SELECT * FROM product_system_data";
-
- /**
- * {@inheritDoc}
- *
- * Description of the Method
- */
- protected Element createContent(WebSession s)
- {
- ElementContainer ec = new ElementContainer();
-
- try
- {
- Connection connection = DatabaseUtilities.getConnection(s);
-
- Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
- ResultSet.CONCUR_READ_ONLY);
- ResultSet results = statement.executeQuery(QUERY);
-
- if (results != null)
- {
- makeSuccess(s);
- ResultSetMetaData resultsMetaData = results.getMetaData();
- ec.addElement(DatabaseUtilities.writeTable(results, resultsMetaData));
- }
- } catch (Exception e)
- {
- s.setMessage("Error generating " + this.getClass().getName());
- e.printStackTrace();
- }
-
- return (ec);
- }
-
- /**
- * Gets the category attribute of the ProductsAdminScreen object
- *
- * @return The category value
- */
- protected Category getDefaultCategory()
- {
- return Category.ADMIN_FUNCTIONS;
- }
-
- /**
- * Gets the role attribute of the ProductsAdminScreen object
- *
- * @return The role value
- */
- public String getRole()
- {
- return HACKED_ADMIN_ROLE;
- }
-
- /**
- * Gets the title attribute of the ProductsAdminScreen object
- *
- * @return The title value
- */
- public String getTitle()
- {
- return ("Product Information");
- }
-
- private final static Integer DEFAULT_RANKING = new Integer(1000);
-
- /**
- * getDefaultRanking.
- *
- * @return a {@link java.lang.Integer} object.
- */
- protected Integer getDefaultRanking()
- {
- return DEFAULT_RANKING;
- }
-}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/admin/RefreshDBScreen.java b/webgoat-container/src/main/java/org/owasp/webgoat/lessons/admin/RefreshDBScreen.java
deleted file mode 100644
index 556701f0b..000000000
--- a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/admin/RefreshDBScreen.java
+++ /dev/null
@@ -1,160 +0,0 @@
-
-package org.owasp.webgoat.lessons.admin;
-
-import java.sql.Connection;
-import org.owasp.webgoat.lessons.*;
-import org.apache.ecs.Element;
-import org.apache.ecs.ElementContainer;
-import org.apache.ecs.StringElement;
-import org.apache.ecs.html.A;
-import org.apache.ecs.html.TD;
-import org.apache.ecs.html.TR;
-import org.apache.ecs.html.Table;
-import org.owasp.webgoat.session.*;
-
-
-/**
- *************************************************************************************************
- *
- *
- * This file is part of WebGoat, an Open Web Application Security Project utility. For details,
- * please see http://www.owasp.org/
- *
- * Copyright (c) 2002 - 20014 Bruce Mayhew
- *
- * This program is free software; you can redistribute it and/or modify it under the terms of the
- * GNU General Public License as published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
- * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with this program; if
- * not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- *
- * Getting Source ==============
- *
- * Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
- * projects.
- *
- * @author Jeff Williams Aspect Security
- * @since October 28, 2003
- * @version $Id: $Id
- */
-public class RefreshDBScreen extends LessonAdapter
-{
-
- private final static String REFRESH = "Refresh";
-
- /**
- * {@inheritDoc}
- *
- * Description of the Method
- */
- protected Element createContent(WebSession s)
- {
- ElementContainer ec = new ElementContainer();
-
- try
- {
- boolean refresh = s.getParser().getBooleanParameter(REFRESH, false);
-
- if (refresh)
- {
- refreshDB(s);
- ec.addElement(new StringElement("Successfully refreshed the database."));
- }
- else
- {
- Element label = new StringElement("Refresh the database? ");
- A link1 = ECSFactory.makeLink("Yes", REFRESH, true);
- A link2 = ECSFactory.makeLink("No", REFRESH, false);
- TD td1 = new TD().addElement(label);
- TD td2 = new TD().addElement(link1);
- TD td3 = new TD().addElement(link2);
- TR row = new TR().addElement(td1).addElement(td2).addElement(td3);
- Table t = new Table().setCellSpacing(40).setWidth("50%");
-
- if (s.isColor())
- {
- t.setBorder(1);
- }
-
- t.addElement(row);
- ec.addElement(t);
- }
- } catch (Exception e)
- {
- s.setMessage("Error generating " + this.getClass().getName());
- e.printStackTrace();
- }
-
- return (ec);
- }
-
- /**
- * Gets the category attribute of the RefreshDBScreen object
- *
- * @return The category value
- */
- protected Category getDefaultCategory()
- {
- return Category.ADMIN_FUNCTIONS;
- }
-
- private final static Integer DEFAULT_RANKING = new Integer(1000);
-
- /**
- * getDefaultRanking.
- *
- * @return a {@link java.lang.Integer} object.
- */
- protected Integer getDefaultRanking()
- {
- return DEFAULT_RANKING;
- }
-
- /**
- * Gets the role attribute of the RefreshDBScreen object
- *
- * @return The role value
- */
- public String getRole()
- {
- return ADMIN_ROLE;
- }
-
- /**
- * Gets the title attribute of the RefreshDBScreen object
- *
- * @return The title value
- */
- public String getTitle()
- {
- return ("Refresh Database");
- }
-
- /**
- * Description of the Method
- *
- * @param s
- * Description of the Parameter
- */
- public void refreshDB(WebSession s)
- {
- try
- {
- Connection connection = DatabaseUtilities.getConnection(s);
-
- CreateDB db = new CreateDB();
- db.makeDB(connection);
- System.out.println("Successfully refreshed the database.");
- } catch (Exception e)
- {
- s.setMessage("Error refreshing database " + this.getClass().getName());
- e.printStackTrace();
- }
- }
-}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/admin/ReportCardScreen.java b/webgoat-container/src/main/java/org/owasp/webgoat/lessons/admin/ReportCardScreen.java
deleted file mode 100644
index 13f31a753..000000000
--- a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/admin/ReportCardScreen.java
+++ /dev/null
@@ -1,295 +0,0 @@
-
-package org.owasp.webgoat.lessons.admin;
-
-import java.util.Iterator;
-import org.apache.ecs.Element;
-import org.apache.ecs.ElementContainer;
-import org.apache.ecs.HtmlColor;
-import org.apache.ecs.StringElement;
-import org.apache.ecs.html.Center;
-import org.apache.ecs.html.H2;
-import org.apache.ecs.html.TD;
-import org.apache.ecs.html.TH;
-import org.apache.ecs.html.TR;
-import org.apache.ecs.html.Table;
-import org.owasp.webgoat.lessons.AbstractLesson;
-import org.owasp.webgoat.lessons.Category;
-import org.owasp.webgoat.lessons.LessonAdapter;
-import org.owasp.webgoat.session.LessonTracker;
-import org.owasp.webgoat.session.Screen;
-import org.owasp.webgoat.session.UserTracker;
-import org.owasp.webgoat.session.WebSession;
-
-
-/**
- *************************************************************************************************
- *
- *
- * This file is part of WebGoat, an Open Web Application Security Project utility. For details,
- * please see http://www.owasp.org/
- *
- * Copyright (c) 2002 - 20014 Bruce Mayhew
- *
- * This program is free software; you can redistribute it and/or modify it under the terms of the
- * GNU General Public License as published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
- * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with this program; if
- * not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- *
- * Getting Source ==============
- *
- * Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
- * projects.
- *
- * @author Bruce Mayhew WebGoat
- * @since October 28, 2003
- * @version $Id: $Id
- */
-public class ReportCardScreen extends LessonAdapter
-{
-
- /**
- * Description of the Field
- */
- protected final static String USERNAME = "Username";
-
- /**
- * {@inheritDoc}
- *
- * Description of the Method
- */
- protected Element createContent(WebSession s)
- {
- ElementContainer ec = new ElementContainer();
-
- String user = null;
-
- try
- {
- if (s.getRequest().isUserInRole(WebSession.WEBGOAT_ADMIN))
- {
- user = s.getParser().getRawParameter(USERNAME);
- }
- else
- {
- user = s.getUserName();
- }
- } catch (Exception e)
- {
- }
-
- if (user == null)
- {
- user = s.getUserName();
- }
-
- ec.addElement(makeFeedback(s));
- ec.addElement(makeReportCard(s, user));
-
- return ec;
- }
-
- private Element makeFeedback(WebSession s)
- {
- ElementContainer ec = new ElementContainer();
- ec.addElement(new StringElement("Comments and suggestions are welcome. "
- + getWebgoatContext().getFeedbackAddressHTML() + " "));
-
- return ec;
- }
-
- /**
- * Gets the category attribute of the UserAdminScreen object
- *
- * @return The category value
- */
- protected Category getDefaultCategory()
- {
- return Category.ADMIN_FUNCTIONS;
- }
-
- private final static Integer DEFAULT_RANKING = new Integer(1000);
-
- /**
- * getDefaultRanking.
- *
- * @return a {@link java.lang.Integer} object.
- */
- protected Integer getDefaultRanking()
- {
- return DEFAULT_RANKING;
- }
-
- /**
- * Gets the role attribute of the UserAdminScreen object
- *
- * @return The role value
- */
- public String getRole()
- {
- return USER_ROLE;
- }
-
- /**
- * Gets the title attribute of the UserAdminScreen object
- *
- * @return The title value
- */
- public String getTitle()
- {
- return ("Report Card");
- }
-
- /**
- * Description of the Method
- *
- * @param screen
- * Description of the Parameter
- * @param s
- * Description of the Parameter
- * @param user
- * Description of the Parameter
- * @return Description of the Return Value
- */
- private TR makeLessonRow(WebSession s, String user, Screen screen)
- {
- LessonTracker lessonTracker = UserTracker.instance().getLessonTracker(s, user, screen);
- TR tr = new TR();
- if (lessonTracker.getCompleted())
- {
- tr.setBgColor(HtmlColor.LIGHTGREEN);
- }
- else if (lessonTracker.getNumVisits() == 0)
- {
- tr.setBgColor(HtmlColor.LIGHTBLUE);
- }
- else if (!lessonTracker.getCompleted() && lessonTracker.getNumVisits() > 10)
- {
- tr.setBgColor(HtmlColor.RED);
- }
- else
- {
- tr.setBgColor(HtmlColor.YELLOW);
- }
- tr.addElement(new TD().addElement(screen.getTitle()));
- tr.addElement(new TD().setAlign("CENTER").addElement(lessonTracker.getCompleted() ? "Y" : "N"));
- tr.addElement(new TD().setAlign("CENTER").addElement(Integer.toString(lessonTracker.getNumVisits())));
- tr.addElement(new TD().setAlign("CENTER").addElement(Integer.toString(lessonTracker.getMaxHintLevel())));
- return tr;
- }
-
- /**
- * {@inheritDoc}
- *
- * Description of the Method
- */
- protected Element makeMessages(WebSession s)
- {
- ElementContainer ec = new ElementContainer();
-
- return (ec);
- }
-
- /**
- * Description of the Method
- *
- * @param s
- * Description of the Parameter
- * @param user
- * Description of the Parameter
- * @return Description of the Return Value
- */
- public Element makeReportCard(WebSession s, String user)
- {
- ElementContainer ec = new ElementContainer();
-
- ec.addElement(makeUser(s, user));
- Table t = new Table().setCellSpacing(0).setCellPadding(2).setBorder(1);
-
- if (s.isColor())
- {
- t.setBorder(1);
- }
- TR tr = new TR();
- t.addElement(makeUserHeaderRow());
-
- // These are all the user lesson
- tr = new TR();
- tr.addElement(new TD().setAlign("CENTER").setColSpan(9).addElement("Normal user lessons"));
- t.addElement(tr);
- for (Iterator lessonIter = s.getCourse().getLessons(s, AbstractLesson.USER_ROLE).iterator(); lessonIter
- .hasNext();)
- {
- Screen screen = (Screen) lessonIter.next();
- t.addElement(makeLessonRow(s, user, screen));
- }
-
- // The user figured out there was a hackable admin acocunt
- tr = new TR();
- tr.addElement(new TD().setAlign("CENTER").setColSpan(9).addElement("Hackable Admin Screens"));
- t.addElement(tr);
- for (Iterator lessonIter = s.getCourse().getLessons(s, AbstractLesson.HACKED_ADMIN_ROLE).iterator(); lessonIter
- .hasNext();)
- {
- Screen screen = (Screen) lessonIter.next();
- t.addElement(makeLessonRow(s, user, screen));
- }
-
- // The user figured out how to actually hack the admin acocunt
- tr = new TR();
- tr.addElement(new TD().setAlign("CENTER").setColSpan(9).addElement("Actual Admin Screens"));
- t.addElement(tr);
- for (Iterator lessonIter = s.getCourse().getLessons(s, AbstractLesson.ADMIN_ROLE).iterator(); lessonIter
- .hasNext();)
- {
- Screen screen = (Screen) lessonIter.next();
- t.addElement(makeLessonRow(s, user, screen));
- }
-
- ec.addElement(t);
- return (ec);
- }
-
- /**
- * Description of the Method
- *
- * @param s
- * Description of the Parameter
- * @param user
- * Description of the Parameter
- * @return Description of the Return Value
- */
- protected Element makeUser(WebSession s, String user)
- {
- H2 h2 = new H2();
- // FIXME: The session is the current session, not the session of the user we are reporting.
- // String type = s.isAdmin() ? " [Administrative User]" : s.isHackedAdmin() ?
- // " [Normal User - Hacked Admin Access]" : " [Normal User]";
- String type = "";
- h2.addElement(new StringElement("Results for: " + user + type));
- return h2;
- }
-
- /**
- * Description of the Method
- *
- * @return Description of the Return Value
- */
- private TR makeUserHeaderRow()
- {
- TR tr = new TR();
-
- tr.addElement(new TH("Lesson"));
- tr.addElement(new TH("Complete"));
- tr.addElement(new TH("Visits"));
- tr.addElement(new TH("Hints"));
-
- return tr;
- }
-}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/admin/SummaryReportCardScreen.java b/webgoat-container/src/main/java/org/owasp/webgoat/lessons/admin/SummaryReportCardScreen.java
deleted file mode 100644
index 00225fcc8..000000000
--- a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/admin/SummaryReportCardScreen.java
+++ /dev/null
@@ -1,326 +0,0 @@
-
-package org.owasp.webgoat.lessons.admin;
-
-import java.util.Enumeration;
-import java.util.Iterator;
-import org.apache.ecs.Element;
-import org.apache.ecs.ElementContainer;
-import org.apache.ecs.HtmlColor;
-import org.apache.ecs.html.Center;
-import org.apache.ecs.html.Input;
-import org.apache.ecs.html.P;
-import org.apache.ecs.html.TD;
-import org.apache.ecs.html.TH;
-import org.apache.ecs.html.TR;
-import org.apache.ecs.html.Table;
-import org.owasp.webgoat.lessons.AbstractLesson;
-import org.owasp.webgoat.lessons.Category;
-import org.owasp.webgoat.lessons.LessonAdapter;
-import org.owasp.webgoat.session.LessonTracker;
-import org.owasp.webgoat.session.Screen;
-import org.owasp.webgoat.session.UserTracker;
-import org.owasp.webgoat.session.WebSession;
-
-
-/**
- *************************************************************************************************
- *
- *
- * This file is part of WebGoat, an Open Web Application Security Project utility. For details,
- * please see http://www.owasp.org/
- *
- * Copyright (c) 2002 - 20014 Bruce Mayhew
- *
- * This program is free software; you can redistribute it and/or modify it under the terms of the
- * GNU General Public License as published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
- * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with this program; if
- * not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- *
- * Getting Source ==============
- *
- * Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
- * projects.
- *
- * @author Bruce mayhew WebGoat
- * @since October 28, 2003
- * @version $Id: $Id
- */
-public class SummaryReportCardScreen extends LessonAdapter
-{
-
- private int totalUsersNormalComplete = 0;
-
- private int totalUsersAdminComplete = 0;
-
- /**
- * {@inheritDoc}
- *
- * Description of the Method
- */
- protected Element createContent(WebSession s)
- {
- ElementContainer ec = new ElementContainer();
-
- String selectedUser = null;
-
- try
- {
- if (s.getRequest().isUserInRole(WebSession.WEBGOAT_ADMIN))
- {
- Enumeration e = s.getParser().getParameterNames();
-
- while (e.hasMoreElements())
- {
- String key = (String) e.nextElement();
- if (key.startsWith("View_"))
- {
- selectedUser = key.substring("View_".length());
- ReportCardScreen reportCard = new ReportCardScreen();
- return reportCard.makeReportCard(s, selectedUser);
- }
- if (key.startsWith("Delete_"))
- {
- selectedUser = key.substring("Delete_".length());
- deleteUser(selectedUser);
- }
- }
- }
- } catch (Exception e)
- {
- e.printStackTrace();
- }
-
- ec.addElement(new Center().addElement(makeSummary(s)));
-
- ec.addElement(new P());
-
- Table t = new Table().setCellSpacing(0).setCellPadding(4).setBorder(1).setWidth("100%");
- if (s.isColor())
- {
- t.setBorder(1);
- }
- t.addElement(makeUserSummaryHeader());
-
- for (Iterator userIter = UserTracker.instance().getAllUsers(WebSession.WEBGOAT_USER).iterator(); userIter
- .hasNext();)
- {
-
- String user = userIter.next();
- t.addElement(makeUserSummaryRow(s, user));
- }
-
- ec.addElement(new Center().addElement(t));
-
- return ec;
- }
-
- /**
- * makeSummary.
- *
- * @param s a {@link org.owasp.webgoat.session.WebSession} object.
- * @return a {@link org.apache.ecs.Element} object.
- */
- protected Element makeSummary(WebSession s)
- {
- Table t = new Table().setCellSpacing(0).setCellPadding(2).setBorder(0).setWidth("100%");
- if (s.isColor())
- {
- t.setBorder(1);
- }
- TR tr = new TR();
- // tr.addElement( new TH().addElement( "Summary").setColSpan(1));
- // t.addElement( tr );
-
- tr = new TR();
- tr.addElement(new TD().setWidth("60%").addElement("Total number of users"));
- tr.addElement(new TD().setAlign("LEFT").addElement(
- Integer.toString(UserTracker.instance()
- .getAllUsers(WebSession.WEBGOAT_USER).size())));
- t.addElement(tr);
-
- tr = new TR();
- tr.addElement(new TD().setWidth("60%").addElement("Total number of users that completed all normal lessons"));
- tr.addElement(new TD().setAlign("LEFT").addElement(Integer.toString(totalUsersNormalComplete)));
- t.addElement(tr);
-
- tr = new TR();
- tr.addElement(new TD().setWidth("60%").addElement("Total number of users that completed all admin lessons"));
- tr.addElement(new TD().setAlign("LEFT").addElement(Integer.toString(totalUsersAdminComplete)));
- t.addElement(tr);
- return t;
- }
-
- private void deleteUser(String user)
- {
- UserTracker.instance().deleteUser(user);
- }
-
- /**
- * Gets the category attribute of the UserAdminScreen object
- *
- * @return The category value
- */
- protected Category getDefaultCategory()
- {
- return Category.ADMIN_FUNCTIONS;
- }
-
- private final static Integer DEFAULT_RANKING = new Integer(1000);
-
- /**
- * getDefaultRanking.
- *
- * @return a {@link java.lang.Integer} object.
- */
- protected Integer getDefaultRanking()
- {
- return DEFAULT_RANKING;
- }
-
- /**
- * Gets the role attribute of the UserAdminScreen object
- *
- * @return The role value
- */
- public String getRole()
- {
- return ADMIN_ROLE;
- }
-
- /**
- * Gets the title attribute of the UserAdminScreen object
- *
- * @return The title value
- */
- public String getTitle()
- {
- return ("Summary Report Card");
- }
-
- /**
- * {@inheritDoc}
- *
- * Description of the Method
- */
- protected Element makeMessages(WebSession s)
- {
- ElementContainer ec = new ElementContainer();
-
- return (ec);
- }
-
- /**
- * Description of the Method
- *
- * @return Description of the Return Value
- */
- protected Element makeUserSummaryHeader()
- {
- TR tr = new TR();
-
- tr.addElement(new TH("User Name"));
- tr.addElement(new TH("Normal Complete"));
- tr.addElement(new TH("Admin Complete"));
- tr.addElement(new TH("View"));
- tr.addElement(new TH("Delete"));
-
- return tr;
- }
-
- /**
- * Description of the Method
- *
- * @param s
- * Description of the Parameter
- * @param user
- * Description of the Parameter
- * @return Description of the Return Value
- */
- protected Element makeUserSummaryRow(WebSession s, String user)
- {
- TR tr = new TR();
-
- tr.addElement(new TD().setAlign("LEFT").addElement(user));
- int lessonCount = 0;
- int passedCount = 0;
- boolean normalComplete = false;
- boolean adminComplete = false;
-
- for (Iterator lessonIter = s.getCourse().getLessons(s, AbstractLesson.USER_ROLE).iterator(); lessonIter
- .hasNext();)
- {
- lessonCount++;
- Screen screen = (Screen) lessonIter.next();
-
- LessonTracker lessonTracker = UserTracker.instance().getLessonTracker(s, user, screen);
- if (lessonTracker.getCompleted())
- {
- passedCount++;
- }
- }
- if (lessonCount == passedCount)
- {
- normalComplete = true;
- totalUsersNormalComplete++;
- }
- String text = Integer.toString(passedCount) + " of " + Integer.toString(lessonCount);
- tr.addElement(new TD().setAlign("CENTER").addElement(text));
-
- lessonCount = 0;
- passedCount = 0;
- for (Iterator lessonIter = s.getCourse().getLessons(s, AbstractLesson.HACKED_ADMIN_ROLE).iterator(); lessonIter
- .hasNext();)
- {
- lessonCount++;
- Screen screen = (Screen) lessonIter.next();
-
- LessonTracker lessonTracker = UserTracker.instance().getLessonTracker(s, user, screen);
- if (lessonTracker.getCompleted())
- {
- passedCount++;
- }
- }
- if (lessonCount == passedCount)
- {
- adminComplete = true;
- totalUsersAdminComplete++;
- }
- text = Integer.toString(passedCount) + " of " + Integer.toString(lessonCount);
- tr.addElement(new TD().setAlign("CENTER").addElement(text));
-
- tr.addElement(new TD().setAlign("CENTER").addElement(new Input(Input.SUBMIT, "View_" + user, "View")));
- tr.addElement(new TD().setAlign("CENTER").addElement(new Input(Input.SUBMIT, "Delete_" + user, "Delete")));
-
- if (normalComplete && adminComplete)
- {
- tr.setBgColor(HtmlColor.GREEN);
- }
- else if (normalComplete)
- {
- tr.setBgColor(HtmlColor.LIGHTGREEN);
- }
- else
- {
- tr.setBgColor(HtmlColor.LIGHTBLUE);
- }
-
- return (tr);
- }
-
- /**
- * isEnterprise.
- *
- * @return a boolean.
- */
- public boolean isEnterprise()
- {
- return true;
- }
-}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/admin/UserAdminScreen.java b/webgoat-container/src/main/java/org/owasp/webgoat/lessons/admin/UserAdminScreen.java
deleted file mode 100644
index 7cae656e5..000000000
--- a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/admin/UserAdminScreen.java
+++ /dev/null
@@ -1,124 +0,0 @@
-
-package org.owasp.webgoat.lessons.admin;
-
-import java.sql.Connection;
-import java.sql.ResultSet;
-import java.sql.ResultSetMetaData;
-import java.sql.Statement;
-import org.apache.ecs.Element;
-import org.apache.ecs.ElementContainer;
-import org.owasp.webgoat.lessons.Category;
-import org.owasp.webgoat.lessons.LessonAdapter;
-import org.owasp.webgoat.session.DatabaseUtilities;
-import org.owasp.webgoat.session.WebSession;
-
-
-/**
- *************************************************************************************************
- *
- *
- * This file is part of WebGoat, an Open Web Application Security Project utility. For details,
- * please see http://www.owasp.org/
- *
- * Copyright (c) 2002 - 20014 Bruce Mayhew
- *
- * This program is free software; you can redistribute it and/or modify it under the terms of the
- * GNU General Public License as published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
- * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with this program; if
- * not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- *
- * Getting Source ==============
- *
- * Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
- * projects.
- *
- * @author Bruce Mayhew WebGoat
- * @since October 28, 2003
- * @version $Id: $Id
- */
-public class UserAdminScreen extends LessonAdapter
-{
-
- private final static String QUERY = "SELECT * FROM user_system_data";
-
- /**
- * {@inheritDoc}
- *
- * Description of the Method
- */
- protected Element createContent(WebSession s)
- {
- ElementContainer ec = new ElementContainer();
-
- try
- {
- Connection connection = DatabaseUtilities.getConnection(s);
-
- Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
- ResultSet.CONCUR_READ_ONLY);
- ResultSet results = statement.executeQuery(QUERY);
-
- if (results != null)
- {
- makeSuccess(s);
- ResultSetMetaData resultsMetaData = results.getMetaData();
- ec.addElement(DatabaseUtilities.writeTable(results, resultsMetaData));
- }
- } catch (Exception e)
- {
- s.setMessage("Error generating " + this.getClass().getName());
- e.printStackTrace();
- }
-
- return (ec);
- }
-
- /**
- * Gets the category attribute of the UserAdminScreen object
- *
- * @return The category value
- */
- protected Category getDefaultCategory()
- {
- return Category.ADMIN_FUNCTIONS;
- }
-
- private final static Integer DEFAULT_RANKING = new Integer(1000);
-
- /**
- * getDefaultRanking.
- *
- * @return a {@link java.lang.Integer} object.
- */
- protected Integer getDefaultRanking()
- {
- return DEFAULT_RANKING;
- }
-
- /**
- * Gets the role attribute of the UserAdminScreen object
- *
- * @return The role value
- */
- public String getRole()
- {
- return HACKED_ADMIN_ROLE;
- }
-
- /**
- * Gets the title attribute of the UserAdminScreen object
- *
- * @return The title value
- */
- public String getTitle()
- {
- return ("User Information");
- }
-}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/admin/ViewDatabase.java b/webgoat-container/src/main/java/org/owasp/webgoat/lessons/admin/ViewDatabase.java
deleted file mode 100644
index c967255ff..000000000
--- a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/admin/ViewDatabase.java
+++ /dev/null
@@ -1,165 +0,0 @@
-
-package org.owasp.webgoat.lessons.admin;
-
-import java.sql.Connection;
-import java.sql.ResultSet;
-import java.sql.ResultSetMetaData;
-import java.sql.Statement;
-import java.util.ArrayList;
-import java.util.List;
-import org.owasp.webgoat.lessons.*;
-import org.apache.ecs.Element;
-import org.apache.ecs.ElementContainer;
-import org.apache.ecs.StringElement;
-import org.apache.ecs.html.Input;
-import org.owasp.webgoat.session.*;
-
-
-/**
- *************************************************************************************************
- *
- *
- * This file is part of WebGoat, an Open Web Application Security Project utility. For details,
- * please see http://www.owasp.org/
- *
- * Copyright (c) 2002 - 20014 Bruce Mayhew
- *
- * This program is free software; you can redistribute it and/or modify it under the terms of the
- * GNU General Public License as published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
- * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with this program; if
- * not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- *
- * Getting Source ==============
- *
- * Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
- * projects.
- *
- * @author Jeff Williams Aspect Security
- * @since October 28, 2003
- * @version $Id: $Id
- */
-public class ViewDatabase extends LessonAdapter
-{
-
- private final static String SQL = "sql";
-
- /**
- * {@inheritDoc}
- *
- * Description of the Method
- */
- protected Element createContent(WebSession s)
- {
- ElementContainer ec = new ElementContainer();
-
- try
- {
- ec.addElement(new StringElement("Enter a SQL statement: "));
-
- StringBuffer sqlStatement = new StringBuffer(s.getParser().getRawParameter(SQL, ""));
- Input input = new Input(Input.TEXT, SQL, sqlStatement.toString());
- ec.addElement(input);
-
- Element b = ECSFactory.makeButton("Go!");
- ec.addElement(b);
-
- Connection connection = DatabaseUtilities.getConnection(s);
-
- if (sqlStatement.length() > 0)
- {
-
- Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
- ResultSet.CONCUR_READ_ONLY);
- ResultSet results = statement.executeQuery(sqlStatement.toString());
-
- if ((results != null) && (results.first() == true))
- {
- makeSuccess(s);
- ResultSetMetaData resultsMetaData = results.getMetaData();
- ec.addElement(DatabaseUtilities.writeTable(results, resultsMetaData));
- }
-
- }
- } catch (Exception e)
- {
- s.setMessage("Error generating " + this.getClass().getName());
- e.printStackTrace();
- }
-
- return (ec);
- }
-
- /**
- * Gets the category attribute of the DatabaseScreen object
- *
- * @return The category value
- */
- protected Category getDefaultCategory()
- {
- return Category.ADMIN_FUNCTIONS;
- }
-
- private final static Integer DEFAULT_RANKING = new Integer(1000);
-
- /**
- * getDefaultRanking.
- *
- * @return a {@link java.lang.Integer} object.
- */
- protected Integer getDefaultRanking()
- {
- return DEFAULT_RANKING;
- }
-
- /**
- * {@inheritDoc}
- *
- * Gets the hints attribute of the DatabaseScreen object
- */
- protected List getHints(WebSession s)
- {
- List hints = new ArrayList();
- hints.add("There are no hints defined");
-
- return hints;
- }
-
- /**
- * {@inheritDoc}
- *
- * Gets the instructions attribute of the ViewDatabase object
- */
- public String getInstructions(WebSession s)
- {
- String instructions = "Please post a message to to the WebGoat forum. Your messages will be available for everyone to read.";
-
- return (instructions);
- }
-
- /**
- * Gets the role attribute of the ViewDatabase object
- *
- * @return The role value
- */
- public String getRole()
- {
- return HACKED_ADMIN_ROLE;
- }
-
- /**
- * Gets the title attribute of the DatabaseScreen object
- *
- * @return The title value
- */
- public String getTitle()
- {
- return ("Adhoc Query");
- }
-}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/admin/WelcomeAdminScreen.java b/webgoat-container/src/main/java/org/owasp/webgoat/lessons/admin/WelcomeAdminScreen.java
deleted file mode 100644
index b6b456a10..000000000
--- a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/admin/WelcomeAdminScreen.java
+++ /dev/null
@@ -1,87 +0,0 @@
-
-package org.owasp.webgoat.lessons.admin;
-
-import org.owasp.webgoat.lessons.WelcomeScreen;
-import org.apache.ecs.Element;
-import org.apache.ecs.ElementContainer;
-import org.apache.ecs.html.Center;
-import org.apache.ecs.html.H1;
-import org.owasp.webgoat.session.WebSession;
-
-
-/**
- *************************************************************************************************
- *
- *
- * This file is part of WebGoat, an Open Web Application Security Project utility. For details,
- * please see http://www.owasp.org/
- *
- * Copyright (c) 2002 - 20014 Bruce Mayhew
- *
- * This program is free software; you can redistribute it and/or modify it under the terms of the
- * GNU General Public License as published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
- * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with this program; if
- * not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- *
- * Getting Source ==============
- *
- * Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
- * projects.
- *
- * @author Jeff Williams Aspect Security
- * @since October 28, 2003
- * @version $Id: $Id
- */
-public class WelcomeAdminScreen extends WelcomeScreen
-{
-
- /**
- * Constructor for the WelcomeAdminScreen object
- *
- * @param s
- * Description of the Parameter
- */
- public WelcomeAdminScreen(WebSession s)
- {
- super(s);
- }
-
- /**
- * Constructor for the WelcomeAdminScreen object
- */
- public WelcomeAdminScreen()
- {
- }
-
- /**
- * {@inheritDoc}
- *
- * Description of the Method
- */
- protected Element createContent(WebSession s)
- {
- ElementContainer ec = new ElementContainer();
-
- ec.addElement(new Center(new H1("You are logged on as an administrator")));
- ec.addElement(super.createContent(s));
-
- return (ec);
- }
-
- /**
- * Gets the title attribute of the WelcomeAdminScreen object
- *
- * @return The title value
- */
- public String getTitle()
- {
- return ("Admin Welcome");
- }
-}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/model/AttackResult.java b/webgoat-container/src/main/java/org/owasp/webgoat/lessons/model/AttackResult.java
new file mode 100644
index 000000000..bfcc34c68
--- /dev/null
+++ b/webgoat-container/src/main/java/org/owasp/webgoat/lessons/model/AttackResult.java
@@ -0,0 +1,72 @@
+package org.owasp.webgoat.lessons.model;
+
+import lombok.Getter;
+
+/**
+ * ************************************************************************************************
+ * This file is part of WebGoat, an Open Web Application Security Project utility. For details,
+ * please see http://www.owasp.org/
+ *
+ * Copyright (c) 2002 - 20014 Bruce Mayhew
+ *
+ * This program is free software; you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program; if
+ * not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Getting Source ==============
+ *
+ * Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
+ * projects.
+ *
+ *
+ * @author WebGoat
+ * @version $Id: $Id
+ * @since August 13, 2016
+ */
+@Getter
+public class AttackResult {
+
+ private boolean lessonCompleted;
+ private String feedback;
+ private String output;
+
+ public static AttackResult success() {
+ return AttackResult.success("Congratulations");
+ }
+
+ public static AttackResult success(String feedback) {
+ return success(feedback, "");
+ }
+
+ public static AttackResult success(String feedback, String output) {
+ AttackResult attackResult = new AttackResult();
+ attackResult.lessonCompleted = true;
+ attackResult.feedback = feedback;
+ attackResult.output = output;
+ return attackResult;
+ }
+
+ public static AttackResult failed(String feedback) {
+ return failed(feedback, "");
+ }
+
+ public static AttackResult failed(String feedback, String output) {
+ AttackResult attackResult = new AttackResult();
+ attackResult.lessonCompleted = false;
+ attackResult.feedback = feedback;
+ attackResult.output = output;
+ return attackResult;
+ }
+
+ public boolean assignmentSolved() {
+ return lessonCompleted;
+ }
+}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/model/LessonInfoModel.java b/webgoat-container/src/main/java/org/owasp/webgoat/lessons/model/LessonInfoModel.java
index a08decbc6..427a7f57c 100644
--- a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/model/LessonInfoModel.java
+++ b/webgoat-container/src/main/java/org/owasp/webgoat/lessons/model/LessonInfoModel.java
@@ -1,7 +1,7 @@
package org.owasp.webgoat.lessons.model;
+import lombok.Getter;
import org.owasp.webgoat.lessons.AbstractLesson;
-import org.owasp.webgoat.lessons.Category;
import org.owasp.webgoat.session.WebSession;
/**
@@ -10,6 +10,8 @@ import org.owasp.webgoat.session.WebSession;
* @author dm
* @version $Id: $Id
*/
+//// TODO: 11/5/2016 this can be removed???
+@Getter
public class LessonInfoModel {
private String lessonTitle;
@@ -27,78 +29,11 @@ public class LessonInfoModel {
public LessonInfoModel(WebSession webSession) {
AbstractLesson lesson = webSession.getCurrentLesson();
//TODO make these first class citizens of the lesson itself; and stop passing the session all over ... and generally tighten the checks up
- this.hasSource = !lesson.getSource(webSession).contains("Could not find the source file or source file does not exist");
- this.hasPlan = !lesson.getSource(webSession).contains("Could not find lesson plan");
- this.hasSolution = !lesson.getSolution(webSession).contains("Could not find the solution file or solution file does not exist");
+ this.hasSource = false;
+ this.hasPlan = false;
+ this.hasSolution = false;
this.lessonTitle = lesson.getTitle();
- this.numberHints = lesson.getHintCount(webSession);
+ this.numberHints = lesson.getHintCount();
this.submitMethod = lesson.getSubmitMethod();
-
- if ( this.numberHints < 1 || lesson.getHint(webSession,0).equals("Hint: There are no hints defined.")) {
- this.numberHints = 0;
- }
- //special challenge case
- if (lesson.getCategory().equals(Category.CHALLENGE)) {
- this.numberHints = (lesson.isAuthorized(webSession, AbstractLesson.CHALLENGE_ROLE, WebSession.SHOWHINTS)) ? lesson.getHintCount(webSession) : 0;
- this.hasSource = (lesson.isAuthorized(webSession, AbstractLesson.CHALLENGE_ROLE, WebSession.SHOWHINTS));
- this.hasSolution = (lesson.isAuthorized(webSession, AbstractLesson.CHALLENGE_ROLE, WebSession.SHOWHINTS)); //assuming we want this to fall in line with source and solution
- this.hasPlan = (lesson.isAuthorized(webSession, AbstractLesson.CHALLENGE_ROLE, WebSession.SHOWHINTS)); //assuming we want this to fall in line with source and solutionn
- }
}
-
- // GETTERS
- /**
- *
Getter for the field lessonTitle
.
- *
- * @return a {@link java.lang.String} object.
- */
- public String getLessonTitle() {
- return lessonTitle;
- }
-
- /**
- * Getter for the field numberHints
.
- *
- * @return a int.
- */
- public int getNumberHints() {
- return numberHints;
- }
-
- /**
- * isHasSource.
- *
- * @return a boolean.
- */
- public boolean isHasSource() {
- return hasSource;
- }
-
- /**
- * isHasSolution.
- *
- * @return a boolean.
- */
- public boolean isHasSolution() {
- return hasSolution;
- }
-
- /**
- * isHasPlan.
- *
- * @return a boolean.
- */
- public boolean isHasPlan() {
- return hasPlan;
- }
-
- /**
- * Getter for the field submitMethod
.
- *
- * @return a {@link java.lang.String} object.
- */
- public String getSubmitMethod() {
- return submitMethod;
- }
-
}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/model/SourceListing.java b/webgoat-container/src/main/java/org/owasp/webgoat/lessons/model/SourceListing.java
deleted file mode 100644
index 0e7e3272c..000000000
--- a/webgoat-container/src/main/java/org/owasp/webgoat/lessons/model/SourceListing.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * To change this license header, choose License Headers in Project Properties.
- * To change this template file, choose Tools | Templates
- * and open the template in the editor.
- */
-
-package org.owasp.webgoat.lessons.model;
-
-/**
- * SourceListing class.
- *
- * @author rlawson
- * @version $Id: $Id
- */
-public class SourceListing {
-
- private String source;
-
- /**
- * Getter for the field source
.
- *
- * @return the source
- */
- public String getSource() {
- return source;
- }
-
- /**
- * Setter for the field source
.
- *
- * @param source the source to set
- */
- public void setSource(String source) {
- this.source = source;
- }
-
-}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/plugins/LegacyLoader.java b/webgoat-container/src/main/java/org/owasp/webgoat/plugins/LegacyLoader.java
deleted file mode 100644
index ff337f19a..000000000
--- a/webgoat-container/src/main/java/org/owasp/webgoat/plugins/LegacyLoader.java
+++ /dev/null
@@ -1,260 +0,0 @@
-package org.owasp.webgoat.plugins;
-
-import org.owasp.webgoat.lessons.AbstractLesson;
-import org.owasp.webgoat.session.WebgoatContext;
-import org.owasp.webgoat.session.WebgoatProperties;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.servlet.ServletContext;
-import java.io.File;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Set;
-
-/**
- *************************************************************************************************
- *
- *
- * This file is part of WebGoat, an Open Web Application Security Project utility. For details,
- * please see http://www.owasp.org/
- *
- * Copyright (c) 2002 - 20014 Bruce Mayhew
- *
- * This program is free software; you can redistribute it and/or modify it under the terms of the
- * GNU General Public License as published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
- * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with this program; if
- * not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- *
- * Getting Source ==============
- *
- * Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
- * projects.
- *
- * @author Bruce Mayhew WebGoat
- * @since October 28, 2003
- * @version $Id: $Id
- */
-public class LegacyLoader {
-
- final Logger logger = LoggerFactory.getLogger(LegacyLoader.class);
-
- private final List files = new LinkedList();
-
- /**
- * Constructor for LegacyLoader.
- */
- public LegacyLoader() {
- }
-
- /**
- * Take an absolute file and return the filename.
- *
- * Ex. /etc/password becomes password
- *
- * @param s
- * @return the file name
- */
- private static String getFileName(String s) {
- String fileName = new File(s).getName();
-
- if (fileName.contains("/")) {
- fileName = fileName.substring(fileName.lastIndexOf("/"), fileName.length());
- }
-
- if (fileName.contains(".")) {
- fileName = fileName.substring(0, fileName.indexOf("."));
- }
-
- return fileName;
- }
-
- /**
- * Take a class name and return the equivalent file name
- *
- * Ex. org.owasp.webgoat becomes org/owasp/webgoat.java
- *
- * @param className
- * @return
- */
- private static String getSourceFile(String className) {
- StringBuilder sb = new StringBuilder();
-
- sb.append(className.replace(".", "/"));
- sb.append(".java");
-
- return sb.toString();
- }
-
- /**
- * Takes a file name and builds the class file name
- *
- * @param fileName Description of the Parameter
- * @param path Description of the Parameter
- * @return Description of the Return Value
- */
- private static String getClassFile(String fileName, String path) {
- String ext = ".class";
- fileName = fileName.trim();
-
- /**
- * We do not handle directories. We do not handle files with different
- * extensions
- */
- if (fileName.endsWith("/") || !fileName.endsWith(ext)) {
- return null;
- }
-
- // skip over plugins and/or extracted plugins
- if ( fileName.indexOf("lessons/plugin") >= 0 || fileName.indexOf("plugin_extracted") >= 0) {
- return null;
- }
-
- // if the file is in /WEB-INF/classes strip the dir info off
- int index = fileName.indexOf("/WEB-INF/classes/");
- if (index != -1) {
- fileName = fileName.substring(index + "/WEB-INF/classes/".length(), fileName.length() - ext.length());
- fileName = fileName.replace('/', '.');
- fileName = fileName.replace('\\', '.');
- } else {
- // Strip off the leading path info
- fileName = fileName.substring(path.length(), fileName.length() - ext.length());
- }
-
- return fileName;
- }
-
-
-
- /**
- * Load all of the filenames into a temporary cache
- *
- * @param context a {@link javax.servlet.ServletContext} object.
- * @param path a {@link java.lang.String} object.
- */
- public void loadFiles(ServletContext context, String path) {
- logger.debug("Loading files into cache, path: " + path);
- Set resourcePaths = context.getResourcePaths(path);
- if (resourcePaths == null) {
- logger.error("Unable to load file cache for courses, this is probably a bug or configuration issue");
- return;
- }
- Iterator itr = resourcePaths.iterator();
-
- while (itr.hasNext()) {
- String file = (String) itr.next();
-
- if (file.length() != 1 && file.endsWith("/")) {
- loadFiles(context, file);
- } else {
- files.add(file);
- }
- }
- }
-
- /**
- * Instantiate all the lesson objects into a cache
- *
- * @param path a {@link java.lang.String} object.
- * @param context a {@link javax.servlet.ServletContext} object.
- * @param webgoatContext a {@link org.owasp.webgoat.session.WebgoatContext} object.
- * @param properties a {@link org.owasp.webgoat.session.WebgoatProperties} object.
- * @return a {@link java.util.List} object.
- */
- public List loadLessons(WebgoatContext webgoatContext, ServletContext context, String path, WebgoatProperties properties ) {
-
- loadFiles(context, path);
-
- List lessons = new LinkedList();
-
- for (String file : files) {
- String className = getClassFile(file, path);
-
- if (className != null && !className.endsWith("_i") && className.startsWith("org.owasp.webgoat.lessons.admin")) {
- try {
- Class c = Class.forName(className);
- Object o = c.newInstance();
-
- if (o instanceof AbstractLesson) {
- AbstractLesson lesson = (AbstractLesson) o;
- lesson.setWebgoatContext(webgoatContext);
-
- lesson.update(properties);
-
- if (lesson.getHidden() == false) {
- lessons.add(lesson);
- }
- }
- } catch (Exception e) {
- // Bruce says:
- // I don't think we want to log the exception here. We could
- // be potentially showing a lot of exceptions that don't matter.
- // We would only care if the lesson extended AbstractLesson and we
- // can't tell that because it threw the exception. Catch 22
- // logger.error("Error in loadLessons: ", e);
- }
- }
- }
- loadResources(lessons);
- return lessons;
- }
-
- private String getLanguageFromFileName(String first, String absoluteFile) {
- int p1 = absoluteFile.indexOf("/", absoluteFile.indexOf(first) + 1);
- int p2 = absoluteFile.indexOf("/", p1 + 1);
- String langStr = absoluteFile.substring(p1 + 1, p2);
-
- return langStr;
- }
-
- /**
- * For each lesson, set the source file and lesson file
- *
- * @param lessons a {@link java.util.List} object.
- */
- public void loadResources(List lessons ) {
- for (AbstractLesson lesson : lessons) {
- logger.info("Loading resources for lesson -> " + lesson.getName());
- String className = lesson.getClass().getName();
- String classFile = getSourceFile(className);
- logger.info("Lesson classname: " + className);
- logger.info("Lesson java file: " + classFile);
-
- for (String absoluteFile : files) {
- String fileName = getFileName(absoluteFile);
- //logger.debug("Course: looking at file: " + absoluteFile);
-
- if (absoluteFile.endsWith(classFile)) {
- logger.info("Set source file for " + classFile);
- lesson.setSourceFileName(absoluteFile);
- }
-
- if (absoluteFile.startsWith("/lesson_plans") && absoluteFile.endsWith(".html")
- && className.endsWith(fileName)) {
- logger.info("setting lesson plan file " + absoluteFile + " for lesson "
- + lesson.getClass().getName());
- logger.info("fileName: " + fileName + " == className: " + className);
- String language = getLanguageFromFileName("/lesson_plans", absoluteFile);
- lesson.setLessonPlanFileName(language, absoluteFile);
- }
- if (absoluteFile.startsWith("/lesson_solutions") && absoluteFile.endsWith(".html")
- && className.endsWith(fileName)) {
- logger.info("setting lesson solution file " + absoluteFile + " for lesson "
- + lesson.getClass().getName());
- logger.info("fileName: " + fileName + " == className: " + className);
- lesson.setLessonSolutionFileName(absoluteFile);
- }
- }
- }
- }
-
-
-}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/plugins/Plugin.java b/webgoat-container/src/main/java/org/owasp/webgoat/plugins/Plugin.java
index 7621e6338..4c4d36bb7 100644
--- a/webgoat-container/src/main/java/org/owasp/webgoat/plugins/Plugin.java
+++ b/webgoat-container/src/main/java/org/owasp/webgoat/plugins/Plugin.java
@@ -2,38 +2,47 @@ package org.owasp.webgoat.plugins;
import com.google.common.base.Optional;
import com.google.common.collect.Lists;
-import org.apache.catalina.loader.WebappClassLoader;
+import lombok.Getter;
import org.owasp.webgoat.lessons.AbstractLesson;
+import org.owasp.webgoat.lessons.Assignment;
+import org.owasp.webgoat.lessons.Endpoint;
+import org.owasp.webgoat.lessons.NewLesson;
import org.springframework.util.StringUtils;
import java.io.File;
-import java.io.IOException;
import java.nio.file.Path;
-import java.util.Arrays;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
import static org.owasp.webgoat.plugins.PluginFileUtils.fileEndsWith;
-import static org.owasp.webgoat.plugins.PluginFileUtils.hasParentDirectoryWithName;
-import static org.owasp.webgoat.plugins.PluginFileUtils.replaceInFiles;
/**
* Plugin class.
*
- * @version $Id: $Id
* @author dm
+ * @version $Id: $Id
*/
public class Plugin {
- private static final String NAME_LESSON_SOLUTION_DIRECTORY = "lessonSolutions";
- private static final String NAME_LESSON_PLANS_DIRECTORY = "lessonPlans";
-
- private Class lesson;
- private Map solutionLanguageFiles = new HashMap<>();
- private Map lessonPlansLanguageFiles = new HashMap<>();
+ @Getter
+ private final String originationJar;
+ private PluginClassLoader classLoader;
+ private Class newLesson;
+ private List> assignments = Lists.newArrayList();
+ private List> endpoints = Lists.newArrayList();
private List pluginFiles = Lists.newArrayList();
- private File lessonSourceFile;
+
+ public Plugin(PluginClassLoader classLoader, String originatingJar) {
+ this.classLoader = classLoader;
+ this.originationJar = originatingJar;
+ }
+
+ public List> getAssignments() {
+ return this.assignments;
+ }
+
+ public List> getEndpoints() {
+ return this.endpoints;
+ }
/**
* findLesson.
@@ -48,77 +57,46 @@ public class Plugin {
private void findLesson(String name) {
String realClassName = StringUtils.trimLeadingCharacter(name, '/').replaceAll("/", ".").replaceAll(".class", "");
- //TODO should be passed in (refactor)
- WebappClassLoader cl = (WebappClassLoader) Thread.currentThread().getContextClassLoader();
try {
- Class clazz = cl.loadClass(realClassName, true);
-
- if (AbstractLesson.class.isAssignableFrom(clazz)) {
- this.lesson = clazz;
+ Class clazz = classLoader.loadClass(realClassName);
+ if (NewLesson.class.isAssignableFrom(clazz)) {
+ this.newLesson = clazz;
}
} catch (ClassNotFoundException ce) {
throw new PluginLoadingFailure("Class " + realClassName + " listed in jar but unable to load the class.", ce);
}
}
+ public void findEndpoints(List classes) {
+ for (String clazzName : classes) {
+ String realClassName = StringUtils.trimLeadingCharacter(clazzName, '/').replaceAll("/", ".").replaceAll(".class", "");
+
+ try {
+ Class clazz = classLoader.loadClass(realClassName);
+
+ if (Assignment.class.isAssignableFrom(clazz)) {
+ this.assignments.add(clazz);
+ } else if (Endpoint.class.isAssignableFrom(clazz)) {
+ this.endpoints.add(clazz);
+ }
+ } catch (ClassNotFoundException ce) {
+ throw new PluginLoadingFailure("Class " + realClassName + " listed in jar but unable to load the class.", ce);
+ }
+ }
+ }
+
/**
* loadFiles.
*
* @param file a {@link java.nio.file.Path} object.
*/
public void loadFiles(Path file) {
- if (fileEndsWith(file, ".html") && hasParentDirectoryWithName(file, NAME_LESSON_SOLUTION_DIRECTORY)) {
- solutionLanguageFiles.put(file.getParent().getFileName().toString(), file.toFile());
- }
- if (fileEndsWith(file, ".html") && hasParentDirectoryWithName(file, NAME_LESSON_PLANS_DIRECTORY)) {
- lessonPlansLanguageFiles.put(file.getParent().getFileName().toString(), file.toFile());
- }
- if (fileEndsWith(file, ".java")) {
- lessonSourceFile = file.toFile();
- }
-
if (fileEndsWith(file, ".css", ".jsp", ".js")) {
pluginFiles.add(file.toFile());
}
}
- /**
- * rewritePaths.
- *
- * @param pluginTarget a {@link java.nio.file.Path} object.
- */
- public void rewritePaths(Path pluginTarget) {
- try {
- replaceInFiles(this.lesson.getSimpleName() + "_files",
- pluginTarget.getFileName().toString() + "/plugin/" + this.lesson
- .getSimpleName() + "/lessonSolutions/en/" + this.lesson.getSimpleName() + "_files",
- solutionLanguageFiles.values());
- replaceInFiles(this.lesson.getSimpleName() + "_files",
- pluginTarget.getFileName().toString() + "/plugin/" + this.lesson
- .getSimpleName() + "/lessonPlans/en/" + this.lesson.getSimpleName() + "_files",
- lessonPlansLanguageFiles.values());
-
- String[] replacements = {"jsp", "js"};
- for (String replacement : replacements) {
- String s = String.format("plugin/%s/%s/", this.lesson.getSimpleName(), replacement);
- String r = String.format("%s/plugin/%s/%s/", pluginTarget.getFileName().toString(),
- this.lesson.getSimpleName(), replacement);
- replaceInFiles(s, r, pluginFiles);
- replaceInFiles(s, r, Arrays.asList(lessonSourceFile));
- }
-
- //CSS with url('/plugin/images') should not begin with / otherwise image cannot be found
- String s = String.format("/plugin/%s/images/", this.lesson.getSimpleName());
- String r = String
- .format("%s/plugin/%s/images/", pluginTarget.getFileName().toString(), this.lesson.getSimpleName());
- replaceInFiles(s, r, pluginFiles);
- replaceInFiles(s, r, Arrays.asList(lessonSourceFile));
- } catch (IOException e) {
- throw new PluginLoadingFailure("Unable to rewrite the paths in the solutions", e);
- }
- }
-
/**
* Lesson is optional, it is also possible that the supplied jar contains only helper classes.
*
@@ -126,51 +104,16 @@ public class Plugin {
*/
public Optional getLesson() {
try {
- if (lesson != null) {
- return Optional.of(lesson.newInstance());
+ if (newLesson != null) {
+ AbstractLesson lesson = newLesson.newInstance();
+ lesson.setAssignments(this.assignments);
+ return Optional.of(newLesson.newInstance());
}
} catch (IllegalAccessException | InstantiationException e) {
- throw new PluginLoadingFailure("Unable to instantiate the lesson " + lesson.getName(), e);
+ throw new PluginLoadingFailure("Unable to instantiate the lesson " + newLesson.getName(), e);
}
return Optional.absent();
}
- /**
- * getLessonSolution.
- *
- * @param language a {@link java.lang.String} object.
- * @return a {@link com.google.common.base.Optional} object.
- */
- public Optional getLessonSolution(String language) {
- return Optional.fromNullable(this.solutionLanguageFiles.get(language));
- }
-
- /**
- * getLessonSolutions.
- *
- * @return a {@link java.util.Map} object.
- */
- public Map getLessonSolutions() {
- return this.solutionLanguageFiles;
- }
-
- /**
- * getLessonSource.
- *
- * @return a {@link com.google.common.base.Optional} object.
- */
- public Optional getLessonSource() {
- return Optional.fromNullable(lessonSourceFile);
- }
-
- /**
- * getLessonPlans.
- *
- * @return a {@link java.util.Map} object.
- */
- public Map getLessonPlans() {
- return this.lessonPlansLanguageFiles;
- }
-
}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/plugins/PluginClassLoader.java b/webgoat-container/src/main/java/org/owasp/webgoat/plugins/PluginClassLoader.java
new file mode 100644
index 000000000..24aa42041
--- /dev/null
+++ b/webgoat-container/src/main/java/org/owasp/webgoat/plugins/PluginClassLoader.java
@@ -0,0 +1,16 @@
+package org.owasp.webgoat.plugins;
+
+import java.net.URL;
+import java.net.URLClassLoader;
+
+public class PluginClassLoader extends URLClassLoader {
+
+ public PluginClassLoader(ClassLoader parent) {
+ super(new URL[] {}, parent);
+ }
+
+ @Override
+ public void addURL(URL url) {
+ super.addURL(url);
+ }
+}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/plugins/PluginEndpointPublisher.java b/webgoat-container/src/main/java/org/owasp/webgoat/plugins/PluginEndpointPublisher.java
new file mode 100644
index 000000000..9c8654669
--- /dev/null
+++ b/webgoat-container/src/main/java/org/owasp/webgoat/plugins/PluginEndpointPublisher.java
@@ -0,0 +1,66 @@
+package org.owasp.webgoat.plugins;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowire;
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.beans.factory.support.DefaultListableBeanFactory;
+import org.springframework.beans.factory.support.RootBeanDefinition;
+import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoint;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.support.AbstractApplicationContext;
+import org.springframework.stereotype.Component;
+
+/**
+ * ************************************************************************************************
+ * This file is part of WebGoat, an Open Web Application Security Project utility. For details,
+ * please see http://www.owasp.org/
+ *
+ * Copyright (c) 2002 - 20014 Bruce Mayhew
+ *
+ * This program is free software; you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program; if
+ * not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Getting Source ==============
+ *
+ * Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
+ * projects.
+ *
+ *
+ * @author nbaars
+ * @version $Id: $Id
+ * @since October 16, 2016
+ */
+@Component
+@Slf4j
+public class PluginEndpointPublisher {
+
+ private AbstractApplicationContext applicationContext;
+
+ public PluginEndpointPublisher(ApplicationContext applicationContext) {
+ this.applicationContext = (AbstractApplicationContext) applicationContext;
+ }
+
+ public void publish(Plugin plugin) {
+ plugin.getAssignments().forEach(e -> publishEndpoint(e));
+ plugin.getEndpoints().forEach(e -> publishEndpoint(e));
+ }
+
+ private void publishEndpoint(Class extends MvcEndpoint> e) {
+ try {
+ BeanDefinition beanDefinition = new RootBeanDefinition(e, Autowire.BY_TYPE.value(), true);
+ DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) applicationContext.getBeanFactory();
+ beanFactory.registerBeanDefinition(beanDefinition.getBeanClassName(), beanDefinition);
+ } catch (Exception ex) {
+ log.error("Failed to register " + e.getSimpleName() + " as endpoint with Spring, skipping...");
+ }
+ }
+}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/plugins/PluginExtractor.java b/webgoat-container/src/main/java/org/owasp/webgoat/plugins/PluginExtractor.java
index 1d7b1cf24..fef9b13d6 100644
--- a/webgoat-container/src/main/java/org/owasp/webgoat/plugins/PluginExtractor.java
+++ b/webgoat-container/src/main/java/org/owasp/webgoat/plugins/PluginExtractor.java
@@ -34,15 +34,15 @@ public class PluginExtractor {
* @return a {@link org.owasp.webgoat.plugins.Plugin} object.
* @throws java.io.IOException if any.
*/
- public Plugin extractJarFile(final File archive, final File targetDirectory) throws IOException {
+ public Plugin extractJarFile(final File archive, final File targetDirectory, PluginClassLoader cl) throws IOException {
ZipFile zipFile = new ZipFile(archive);
- Plugin plugin = new Plugin();
+ Plugin plugin = new Plugin(cl, zipFile.getName());
try {
Enumeration extends ZipEntry> entries = zipFile.entries();
while (entries.hasMoreElements()) {
final ZipEntry zipEntry = entries.nextElement();
if (shouldProcessFile(zipEntry)) {
- boolean processed = processClassFile(zipEntry);
+ boolean processed = processClassFile(zipFile, zipEntry, targetDirectory);
if (!processed) {
processed = processPropertyFile(zipFile, zipEntry, targetDirectory);
@@ -54,9 +54,7 @@ public class PluginExtractor {
}
} finally {
plugin.findLesson(this.classes);
- if (plugin.getLesson().isPresent()) {
- plugin.rewritePaths(targetDirectory.toPath());
- }
+ plugin.findEndpoints(this.classes);
zipFile.close();
}
return plugin;
@@ -79,9 +77,11 @@ public class PluginExtractor {
return false;
}
- private boolean processClassFile(ZipEntry zipEntry) {
+ private boolean processClassFile(ZipFile zipFile, ZipEntry zipEntry, File targetDirectory) throws IOException {
if (zipEntry.getName().endsWith(".class")) {
classes.add(zipEntry.getName());
+ final File targetFile = new File(targetDirectory, zipEntry.getName());
+ copyFile(zipFile, zipEntry, targetFile, false);
return true;
}
return false;
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/plugins/PluginFileUtils.java b/webgoat-container/src/main/java/org/owasp/webgoat/plugins/PluginFileUtils.java
index 1b9cef313..d744f2dac 100644
--- a/webgoat-container/src/main/java/org/owasp/webgoat/plugins/PluginFileUtils.java
+++ b/webgoat-container/src/main/java/org/owasp/webgoat/plugins/PluginFileUtils.java
@@ -2,6 +2,7 @@ package org.owasp.webgoat.plugins;
import com.google.common.base.Preconditions;
+import lombok.experimental.UtilityClass;
import org.apache.commons.io.IOUtils;
import java.io.File;
@@ -18,6 +19,7 @@ import java.util.Collection;
* @version $Id: $Id
* @author dm
*/
+@UtilityClass
public class PluginFileUtils {
/**
@@ -64,20 +66,6 @@ public class PluginFileUtils {
return hasParentDirectoryWithName(p.getParent(), s);
}
- /**
- *
createDirsIfNotExists.
- *
- * @param p a {@link java.nio.file.Path} object.
- * @return a {@link java.nio.file.Path} object.
- * @throws java.io.IOException if any.
- */
- public static Path createDirsIfNotExists(Path p) throws IOException {
- if (Files.notExists(p)) {
- Files.createDirectories(p);
- }
- return p;
- }
-
/**
* replaceInFiles.
*
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/plugins/PluginLoadingFailure.java b/webgoat-container/src/main/java/org/owasp/webgoat/plugins/PluginLoadingFailure.java
index ec9104791..007228ddb 100644
--- a/webgoat-container/src/main/java/org/owasp/webgoat/plugins/PluginLoadingFailure.java
+++ b/webgoat-container/src/main/java/org/owasp/webgoat/plugins/PluginLoadingFailure.java
@@ -8,6 +8,15 @@ package org.owasp.webgoat.plugins;
*/
public class PluginLoadingFailure extends RuntimeException {
+ /**
+ * Constructor for PluginLoadingFailure.
+ *
+ * @param message a {@link java.lang.String} object.
+ */
+ public PluginLoadingFailure(String message) {
+ super(message);
+ }
+
/**
* Constructor for PluginLoadingFailure.
*
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/plugins/PluginsLoader.java b/webgoat-container/src/main/java/org/owasp/webgoat/plugins/PluginsLoader.java
index 478af0926..35e2677fb 100644
--- a/webgoat-container/src/main/java/org/owasp/webgoat/plugins/PluginsLoader.java
+++ b/webgoat-container/src/main/java/org/owasp/webgoat/plugins/PluginsLoader.java
@@ -1,69 +1,50 @@
package org.owasp.webgoat.plugins;
import com.google.common.collect.Lists;
-import org.apache.catalina.loader.WebappClassLoader;
+import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
-import org.owasp.webgoat.util.LabelProvider;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import org.owasp.webgoat.i18n.LabelProvider;
import org.springframework.util.ResourceUtils;
+import java.io.File;
+import java.io.FileOutputStream;
import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
import java.net.URL;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
+import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
+import java.util.Enumeration;
import java.util.List;
-import java.util.Objects;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
/**
* PluginsLoader class.
*
- * @version $Id: $Id
* @author dm
+ * @version $Id: $Id
*/
+@Slf4j
public class PluginsLoader {
private static final String WEBGOAT_PLUGIN_EXTENSION = "jar";
- private static boolean alreadyLoaded = false;
- private final Logger logger = LoggerFactory.getLogger(this.getClass());
- private final Path pluginSource;
- private Path pluginTarget;
+ private static final int BUFFER_SIZE = 32 * 1024;
+ private final File pluginTargetDirectory;
+ private final PluginClassLoader classLoader;
- /**
- * Constructor for PluginsLoader.
- *
- * @param pluginSource a {@link java.nio.file.Path} object.
- * @param pluginTarget a {@link java.nio.file.Path} object.
- */
- public PluginsLoader(Path pluginSource, Path pluginTarget) {
- this.pluginSource = Objects.requireNonNull(pluginSource, "plugin source cannot be null");
- this.pluginTarget = Objects.requireNonNull(pluginTarget, "plugin target cannot be null");
- }
-
- /**
- * Copy jars to the lib directory
- */
- public void copyJars() {
- try {
- if (!alreadyLoaded) {
- WebappClassLoader cl = (WebappClassLoader) Thread.currentThread().getContextClassLoader();
- List jars = listJars();
- for (URL jar : jars) {
- cl.addRepository(jar.toString());
- }
- alreadyLoaded = true;
- }
- } catch (Exception e) {
- logger.error("Copying plugins failed", e);
- }
+ public PluginsLoader(File pluginTargetDirectory, PluginClassLoader pluginClassLoader) {
+ this.classLoader = pluginClassLoader;
+ this.pluginTargetDirectory = pluginTargetDirectory;
}
/**
@@ -72,34 +53,76 @@ public class PluginsLoader {
* @return a {@link java.util.List} object.
*/
public List loadPlugins() {
- copyJars();
List plugins = Lists.newArrayList();
-
try {
- PluginFileUtils.createDirsIfNotExists(pluginTarget);
- cleanupExtractedPluginsDirectory();
+ URL location = this.getClass().getProtectionDomain().getCodeSource().getLocation();
+ log.trace("Determining whether we run as standalone jar or as directory...");
+ if (ResourceUtils.isFileURL(location)) {
+ log.trace("Running from directory, copying lessons from {}", location.toString());
+ extractToTargetDirectoryFromExplodedDirectory(ResourceUtils.getFile(location));
+ } else {
+ log.trace("Running from standalone jar, extracting lessons from {}", location.toString());
+ extractToTargetDirectoryFromJarFile(ResourceUtils.getFile(ResourceUtils.extractJarFileURL(location)));
+ }
List jars = listJars();
-
plugins = processPlugins(jars);
} catch (Exception e) {
- logger.error("Loading plugins failed", e);
+ log.error("Loading plugins failed", e);
}
return plugins;
}
- private void cleanupExtractedPluginsDirectory() {
- Path i18nDirectory = pluginTarget.resolve("plugin/i18n/");
- FileUtils.deleteQuietly(i18nDirectory.toFile());
+ private void extractToTargetDirectoryFromJarFile(File jarFile) throws IOException {
+ ZipFile jar = new ZipFile(jarFile);
+ Enumeration extends ZipEntry> entries = jar.entries();
+ while (entries.hasMoreElements()) {
+ ZipEntry zipEntry = entries.nextElement();
+ if (zipEntry.getName().contains("plugin_lessons") && zipEntry.getName().endsWith(".jar")) {
+ unpack(jar, zipEntry);
+ }
+ }
}
- private List listJars() throws IOException {
+ private void unpack(ZipFile jar, ZipEntry zipEntry) throws IOException {
+ try (InputStream inputStream = jar.getInputStream(zipEntry)) {
+ String name = zipEntry.getName();
+ if (name.lastIndexOf("/") != -1) {
+ name = name.substring(name.lastIndexOf("/") + 1);
+ }
+ try (OutputStream outputStream = new FileOutputStream(new File(pluginTargetDirectory, name))) {
+ byte[] buffer = new byte[BUFFER_SIZE];
+ int bytesRead = -1;
+ while ((bytesRead = inputStream.read(buffer)) != -1) {
+ outputStream.write(buffer, 0, bytesRead);
+ }
+ outputStream.flush();
+ }
+ }
+ log.trace("Extracting {} to {}", jar.getName(), pluginTargetDirectory);
+ }
+
+ private void extractToTargetDirectoryFromExplodedDirectory(File directory) throws IOException {
+ Files.walkFileTree(directory.toPath(), new SimpleFileVisitor() {
+ @Override
+ public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
+ if (dir.endsWith("plugin_lessons")) {
+ log.trace("Copying {} to {}", dir.toString(), pluginTargetDirectory);
+ FileUtils.copyDirectory(dir.toFile(), pluginTargetDirectory);
+ }
+ return FileVisitResult.CONTINUE;
+ }
+ });
+ }
+
+ private List listJars() throws Exception {
final List jars = Lists.newArrayList();
- Files.walkFileTree(pluginSource, new SimpleFileVisitor() {
+ Files.walkFileTree(Paths.get(pluginTargetDirectory.toURI()), new SimpleFileVisitor() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
if (PluginFileUtils.fileEndsWith(file, WEBGOAT_PLUGIN_EXTENSION)) {
jars.add(file.toUri().toURL());
+ log.trace("Found jar file at location: {}", file.toString());
}
return FileVisitResult.CONTINUE;
}
@@ -114,17 +137,21 @@ public class PluginsLoader {
final CompletionService completionService = new ExecutorCompletionService<>(executorService);
final List> callables = extractJars(jars);
- for (Callable s : callables) {
- completionService.submit(s);
- }
+ callables.forEach(s -> completionService.submit(s));
int n = callables.size();
+
for (int i = 0; i < n; i++) {
Plugin plugin = completionService.take().get();
if (plugin.getLesson().isPresent()) {
+ log.trace("Plugin jar '{}' contains a lesson, loading into WebGoat...", plugin.getOriginationJar());
plugins.add(plugin);
+ } else {
+ log.trace("Plugin jar: '{}' does not contain a lesson not processing as a plugin (can be a utility jar)",
+ plugin.getOriginationJar());
}
}
- LabelProvider.updatePluginResources(pluginTarget.resolve("plugin/i18n/WebGoatLabels.properties"));
+ LabelProvider.updatePluginResources(
+ pluginTargetDirectory.toPath().resolve("plugin/i18n/WebGoatLabels.properties"));
return plugins;
} finally {
executorService.shutdown();
@@ -133,14 +160,12 @@ public class PluginsLoader {
private List> extractJars(List jars) {
List> extractorCallables = Lists.newArrayList();
- for (final URL jar : jars) {
- extractorCallables.add(new Callable() {
- @Override
- public Plugin call() throws Exception {
- PluginExtractor extractor = new PluginExtractor();
- return extractor.extractJarFile(ResourceUtils.getFile(jar), pluginTarget.toFile());
- }
+ for (final URL jar : jars) {
+ classLoader.addURL(jar);
+ extractorCallables.add(() -> {
+ PluginExtractor extractor = new PluginExtractor();
+ return extractor.extractJarFile(ResourceUtils.getFile(jar), pluginTargetDirectory, classLoader);
});
}
return extractorCallables;
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/service/ApplicationService.java b/webgoat-container/src/main/java/org/owasp/webgoat/service/ApplicationService.java
deleted file mode 100644
index e348f67bd..000000000
--- a/webgoat-container/src/main/java/org/owasp/webgoat/service/ApplicationService.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/**
- * *************************************************************************************************
- *
- *
- * This file is part of WebGoat, an Open Web Application Security Project
- * utility. For details, please see http://www.owasp.org/
- *
- * Copyright (c) 2002 - 20014 Bruce Mayhew
- *
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License as published by the Free Software
- * Foundation; either version 2 of the License, or (at your option) any later
- * version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * Getting Source ==============
- *
- * Source for this application is maintained at
- * https://github.com/WebGoat/WebGoat, a repository for free software projects.
- *
- */
-package org.owasp.webgoat.service;
-
-import javax.servlet.http.HttpSession;
-import org.owasp.webgoat.application.Application;
-import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.ResponseBody;
-
-/**
- * ApplicationService class.
- *
- * @author rlawson
- * @version $Id: $Id
- */
-@Controller
-public class ApplicationService extends BaseService {
-
- /**
- * Returns global application info
- *
- * @param session a {@link javax.servlet.http.HttpSession} object.
- * @return a {@link org.owasp.webgoat.application.Application} object.
- */
- @RequestMapping(value = "/application.mvc", produces = "application/json")
- public @ResponseBody
- Application showApplication(HttpSession session) {
- Application app = Application.getInstance();
- return app;
- }
-
-}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/service/BaseService.java b/webgoat-container/src/main/java/org/owasp/webgoat/service/BaseService.java
deleted file mode 100644
index aec0d2076..000000000
--- a/webgoat-container/src/main/java/org/owasp/webgoat/service/BaseService.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/**
- * *************************************************************************************************
- *
- *
- * This file is part of WebGoat, an Open Web Application Security Project
- * utility. For details, please see http://www.owasp.org/
- *
- * Copyright (c) 2002 - 20014 Bruce Mayhew
- *
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License as published by the Free Software
- * Foundation; either version 2 of the License, or (at your option) any later
- * version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * Getting Source ==============
- *
- * Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository
- * for free software projects.
- *
- */
-package org.owasp.webgoat.service;
-
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpSession;
-import org.owasp.webgoat.session.WebSession;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.http.HttpStatus;
-import org.springframework.web.bind.annotation.ExceptionHandler;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.ResponseBody;
-import org.springframework.web.bind.annotation.ResponseStatus;
-
-/**
- * Abstract BaseService class.
- *
- * @author rlawson
- * @version $Id: $Id
- */
-@RequestMapping("/service")
-public abstract class BaseService {
-
- private static final Logger logger = LoggerFactory.getLogger(BaseService.class);
-
- /**
- * handleException.
- *
- * @param request a {@link javax.servlet.http.HttpServletRequest} object.
- * @param ex a {@link java.lang.Exception} object.
- * @return a {@link org.owasp.webgoat.service.ExceptionInfo} object.
- */
- @ExceptionHandler(Exception.class)
- @ResponseStatus(value = HttpStatus.I_AM_A_TEAPOT)
- public @ResponseBody
- ExceptionInfo handleException(HttpServletRequest request, Exception ex) {
- String url = request.getRequestURL().toString();
- logger.error("Exception handler for service caught exception when processing: " + url, ex);
- ExceptionInfo response = new ExceptionInfo();
- response.setUrl(url);
-
- response.setMessage(getStringStackTrace(ex));
-
- return response;
- }
-
- /**
- * getWebSession.
- *
- * @param session a {@link javax.servlet.http.HttpSession} object.
- * @return a {@link org.owasp.webgoat.session.WebSession} object.
- */
- public WebSession getWebSession(HttpSession session) {
- WebSession ws;
- Object o = session.getAttribute(WebSession.SESSION);
- if (o == null) {
- throw new IllegalArgumentException("No valid WebSession object found, has session timed out? [" + session.getId() + "]");
- }
- if (!(o instanceof WebSession)) {
- throw new IllegalArgumentException("Invalid WebSession object found, this is probably a bug! [" + o.getClass() + " | " + session.getId() + "]");
- }
- ws = (WebSession) o;
- return ws;
- }
-
- /**
- * getStringStackTrace.
- *
- * @param t a {@link java.lang.Throwable} object.
- * @return a {@link java.lang.String} object.
- */
- public String getStringStackTrace(Throwable t){
- StringWriter sw = new StringWriter();
- PrintWriter pw = new PrintWriter(sw);
- t.printStackTrace(pw);
- return sw.toString();
- }
-}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/service/CookieService.java b/webgoat-container/src/main/java/org/owasp/webgoat/service/CookieService.java
index 5edd61323..fd9f55ae0 100644
--- a/webgoat-container/src/main/java/org/owasp/webgoat/service/CookieService.java
+++ b/webgoat-container/src/main/java/org/owasp/webgoat/service/CookieService.java
@@ -29,16 +29,14 @@
*/
package org.owasp.webgoat.service;
-import java.util.Collections;
-import java.util.List;
-import javax.servlet.http.Cookie;
-import javax.servlet.http.HttpSession;
-import org.owasp.webgoat.lessons.model.RequestParameter;
-import org.owasp.webgoat.session.WebSession;
+import com.google.common.collect.Lists;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
-import org.springframework.web.servlet.ModelAndView;
+
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpSession;
+import java.util.List;
/**
* CookieService class.
@@ -47,7 +45,7 @@ import org.springframework.web.servlet.ModelAndView;
* @version $Id: $Id
*/
@Controller
-public class CookieService extends BaseService {
+public class CookieService {
/**
* Returns cookies for last attack
@@ -55,30 +53,11 @@ public class CookieService extends BaseService {
* @param session a {@link javax.servlet.http.HttpSession} object.
* @return a {@link java.util.List} object.
*/
- @RequestMapping(value = "/cookie.mvc", produces = "application/json")
+ @RequestMapping(path = "/service/cookie.mvc", produces = "application/json")
public @ResponseBody
- List showCookies(HttpSession session) {
- WebSession ws = getWebSession(session);
- List cookies = ws.getCookiesOnLastRequest();
+ List showCookies() {
+ //// TODO: 11/6/2016 to be decided
+ List cookies = Lists.newArrayList();
return cookies;
}
-
- /**
- * Returns cookies and params for current lesson
- *
- * @param session a {@link javax.servlet.http.HttpSession} object.
- * @return a {@link org.springframework.web.servlet.ModelAndView} object.
- */
- @RequestMapping(value = "/cookies_widget.mvc", produces = "text/html")
- public ModelAndView showCookiesAndParamsAsHtml(HttpSession session) {
- ModelAndView model = new ModelAndView();
- WebSession ws = getWebSession(session);
- List cookies = ws.getCookiesOnLastRequest();
- List listParms = ws.getParmsOnLastRequest();
- Collections.sort(listParms);
- model.addObject("wgcookies", cookies);
- model.addObject("wgparams", listParms);
- model.setViewName("widgets/cookies_and_params");
- return model;
- }
}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/service/HintService.java b/webgoat-container/src/main/java/org/owasp/webgoat/service/HintService.java
index 20cd36691..8ec3fa8df 100644
--- a/webgoat-container/src/main/java/org/owasp/webgoat/service/HintService.java
+++ b/webgoat-container/src/main/java/org/owasp/webgoat/service/HintService.java
@@ -5,17 +5,17 @@
*/
package org.owasp.webgoat.service;
-import java.util.ArrayList;
-import java.util.List;
-import javax.servlet.http.HttpSession;
import org.owasp.webgoat.lessons.AbstractLesson;
-import org.owasp.webgoat.lessons.Category;
import org.owasp.webgoat.lessons.model.Hint;
import org.owasp.webgoat.session.WebSession;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
-import org.springframework.web.servlet.ModelAndView;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static java.util.stream.Collectors.toList;
/**
* HintService class.
@@ -24,73 +24,43 @@ import org.springframework.web.servlet.ModelAndView;
* @version $Id: $Id
*/
@Controller
-public class HintService extends BaseService {
+public class HintService {
+
+ private final WebSession webSession;
+
+ public HintService(WebSession webSession) {
+ this.webSession = webSession;
+ }
/**
* Returns hints for current lesson
*
- * @param session a {@link javax.servlet.http.HttpSession} object.
* @return a {@link java.util.List} object.
*/
- @RequestMapping(value = "/hint.mvc", produces = "application/json")
- public @ResponseBody
- List showHint(HttpSession session) {
+ @RequestMapping(path = "/service/hint.mvc", produces = "application/json")
+ public
+ @ResponseBody
+ List showHint() {
List listHints = new ArrayList();
- WebSession ws = getWebSession(session);
- AbstractLesson l = ws.getCurrentLesson();
+ AbstractLesson l = webSession.getCurrentLesson();
if (l == null) {
return listHints;
}
- List hints = (l.getCategory().equals(Category.CHALLENGE)) ? null : l.getHintsPublic(ws);
+ List hints = l.getHints();
if (hints == null) {
return listHints;
}
int idx = 0;
- for (String h : hints) {
- Hint hint = new Hint();
- hint.setHint(h);
- hint.setLesson(l.getName());
- hint.setNumber(idx);
- listHints.add(hint);
- idx++;
- }
- return listHints;
+ return hints.stream().map(h -> createHint(h, l.getName(), idx)).collect(toList());
}
- /**
- * showHintsAsHtml.
- *
- * @param session a {@link javax.servlet.http.HttpSession} object.
- * @return a {@link org.springframework.web.servlet.ModelAndView} object.
- */
- @RequestMapping(value = "/hint_widget.mvc", produces = "text/html")
- public
- ModelAndView showHintsAsHtml(HttpSession session) {
- ModelAndView model = new ModelAndView();
- List listHints = new ArrayList();
- model.addObject("hints", listHints);
- WebSession ws = getWebSession(session);
- AbstractLesson l = ws.getCurrentLesson();
- if (l == null) {
- return model;
- }
- List hints;
- hints = l.getHintsPublic(ws);
- if (hints == null) {
- return model;
- }
- int idx = 0;
- for (String h : hints) {
- Hint hint = new Hint();
- hint.setHint(h);
- hint.setLesson(l.getName());
- hint.setNumber(idx);
- listHints.add(hint);
- idx++;
- }
- model.setViewName("widgets/hints");
- return model;
+ private Hint createHint(String hintText, String lesson, int idx) {
+ Hint hint = new Hint();
+ hint.setHint(hintText);
+ hint.setLesson(lesson);
+ hint.setNumber(idx);
+ return hint;
}
}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/service/LabelDebugService.java b/webgoat-container/src/main/java/org/owasp/webgoat/service/LabelDebugService.java
index 86fbd51cc..f9cafd327 100644
--- a/webgoat-container/src/main/java/org/owasp/webgoat/service/LabelDebugService.java
+++ b/webgoat-container/src/main/java/org/owasp/webgoat/service/LabelDebugService.java
@@ -29,9 +29,6 @@
*/
package org.owasp.webgoat.service;
-import java.util.HashMap;
-import java.util.Map;
-
import org.owasp.webgoat.session.LabelDebugger;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -44,6 +41,9 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
+import java.util.HashMap;
+import java.util.Map;
+
/**
* LabelDebugService class.
*
@@ -51,9 +51,9 @@ import org.springframework.web.bind.annotation.ResponseBody;
* @version $Id: $Id
*/
@Controller
-public class LabelDebugService extends BaseService {
+public class LabelDebugService {
- private static final String URL_DEBUG_LABELS_MVC = "/debug/labels.mvc";
+ private static final String URL_DEBUG_LABELS_MVC = "/service/debug/labels.mvc";
private static final String KEY_ENABLED = "enabled";
private static final String KEY_SUCCESS = "success";
@@ -68,12 +68,12 @@ public class LabelDebugService extends BaseService {
*
* @return a {@link org.springframework.http.ResponseEntity} object.
*/
- @RequestMapping(value = URL_DEBUG_LABELS_MVC, produces = MediaType.APPLICATION_JSON_VALUE)
+ @RequestMapping(path = URL_DEBUG_LABELS_MVC, produces = MediaType.APPLICATION_JSON_VALUE)
public @ResponseBody
ResponseEntity> checkDebuggingStatus() {
logger.debug("Checking label debugging, it is " + labelDebugger.isEnabled()); // FIXME parameterize
Map result = createResponse(labelDebugger.isEnabled());
- return new ResponseEntity>(result, HttpStatus.OK);
+ return new ResponseEntity<>(result, HttpStatus.OK);
}
/**
@@ -88,7 +88,7 @@ public class LabelDebugService extends BaseService {
logger.debug("Setting label debugging to " + labelDebugger.isEnabled()); // FIXME parameterize
Map result = createResponse(enabled);
labelDebugger.setEnabled(enabled);
- return new ResponseEntity>(result, HttpStatus.OK);
+ return new ResponseEntity<>(result, HttpStatus.OK);
}
/**
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/service/LessonInfoService.java b/webgoat-container/src/main/java/org/owasp/webgoat/service/LessonInfoService.java
index b334c4720..f249336b4 100644
--- a/webgoat-container/src/main/java/org/owasp/webgoat/service/LessonInfoService.java
+++ b/webgoat-container/src/main/java/org/owasp/webgoat/service/LessonInfoService.java
@@ -1,19 +1,10 @@
package org.owasp.webgoat.service;
-import org.owasp.webgoat.lessons.AbstractLesson;
import org.owasp.webgoat.lessons.model.LessonInfoModel;
-import org.owasp.webgoat.lessons.model.LessonMenuItem;
import org.owasp.webgoat.session.WebSession;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
-import org.springframework.web.bind.annotation.ResponseStatus;
-
-import javax.servlet.http.HttpSession;
@Controller
/**
@@ -22,45 +13,23 @@ import javax.servlet.http.HttpSession;
* @author dm
* @version $Id: $Id
*/
-public class LessonInfoService extends BaseService {
+public class LessonInfoService {
- private static final Logger logger = LoggerFactory.getLogger(LessonMenuService.class);
+ private final WebSession webSession;
+
+ public LessonInfoService(WebSession webSession) {
+ this.webSession = webSession;
+ }
/**
* getLessonInfo.
*
- * @param session a {@link javax.servlet.http.HttpSession} object.
* @return a {@link org.owasp.webgoat.lessons.model.LessonInfoModel} object.
*/
- @RequestMapping(value = "/lessoninfo.mvc", produces = "application/json")
+ @RequestMapping(path = "/service/lessoninfo.mvc", produces = "application/json")
public @ResponseBody
- LessonInfoModel getLessonInfo(HttpSession session) {
- WebSession webSession = getWebSession(session);
+ LessonInfoModel getLessonInfo() {
return new LessonInfoModel(webSession);
}
- /**
- * handleException.
- *
- * @param ex a {@link java.lang.Exception} object.
- * @return a {@link java.lang.String} object.
- */
- @ExceptionHandler(Exception.class)
- @ResponseBody
- @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
- public String handleException(Exception ex) {
- return "An error occurred retrieving the LessonInfoModel:" + ex.getMessage();
- }
-
- /**
- * getLessonInfoModel.
- *
- * @param webSession a {@link org.owasp.webgoat.session.WebSession} object.
- * @return a {@link org.owasp.webgoat.lessons.model.LessonInfoModel} object.
- */
- protected LessonInfoModel getLessonInfoModel(WebSession webSession) {
- return new LessonInfoModel(webSession);
- }
-
-
}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/service/LessonMenuService.java b/webgoat-container/src/main/java/org/owasp/webgoat/service/LessonMenuService.java
index 20f5d8cee..a8c3aca7f 100644
--- a/webgoat-container/src/main/java/org/owasp/webgoat/service/LessonMenuService.java
+++ b/webgoat-container/src/main/java/org/owasp/webgoat/service/LessonMenuService.java
@@ -1,50 +1,49 @@
/**
* *************************************************************************************************
- *
- *
+ *
+ *
* This file is part of WebGoat, an Open Web Application Security Project
* utility. For details, please see http://www.owasp.org/
- *
+ *
* Copyright (c) 2002 - 20014 Bruce Mayhew
- *
+ *
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option) any later
* version.
- *
+ *
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
- *
+ *
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place - Suite 330, Boston, MA 02111-1307, USA.
- *
+ *
* Getting Source ==============
- *
+ *
* Source for this application is maintained at
* https://github.com/WebGoat/WebGoat, a repository for free software projects.
- *
*/
package org.owasp.webgoat.service;
-import java.util.ArrayList;
-import java.util.List;
-import javax.servlet.http.HttpSession;
+import lombok.AllArgsConstructor;
import org.owasp.webgoat.lessons.AbstractLesson;
import org.owasp.webgoat.lessons.Category;
-import org.owasp.webgoat.lessons.RandomLessonAdapter;
import org.owasp.webgoat.lessons.model.LessonMenuItem;
import org.owasp.webgoat.lessons.model.LessonMenuItemType;
import org.owasp.webgoat.session.Course;
+import org.owasp.webgoat.session.LessonTracker;
+import org.owasp.webgoat.session.UserTracker;
import org.owasp.webgoat.session.WebSession;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
+import java.util.ArrayList;
+import java.util.List;
+
/**
*
LessonMenuService class.
*
@@ -52,23 +51,23 @@ import org.springframework.web.bind.annotation.ResponseBody;
* @version $Id: $Id
*/
@Controller
-public class LessonMenuService extends BaseService {
+@AllArgsConstructor
+public class LessonMenuService {
- private static final Logger logger = LoggerFactory.getLogger(LessonMenuService.class);
+ private final Course course;
+ private UserTracker userTracker;
+ private final WebSession webSession;
/**
* Returns the lesson menu which is used to build the left nav
*
- * @param session a {@link javax.servlet.http.HttpSession} object.
* @return a {@link java.util.List} object.
*/
- @RequestMapping(value = "/lessonmenu.mvc", produces = "application/json")
- public @ResponseBody
- List showLeftNav(HttpSession session) {
+ @RequestMapping(path = "/service/lessonmenu.mvc", produces = "application/json")
+ public
+ @ResponseBody
+ List showLeftNav() {
List menu = new ArrayList();
- WebSession ws = getWebSession(session);
- // Get the categories, these are the main menu items
- Course course = ws.getCourse();
List categories = course.getCategories();
for (Category category : categories) {
@@ -76,41 +75,15 @@ public class LessonMenuService extends BaseService {
categoryItem.setName(category.getName());
categoryItem.setType(LessonMenuItemType.CATEGORY);
// check for any lessons for this category
- List lessons = ws.getLessons(category);
- String role = ws.getRole();
- logger.info("Role: " + role);
+ List lessons = course.getLessons(category);
for (AbstractLesson lesson : lessons) {
LessonMenuItem lessonItem = new LessonMenuItem();
lessonItem.setName(lesson.getTitle());
lessonItem.setLink(lesson.getLink());
lessonItem.setType(LessonMenuItemType.LESSON);
- if (lesson.isCompleted(ws)) {
- lessonItem.setComplete(true);
- }
-
+ LessonTracker lessonTracker = userTracker.getLessonTracker(lesson);
+ lessonItem.setComplete(lessonTracker.isLessonSolved());
categoryItem.addChild(lessonItem);
- // Does the lesson have stages
- if (lesson instanceof RandomLessonAdapter) {
- RandomLessonAdapter rla = (RandomLessonAdapter) lesson;
- String[] stages = rla.getStages();
- if (stages != null) {
- String lessonLink = lesson.getLink();
- int stageIdx = 1;
- for (String stage : stages) {
- LessonMenuItem stageItem = new LessonMenuItem();
- stageItem.setName("Stage " + stageIdx + ": " + stage);
- // build the link for the stage
- String stageLink = lessonLink + "/" + stageIdx;
- stageItem.setLink(stageLink);
- stageItem.setType(LessonMenuItemType.STAGE);
- if (rla.isStageComplete(ws, stage)) {
- stageItem.setComplete(true);
- }
- lessonItem.addChild(stageItem);
- stageIdx++;
- }
- }
- }
}
menu.add(categoryItem);
}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/service/LessonPlanService.java b/webgoat-container/src/main/java/org/owasp/webgoat/service/LessonPlanService.java
index 6a35a45b5..c28a7bd83 100644
--- a/webgoat-container/src/main/java/org/owasp/webgoat/service/LessonPlanService.java
+++ b/webgoat-container/src/main/java/org/owasp/webgoat/service/LessonPlanService.java
@@ -29,15 +29,11 @@
*/
package org.owasp.webgoat.service;
-import org.owasp.webgoat.lessons.AbstractLesson;
-import org.owasp.webgoat.session.Course;
import org.owasp.webgoat.session.WebSession;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
-import javax.servlet.http.HttpSession;
-
/**
* LessonPlanService class.
*
@@ -45,42 +41,33 @@ import javax.servlet.http.HttpSession;
* @version $Id: $Id
*/
@Controller
-public class LessonPlanService extends BaseService {
+//TODO remove
+public class LessonPlanService {
+
+ private final WebSession webSession;
+
+ public LessonPlanService(WebSession webSession) {
+ this.webSession = webSession;
+ }
/**
* Returns source for current attack
*
- * @param session a {@link javax.servlet.http.HttpSession} object.
* @return a {@link java.lang.String} object.
*/
- @RequestMapping(value = "/lessonplan.mvc", produces = "application/html")
+ @RequestMapping(path = "/service/lessonplan.mvc", produces = "application/html")
public @ResponseBody
- String showPlan(HttpSession session) {
- WebSession ws = getWebSession(session);
- String plan = getPlan(ws);
+ String showPlan() {
+ String plan = getPlan();
return plan;
}
/**
* Description of the Method
*
- * @param s Description of the Parameter
* @return Description of the Return Value
*/
- protected String getPlan(WebSession s) {
- String plan = null;
- int scr = s.getCurrentScreen();
- Course course = s.getCourse();
-
- if (s.isUser() || s.isAdmin()) {
- AbstractLesson lesson = course.getLesson(s, scr, AbstractLesson.USER_ROLE);
- if (lesson != null) {
- plan = lesson.getLessonPlan(s);
- }
- }
- if (plan == null) {
- plan = "Plan is not available for this lesson.";
- }
- return plan;
+ protected String getPlan() {
+ return "Plan is not available for this lesson.";
}
}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/service/LessonProgressService.java b/webgoat-container/src/main/java/org/owasp/webgoat/service/LessonProgressService.java
index 23701894d..aeb4375f2 100644
--- a/webgoat-container/src/main/java/org/owasp/webgoat/service/LessonProgressService.java
+++ b/webgoat-container/src/main/java/org/owasp/webgoat/service/LessonProgressService.java
@@ -1,52 +1,48 @@
package org.owasp.webgoat.service;
import com.google.common.collect.Maps;
-import org.owasp.webgoat.lessons.AbstractLesson;
-import org.owasp.webgoat.lessons.RandomLessonAdapter;
+import lombok.AllArgsConstructor;
+import org.owasp.webgoat.i18n.LabelManager;
import org.owasp.webgoat.lessons.model.LessonInfoModel;
+import org.owasp.webgoat.session.LessonTracker;
+import org.owasp.webgoat.session.UserTracker;
import org.owasp.webgoat.session.WebSession;
-import org.owasp.webgoat.util.LabelManager;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
-import javax.servlet.http.HttpSession;
import java.util.Map;
-@Controller
+
/**
* LessonProgressService class.
*
* @author webgoat
*/
-public class LessonProgressService extends BaseService {
+@Controller
+@AllArgsConstructor
+public class LessonProgressService {
- private static final Logger logger = LoggerFactory.getLogger(LessonMenuService.class);
private LabelManager labelManager;
-
- @Autowired
- public LessonProgressService(final LabelManager labelManager) {
- this.labelManager = labelManager;
- }
+ private UserTracker userTracker;
+ private WebSession webSession;
/**
* LessonProgressService.
*
- * @param session a {@link HttpSession} object.
* @return a {@link LessonInfoModel} object.
*/
- @RequestMapping(value = "/lessonprogress.mvc", produces = "application/json")
+ @RequestMapping(value = "/service/lessonprogress.mvc", produces = "application/json")
@ResponseBody
- public Map getLessonInfo(HttpSession session) {
- WebSession webSession = getWebSession(session);
- AbstractLesson lesson = webSession.getCurrentLesson();
- boolean lessonCompleted = lesson.isCompleted(webSession);
- String successMessage = lesson instanceof RandomLessonAdapter ? "Congratulations, you have completed this lab" : labelManager
- .get("LessonCompleted");
+ public Map getLessonInfo() {
+ LessonTracker lessonTracker = userTracker.getLessonTracker(webSession.getCurrentLesson());
Map json = Maps.newHashMap();
+ String successMessage = "";
+ boolean lessonCompleted = false;
+ if (lessonTracker != null) {
+ lessonCompleted = lessonTracker.isLessonSolved();
+ successMessage = labelManager.get("LessonCompleted");
+ }
json.put("lessonCompleted", lessonCompleted);
json.put("successMessage", successMessage);
return json;
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/service/LessonTitleService.java b/webgoat-container/src/main/java/org/owasp/webgoat/service/LessonTitleService.java
index 3c58a0efc..c3d7a82b5 100644
--- a/webgoat-container/src/main/java/org/owasp/webgoat/service/LessonTitleService.java
+++ b/webgoat-container/src/main/java/org/owasp/webgoat/service/LessonTitleService.java
@@ -1,46 +1,38 @@
package org.owasp.webgoat.service;
-import javax.servlet.http.HttpSession;
-
import org.owasp.webgoat.lessons.AbstractLesson;
-import org.owasp.webgoat.session.Course;
import org.owasp.webgoat.session.WebSession;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
-@Controller
+
/**
* LessonTitleService class.
*
- * @version $Id: $Id
* @author dm
+ * @version $Id: $Id
*/
-public class LessonTitleService extends BaseService {
-
+@Controller
+public class LessonTitleService {
+
+ private final WebSession webSession;
+
+ public LessonTitleService(final WebSession webSession) {
+ this.webSession = webSession;
+ }
+
/**
* Returns the title for the current attack
*
- * @param session a {@link javax.servlet.http.HttpSession} object.
* @return a {@link java.lang.String} object.
*/
- @RequestMapping(value = "/lessontitle.mvc", produces = "application/html")
- public @ResponseBody
- String showPlan(HttpSession session) {
- WebSession ws = getWebSession(session);
- return getLessonTitle(ws);
- }
-
- private String getLessonTitle(WebSession s) {
- String title = "";
- int scr = s.getCurrentScreen();
- Course course = s.getCourse();
-
- if (s.isUser() || s.isChallenge()) {
- AbstractLesson lesson = course.getLesson(s, scr, AbstractLesson.USER_ROLE);
- title = lesson != null ? lesson.getTitle() : "";
- }
- return title;
+ @RequestMapping(path = "/service/lessontitle.mvc", produces = "application/html")
+ public
+ @ResponseBody
+ String showPlan() {
+ AbstractLesson lesson = webSession.getCurrentLesson();
+ return lesson != null ? lesson.getTitle() : "";
}
}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/service/ParameterService.java b/webgoat-container/src/main/java/org/owasp/webgoat/service/ParameterService.java
index e7ebc9c39..f4bce560a 100644
--- a/webgoat-container/src/main/java/org/owasp/webgoat/service/ParameterService.java
+++ b/webgoat-container/src/main/java/org/owasp/webgoat/service/ParameterService.java
@@ -29,18 +29,16 @@
*/
package org.owasp.webgoat.service;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import javax.servlet.http.HttpSession;
+import com.google.common.collect.Lists;
import org.owasp.webgoat.lessons.model.RequestParameter;
-import org.owasp.webgoat.session.WebSession;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
+import javax.servlet.http.HttpSession;
+import java.util.Collections;
+import java.util.List;
+
/**
* ParameterService class.
*
@@ -48,9 +46,7 @@ import org.springframework.web.bind.annotation.ResponseBody;
* @version $Id: $Id
*/
@Controller
-public class ParameterService extends BaseService {
-
- final Logger logger = LoggerFactory.getLogger(ParameterService.class);
+public class ParameterService {
/**
* Returns request parameters for last attack
@@ -58,11 +54,11 @@ public class ParameterService extends BaseService {
* @param session a {@link javax.servlet.http.HttpSession} object.
* @return a {@link java.util.List} object.
*/
- @RequestMapping(value = "/parameter.mvc", produces = "application/json")
+ @RequestMapping(path = "/service/parameter.mvc", produces = "application/json")
public @ResponseBody
List showParameters(HttpSession session) {
- WebSession ws = getWebSession(session);
- List listParms = ws.getParmsOnLastRequest();
+ //// TODO: 11/6/2016 to decide not sure about the role in WebGoat 8
+ List listParms = Lists.newArrayList();
Collections.sort(listParms);
return listParms;
}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/service/PluginReloadService.java b/webgoat-container/src/main/java/org/owasp/webgoat/service/PluginReloadService.java
index 6355318aa..e9e494523 100644
--- a/webgoat-container/src/main/java/org/owasp/webgoat/service/PluginReloadService.java
+++ b/webgoat-container/src/main/java/org/owasp/webgoat/service/PluginReloadService.java
@@ -29,16 +29,6 @@
*/
package org.owasp.webgoat.service;
-import java.nio.file.Paths;
-import java.util.HashMap;
-import java.util.Map;
-
-import javax.servlet.http.HttpSession;
-
-import org.owasp.webgoat.plugins.PluginsLoader;
-import org.owasp.webgoat.session.WebSession;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
@@ -46,6 +36,10 @@ import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
+import javax.servlet.http.HttpSession;
+import java.util.HashMap;
+import java.util.Map;
+
/**
* PluginReloadService class.
*
@@ -53,9 +47,7 @@ import org.springframework.web.bind.annotation.ResponseBody;
* @version $Id: $Id
*/
@Controller
-public class PluginReloadService extends BaseService {
-
- private static final Logger logger = LoggerFactory.getLogger(PluginReloadService.class);
+public class PluginReloadService {
/**
* Reload all the plugins
@@ -63,20 +55,21 @@ public class PluginReloadService extends BaseService {
* @param session a {@link javax.servlet.http.HttpSession} object.
* @return a {@link org.springframework.http.ResponseEntity} object.
*/
- @RequestMapping(value = "/reloadplugins.mvc", produces = MediaType.APPLICATION_JSON_VALUE)
+ @RequestMapping(path = "/service/reloadplugins.mvc", produces = MediaType.APPLICATION_JSON_VALUE)
public @ResponseBody
ResponseEntity> reloadPlugins(HttpSession session) {
- WebSession webSession = (WebSession) session.getAttribute(WebSession.SESSION);
-
- logger.debug("Loading plugins into cache");
- String pluginPath = session.getServletContext().getRealPath("plugin_lessons");
- String targetPath = session.getServletContext().getRealPath("plugin_extracted");
- new PluginsLoader(Paths.get(pluginPath), Paths.get(targetPath)).copyJars();
- webSession.getCourse().loadLessonFromPlugin(session.getServletContext());
+// WebSession webSession = (WebSession) session.getAttribute(WebSession.SESSION);
+//
+// logger.debug("Loading plugins into cache");
+// String pluginPath = session.getServletContext().getRealPath("plugin_lessons");
+// String targetPath = session.getServletContext().getRealPath("plugin_extracted");
+// //TODO fix me
+// //new PluginsLoader(Paths.get(pluginPath), Paths.get(targetPath)).copyJars();
+// //webSession.getCourse().createLessonsFromPlugins();
Map result = new HashMap();
result.put("success", true);
result.put("message", "Plugins reloaded");
- return new ResponseEntity>(result, HttpStatus.OK);
+ return new ResponseEntity<>(result, HttpStatus.OK);
}
}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/service/RestartLessonService.java b/webgoat-container/src/main/java/org/owasp/webgoat/service/RestartLessonService.java
index 909433e54..34650cc1c 100644
--- a/webgoat-container/src/main/java/org/owasp/webgoat/service/RestartLessonService.java
+++ b/webgoat-container/src/main/java/org/owasp/webgoat/service/RestartLessonService.java
@@ -1,39 +1,38 @@
/***************************************************************************************************
- *
- *
* This file is part of WebGoat, an Open Web Application Security Project utility. For details,
* please see http://www.owasp.org/
- *
+ *
* Copyright (c) 2002 - 20014 Bruce Mayhew
- *
+ *
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
- *
+ *
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
- *
+ *
* Getting Source ==============
- *
+ *
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
* projects.
- *
*/
package org.owasp.webgoat.service;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.owasp.webgoat.lessons.AbstractLesson;
+import org.owasp.webgoat.session.UserTracker;
import org.owasp.webgoat.session.WebSession;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseStatus;
-import javax.servlet.http.HttpSession;
-
/**
*
RestartLessonService class.
*
@@ -41,20 +40,24 @@ import javax.servlet.http.HttpSession;
* @version $Id: $Id
*/
@Controller
-public class RestartLessonService extends BaseService {
+@AllArgsConstructor
+@Slf4j
+public class RestartLessonService {
+
+ private final WebSession webSession;
+ private final UserTracker userTracker;
/**
* Returns current lesson
*
- * @param session a {@link javax.servlet.http.HttpSession} object.
+ * @return a {@link java.lang.String} object.
*/
- @RequestMapping(value = "/restartlesson.mvc")
+ @RequestMapping(path = "/service/restartlesson.mvc", produces = "text/text")
@ResponseStatus(value = HttpStatus.OK)
- public void restartLesson(HttpSession session) {
- WebSession ws = getWebSession(session);
- int currentScreen = ws.getCurrentScreen();
- if(currentScreen > 0){
- ws.restartLesson(currentScreen);
- }
+ public void restartLesson() {
+ AbstractLesson al = webSession.getCurrentLesson();
+ log.debug("Restarting lesson: " + al);
+
+ userTracker.reset(al);
}
}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/service/SessionService.java b/webgoat-container/src/main/java/org/owasp/webgoat/service/SessionService.java
index caec4f34d..715f4e88f 100644
--- a/webgoat-container/src/main/java/org/owasp/webgoat/service/SessionService.java
+++ b/webgoat-container/src/main/java/org/owasp/webgoat/service/SessionService.java
@@ -5,16 +5,17 @@
*/
package org.owasp.webgoat.service;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
import java.util.List;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpSession;
-import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.ResponseBody;
/**
* SessionService class.
@@ -23,7 +24,7 @@ import org.springframework.web.bind.annotation.ResponseBody;
* @version $Id: $Id
*/
@Controller
-public class SessionService extends BaseService {
+public class SessionService {
/**
* Returns hints for current lesson
@@ -32,7 +33,7 @@ public class SessionService extends BaseService {
* @param request a {@link javax.servlet.http.HttpServletRequest} object.
* @return a {@link java.lang.String} object.
*/
- @RequestMapping(value = "/session.mvc", produces = "application/json")
+ @RequestMapping(path = "/service/session.mvc", produces = "application/json")
public @ResponseBody
String showSession(HttpServletRequest request, HttpSession session) {
StringBuilder sb = new StringBuilder();
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/service/SolutionService.java b/webgoat-container/src/main/java/org/owasp/webgoat/service/SolutionService.java
index b91d153b4..2314ac6d5 100644
--- a/webgoat-container/src/main/java/org/owasp/webgoat/service/SolutionService.java
+++ b/webgoat-container/src/main/java/org/owasp/webgoat/service/SolutionService.java
@@ -1,43 +1,37 @@
/**
* *************************************************************************************************
- *
- *
+ *
+ *
* This file is part of WebGoat, an Open Web Application Security Project
* utility. For details, please see http://www.owasp.org/
- *
+ *
* Copyright (c) 2002 - 20014 Bruce Mayhew
- *
+ *
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option) any later
* version.
- *
+ *
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
- *
+ *
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place - Suite 330, Boston, MA 02111-1307, USA.
- *
+ *
* Getting Source ==============
- *
+ *
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository
* for free software projects.
- *
*/
package org.owasp.webgoat.service;
-import org.owasp.webgoat.lessons.AbstractLesson;
-import org.owasp.webgoat.session.Course;
-import org.owasp.webgoat.session.WebSession;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
-import javax.servlet.http.HttpSession;
-
/**
*
SolutionService class.
*
@@ -45,42 +39,28 @@ import javax.servlet.http.HttpSession;
* @version $Id: $Id
*/
@Controller
-public class SolutionService extends BaseService {
+public class SolutionService {
/**
* Returns solution for current attack
*
- * @param session a {@link javax.servlet.http.HttpSession} object.
* @return a {@link java.lang.String} object.
*/
- @RequestMapping(value = "/solution.mvc", produces = "text/html")
- public @ResponseBody
- String showSolution(HttpSession session) {
- WebSession ws = getWebSession(session);
- String source = getSolution(ws);
+ @RequestMapping(path = "/service/solution.mvc", produces = "text/html")
+ public
+ @ResponseBody
+ String showSolution() {
+ //// TODO: 11/6/2016 to decide not sure about the role in WebGoat 8
+ String source = getSolution();
return source;
}
/**
* getSolution.
*
- * @param s a {@link org.owasp.webgoat.session.WebSession} object.
* @return a {@link java.lang.String} object.
*/
- protected String getSolution(WebSession s) {
- String source = null;
- int scr = s.getCurrentScreen();
- Course course = s.getCourse();
-
- if (s.isUser() || s.isAdmin()) {
- AbstractLesson lesson = course.getLesson(s, scr, AbstractLesson.USER_ROLE);
- if (lesson != null) {
- source = lesson.getSolution(s);
- }
- }
- if (source == null) {
- return "Solution is not available. Contact " + s.getWebgoatContext().getFeedbackAddressHTML();
- }
- return source;
+ protected String getSolution() {
+ return "Solution is not available";
}
}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/service/SourceService.java b/webgoat-container/src/main/java/org/owasp/webgoat/service/SourceService.java
index 059eeb470..15267f29d 100644
--- a/webgoat-container/src/main/java/org/owasp/webgoat/service/SourceService.java
+++ b/webgoat-container/src/main/java/org/owasp/webgoat/service/SourceService.java
@@ -1,47 +1,40 @@
/**
* *************************************************************************************************
- *
- *
+ *
+ *
* This file is part of WebGoat, an Open Web Application Security Project
* utility. For details, please see http://www.owasp.org/
- *
+ *
* Copyright (c) 2002 - 20014 Bruce Mayhew
- *
+ *
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option) any later
* version.
- *
+ *
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
- *
+ *
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place - Suite 330, Boston, MA 02111-1307, USA.
- *
+ *
* Getting Source ==============
- *
+ *
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository
* for free software projects.
- *
*/
package org.owasp.webgoat.service;
import org.apache.commons.lang3.StringEscapeUtils;
-import org.owasp.webgoat.lessons.AbstractLesson;
-import org.owasp.webgoat.session.Course;
-import org.owasp.webgoat.session.WebSession;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpSession;
-import static org.owasp.webgoat.LessonSource.END_SOURCE_SKIP;
-import static org.owasp.webgoat.LessonSource.START_SOURCE_SKIP;
-
/**
*
SourceService class.
*
@@ -49,7 +42,16 @@ import static org.owasp.webgoat.LessonSource.START_SOURCE_SKIP;
* @version $Id: $Id
*/
@Controller
-public class SourceService extends BaseService {
+//TODO REMOVE!
+public class SourceService {
+
+ /**
+ * Description of the Field
+ */
+ public final static String START_SOURCE_SKIP = "START_OMIT_SOURCE";
+
+ /** Constant END_SOURCE_SKIP="END_OMIT_SOURCE"
*/
+ public final static String END_SOURCE_SKIP = "END_OMIT_SOURCE";
/**
* Returns source for current attack
@@ -57,11 +59,12 @@ public class SourceService extends BaseService {
* @param session a {@link javax.servlet.http.HttpSession} object.
* @return a {@link java.lang.String} object.
*/
- @RequestMapping(value = "/source.mvc", produces = "application/text")
- public @ResponseBody
+ @RequestMapping(path = "/service/source.mvc", produces = "application/text")
+ public
+ @ResponseBody
String showSource(HttpSession session) {
- WebSession ws = getWebSession(session);
- String source = getSource(ws);
+ //// TODO: 11/6/2016 to decide not sure about the role in WebGoat 8
+ String source = getSource();
if (source == null) {
source = "No source listing found";
}
@@ -71,24 +74,9 @@ public class SourceService extends BaseService {
/**
* Description of the Method
*
- * @param s Description of the Parameter
* @return Description of the Return Value
*/
- protected String getSource(WebSession s) {
- String source = null;
- int scr = s.getCurrentScreen();
- Course course = s.getCourse();
-
- if (s.isUser() || s.isAdmin()) {
- AbstractLesson lesson = course.getLesson(s, scr, AbstractLesson.USER_ROLE);
- if (lesson != null) {
- source = lesson.getRawSource(s);
- }
- }
- if (source == null) {
- return "Source code is not available for this lesson.";
- }
- return source.replaceAll("(?s)" + START_SOURCE_SKIP + ".*" + END_SOURCE_SKIP,
- "Code Section Deliberately Omitted");
+ protected String getSource() {
+ return "Source code is not available for this lesson.";
}
}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/session/Authorization.java b/webgoat-container/src/main/java/org/owasp/webgoat/session/Authorization.java
deleted file mode 100644
index 36c8c3a67..000000000
--- a/webgoat-container/src/main/java/org/owasp/webgoat/session/Authorization.java
+++ /dev/null
@@ -1,73 +0,0 @@
-
-package org.owasp.webgoat.session;
-
-import java.util.Hashtable;
-import java.util.Map;
-
-
-/**
- *************************************************************************************************
- *
- *
- * This file is part of WebGoat, an Open Web Application Security Project utility. For details,
- * please see http://www.owasp.org/
- *
- * Copyright (c) 2002 - 20014 Bruce Mayhew
- *
- * This program is free software; you can redistribute it and/or modify it under the terms of the
- * GNU General Public License as published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
- * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with this program; if
- * not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- *
- * Getting Source ==============
- *
- * Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
- * projects.
- *
- * * @version $Id: $Id
- *
- * @author dm
- * @version $Id: $Id
- */
-public class Authorization
-{
-
- Map permissions = new Hashtable();
-
- /**
- * Constructor for Authorization.
- */
- public Authorization()
- {
- }
-
- /**
- * setPermission.
- *
- * @param userId a int.
- * @param functionId a int.
- */
- public void setPermission(int userId, int functionId)
- {
- permissions.put(new Integer(userId), new Integer(functionId));
- }
-
- /**
- * isAllowed.
- *
- * @param userId a int.
- * @param functionId a int.
- * @return a boolean.
- */
- public boolean isAllowed(int userId, int functionId)
- {
- return (permissions.get(new Integer(userId)) != null);
- }
-}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/session/Course.java b/webgoat-container/src/main/java/org/owasp/webgoat/session/Course.java
index 2e27378d0..d2272bfe0 100644
--- a/webgoat-container/src/main/java/org/owasp/webgoat/session/Course.java
+++ b/webgoat-container/src/main/java/org/owasp/webgoat/session/Course.java
@@ -1,175 +1,58 @@
package org.owasp.webgoat.session;
-import org.owasp.webgoat.HammerHead;
+import lombok.extern.slf4j.Slf4j;
import org.owasp.webgoat.lessons.AbstractLesson;
import org.owasp.webgoat.lessons.Category;
+import org.owasp.webgoat.lessons.NewLesson;
import org.owasp.webgoat.plugins.Plugin;
-import org.owasp.webgoat.plugins.PluginsLoader;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import javax.servlet.ServletContext;
-import java.io.File;
-import java.io.IOException;
-import java.nio.file.Paths;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
-import java.util.Map;
-import javax.servlet.ServletContext;
-import org.owasp.webgoat.HammerHead;
-import org.owasp.webgoat.lessons.AbstractLesson;
-import org.owasp.webgoat.lessons.Category;
-import org.owasp.webgoat.plugins.LegacyLoader;
-import org.owasp.webgoat.plugins.Plugin;
-import org.owasp.webgoat.plugins.PluginsLoader;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import static java.util.stream.Collectors.toList;
/**
- *************************************************************************************************
- *
- *
+ * ************************************************************************************************
+ *
+ *
* This file is part of WebGoat, an Open Web Application Security Project utility. For details,
* please see http://www.owasp.org/
- *
+ *
* Copyright (c) 2002 - 20014 Bruce Mayhew
- *
+ *
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
- *
+ *
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
- *
+ *
* Getting Source ==============
- *
+ *
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
* projects.
*
* @author Bruce Mayhew WebGoat
- * @since October 28, 2003
* @version $Id: $Id
+ * @since October 28, 2003
*/
+@Slf4j
public class Course {
- final Logger logger = LoggerFactory.getLogger(Course.class);
-
- private final List lessons = new LinkedList();
-
- private final static String PROPERTIES_FILENAME = HammerHead.propertiesPath;
-
- private WebgoatProperties properties = null;
-
- private WebgoatContext webgoatContext;
-
- /**
- * Constructor for Course.
- */
- public Course() {
- try {
- properties = new WebgoatProperties(PROPERTIES_FILENAME);
- } catch (IOException e) {
- logger.error("Error loading webgoat properties", e);
- }
- }
-
- /**
- * Take an absolute file and return the filename.
- *
- * Ex. /etc/password becomes password
- *
- * @param s
- * @return the file name
- */
- private static String getFileName(String s) {
- String fileName = new File(s).getName();
-
- if (fileName.contains("/")) {
- fileName = fileName.substring(fileName.lastIndexOf("/"), fileName.length());
- }
-
- if (fileName.contains(".")) {
- fileName = fileName.substring(0, fileName.indexOf("."));
- }
-
- return fileName;
- }
-
- /**
- * Take a class name and return the equivalent file name
- *
- * Ex. org.owasp.webgoat becomes org/owasp/webgoat.java
- *
- * @param className
- * @return
- */
- private static String getSourceFile(String className) {
- StringBuilder sb = new StringBuilder();
-
- sb.append(className.replace(".", "/"));
- sb.append(".java");
-
- return sb.toString();
- }
-
- /**
- * Takes a file name and builds the class file name
- *
- * @param fileName Description of the Parameter
- * @param path Description of the Parameter
- * @return Description of the Return Value
- */
- private static String getClassFile(String fileName, String path) {
- String ext = ".class";
- fileName = fileName.trim();
-
- /**
- * We do not handle directories. We do not handle files with different
- * extensions
- */
- if (fileName.endsWith("/") || !fileName.endsWith(ext)) {
- return null;
- }
-
- // if the file is in /WEB-INF/classes strip the dir info off
- int index = fileName.indexOf("/WEB-INF/classes/");
- if (index != -1) {
- fileName = fileName.substring(index + "/WEB-INF/classes/".length(), fileName.length() - ext.length());
- fileName = fileName.replace('/', '.');
- fileName = fileName.replace('\\', '.');
- } else {
- // Strip off the leading path info
- fileName = fileName.substring(path.length(), fileName.length() - ext.length());
- }
-
- return fileName;
- }
+ private List lessons = new LinkedList<>();
/**
* Gets the categories attribute of the Course object
*
* @return The categories value
*/
- public List getCategories() {
- List categories = new ArrayList();
- for (AbstractLesson lesson : lessons) {
- if (!categories.contains(lesson.getCategory())) {
- categories.add(lesson.getCategory());
- }
- }
-
- Collections.sort(categories);
-
- return categories;
+ public List getCategories() {
+ return lessons.parallelStream().map(l -> l.getCategory()).distinct().sorted().collect(toList());
}
/**
@@ -178,202 +61,46 @@ public class Course {
* @return The firstLesson value
*/
public AbstractLesson getFirstLesson() {
- List roles = new ArrayList();
- roles.add(AbstractLesson.USER_ROLE);
// Category 0 is the admin function. We want the first real category
// to be returned. This is normally the General category and the Http Basics lesson
- return ((AbstractLesson) getLessons((Category) getCategories().get(0), roles).get(0));
- }
-
- /**
- * Gets the lesson attribute of the Course object
- *
- * @param s a {@link org.owasp.webgoat.session.WebSession} object.
- * @param lessonId Description of the Parameter
- * @param roles a {@link java.util.List} object.
- * @return The lesson value
- */
- public AbstractLesson getLesson(WebSession s, int lessonId, List roles) {
- if (s.isHackedAdmin()) {
- roles.add(AbstractLesson.HACKED_ADMIN_ROLE);
- }
- // System.out.println("getLesson() with roles: " + roles);
- Iterator iter = lessons.iterator();
-
- while (iter.hasNext()) {
- AbstractLesson lesson = iter.next();
-
- if (lesson.getScreenId() == lessonId && roles.contains(lesson.getRole())) {
- return lesson;
- }
- }
-
- return null;
- }
-
- /**
- * getLesson.
- *
- * @param s a {@link org.owasp.webgoat.session.WebSession} object.
- * @param lessonId a int.
- * @param role a {@link java.lang.String} object.
- * @return a {@link org.owasp.webgoat.lessons.AbstractLesson} object.
- */
- public AbstractLesson getLesson(WebSession s, int lessonId, String role) {
- List roles = new ArrayList();
- roles.add(role);
- return getLesson(s, lessonId, roles);
+ return getLessons(getCategories().get(0)).get(0);
}
/**
* Getter for the field lessons
.
*
- * @param s a {@link org.owasp.webgoat.session.WebSession} object.
- * @param role a {@link java.lang.String} object.
* @return a {@link java.util.List} object.
*/
- public List getLessons(WebSession s, String role) {
- List roles = new ArrayList();
- roles.add(role);
- return getLessons(s, roles);
- }
-
- /**
- * Gets the lessons attribute of the Course object
- *
- * @param s a {@link org.owasp.webgoat.session.WebSession} object.
- * @param roles a {@link java.util.List} object.
- * @return The lessons value
- */
- public List getLessons(WebSession s, List roles) {
- if (s.isHackedAdmin()) {
- roles.add(AbstractLesson.HACKED_ADMIN_ROLE);
- }
- List lessonList = new ArrayList();
- Iterator categoryIter = getCategories().iterator();
-
- while (categoryIter.hasNext()) {
- lessonList.addAll(getLessons(s, (Category) categoryIter.next(), roles));
- }
- return lessonList;
- }
-
- /**
- * Gets the lessons attribute of the Course object
- *
- * @param category Description of the Parameter
- * @param role Description of the Parameter
- * @return The lessons value
- */
- private List getLessons(Category category, List roles) {
- List lessonList = new ArrayList();
-
- for (AbstractLesson lesson : lessons) {
- if (lesson.getCategory().equals(category) && roles.contains(lesson.getRole())) {
- lessonList.add(lesson);
- }
- }
-
- Collections.sort(lessonList);
- return lessonList;
+ public List getLessons() {
+ return this.lessons;
}
/**
* Getter for the field lessons
.
*
- * @param s a {@link org.owasp.webgoat.session.WebSession} object.
* @param category a {@link org.owasp.webgoat.lessons.Category} object.
- * @param role a {@link java.lang.String} object.
* @return a {@link java.util.List} object.
*/
- public List getLessons(WebSession s, Category category, String role) {
- List roles = new ArrayList();
- roles.add(role);
- return getLessons(s, category, roles);
+ public List getLessons(Category category) {
+ return this.lessons.stream().filter(l -> l.getCategory() == category).collect(toList());
+ }
+
+ public void setLessons(List lessons) {
+ this.lessons = lessons;
}
/**
- * Getter for the field lessons
.
- *
- * @param s a {@link org.owasp.webgoat.session.WebSession} object.
- * @param category a {@link org.owasp.webgoat.lessons.Category} object.
- * @param roles a {@link java.util.List} object.
- * @return a {@link java.util.List} object.
+ * createLessonsFromPlugins.
*/
- public List getLessons(WebSession s, Category category, List roles) {
- if (s.isHackedAdmin()) {
- roles.add(AbstractLesson.HACKED_ADMIN_ROLE);
- }
- return getLessons(category, roles);
- }
-
- /**
- * getLesson.
- *
- * @param lessonId a int.
- * @return a {@link org.owasp.webgoat.lessons.AbstractLesson} object.
- */
- public AbstractLesson getLesson(int lessonId) {
- for (AbstractLesson l : lessons) {
- if (l.getScreenId() == lessonId) {
- return l;
- }
- }
- return null;
- }
-
- /**
- * loadLessonFromPlugin.
- *
- * @param context a {@link javax.servlet.ServletContext} object.
- */
- public void loadLessonFromPlugin(ServletContext context) {
- logger.debug("Loading plugins into cache");
- String pluginPath = context.getRealPath("plugin_lessons");
- String targetPath = context.getRealPath("plugin_extracted");
-
- if (pluginPath == null) {
- logger.error("Plugins directory {} not found", pluginPath);
- return;
- }
- lessons.clear();
- List plugins = new PluginsLoader(Paths.get(pluginPath), Paths.get(targetPath)).loadPlugins();
+ public void createLessonsFromPlugins(List plugins) {
for (Plugin plugin : plugins) {
try {
- AbstractLesson lesson = plugin.getLesson().get();
- lesson.setWebgoatContext(webgoatContext);
- lesson.update(properties);
-
- if (!lesson.getHidden()) {
- lessons.add(lesson);
- }
- for(Map.Entry lessonPlan : plugin.getLessonPlans().entrySet()) {
- lesson.setLessonPlanFileName(lessonPlan.getKey(), lessonPlan.getValue().toString());
- }
- if (plugin.getLessonSolution("en").isPresent()) {
- lesson.setLessonSolutionFileName(plugin.getLessonSolution("en").get().toString());
- }
- if (plugin.getLessonSource().isPresent()) {
- lesson.setSourceFileName(plugin.getLessonSource().get().toString());
- }
+ NewLesson lesson = (NewLesson) plugin.getLesson().get();
+ lesson.setAssignments(plugin.getAssignments());
+ lessons.add(lesson);
} catch (Exception e) {
- logger.error("Error in loadLessons: ", e);
+ log.error("Error in loadLessons: ", e);
}
}
}
-
- /**
- * Description of the Method
- *
- * @param webgoatContext a {@link org.owasp.webgoat.session.WebgoatContext} object.
- * @param path Description of the Parameter
- * @param context Description of the Parameter
- */
- public void loadCourses(WebgoatContext webgoatContext, ServletContext context, String path) {
- logger.info("Loading courses: " + path);
- this.webgoatContext = webgoatContext;
- loadLessonFromPlugin(context);
- LegacyLoader loader = new LegacyLoader();
- lessons.addAll(loader.loadLessons(webgoatContext, context, path, properties));
- }
}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/session/CreateDB.java b/webgoat-container/src/main/java/org/owasp/webgoat/session/CreateDB.java
index 2afc1296f..4031e0c82 100644
--- a/webgoat-container/src/main/java/org/owasp/webgoat/session/CreateDB.java
+++ b/webgoat-container/src/main/java/org/owasp/webgoat/session/CreateDB.java
@@ -4,7 +4,6 @@ package org.owasp.webgoat.session;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
-import org.owasp.webgoat.lessons.AbstractLesson;
/**
@@ -759,16 +758,16 @@ public class CreateDB
String insertData25_1 = "INSERT INTO auth VALUES('admin', 'SearchStaff')";
String insertData25_2 = "INSERT INTO auth VALUES('admin', 'FindProfile')";
- // Add a permission for the webgoat role to see the source.
- // The challenge(s) will change the default role to "challenge"
- String insertData26 = "INSERT INTO auth VALUES('" + AbstractLesson.USER_ROLE + "','" + WebSession.SHOWSOURCE
- + "')";
- String insertData27 = "INSERT INTO auth VALUES('" + AbstractLesson.USER_ROLE + "','" + WebSession.SHOWHINTS
- + "')";
+// // Add a permission for the webgoat role to see the source.
+// // The challenge(s) will change the default role to "challenge"
+// String insertData26 = "INSERT INTO auth VALUES('" + AbstractLesson.USER_ROLE + "','" + WebSession.SHOWSOURCE
+// + "')";
+// String insertData27 = "INSERT INTO auth VALUES('" + AbstractLesson.USER_ROLE + "','" + WebSession.SHOWHINTS
+// + "')";
// Add a permission for the webgoat role to see the solution.
// The challenge(s) will change the default role to "challenge"
- String insertData28 = "INSERT INTO auth VALUES('" + AbstractLesson.USER_ROLE + "','" + WebSession.SHOWSOLUTION
- + "')";
+// String insertData28 = "INSERT INTO auth VALUES('" + AbstractLesson.USER_ROLE + "','" + WebSession.SHOWSOLUTION
+// + "')";
statement.executeUpdate(insertData1);
statement.executeUpdate(insertData2);
@@ -803,9 +802,9 @@ public class CreateDB
statement.executeUpdate(insertData25);
statement.executeUpdate(insertData25_1);
statement.executeUpdate(insertData25_2);
- statement.executeUpdate(insertData26);
- statement.executeUpdate(insertData27);
- statement.executeUpdate(insertData28);
+ //statement.executeUpdate(insertData26);
+ //statement.executeUpdate(insertData27);
+ //statement.executeUpdate(insertData28);
}
private void createOwnershipTable(Connection connection) throws SQLException
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/session/DatabaseUtilities.java b/webgoat-container/src/main/java/org/owasp/webgoat/session/DatabaseUtilities.java
index 391baec5c..4692528b4 100644
--- a/webgoat-container/src/main/java/org/owasp/webgoat/session/DatabaseUtilities.java
+++ b/webgoat-container/src/main/java/org/owasp/webgoat/session/DatabaseUtilities.java
@@ -1,19 +1,13 @@
package org.owasp.webgoat.session;
-import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
-import java.sql.ResultSet;
-import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
-import org.apache.ecs.MultiPartElement;
-import org.apache.ecs.html.B;
-import org.apache.ecs.html.TD;
-import org.apache.ecs.html.TR;
-import org.apache.ecs.html.Table;
+
+import org.springframework.beans.factory.annotation.Autowired;
/**
@@ -131,73 +125,5 @@ public class DatabaseUtilities
String url = context.getDatabaseConnectionString().replaceAll("\\$\\{USER\\}", user);
return DriverManager.getConnection(url, "sa", "");
}
-
- /**
- * Description of the Method
- *
- * @param results
- * Description of the Parameter
- * @param resultsMetaData
- * Description of the Parameter
- * @param resultsMetaData
- * Description of the Parameter
- * @param resultsMetaData
- * Description of the Parameter
- * @param resultsMetaData
- * Description of the Parameter
- * @param resultsMetaData
- * Description of the Parameter
- * @param resultsMetaData
- * Description of the Parameter
- * @return Description of the Return Value
- * @exception IOException
- * Description of the Exception
- * @exception SQLException
- * Description of the Exception
- * @throws java.io.IOException if any.
- * @throws java.sql.SQLException if any.
- */
- public static MultiPartElement writeTable(ResultSet results, ResultSetMetaData resultsMetaData) throws IOException,
- SQLException
- {
- int numColumns = resultsMetaData.getColumnCount();
- results.beforeFirst();
-
- if (results.next())
- {
- Table t = new Table(1); // 1 = with border
- t.setCellPadding(1);
-
- TR tr = new TR();
-
- for (int i = 1; i < (numColumns + 1); i++)
- {
- tr.addElement(new TD(new B(resultsMetaData.getColumnName(i))));
- }
-
- t.addElement(tr);
- results.beforeFirst();
-
- while (results.next())
- {
- TR row = new TR();
-
- for (int i = 1; i < (numColumns + 1); i++)
- {
- String str = results.getString(i);
- if (str == null) str = "";
- row.addElement(new TD(str.replaceAll(" ", " ")));
- }
-
- t.addElement(row);
- }
-
- return (t);
- }
- else
- {
- return (new B("Query Successful; however no data was returned from this query."));
- }
- }
-
+
}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/session/ECSFactory.java b/webgoat-container/src/main/java/org/owasp/webgoat/session/ECSFactory.java
deleted file mode 100644
index e3f85f263..000000000
--- a/webgoat-container/src/main/java/org/owasp/webgoat/session/ECSFactory.java
+++ /dev/null
@@ -1,754 +0,0 @@
-
-package org.owasp.webgoat.session;
-
-import java.util.Iterator;
-import java.util.List;
-import java.util.StringTokenizer;
-import java.util.Vector;
-import org.apache.ecs.Element;
-import org.apache.ecs.ElementContainer;
-import org.apache.ecs.StringElement;
-import org.apache.ecs.html.A;
-import org.apache.ecs.html.BR;
-import org.apache.ecs.html.H3;
-import org.apache.ecs.html.Input;
-import org.apache.ecs.html.Label;
-import org.apache.ecs.html.Option;
-import org.apache.ecs.html.P;
-import org.apache.ecs.html.Select;
-import org.apache.ecs.html.TD;
-import org.apache.ecs.html.TH;
-import org.apache.ecs.html.TR;
-import org.apache.ecs.html.U;
-
-
-/**
- *************************************************************************************************
- *
- *
- * This file is part of WebGoat, an Open Web Application Security Project utility. For details,
- * please see http://www.owasp.org/
- *
- * Copyright (c) 2002 - 20014 Bruce Mayhew
- *
- * This program is free software; you can redistribute it and/or modify it under the terms of the
- * GNU General Public License as published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
- * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with this program; if
- * not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- *
- * Getting Source ==============
- *
- * Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
- * projects.
- *
- * @author Jeff Williams (jeff.williams@aspectsecurity.com)
- * @since October 29, 2003
- * @version $Id: $Id
- */
-public class ECSFactory
-{
-
- /**
- * Description of the Field
- */
-
- public final static String ON = "On";
-
- /**
- * Description of the Field
- */
-
- public final static String PASSWORD = "Password";
-
- /**
- * Don't let anyone instantiate this class
- */
-
- private ECSFactory()
- {
- }
-
- /**
- * Description of the Method
- *
- * @param name
- * Description of the Parameter
- * @param value
- * Description of the Parameter
- * @return Description of the Return Value
- */
- public static Element makeBox(String name, String value)
- {
-
- Input i = new Input(Input.CHECKBOX, name, ON);
-
- i.setChecked(value.equals(ON));
-
- return (i);
- }
-
- /**
- * Description of the Method
- *
- * @param text
- * Description of the Parameter
- * @return Description of the Return Value
- */
- public static Element makeButton(String text)
- {
-
- Input b = new Input();
-
- b.setType(Input.SUBMIT);
- b.setValue(text);
- b.setName(Input.SUBMIT);
-
- return (b);
- }
-
- /**
- * makeButton.
- *
- * @param text a {@link java.lang.String} object.
- * @param onClickFunction a {@link java.lang.String} object.
- * @return a {@link org.apache.ecs.Element} object.
- */
- public static Element makeButton(String text, String onClickFunction)
- {
-
- Input b = (Input) makeButton(text);
- b.setOnClick(onClickFunction);
-
- return (b);
- }
-
- /**
- * Description of the Method
- *
- * @param labeltext
- * Description of the Parameter
- * @param value
- * Description of the Parameter
- * @param e
- * Description of the Parameter
- * @return Description of the Return Value
- */
- public static TR makeField(String labeltext, String value, Element e)
- {
-
- TD left = new TD().setAlign("right");
-
- Label label = new Label().addElement(labeltext);
-
- left.addElement(label);
-
- TD right = new TD().setAlign("left");
-
- right.addElement(e);
-
- TR row = new TR();
-
- row.addElement(left);
-
- row.addElement(right);
-
- return (row);
- }
-
- /**
- * Description of the Method
- *
- * @param labeltext
- * Description of the Parameter
- * @param name
- * Description of the Parameter
- * @param value
- * Description of the Parameter
- * @param size
- * Description of the Parameter
- * @return Description of the Return Value
- */
- public static TR makeField(String labeltext, String name, String value, int size)
- {
-
- Input field = new Input().setName(name).setValue(value).setSize(size).setMaxlength(size);
-
- // double check in case someone means to make a * starred out password field
-
- if (name.equals(PASSWORD))
- {
-
- field.setType(Input.PASSWORD);
-
- }
-
- return (makeField(labeltext, value, field));
- }
-
- /**
- * Description of the Method
- *
- * @param label
- * Description of the Parameter
- * @param type
- * Description of the Parameter
- * @param name
- * Description of the Parameter
- * @param value
- * Description of the Parameter
- * @param alignment
- * Description of the Parameter
- * @param selected
- * Description of the Parameter
- * @return Description of the Return Value
- */
- public static Element makeInput(String label, String type, String name, boolean value, boolean selected,
- String alignment)
- {
-
- return makeInput(label, type, name, new Boolean(value).toString(), selected, alignment);
- }
-
- /**
- * Description of the Method
- *
- * @param label
- * Description of the Parameter
- * @param type
- * Description of the Parameter
- * @param name
- * Description of the Parameter
- * @param value
- * Description of the Parameter
- * @return Description of the Return Value
- */
- public static Element makeInput(String label, String type, String name, String value)
- {
-
- return makeInput(label, type, name, value, new Boolean(value).booleanValue(), "RIGHT");
- }
-
- /**
- * Description of the Method
- *
- * @param label
- * Description of the Parameter
- * @param type
- * Description of the Parameter
- * @param name
- * Description of the Parameter
- * @param value
- * Description of the Parameter
- * @param alignment
- * Description of the Parameter
- * @param selected
- * Description of the Parameter
- * @return Description of the Return Value
- */
- public static Element makeInput(String label, String type, String name, String value, boolean selected,
- String alignment)
- {
-
- ElementContainer ec = new ElementContainer();
-
- if (!alignment.equalsIgnoreCase("LEFT"))
- {
-
- ec.addElement(new StringElement(label));
-
- }
-
- Input input = new Input(type, name, value);
-
- ec.addElement(input);
-
- if (alignment.equalsIgnoreCase("LEFT"))
- {
-
- ec.addElement(new StringElement(label));
-
- }
-
- if (type.equalsIgnoreCase("CHECKBOX"))
- {
-
- input.setChecked(selected);
-
- }
-
- return (ec);
- }
-
- /**
- * Description of the Method
- *
- * @param text
- * Description of the Parameter
- * @param name
- * Description of the Parameter
- * @param value
- * Description of the Parameter
- * @return Description of the Return Value
- */
- public static A makeLink(String text, String name, String value)
- {
-
- String href = "attack?" + name;
-
- if (value.length() > 0)
- {
-
- href = href + "=" + value;
-
- }
-
- A a = new A(href);
-
- a.addElement(new U().addElement(text));
-
- a.addAttribute("style", "cursor:hand");
-
- return (a);
- }
-
- /**
- * Description of the Method
- *
- * @param text
- * Description of the Parameter
- * @param name
- * Description of the Parameter
- * @param value
- * Description of the Parameter
- * @return Description of the Return Value
- */
- public static A makeLink(String text, String name, int value)
- {
-
- return (makeLink(text, name, Integer.toString(value)));
- }
-
- /**
- * Description of the Method
- *
- * @param text
- * Description of the Parameter
- * @param name
- * Description of the Parameter
- * @param value
- * Description of the Parameter
- * @return Description of the Return Value
- */
- public static A makeLink(String text, String name, boolean value)
- {
-
- return (makeLink(text, name, new Boolean(value).toString()));
- }
-
- /**
- * Description of the Method
- *
- * @param text
- * Description of the Parameter
- * @param clickAction
- * Description of the Parameter
- * @param type
- * Description of the Parameter
- * @return Description of the Return Value
- */
- public static Input makeOnClickInput(String text, String clickAction, String type)
- {
-
- Input b = new Input();
-
- b.setType(type);
-
- b.setValue(text);
-
- b.setOnClick(clickAction);
-
- return (b);
- }
-
- /**
- * Description of the Method
- *
- * @param labeltext
- * Description of the Parameter
- * @param value
- * Description of the Parameter
- * @param e
- * Description of the Parameter
- * @return Description of the Return Value
- */
- public static TR makeOption(String labeltext, String value, Element e)
- {
-
- TD left = new TD().setAlign("left").setWidth("10%");
-
- left.addElement(e);
-
- TD right = new TD().setAlign("right");
-
- Label label = new Label().addElement(labeltext);
-
- right.addElement(label);
-
- TR row = new TR();
-
- row.addElement(right);
-
- row.addElement(left);
-
- return (row);
- }
-
- /**
- * Description of the Method
- *
- * @param label
- * Description of the Parameter
- * @param value
- * Description of the Parameter
- * @return Description of the Return Value
- */
- public static Option makeOption(String label, boolean value)
- {
-
- Option option = new Option(label, new Boolean(value).toString());
-
- option.setSelected(value);
-
- return option;
- }
-
- /**
- * Description of the Method
- *
- * @param line
- * Description of the Parameter
- * @return Description of the Return Value
- */
-
- private static org.apache.ecs.html.Option makeOption(String line)
- {
-
- StringTokenizer st = new StringTokenizer(line, "|");
-
- org.apache.ecs.html.Option o = new org.apache.ecs.html.Option();
-
- String token = "";
-
- if (st.hasMoreTokens())
- {
-
- token = st.nextToken();
-
- }
-
- o.addElement(token);
-
- return (o);
- }
-
- /**
- * Description of the Method
- *
- * @param name
- * Description of the Parameter
- * @param options
- * Description of the Parameter
- * @return Description of the Return Value
- */
- public static Element makePulldown(String name, List options)
- {
-
- Select s = new Select(name);
-
- s.addElement(options.toArray(new String[options.size()]));
-
- return (s);
- }
-
- /**
- * Description of the Method
- *
- * @param results
- * Description of the Parameter
- * @return Description of the Return Value
- * @param name a {@link java.lang.String} object.
- */
- public static Element makePulldown(String name, String results)
- {
-
- Select select = new Select(name);
-
- StringTokenizer st = new StringTokenizer(results, "\n");
-
- if (!st.hasMoreTokens()) {
-
- return (new StringElement("")); }
-
- while (st.hasMoreTokens())
- {
-
- String line = st.nextToken();
-
- select.addElement(makeOption(line));
-
- }
-
- select.addElement("-------------------------");
-
- return (select);
- }
-
- /**
- * Description of the Method
- *
- * @param name
- * Description of the Parameter
- * @param list
- * Description of the Parameter
- * @param selected
- * Description of the Parameter
- * @param rowsShowing
- * Description of the Parameter
- * @return Description of the Return Value
- */
- public static Select makePulldown(String name, Object[] list, String selected, int rowsShowing)
- {
-
- Select select = new Select(name);
-
- for (int loop = 0; loop < list.length; loop++)
- {
-
- String value = list[loop].toString();
-
- org.apache.ecs.html.Option o = new org.apache.ecs.html.Option(value, value, value);
-
- if (value.equals(selected))
- {
-
- o.setSelected(true);
-
- }
-
- select.addElement(o);
-
- }
-
- select.setSize(rowsShowing);
-
- return select;
- }
-
- /**
- * Default size of 1 for rows showing in select box.
- *
- * @param diffNames
- * Description of the Parameter
- * @param select
- * Description of the Parameter
- * @param selected
- * Description of the Parameter
- * @param selected
- * Description of the Parameter
- * @param selected
- * Description of the Parameter
- * @param selected
- * Description of the Parameter
- * @param name
- * Description of the Parameter
- * @param options
- * Description of the Parameter
- * @param list
- * Description of the Parameter
- * @param selected
- * Description of the Parameter
- * @param selected
- * Description of the Parameter
- * @return Description of the Return Value
- */
- public static Element makeSelect(boolean diffNames, Select select, String name, Vector options,
- String[] list, String selected)
- {
-
- return makeSelect(diffNames, select, name, options, list, selected, 1);
- }
-
- /**
- * Description of the Method
- *
- * @param diffNames
- * Description of the Parameter
- * @param select
- * Description of the Parameter
- * @param selected
- * Description of the Parameter
- * @param selected
- * Description of the Parameter
- * @param selected
- * Description of the Parameter
- * @param selected
- * Description of the Parameter
- * @param name
- * Description of the Parameter
- * @param options
- * Description of the Parameter
- * @param list
- * Description of the Parameter
- * @param selected
- * Description of the Parameter
- * @param selected
- * Description of the Parameter
- * @param rowsShowing
- * Description of the Parameter
- * @return Description of the Return Value
- */
- public static Select makeSelect(boolean diffNames, Select select, String name, Vector options,
- String[] list, String selected, int rowsShowing)
- {
-
- if (select == null)
- {
-
- select = new Select(name);
-
- if (diffNames)
- {
-
- for (int loop = 0; loop < list.length; loop += 2)
- {
-
- String value = list[loop];
-
- String label = list[loop + 1];
-
- Option o = new Option(value);
-
- if (loop == 0)
- {
-
- o.setSelected(true);
-
- }
-
- options.addElement(o);// add to Vector containing all options
-
- select.addElement(o);
-
- select.addElement(label);
-
- }
-
- }
-
- else
- {
-
- for (int loop = 0; loop < list.length; loop++)
- {
-
- String value = list[loop];
-
- org.apache.ecs.html.Option o = new org.apache.ecs.html.Option(value);
-
- if (loop == 0)
- {
-
- o.setSelected(true);
-
- }
-
- options.addElement(o);// add to Vector containing all options
-
- select.addElement(o);
-
- select.addElement(value);
-
- }
-
- }
-
- }
-
- // find selected option and set selected
-
- Iterator i = options.iterator();
-
- while (i.hasNext())
- {
-
- org.apache.ecs.html.Option o = (org.apache.ecs.html.Option) i.next();
-
- if (selected.equalsIgnoreCase(o.getAttribute("value")))
- {
-
- o.setSelected(true);
-
- }
-
- }
-
- select.setSize(rowsShowing);
-
- return (select);
- }
-
- /**
- * Description of the Method
- *
- * @param title
- * Description of the Parameter
- * @return Description of the Return Value
- */
- public static Element makeTallHeader(String title)
- {
- StringBuffer buff = new StringBuffer();
- for (int i = 0; i < title.length(); i++)
- {
- buff.append(title.charAt(i));
- buff.append(" ");
- }
- return new TH(buff.toString());
- }
-
- /**
- * Description of the Method
- *
- * @param title
- * Description of the Parameter
- * @param text
- * Description of the Parameter
- * @return Description of the Return Value
- */
- public static Element makeTextArea(String title, String text)
- {
-
- ElementContainer ec = new ElementContainer();
-
- ec.addElement(new BR());
-
- ec.addElement(new H3().addElement(title));
-
- ec.addElement(new P());
-
- ec.addElement(" ");
-
- ec.addElement(new BR());
-
- ec.addElement(new BR());
-
- return (ec);
- }
-
-}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/session/ErrorScreen.java b/webgoat-container/src/main/java/org/owasp/webgoat/session/ErrorScreen.java
deleted file mode 100644
index 2020521c8..000000000
--- a/webgoat-container/src/main/java/org/owasp/webgoat/session/ErrorScreen.java
+++ /dev/null
@@ -1,283 +0,0 @@
-
-package org.owasp.webgoat.session;
-
-import java.io.ByteArrayOutputStream;
-import java.io.PrintWriter;
-import java.util.StringTokenizer;
-import javax.servlet.ServletException;
-import org.owasp.webgoat.lessons.AbstractLesson;
-import org.apache.ecs.Element;
-import org.apache.ecs.ElementContainer;
-import org.apache.ecs.HtmlColor;
-import org.apache.ecs.StringElement;
-import org.apache.ecs.html.Div;
-import org.apache.ecs.html.Form;
-import org.apache.ecs.html.H2;
-import org.apache.ecs.html.Small;
-import org.apache.ecs.html.TD;
-import org.apache.ecs.html.TR;
-import org.apache.ecs.html.Table;
-
-
-/**
- *************************************************************************************************
- *
- *
- * This file is part of WebGoat, an Open Web Application Security Project utility. For details,
- * please see http://www.owasp.org/
- *
- * Copyright (c) 2002 - 20014 Bruce Mayhew
- *
- * This program is free software; you can redistribute it and/or modify it under the terms of the
- * GNU General Public License as published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
- * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with this program; if
- * not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- *
- * Getting Source ==============
- *
- * Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
- * projects.
- *
- * @author Jeff Williams Aspect Security
- * @since November 4, 2003
- * @version $Id: $Id
- */
-public class ErrorScreen extends Screen
-{
- /**
- * Description of the Field
- */
- protected Throwable error;
-
- /**
- * Description of the Field
- */
- protected String message;
-
- /**
- * Constructor for the ErrorScreen object
- *
- * @param s
- * Description of the Parameter
- * @param t
- * Description of the Parameter
- */
- public ErrorScreen(WebSession s, Throwable t)
- {
- this.error = t;
- fixCurrentScreen(s);
- setup(s);
- }
-
- /**
- * Constructor for the ErrorScreen object
- *
- * @param s
- * Description of the Parameter
- * @param msg
- * Description of the Parameter
- */
- public ErrorScreen(WebSession s, String msg)
- {
- this.message = msg;
- fixCurrentScreen(s);
- setup(s);
- }
-
- /**
- * fixCurrentScreen.
- *
- * @param s a {@link org.owasp.webgoat.session.WebSession} object.
- */
- public void fixCurrentScreen(WebSession s)
- {
- // So the user can't get stuck on the error screen, reset the
- // current screen to something known
- if (s != null)
- {
- try
- {
- s.setCurrentScreen(s.getCourse().getFirstLesson().getScreenId());
- } catch (Throwable t)
- {
- s.setCurrentScreen(WebSession.WELCOME);
- }
- }
- }
-
- /**
- * setup.
- *
- * @param s a {@link org.owasp.webgoat.session.WebSession} object.
- */
- public void setup(WebSession s)
- {
- // call createContent first so messages will go somewhere
-
- Form form = new Form("attack", Form.POST).setName("form").setEncType("");
-
- form.addElement(wrapForm(s));
-
- TD lowerright = new TD().setHeight("100%").setVAlign("top").setAlign("left").addElement(form);
- TR row = new TR().addElement(lowerright);
- Table layout = new Table().setBgColor(HtmlColor.WHITE).setCellSpacing(0).setCellPadding(0).setBorder(0);
-
- layout.addElement(row);
-
- setContent(layout);
- }
-
- /**
- * wrapForm.
- *
- * @param s a {@link org.owasp.webgoat.session.WebSession} object.
- * @return a {@link org.apache.ecs.Element} object.
- */
- protected Element wrapForm(WebSession s)
- {
- if (s == null) { return new StringElement("Invalid Session"); }
-
- Table container = new Table().setWidth("100%").setCellSpacing(10).setCellPadding(0).setBorder(0);
-
- // CreateContent can generate error messages so you MUST call it before makeMessages()
- Element content = createContent(s);
- container.addElement(new TR().addElement(new TD().setColSpan(2).setVAlign("TOP").addElement(makeMessages(s))));
- container.addElement(new TR().addElement(new TD().setColSpan(2).addElement(content)));
- container.addElement(new TR());
-
- return (container);
- }
-
- /**
- * {@inheritDoc}
- *
- * Description of the Method
- */
- protected Element createContent(WebSession s)
- {
- System.out.println("errorscreen createContent Error:" + this.error + " message:" + this.message);
-
- Element content;
-
- if (this.error != null)
- {
- content = createContent(this.error);
- }
- else if (this.message != null)
- {
- content = createContent(this.message);
- }
- else
- {
- content = new StringElement("An unknown error occurred.");
- }
-
- return content;
- }
-
- /**
- * Description of the Method
- *
- * @param s
- * Description of the Parameter
- * @return Description of the Return Value
- */
- protected Element createContent(String s)
- {
- StringElement list = new StringElement(s);
-
- return (list);
- }
-
- /**
- * Description of the Method
- *
- * @param t
- * Description of the Parameter
- * @return Description of the Return Value
- */
- protected Element createContent(Throwable t)
- {
- StringElement list = new StringElement();
- list.addElement(new H2().addElement(new StringElement("Error Message: " + t.getMessage())));
- list.addElement(formatStackTrace(t));
-
- if (t instanceof ServletException)
- {
- Throwable root = ((ServletException) t).getRootCause();
-
- if (root != null)
- {
- list.addElement(new H2().addElement(new StringElement("Root Message: " + root.getMessage())));
- list.addElement(formatStackTrace(root));
- }
- }
-
- return (new Small().addElement(list));
- }
-
- /**
- * Description of the Method
- *
- * @param t
- * Description of the Parameter
- * @return Description of the Return Value
- */
- public static Element formatStackTrace(Throwable t)
- {
- String trace = getStackTrace(t);
- StringElement list = new StringElement();
- StringTokenizer st = new StringTokenizer(trace, "\r\n\t");
-
- while (st.hasMoreTokens())
- {
- String line = st.nextToken();
- list.addElement(new Div(line));
- }
-
- return (list);
- }
-
- /**
- * Gets the stackTrace attribute of the ErrorScreen class
- *
- * @param t
- * Description of the Parameter
- * @return The stackTrace value
- */
- public static String getStackTrace(Throwable t)
- {
- ByteArrayOutputStream bytes = new ByteArrayOutputStream();
- PrintWriter writer = new PrintWriter(bytes, true);
- t.printStackTrace(writer);
-
- return (bytes.toString());
- }
-
- /**
- * Gets the title attribute of the ErrorScreen object
- *
- * @return The title value
- */
- public String getTitle()
- {
- return ("Error");
- }
-
- /**
- * getRole.
- *
- * @return a {@link java.lang.String} object.
- */
- public String getRole()
- {
- return AbstractLesson.USER_ROLE;
- }
-}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/session/LessonSession.java b/webgoat-container/src/main/java/org/owasp/webgoat/session/LessonSession.java
deleted file mode 100644
index 674ba0618..000000000
--- a/webgoat-container/src/main/java/org/owasp/webgoat/session/LessonSession.java
+++ /dev/null
@@ -1,83 +0,0 @@
-
-package org.owasp.webgoat.session;
-
-/**
- *************************************************************************************************
- *
- *
- * This file is part of WebGoat, an Open Web Application Security Project utility. For details,
- * please see http://www.owasp.org/
- *
- * Copyright (c) 2002 - 20014 Bruce Mayhew
- *
- * This program is free software; you can redistribute it and/or modify it under the terms of the
- * GNU General Public License as published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
- * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with this program; if
- * not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- *
- * Getting Source ==============
- *
- * Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
- * projects.
- *
- * Represents a virtual session for a lesson. Lesson-specific session data may be stored here.
- *
- * @author David Anderson Aspect Security
- * @since January 19, 2006
- * @version $Id: $Id
- */
-public class LessonSession
-{
-
- private boolean isAuthenticated = false;
-
- private String currentLessonScreen;
-
- /**
- * setAuthenticated.
- *
- * @param isAuthenticated a boolean.
- */
- public void setAuthenticated(boolean isAuthenticated)
- {
- this.isAuthenticated = isAuthenticated;
- }
-
- /**
- * isAuthenticated.
- *
- * @return a boolean.
- */
- public boolean isAuthenticated()
- {
- return this.isAuthenticated;
- }
-
- /**
- * Setter for the field currentLessonScreen
.
- *
- * @param currentLessonScreen a {@link java.lang.String} object.
- */
- public void setCurrentLessonScreen(String currentLessonScreen)
- {
- this.currentLessonScreen = currentLessonScreen;
- }
-
- /**
- * Getter for the field currentLessonScreen
.
- *
- * @return a {@link java.lang.String} object.
- */
- public String getCurrentLessonScreen()
- {
- return this.currentLessonScreen;
- }
-
-}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/session/LessonTracker.java b/webgoat-container/src/main/java/org/owasp/webgoat/session/LessonTracker.java
index 1d4196781..ccfe3b0cc 100644
--- a/webgoat-container/src/main/java/org/owasp/webgoat/session/LessonTracker.java
+++ b/webgoat-container/src/main/java/org/owasp/webgoat/session/LessonTracker.java
@@ -1,435 +1,82 @@
package org.owasp.webgoat.session;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.util.Properties;
+import com.google.common.collect.Sets;
+import org.owasp.webgoat.lessons.AbstractLesson;
+
+import java.io.Serializable;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
/**
- *************************************************************************************************
- *
- *
+ * ************************************************************************************************
+ *
+ *
* This file is part of WebGoat, an Open Web Application Security Project utility. For details,
* please see http://www.owasp.org/
- *
+ *
* Copyright (c) 2002 - 20014 Bruce Mayhew
- *
+ *
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
- *
+ *
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
- *
+ *
* Getting Source ==============
- *
+ *
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
* projects.
*
* @author Bruce Mayhew WebGoat
- * @since October 29, 2003
* @version $Id: $Id
+ * @since October 29, 2003
*/
-public class LessonTracker
-{
+public class LessonTracker implements Serializable {
+ private static final long serialVersionUID = 5410058267505412928L;
+ private final List assignments;
+ private final Set solvedAssignments = Sets.newHashSet();
+ private int numberOfAttempts = 0;
- private boolean completed = false;
+ public LessonTracker(AbstractLesson lesson) {
+ this.assignments = lesson.getAssignments().stream().map(a -> a.getSimpleName()).collect(Collectors.toList());
+ }
- private int maxHintLevel = 0;
+ /**
+ * Mark an assingment as solved
+ *
+ * @param solvedAssignment the assignment which the user solved
+ */
+ public void assignmentSolved(String solvedAssignment) {
+ solvedAssignments.add(solvedAssignment);
+ }
- private int numVisits = 0;
+ /**
+ * @return did they user solved all assignments for the lesson?
+ */
+ public boolean isLessonSolved() {
+ return solvedAssignments.size() == assignments.size();
+ }
- private boolean viewedCookies = false;
+ /**
+ * Increase the number attempts to solve the lesson
+ */
+ public void incrementAttempts() {
+ numberOfAttempts++;
+ }
- private boolean viewedHtml = false;
-
- private boolean viewedLessonPlan = false;
-
- private boolean viewedParameters = false;
-
- private boolean viewedSource = false;
-
- private boolean viewedSolution = false;
-
- Properties lessonProperties = new Properties();
-
- /**
- * Gets the completed attribute of the LessonTracker object
- *
- * @return The completed value
- */
- public boolean getCompleted()
- {
- return completed;
- }
-
- /**
- * Gets the maxHintLevel attribute of the LessonTracker object
- *
- * @return The maxHintLevel value
- */
- public int getMaxHintLevel()
- {
- return maxHintLevel;
- }
-
- /**
- * Gets the numVisits attribute of the LessonTracker object
- *
- * @return The numVisits value
- */
- public int getNumVisits()
- {
- return numVisits;
- }
-
- /**
- * Gets the viewedCookies attribute of the LessonTracker object
- *
- * @return The viewedCookies value
- */
- public boolean getViewedCookies()
- {
- return viewedCookies;
- }
-
- /**
- * Gets the viewedHtml attribute of the LessonTracker object
- *
- * @return The viewedHtml value
- */
- public boolean getViewedHtml()
- {
- return viewedHtml;
- }
-
- /**
- * Gets the viewedLessonPlan attribute of the LessonTracker object
- *
- * @return The viewedLessonPlan value
- */
- public boolean getViewedLessonPlan()
- {
- return viewedLessonPlan;
- }
-
- /**
- * Gets the viewedParameters attribute of the LessonTracker object
- *
- * @return The viewedParameters value
- */
- public boolean getViewedParameters()
- {
- return viewedParameters;
- }
-
- /**
- * Gets the viewedSource attribute of the LessonTracker object
- *
- * @return The viewedSource value
- */
- public boolean getViewedSource()
- {
- return viewedSource;
- }
-
- /**
- * Getter for the field viewedSolution
.
- *
- * @return a boolean.
- */
- public boolean getViewedSolution()
- {
- return viewedSource;
- }
-
- /**
- * Description of the Method
- */
- public void incrementNumVisits()
- {
- numVisits++;
- }
-
- /**
- * Sets the properties attribute of the LessonTracker object
- *
- * @param props
- * The new properties value
- * @param screen a {@link org.owasp.webgoat.session.Screen} object.
- */
- protected void setProperties(Properties props, Screen screen)
- {
- completed = Boolean.valueOf(props.getProperty(screen.getTitle() + ".completed")).booleanValue();
- maxHintLevel = Integer.parseInt(props.getProperty(screen.getTitle() + ".maxHintLevel", "0"));
- numVisits = Integer.parseInt(props.getProperty(screen.getTitle() + ".numVisits", "0"));
- viewedCookies = Boolean.valueOf(props.getProperty(screen.getTitle() + ".viewedCookies", "false")).booleanValue();
- viewedHtml = Boolean.valueOf(props.getProperty(screen.getTitle() + ".viewedHtml", "false")).booleanValue();
- viewedLessonPlan = Boolean.valueOf(props.getProperty(screen.getTitle() + ".viewedLessonPlan", "false")).booleanValue();
- viewedParameters = Boolean.valueOf(props.getProperty(screen.getTitle() + ".viewedParameters", "false")).booleanValue();
- viewedSource = Boolean.valueOf(props.getProperty(screen.getTitle() + ".viewedSource", "false")).booleanValue();
- }
-
- /**
- * getUserDir.
- *
- * @param s a {@link org.owasp.webgoat.session.WebSession} object.
- * @return a {@link java.lang.String} object.
- */
- public static String getUserDir(WebSession s)
- {
- return s.getContext().getRealPath("users") + "/";
- }
-
- private static String getTrackerFile(WebSession s, String user, Screen screen)
- {
- return getUserDir(s) + user + "." + screen.getClass().getName() + ".props";
- }
-
- /**
- * Description of the Method
- *
- * @param screen
- * Description of the Parameter
- * @param screen
- * Description of the Parameter
- * @param screen
- * Description of the Parameter
- * @param screen
- * Description of the Parameter
- * @param screen
- * Description of the Parameter
- * @param screen
- * Description of the Parameter
- * @param s
- * Description of the Parameter
- * @return Description of the Return Value
- * @param user a {@link java.lang.String} object.
- */
- public static LessonTracker load(WebSession s, String user, Screen screen)
- {
- FileInputStream in = null;
- try
- {
- String fileName = getTrackerFile(s, user, screen);
- if (fileName != null)
- {
- Properties tempProps = new Properties();
- // System.out.println("Loading lesson state from: " + fileName);
- in = new FileInputStream(fileName);
- tempProps.load(in);
- // allow the screen to use any custom properties it may have set
- LessonTracker tempLessonTracker = screen.createLessonTracker(tempProps);
- tempLessonTracker.setProperties(tempProps, screen);
- return tempLessonTracker;
- }
- } catch (FileNotFoundException e)
- {
- // Normal if the lesson has not been accessed yet.
- } catch (Exception e)
- {
- System.out.println("Failed to load lesson state for " + screen);
- e.printStackTrace();
- } finally
- {
- try
- {
- in.close();
- } catch (Exception e)
- {
- }
- }
-
- return screen.createLessonTracker();
- }
-
- /**
- * Sets the completed attribute of the LessonTracker object
- *
- * @param completed
- * The new completed value
- */
- public void setCompleted(boolean completed)
- {
- this.completed = completed;
- }
-
- /**
- * Sets the maxHintLevel attribute of the LessonTracker object
- *
- * @param maxHintLevel
- * The new maxHintLevel value
- */
- public void setMaxHintLevel(int maxHintLevel)
- {
- this.maxHintLevel = Math.max(this.maxHintLevel, maxHintLevel);
- }
-
- /**
- * Sets the viewedCookies attribute of the LessonTracker object
- *
- * @param viewedCookies
- * The new viewedCookies value
- */
- public void setViewedCookies(boolean viewedCookies)
- {
- this.viewedCookies = viewedCookies;
- }
-
- /**
- * Sets the viewedHtml attribute of the LessonTracker object
- *
- * @param viewedHtml
- * The new viewedHtml value
- */
- public void setViewedHtml(boolean viewedHtml)
- {
- this.viewedHtml = viewedHtml;
- }
-
- /**
- * Sets the viewedLessonPlan attribute of the LessonTracker object
- *
- * @param viewedLessonPlan
- * The new viewedLessonPlan value
- */
- public void setViewedLessonPlan(boolean viewedLessonPlan)
- {
- this.viewedLessonPlan = viewedLessonPlan;
- }
-
- /**
- * Sets the viewedParameters attribute of the LessonTracker object
- *
- * @param viewedParameters
- * The new viewedParameters value
- */
- public void setViewedParameters(boolean viewedParameters)
- {
- this.viewedParameters = viewedParameters;
- }
-
- /**
- * Sets the viewedSource attribute of the LessonTracker object
- *
- * @param viewedSource
- * The new viewedSource value
- */
- public void setViewedSource(boolean viewedSource)
- {
- this.viewedSource = viewedSource;
- }
-
- /**
- * Sets the viewedSource attribute of the LessonTracker object
- *
- * @param viewedSolution a boolean.
- */
- public void setViewedSolution(boolean viewedSolution)
- {
- this.viewedSolution = viewedSolution;
- }
-
- /**
- * Allows the storing of properties for the logged in and a screen.
- *
- * @param s
- * Description of the Parameter
- * @param screen a {@link org.owasp.webgoat.session.Screen} object.
- * @param screen a {@link org.owasp.webgoat.session.Screen} object.
- */
- public void store(WebSession s, Screen screen)
- {
- store(s, screen, s.getUserName());
- }
-
- /**
- * Allows the storing of properties for a user and a screen.
- *
- * @param s
- * Description of the Parameter
- * @param screen a {@link org.owasp.webgoat.session.Screen} object.
- * @param screen a {@link org.owasp.webgoat.session.Screen} object.
- * @param user a {@link java.lang.String} object.
- */
- public void store(WebSession s, Screen screen, String user)
- {
- FileOutputStream out = null;
- String fileName = getTrackerFile(s, user, screen);
- // System.out.println( "Storing data to" + fileName );
- lessonProperties.setProperty(screen.getTitle() + ".completed", Boolean.toString(completed));
- lessonProperties.setProperty(screen.getTitle() + ".maxHintLevel", Integer.toString(maxHintLevel));
- lessonProperties.setProperty(screen.getTitle() + ".numVisits", Integer.toString(numVisits));
- lessonProperties.setProperty(screen.getTitle() + ".viewedCookies", Boolean.toString(viewedCookies));
- lessonProperties.setProperty(screen.getTitle() + ".viewedHtml", Boolean.toString(viewedHtml));
- lessonProperties.setProperty(screen.getTitle() + ".viewedLessonPlan", Boolean.toString(viewedLessonPlan));
- lessonProperties.setProperty(screen.getTitle() + ".viewedParameters", Boolean.toString(viewedParameters));
- lessonProperties.setProperty(screen.getTitle() + ".viewedSource", Boolean.toString(viewedSource));
- try
- {
- out = new FileOutputStream(fileName);
- lessonProperties.store(out, s.getUserName());
- } catch (Exception e)
- {
- // what do we want to do, I think nothing.
- System.out.println("Warning User data for " + s.getUserName() + " will not persist");
- } finally
- {
- try
- {
- out.close();
- } catch (Exception e)
- {
- }
- }
-
- }
-
- /**
- * Description of the Method
- *
- * @return Description of the Return Value
- */
- public String toString()
- {
- StringBuffer buff = new StringBuffer();
- buff.append("LessonTracker:" + "\n");
- buff.append(" - completed:.......... " + completed + "\n");
- buff.append(" - maxHintLevel:....... " + maxHintLevel + "\n");
- buff.append(" - numVisits:.......... " + numVisits + "\n");
- buff.append(" - viewedCookies:...... " + viewedCookies + "\n");
- buff.append(" - viewedHtml:......... " + viewedHtml + "\n");
- buff.append(" - viewedLessonPlan:... " + viewedLessonPlan + "\n");
- buff.append(" - viewedParameters:... " + viewedParameters + "\n");
- buff.append(" - viewedSource:....... " + viewedSource + "\n" + "\n");
- return buff.toString();
- }
-
- /**
- * Getter for the field lessonProperties
.
- *
- * @return Returns the lessonProperties.
- */
- public Properties getLessonProperties()
- {
- return lessonProperties;
- }
-
- /**
- * Setter for the field lessonProperties
.
- *
- * @param lessonProperties
- * The lessonProperties to set.
- */
- public void setLessonProperties(Properties lessonProperties)
- {
- this.lessonProperties = lessonProperties;
- }
+ /**
+ * Reset the tracker. We do not reset the number of attempts here!
+ */
+ void reset() {
+ solvedAssignments.clear();
+ }
}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/session/Parameter.java b/webgoat-container/src/main/java/org/owasp/webgoat/session/Parameter.java
deleted file mode 100644
index 51191bdf2..000000000
--- a/webgoat-container/src/main/java/org/owasp/webgoat/session/Parameter.java
+++ /dev/null
@@ -1,111 +0,0 @@
-
-package org.owasp.webgoat.session;
-
-/**
- *************************************************************************************************
- *
- *
- * This file is part of WebGoat, an Open Web Application Security Project utility. For details,
- * please see http://www.owasp.org/
- *
- * Copyright (c) 2002 - 20014 Bruce Mayhew
- *
- * This program is free software; you can redistribute it and/or modify it under the terms of the
- * GNU General Public License as published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
- * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with this program; if
- * not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- *
- * Getting Source ==============
- *
- * Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
- * projects.
- *
- * @version $Id: $Id
- * @author dm
- */
-public class Parameter implements Comparable
-{
-
- String name;
-
- String value;
-
- /**
- * Constructor for Parameter.
- *
- * @param name a {@link java.lang.String} object.
- * @param value a {@link java.lang.String} object.
- */
- public Parameter(String name, String value)
- {
- this.name = name;
- this.value = value;
- }
-
- /**
- * Getter for the field name
.
- *
- * @return a {@link java.lang.String} object.
- */
- public String getName()
- {
- return name;
- }
-
- /**
- * Getter for the field value
.
- *
- * @return a {@link java.lang.String} object.
- */
- public String getValue()
- {
- return value;
- }
-
- // @Override
- /** {@inheritDoc} */
- public boolean equals(Object obj)
- {
- if (obj instanceof Parameter)
- {
- Parameter other = (Parameter) obj;
- return (name.equals(other.getName()) && value.equals(other.getValue()));
- }
- return false;
- }
-
- // @Override
- /**
- * hashCode.
- *
- * @return a int.
- */
- public int hashCode()
- {
- return toString().hashCode();
- }
-
- // @Override
- /**
- * toString.
- *
- * @return a {@link java.lang.String} object.
- */
- public String toString()
- {
- return (name + "=" + value);
- }
-
- /** {@inheritDoc} */
- public int compareTo(Object o)
- {
- return toString().compareTo(o.toString());
- }
-}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/session/ParameterParser.java b/webgoat-container/src/main/java/org/owasp/webgoat/session/ParameterParser.java
deleted file mode 100644
index f0ac0b3f6..000000000
--- a/webgoat-container/src/main/java/org/owasp/webgoat/session/ParameterParser.java
+++ /dev/null
@@ -1,1010 +0,0 @@
-package org.owasp.webgoat.session;
-
-import java.util.Enumeration;
-import java.util.StringTokenizer;
-import java.util.Vector;
-import java.util.regex.Pattern;
-import javax.servlet.ServletRequest;
-import org.owasp.webgoat.util.HtmlEncoder;
-
-/**
- * *************************************************************************************************
- *
- *
- * This file is part of WebGoat, an Open Web Application Security Project
- * utility. For details, please see http://www.owasp.org/
- *
- * Copyright (c) 2002 - 20014 Bruce Mayhew
- *
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License as published by the Free Software
- * Foundation; either version 2 of the License, or (at your option) any later
- * version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * Getting Source ==============
- *
- * Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository
- * for free software projects.
- *
- * @author Jeff Williams Aspect Security
- * @version $Id: $Id
- */
-public class ParameterParser {
-
- private final static String ALLOWED_CHARACTERS = "_$()-?.@!,:;=//+"; // Don't
- // allow
- // #&
- // specifically
-
- private ServletRequest request;
-
- /**
- * Constructs a new ParameterParser to handle the parameters of the given
- * request.
- *
- * @param request the servlet request
- */
- public ParameterParser(ServletRequest request) {
- this.request = request;
- }
-
- /**
- * Description of the Method
- *
- * @param s Description of the Parameter
- * @return Description of the Return Value
- */
- private String clean(String s) {
- StringBuffer clean = new StringBuffer();
-
- for (int loop = 0; loop < s.length(); loop++) {
- char c = s.charAt(loop);
-
- if (Character.isLetterOrDigit(c) || Character.isWhitespace(c) || (ALLOWED_CHARACTERS.indexOf(c) != -1)) {
- clean.append(c);
- } else {
- clean.append('.');
- }
- }
-
- return (clean.toString());
- }
-
- /**
- * Gets the named parameter value as a boolean
- *
- * @param name the parameter name
- * @return the parameter value as a boolean
- * @exception ParameterNotFoundException if the parameter was not found
- * @throws org.owasp.webgoat.session.ParameterNotFoundException if any.
- */
- public boolean getBooleanParameter(String name) throws ParameterNotFoundException {
- return new Boolean(getStringParameter(name)).booleanValue();
- }
-
- /**
- * Gets the named parameter value as a boolean, with a default. Returns the
- * default value if the parameter is not found.
- *
- * @param name the parameter name
- * @param def the default parameter value
- * @return the parameter value as a boolean, or the default
- */
- public boolean getBooleanParameter(String name, boolean def) {
- try {
- return getBooleanParameter(name);
- } catch (Exception e) {
- return def;
- }
- }
-
- /**
- * Gets the booleanSubParameter attribute of the ParameterParser object
- *
- * @param first Description of the Parameter
- * @param next Description of the Parameter
- * @param def Description of the Parameter
- * @return The booleanSubParameter value
- */
- public boolean getBooleanSubParameter(String first, String next, boolean def) {
- try {
- return new Boolean(getSubParameter(first, next)).booleanValue();
- } catch (Exception e) {
- return def;
- }
- }
-
- /**
- * Gets the named parameter value as a byte
- *
- * @param name the parameter name
- * @return the parameter value as a byte
- * @exception ParameterNotFoundException if the parameter was not found
- * @exception NumberFormatException if the parameter value could not be
- * converted to a byte
- * @throws org.owasp.webgoat.session.ParameterNotFoundException if any.
- * @throws java.lang.NumberFormatException if any.
- */
- public byte getByteParameter(String name) throws ParameterNotFoundException, NumberFormatException {
- return Byte.parseByte(getStringParameter(name));
- }
-
- /**
- * Gets the named parameter value as a byte, with a default. Returns the
- * default value if the parameter is not found or cannot be converted to a
- * byte.
- *
- * @param name the parameter name
- * @param def the default parameter value
- * @return the parameter value as a byte, or the default
- */
- public byte getByteParameter(String name, byte def) {
- try {
- return getByteParameter(name);
- } catch (Exception e) {
- return def;
- }
- }
-
- /**
- * Gets the named parameter value as a char
- *
- * @param name the parameter name
- * @return the parameter value as a char
- * @exception ParameterNotFoundException if the parameter was not found or
- * was the empty string
- * @throws org.owasp.webgoat.session.ParameterNotFoundException if any.
- */
- public char getCharParameter(String name) throws ParameterNotFoundException {
- String param = getStringParameter(name);
-
- if (param.length() == 0) {
- throw new ParameterNotFoundException(name + " is empty string");
- } else {
- return (param.charAt(0));
- }
- }
-
- /**
- * Gets the named parameter value as a char, with a default. Returns the
- * default value if the parameter is not found.
- *
- * @param name the parameter name
- * @param def the default parameter value
- * @return the parameter value as a char, or the default
- */
- public char getCharParameter(String name, char def) {
- try {
- return getCharParameter(name);
- } catch (Exception e) {
- return def;
- }
- }
-
- /**
- * Gets the classNameParameter attribute of the ParameterParser object
- *
- * @param name Description of the Parameter
- * @return The classNameParameter value
- * @throws org.owasp.webgoat.session.ParameterNotFoundException if any.
- */
- public String getClassNameParameter(String name) throws ParameterNotFoundException {
- String p = getStringParameter(name);
- StringTokenizer st = new StringTokenizer(p);
-
- return (st.nextToken().trim());
- }
-
- // FIXME: check for [a-zA-Z].([a-zA-Z])*
- /**
- * Gets the classNameParameter attribute of the ParameterParser object
- *
- * @param name Description of the Parameter
- * @param def Description of the Parameter
- * @return The classNameParameter value
- */
- public String getClassNameParameter(String name, String def) {
- try {
- return getClassNameParameter(name);
- } catch (Exception e) {
- return def;
- }
- }
-
- /**
- * Gets the named parameter value as a double
- *
- * @param name the parameter name
- * @return the parameter value as a double
- * @exception ParameterNotFoundException if the parameter was not found
- * @exception NumberFormatException if the parameter could not be converted
- * to a double
- * @throws org.owasp.webgoat.session.ParameterNotFoundException if any.
- * @throws java.lang.NumberFormatException if any.
- */
- public double getDoubleParameter(String name) throws ParameterNotFoundException, NumberFormatException {
- return new Double(getStringParameter(name)).doubleValue();
- }
-
- /**
- * Gets the named parameter value as a double, with a default. Returns the
- * default value if the parameter is not found.
- *
- * @param name the parameter name
- * @param def the default parameter value
- * @return the parameter value as a double, or the default
- */
- public double getDoubleParameter(String name, double def) {
- try {
- return getDoubleParameter(name);
- } catch (Exception e) {
- return def;
- }
- }
-
- /**
- * Gets the named parameter value as a float
- *
- * @param name the parameter name
- * @return the parameter value as a float
- * @exception ParameterNotFoundException if the parameter was not found
- * @exception NumberFormatException if the parameter could not be converted
- * to a float
- * @throws org.owasp.webgoat.session.ParameterNotFoundException if any.
- * @throws java.lang.NumberFormatException if any.
- */
- public float getFloatParameter(String name) throws ParameterNotFoundException, NumberFormatException {
- return new Float(getStringParameter(name)).floatValue();
- }
-
- /**
- * Gets the named parameter value as a float, with a default. Returns the
- * default value if the parameter is not found.
- *
- * @param name the parameter name
- * @param def the default parameter value
- * @return the parameter value as a float, or the default
- */
- public float getFloatParameter(String name, float def) {
- try {
- return getFloatParameter(name);
- } catch (Exception e) {
- return def;
- }
- }
-
- /**
- * Gets the named parameter value as an IP String, with a default. Returns
- * the default value if the parameter is not found or is the empty string.
- *
- * @param name the parameter name
- * @param def the default parameter value
- * @return the parameter value as a String, or the default
- */
- public String getIPParameter(String name, String def) {
- try {
- return getIPParameter(name);
- } catch (Exception e) {
- return def;
- }
- }
-
- /**
- * Gets the named parameter value as an IP String
- *
- * @param name the parameter name
- * @return the parameter value as a valid IP String or an Empty string if
- * invalid
- * @exception ParameterNotFoundException if the parameter was not found or
- * was the empty string
- * @throws org.owasp.webgoat.session.ParameterNotFoundException if any.
- */
- public String getIPParameter(String name) throws ParameterNotFoundException {
- boolean valid = true;
- String[] values = request.getParameterValues(name);
- String value;
-
- if (values == null) {
- throw new ParameterNotFoundException(name + " not found");
- } else if (values[0].length() == 0) {
- throw new ParameterNotFoundException(name + " was empty");
- } else {
- // trim illegal characters
- value = clean(values[0].trim());
-
- if (value.indexOf("&") > 0) {
- // truncate additional parameters that follow &
- value = value.substring(0, value.indexOf("&"));
- }
-
- // validate the IP ex: 124.143.12.254
- int startIndex = 0;
- int endIndex = 0;
- int octetCount = 0;
- int octetValue;
- String octet;
-
- // if no .'s then it's not an IP
- if (value.indexOf(".") >= 0) {
- while ((valid == true) && (octetCount < 4)) {
- endIndex = value.indexOf(".", startIndex);
-
- if (endIndex == -1) {
- endIndex = value.length();
- }
-
- octet = value.substring(startIndex, endIndex);
- startIndex = endIndex + 1;
-
- try {
- octetValue = Integer.parseInt(octet);
-
- if ((octetValue <= 0) || (octetValue >= 256)) {
- valid = false;
- }
- } catch (Exception e) {
- valid = false;
- }
-
- octetCount++;
- }
- } else {
- // Not a valid IP
- valid = false;
- }
-
- // Check for any extra garbage. If the last octet was a large value
- // it would be trapped by the above range check.
- if (value.length() != endIndex) {
- valid = false;
- }
-
- return valid ? value : null;
- }
- }
-
- /**
- * Gets the named parameter value as a int
- *
- * @param name the parameter name
- * @return the parameter value as a int
- * @exception ParameterNotFoundException if the parameter was not found
- * @exception NumberFormatException if the parameter could not be converted
- * to a int
- * @throws org.owasp.webgoat.session.ParameterNotFoundException if any.
- * @throws java.lang.NumberFormatException if any.
- */
- public int getIntParameter(String name) throws ParameterNotFoundException, NumberFormatException {
- return Integer.parseInt(getStringParameter(name));
- }
-
- /**
- * Gets the named parameter value as a int, with a default. Returns the
- * default value if the parameter is not found.
- *
- * @param name the parameter name
- * @param def the default parameter value
- * @return the parameter value as a int, or the default
- */
- public int getIntParameter(String name, int def) {
- try {
- return getIntParameter(name);
- } catch (Exception e) {
- return def;
- }
- }
-
- /**
- * Gets the named parameter value as a long
- *
- * @param name the parameter name
- * @return the parameter value as a long
- * @exception ParameterNotFoundException if the parameter was not found
- * @exception NumberFormatException if the parameter could not be converted
- * to a long
- * @throws org.owasp.webgoat.session.ParameterNotFoundException if any.
- * @throws java.lang.NumberFormatException if any.
- */
- public long getLongParameter(String name) throws ParameterNotFoundException, NumberFormatException {
- return Long.parseLong(getStringParameter(name));
- }
-
- /**
- * Gets the named parameter value as a long, with a default. Returns the
- * default value if the parameter is not found.
- *
- * @param name the parameter name
- * @param def the default parameter value
- * @return the parameter value as a long, or the default
- */
- public long getLongParameter(String name, long def) {
- try {
- return getLongParameter(name);
- } catch (Exception e) {
- return def;
- }
- }
-
- /**
- * Determines which of the required parameters were missing from the
- * request. Returns null if all the parameters are present.
- *
- * @param requestuired Description of the Parameter
- * @return an array of missing parameters, or null if none are missing
- */
- public String[] getMissingParameters(String[] requestuired) {
- Vector missing = new Vector();
-
- for (int i = 0; i < requestuired.length; i++) {
- String val = getStringParameter(requestuired[i], null);
-
- if (val == null) {
- missing.addElement(requestuired[i]);
- }
- }
-
- if (missing.size() == 0) {
- return null;
- } else {
- String[] ret = new String[missing.size()];
- missing.copyInto(ret);
-
- return ret;
- }
- }
-
- /**
- * Gets the parameterNames attribute of the ParameterParser object
- *
- * @return The parameterNames value
- */
- public Enumeration getParameterNames() {
- if (request == null) {
- return (null);
- }
-
- return request.getParameterNames();
- }
-
- /**
- * Gets the parameterValues attribute of the ParameterParser object
- *
- * @param name Description of the Parameter
- * @return The parameterValues value
- */
- public String[] getParameterValues(String name) {
- if (request == null) {
- return (null);
- }
-
- return request.getParameterValues(name);
- }
-
- /**
- * Gets the rawParameter attribute of the ParameterParser object
- *
- * @param name Description of the Parameter
- * @param def Description of the Parameter
- * @return The rawParameter value
- */
- public String getRawParameter(String name, String def) {
- try {
- return getRawParameter(name);
- } catch (Exception e) {
- return def;
- }
- }
-
- /**
- * Gets the rawParameter attribute of the ParameterParser object
- *
- * @param name Description of the Parameter
- * @return The rawParameter value
- * @exception ParameterNotFoundException Description of the Exception
- * @throws org.owasp.webgoat.session.ParameterNotFoundException if any.
- */
- public String getRawParameter(String name) throws ParameterNotFoundException {
- String[] values = request.getParameterValues(name);
-
- if (values == null) {
- throw new ParameterNotFoundException(name + " not found");
- } else if (values[0].length() == 0) {
- throw new ParameterNotFoundException(name + " was empty");
- }
-
- return (values[0]);
- }
-
- /**
- * Gets the named parameter value as a short
- *
- * @param name the parameter name
- * @return the parameter value as a short
- * @exception ParameterNotFoundException if the parameter was not found
- * @exception NumberFormatException if the parameter could not be converted
- * to a short
- * @throws org.owasp.webgoat.session.ParameterNotFoundException if any.
- * @throws java.lang.NumberFormatException if any.
- */
- public short getShortParameter(String name) throws ParameterNotFoundException, NumberFormatException {
- return Short.parseShort(getStringParameter(name));
- }
-
- /**
- * Gets the named parameter value as a short, with a default. Returns the
- * default value if the parameter is not found.
- *
- * @param name the parameter name
- * @param def the default parameter value
- * @return the parameter value as a short, or the default
- */
- public short getShortParameter(String name, short def) {
- try {
- return getShortParameter(name);
- } catch (Exception e) {
- return def;
- }
- }
-
- /**
- * Gets the named parameter value as a String
- *
- * @param name the parameter name
- * @return the parameter value as a String
- * @exception ParameterNotFoundException if the parameter was not found or
- * was the empty string
- * @throws org.owasp.webgoat.session.ParameterNotFoundException if any.
- */
- public String getStringParameter(String name) throws ParameterNotFoundException {
- String[] values = request.getParameterValues(name);
- String value;
-
- if (values == null) {
- throw new ParameterNotFoundException(name + " not found");
- } else if (values[0].length() == 0) {
- throw new ParameterNotFoundException(name + " was empty");
- } else {
- // trim illegal characters
- value = clean(values[0].trim());
-
- if (value.indexOf("&") > 0) {
- // truncate additional parameters that follow &
- value = value.substring(0, value.indexOf("&"));
- }
-
- return value;
- }
- }
-
- /**
- * Gets the named parameter value as a String, with a default. Returns the
- * default value if the parameter is not found or is the empty string.
- *
- * @param name the parameter name
- * @param def the default parameter value
- * @return the parameter value as a String, or the default
- */
- public String getStringParameter(String name, String def) {
- try {
- return getStringParameter(name);
- } catch (Exception e) {
- return def;
- }
- }
-
- /**
- * Gets the subParameter attribute of the ParameterParser object
- *
- * @param first Description of the Parameter
- * @param next Description of the Parameter
- * @param def Description of the Parameter
- * @return The subParameter value
- */
- public String getSubParameter(String first, String next, String def) {
- try {
- return getSubParameter(first, next);
- } catch (Exception e) {
- return def;
- }
- }
-
- /**
- * Gets the parameter named 'next' following the parameter 'first'. Presumes
- * the structure: first=firstvalue&next=nextValue
- *
- * @param first Description of the Parameter
- * @param next Description of the Parameter
- * @return The subParameter value
- * @exception ParameterNotFoundException Description of the Exception
- * @throws org.owasp.webgoat.session.ParameterNotFoundException if any.
- */
- public String getSubParameter(String first, String next) throws ParameterNotFoundException {
- String[] values = request.getParameterValues(first);
- String value;
-
- if (values == null) {
- throw new ParameterNotFoundException(first + " not found");
- } else if (values[0].length() == 0) {
- throw new ParameterNotFoundException(first + " was empty");
- } else {
- value = clean(values[0].trim());
-
- int idx = value.indexOf("&") + 1;
-
- // index of first char of first sub-param name
- if (idx == 0) {
- throw new ParameterNotFoundException("No subparameter key");
- }
-
- value = value.substring(idx);
-
- // System.out.println("= = = = = =Parameter parser looking for " +
- // next + " in " + value );
- int nextValueIndex = value.indexOf(next + "=");
-
- // System.out.println("= = = = = =Parameter parser nextValueIndex =
- // " + nextValueIndex );
- if (nextValueIndex < 0) {
- throw new ParameterNotFoundException("No subparameter value");
- }
-
- nextValueIndex += (next.length() + 1);
-
- if (nextValueIndex >= 0) {
- value = value.substring(nextValueIndex);
- } else {
- throw new ParameterNotFoundException(next + " not found");
- }
- }
-
- if (value.indexOf("&") > 0) {
- // truncate additional parameters that follow &
- value = value.substring(0, value.indexOf("&"));
- }
-
- // System.out.println("=-=-=-=-=ParameterParser returning value " +
- // value );
- return value;
- }
-
- /**
- * Gets the wordParameter attribute of the ParameterParser object
- *
- * @param name Description of the Parameter
- * @return The wordParameter value
- * @throws org.owasp.webgoat.session.ParameterNotFoundException if any.
- */
- public String getWordParameter(String name) throws ParameterNotFoundException {
- String p = getStringParameter(name);
- StringTokenizer st = new StringTokenizer(p);
-
- return (st.nextToken().trim());
- }
-
- // FIXME: check for [a-zA-Z]
- /**
- * Gets the wordParameter attribute of the ParameterParser object
- *
- * @param name Description of the Parameter
- * @param def Description of the Parameter
- * @return The wordParameter value
- */
- public String getWordParameter(String name, String def) {
- try {
- return getWordParameter(name);
- } catch (Exception e) {
- return def;
- }
- }
-
- /**
- * Gets the specified parameter from the request and validates it against
- * the provided regular expression. If the regular expression check fails,
- * the default value is returned instead.
- *
- * @param name The name of the parameter to retrieve from the request.
- * @param def The default value of the parameter.
- * @param regexpattern The precompiled regular expression to be used to
- * validate the parameter.
- * @return The validated parameter value, or the default value if validation
- * failed.
- */
- private String getRegexParameter(String name, String def, Pattern regexpattern) throws ValidationException {
- try {
- return getRegexParameter(name, regexpattern);
- } catch (Exception e) {
- // System.out.println("Exception occured in defined pattern match");
- // e.printStackTrace();
- return def;
- }
- }
-
- /**
- * Gets the specified parameter from the request and validates it against
- * the provided regular expression. If the regular expression check fails,
- * the default value is returned instead.
- *
- * @param name The name of the parameter to retrieve from the request.
- * @param def The default value of the parameter.
- * @param regexpattern The precompiled regular expression to be used to
- * validate the parameter.
- * @return The validated parameter value, or the default value if validation
- * failed.
- */
- private String getRegexParameter(String name, Pattern regexpattern) throws ParameterNotFoundException,
- ValidationException {
- String param = getStringParameter(name);
-
- if (regexpattern.matcher(param).matches()) {
- return param;
- } else {
- // System.out.println(param + " didn't match defined pattern.");
- throw new ValidationException(name + " contained an invalid value");
- }
- }
-
- /**
- * getStrictAlphaParameter.
- *
- * @param name a {@link java.lang.String} object.
- * @param maxLength a int.
- * @return a {@link java.lang.String} object.
- * @throws org.owasp.webgoat.session.ParameterNotFoundException if any.
- * @throws org.owasp.webgoat.session.ValidationException if any.
- */
- public String getStrictAlphaParameter(String name, int maxLength) throws ParameterNotFoundException,
- ValidationException {
- String alphaRegEx = "^[a-zA-Z\\s]{0," + maxLength + "}$";
- Pattern alphaPattern = Pattern.compile(alphaRegEx);
-
- return getRegexParameter(name, alphaPattern);
- }
-
- /**
- * getStrictNumericParameter.
- *
- * @param name a {@link java.lang.String} object.
- * @param maxLength a int.
- * @return a {@link java.lang.String} object.
- * @throws org.owasp.webgoat.session.ParameterNotFoundException if any.
- * @throws org.owasp.webgoat.session.ValidationException if any.
- */
- public String getStrictNumericParameter(String name, int maxLength) throws ParameterNotFoundException,
- ValidationException {
- String numericRegEx = "^\\d{0," + maxLength + "}$";
- Pattern numericPattern = Pattern.compile(numericRegEx);
-
- return getRegexParameter(name, numericPattern);
- }
-
- private static final String SSNREGEX = "^\\d{3}-\\d{2}-\\d{4}$";
-
- private static final Pattern Ssnpattern = Pattern.compile(SSNREGEX);
-
- /**
- * getSsnParameter.
- *
- * @param name a {@link java.lang.String} object.
- * @return a {@link java.lang.String} object.
- * @throws org.owasp.webgoat.session.ParameterNotFoundException if any.
- * @throws org.owasp.webgoat.session.ValidationException if any.
- */
- public String getSsnParameter(String name) throws ParameterNotFoundException, ValidationException {
- return getRegexParameter(name, Ssnpattern);
- }
-
- // Validates format for major brands of credit card.
- // private static final String CCNREGEX =
- // "^(?:(?4\\d{3})|(?5[1-5]\\d{2})|(?6011)|(?(?:3[68]\\d{2})|(?:30[0-5]\\d))|(?3[47]\\d{2}))([
- //-]?)(?(DinersClub)(?:\\d{6}\\1\\d{4})|(?(AmericanExpress)(?:\\d{6}\\1\\d{5})|(?:\\d{4}\\1\\d{4
- // }\\1\\d{4})))$";
- private static final String CCNREGEX = "^\\d{16}$";
-
- private static final Pattern Ccnpattern = Pattern.compile(CCNREGEX);
-
- /**
- * getCcnParameter.
- *
- * @param name a {@link java.lang.String} object.
- * @return a {@link java.lang.String} object.
- * @throws org.owasp.webgoat.session.ParameterNotFoundException if any.
- * @throws org.owasp.webgoat.session.ValidationException if any.
- */
- public String getCcnParameter(String name) throws ParameterNotFoundException, ValidationException {
- return getRegexParameter(name, Ccnpattern);
- }
-
- private static final String ZIPREGEX = "^\\d{5}(-\\d{4})?$";
-
- private static final Pattern Zippattern = Pattern.compile(ZIPREGEX);
-
- /**
- * getZipParameter.
- *
- * @param name a {@link java.lang.String} object.
- * @return a {@link java.lang.String} object.
- * @throws org.owasp.webgoat.session.ParameterNotFoundException if any.
- * @throws org.owasp.webgoat.session.ValidationException if any.
- */
- public String getZipParameter(String name) throws ParameterNotFoundException, ValidationException {
- return getZipParameter(name, null);
- }
-
- /**
- * getZipParameter.
- *
- * @param name a {@link java.lang.String} object.
- * @param def a {@link java.lang.String} object.
- * @return a {@link java.lang.String} object.
- * @throws org.owasp.webgoat.session.ValidationException if any.
- */
- public String getZipParameter(String name, String def) throws ValidationException {
- return getRegexParameter(name, def, Zippattern);
- }
-
- private static final String PHONEREGEX = "^\\(?[\\d]{3}\\)?[\\s-]?[\\d]{3}[\\s-]?[\\d]{4}$";
-
- // Or this more forgiving pattern:
- // private static final String PHONEREGEX = "^([\\-()+ 0-9x])+$";
- private static final Pattern phonepattern = Pattern.compile(PHONEREGEX);
-
- /**
- * getPhoneParameter.
- *
- * @param name a {@link java.lang.String} object.
- * @return a {@link java.lang.String} object.
- * @throws org.owasp.webgoat.session.ParameterNotFoundException if any.
- * @throws org.owasp.webgoat.session.ValidationException if any.
- */
- public String getPhoneParameter(String name) throws ParameterNotFoundException, ValidationException {
- return getPhoneParameter(name, null);
- }
-
- /**
- * getPhoneParameter.
- *
- * @param name a {@link java.lang.String} object.
- * @param def a {@link java.lang.String} object.
- * @return a {@link java.lang.String} object.
- * @throws org.owasp.webgoat.session.ValidationException if any.
- */
- public String getPhoneParameter(String name, String def) throws ValidationException {
- return getRegexParameter(name, def, phonepattern);
- }
-
- private static final String EMAILREGEX = "^[\\w-]+(?:\\.[\\w-]+)*@(?:[\\w-]+\\.)+[a-zA-Z]{2,7}$";
-
- private static final Pattern emailpattern = Pattern.compile(EMAILREGEX);
-
- /**
- * getEMailParameter.
- *
- * @param name a {@link java.lang.String} object.
- * @return a {@link java.lang.String} object.
- * @throws org.owasp.webgoat.session.ParameterNotFoundException if any.
- * @throws org.owasp.webgoat.session.ValidationException if any.
- */
- public String getEMailParameter(String name) throws ParameterNotFoundException, ValidationException {
- return getEMailParameter(name, null);
- }
-
- /**
- * getEMailParameter.
- *
- * @param name a {@link java.lang.String} object.
- * @param def a {@link java.lang.String} object.
- * @return a {@link java.lang.String} object.
- * @throws org.owasp.webgoat.session.ValidationException if any.
- */
- public String getEMailParameter(String name, String def) throws ValidationException {
- return getRegexParameter(name, def, emailpattern);
- }
-
- private static final String DATEREGEX = "([\\/ .,:0-9a-zA-Z])+$";
-
- private static final Pattern datepattern = Pattern.compile(DATEREGEX);
-
- /**
- * getDateParameter.
- *
- * @param name a {@link java.lang.String} object.
- * @return a {@link java.lang.String} object.
- * @throws org.owasp.webgoat.session.ParameterNotFoundException if any.
- * @throws org.owasp.webgoat.session.ValidationException if any.
- */
- public String getDateParameter(String name) throws ParameterNotFoundException, ValidationException {
- return getDateParameter(name, null);
- }
-
- /**
- * getDateParameter.
- *
- * @param name a {@link java.lang.String} object.
- * @param def a {@link java.lang.String} object.
- * @return a {@link java.lang.String} object.
- * @throws org.owasp.webgoat.session.ValidationException if any.
- */
- public String getDateParameter(String name, String def) throws ValidationException {
- return getRegexParameter(name, def, datepattern);
- }
-
- private static final String URLREGEX = "^(((https?)://)([-()_.!~*';/?:@&=+$,A-Za-z0-9])+)([).!';/?:,][[:blank:]])?$";
-
- private static final Pattern URLpattern = Pattern.compile(URLREGEX);
-
- /**
- * getURLParameter.
- *
- * @param name a {@link java.lang.String} object.
- * @return a {@link java.lang.String} object.
- * @throws org.owasp.webgoat.session.ParameterNotFoundException if any.
- * @throws org.owasp.webgoat.session.ValidationException if any.
- */
- public String getURLParameter(String name) throws ParameterNotFoundException, ValidationException {
- return getURLParameter(name, null);
- }
-
- /**
- * getURLParameter.
- *
- * @param name a {@link java.lang.String} object.
- * @param def a {@link java.lang.String} object.
- * @return a {@link java.lang.String} object.
- * @throws org.owasp.webgoat.session.ValidationException if any.
- */
- public String getURLParameter(String name, String def) throws ValidationException {
- return getRegexParameter(name, def, URLpattern);
- }
-
- /**
- * htmlEncode.
- *
- * @param s a {@link java.lang.String} object.
- * @return a {@link java.lang.String} object.
- */
- protected static String htmlEncode(String s) {
- return HtmlEncoder.encode(s);
- }
-
- /**
- * Description of the Method
- *
- * @return Description of the Return Value
- */
- public String toString() {
- StringBuffer s = new StringBuffer("[");
- Enumeration e = getParameterNames();
-
- while (e.hasMoreElements()) {
- String key = (String) e.nextElement();
- s.append(key + "=" + getParameterValues(key)[0]);
-
- // FIXME: Other values?
- if (e.hasMoreElements()) {
- s.append(",");
- }
- }
-
- s.append("]");
-
- return (s.toString());
- }
-
- /**
- * Description of the Method
- *
- * @param request Description of the Parameter
- */
- public void update(ServletRequest request) {
- this.request = request;
- }
-}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/session/RandomLessonTracker.java b/webgoat-container/src/main/java/org/owasp/webgoat/session/RandomLessonTracker.java
deleted file mode 100644
index 20df5902e..000000000
--- a/webgoat-container/src/main/java/org/owasp/webgoat/session/RandomLessonTracker.java
+++ /dev/null
@@ -1,165 +0,0 @@
-
-package org.owasp.webgoat.session;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Properties;
-
-
-/**
- * RandomLessonTracker class.
- *
- * @version $Id: $Id
- * @author dm
- */
-public class RandomLessonTracker extends LessonTracker
-{
-
- private String[] stages;
-
- private String stage;
-
- private Map completed = new HashMap();
-
- /**
- * Constructor for RandomLessonTracker.
- *
- * @param stages an array of {@link java.lang.String} objects.
- */
- public RandomLessonTracker(String[] stages)
- {
- if (stages == null) stages = new String[0];
- this.stages = stages;
- }
-
- /**
- * Setter for the field stage
.
- *
- * @param stage a {@link java.lang.String} object.
- */
- public void setStage(String stage)
- {
- this.stage = stage;
- }
-
- /**
- * Getter for the field stage
.
- *
- * @return a {@link java.lang.String} object.
- */
- public String getStage()
- {
- if (this.stage == null && stages.length > 0) return stages[0];
- return this.stage;
- }
-
- /**
- * setStageComplete.
- *
- * @param stage a {@link java.lang.String} object.
- * @param complete a boolean.
- */
- public void setStageComplete(String stage, boolean complete)
- {
- completed.put(stage, Boolean.valueOf(complete));
- if (!complete) return;
- int i = getStageNumber(stage);
- if (i < stages.length - 1) setStage(stages[i + 1]);
- }
-
- /**
- * getStageNumber.
- *
- * @param stage a {@link java.lang.String} object.
- * @return a int.
- */
- public int getStageNumber(String stage)
- {
- for (int i = 0; i < stages.length; i++)
- if (stages[i].equals(stage)) return i;
- return -1;
- }
-
- /**
- * hasCompleted.
- *
- * @param stage a {@link java.lang.String} object.
- * @return a boolean.
- */
- public boolean hasCompleted(String stage)
- {
- Boolean complete = completed.get(stage);
- return complete == null ? false : complete.booleanValue();
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean getCompleted()
- {
- for (int i = 0; i < stages.length; i++)
- if (!hasCompleted(stages[i])) return false;
- return true;
- }
-
- /** {@inheritDoc} */
- @Override
- public void setCompleted(boolean complete)
- {
- if (complete == true) throw new UnsupportedOperationException("Use individual stage completion instead");
- for (int i = 0; i < stages.length; i++)
- setStageComplete(stages[i], false);
- setStage(stages[0]);
- }
-
- /** {@inheritDoc} */
- protected void setProperties(Properties props, Screen screen)
- {
- super.setProperties(props, screen);
- for (int i = 0; i < stages.length; i++)
- {
- String p = props.getProperty(screen.getTitle() + "." + stages[i] + ".completed");
- if (p != null)
- {
- setStageComplete(stages[i], Boolean.valueOf(p));
- }
- }
- setStage(props.getProperty(screen.getTitle() + ".stage"));
- }
-
- /** {@inheritDoc} */
- public void store(WebSession s, Screen screen, String user)
- {
- for (int i = 0; i < stages.length; i++)
- {
- if (hasCompleted(stages[i]))
- {
- lessonProperties.setProperty(screen.getTitle() + "." + stages[i] + ".completed", Boolean.TRUE
- .toString());
- }
- else
- {
- lessonProperties.remove(screen.getTitle() + "." + stages[i] + ".completed");
- }
- }
- lessonProperties.setProperty(screen.getTitle() + ".stage", getStage());
- super.store(s, screen, user);
- }
-
- /**
- * toString.
- *
- * @return a {@link java.lang.String} object.
- */
- public String toString()
- {
- StringBuffer buff = new StringBuffer();
- buff.append(super.toString());
- for (int i = 0; i < stages.length; i++)
- {
- buff.append(" - completed " + stages[i] + " :....... " + hasCompleted(stages[i]) + "\n");
- }
- buff.append(" - currentStage:....... " + getStage() + "\n");
- return buff.toString();
- }
-
-}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/session/Role.java b/webgoat-container/src/main/java/org/owasp/webgoat/session/Role.java
deleted file mode 100644
index 14ca60ab5..000000000
--- a/webgoat-container/src/main/java/org/owasp/webgoat/session/Role.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package org.owasp.webgoat.session;
-
-/**
- * Role class.
- *
- * @version $Id: $Id
- * @author dm
- */
-public class Role {
- private String rolename;
-
- /**
- * Constructor for Role.
- *
- * @param rolename a {@link java.lang.String} object.
- */
- public Role(String rolename) {
- this.rolename = rolename;
- }
-
- /**
- * Getter for the field rolename
.
- *
- * @return a {@link java.lang.String} object.
- */
- public String getRolename() {
- return this.rolename;
- }
-}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/session/Screen.java b/webgoat-container/src/main/java/org/owasp/webgoat/session/Screen.java
index 852c3815c..fae5c7fe7 100644
--- a/webgoat-container/src/main/java/org/owasp/webgoat/session/Screen.java
+++ b/webgoat-container/src/main/java/org/owasp/webgoat/session/Screen.java
@@ -1,15 +1,5 @@
package org.owasp.webgoat.session;
-import java.io.PrintWriter;
-import java.util.Properties;
-import org.apache.ecs.Element;
-import org.apache.ecs.HtmlColor;
-import org.apache.ecs.StringElement;
-import org.apache.ecs.html.A;
-import org.apache.ecs.html.Font;
-import org.apache.ecs.html.IMG;
-import org.owasp.webgoat.lessons.AbstractLesson;
-
/**
* *************************************************************************************************
*
@@ -45,102 +35,12 @@ import org.owasp.webgoat.lessons.AbstractLesson;
*/
public abstract class Screen {
- /**
- * Description of the Field
- */
- public static int MAIN_SIZE = 375;
-
- // private Head head;
- private Element content;
-
- final static IMG logo = new IMG("images/aspectlogo-horizontal-small.jpg").setAlt("Aspect Security").setBorder(0)
- .setHspace(0).setVspace(0);
-
/**
* Constructor for the Screen object
*/
public Screen() {
}
- // FIXME: Each lesson should have a role assigned to it. Each user/student
- // should also have a role(s) assigned. The user would only be allowed
- // to see lessons that correspond to their role. Eventually these roles
- // will be stored in the internal database. The user will be able to hack
- // into the database and change their role. This will allow the user to
- // see the admin screens, once they figure out how to turn the admin switch on.
- /**
- * getRole.
- *
- * @return a {@link java.lang.String} object.
- */
- public abstract String getRole();
-
- /**
- * Description of the Method
- *
- * @param s Description of the Parameter
- * @return Description of the Return Value
- */
- protected abstract Element createContent(WebSession s);
-
-
- /**
- * Creates a new lessonTracker object.
- *
- * @param props The properties file that was used to persist the user data.
- * @return Description of the Return Value
- */
- public LessonTracker createLessonTracker(Properties props) {
-
- // If the lesson had any specialized properties in the user persisted properties,
- // now would be the time to pull them out.
- return createLessonTracker();
- }
-
- /**
- * This allows the screens to provide a custom LessonTracker object if
- * needed.
- *
- * @return Description of the Return Value
- */
- public LessonTracker createLessonTracker() {
- return new LessonTracker();
- }
-
- /**
- * Gets the lessonTracker attribute of the AbstractLesson object
- *
- * @return The lessonTracker value
- * @param s a {@link org.owasp.webgoat.session.WebSession} object.
- */
- public LessonTracker getLessonTracker(WebSession s) {
- UserTracker userTracker = UserTracker.instance();
- return userTracker.getLessonTracker(s, this);
- }
-
- /**
- * getLessonTracker.
- *
- * @param s a {@link org.owasp.webgoat.session.WebSession} object.
- * @param userNameOverride a {@link java.lang.String} object.
- * @return a {@link org.owasp.webgoat.session.LessonTracker} object.
- */
- public LessonTracker getLessonTracker(WebSession s, String userNameOverride) {
- UserTracker userTracker = UserTracker.instance();
- return userTracker.getLessonTracker(s, userNameOverride, this);
- }
-
- /**
- * getLessonTracker.
- *
- * @param s a {@link org.owasp.webgoat.session.WebSession} object.
- * @param lesson a {@link org.owasp.webgoat.lessons.AbstractLesson} object.
- * @return a {@link org.owasp.webgoat.session.LessonTracker} object.
- */
- public LessonTracker getLessonTracker(WebSession s, AbstractLesson lesson) {
- UserTracker userTracker = UserTracker.instance();
- return userTracker.getLessonTracker(s, lesson);
- }
/**
* Fill in a descriptive title for this lesson
@@ -149,168 +49,5 @@ public abstract class Screen {
*/
public abstract String getTitle();
- /**
- * Setter for the field content
.
- *
- * @param content a {@link org.apache.ecs.Element} object.
- */
- protected void setContent(Element content) {
- this.content = content;
- }
- /**
- * Description of the Method
- *
- * @return Description of the Return Value
- */
- protected Element makeLogo() {
-
- return new A("http://www.aspectsecurity.com/webgoat.html", logo);
- }
-
- /**
- * getSponsor.
- *
- * @return a {@link java.lang.String} object.
- */
- public String getSponsor() {
- return "Aspect Security";
- }
-
- /**
- * getSponsorLogoResource.
- *
- * @return a {@link java.lang.String} object.
- */
- public String getSponsorLogoResource() {
- return "images/aspectlogo-horizontal-small.jpg";
- }
-
- /**
- * Description of the Method
- *
- * @param s Description of the Parameter
- * @return Description of the Return Value
- */
- protected Element makeMessages(WebSession s) {
-
- if (s == null) {
-
- return (new StringElement(""));
- }
-
- Font f = new Font().setColor(HtmlColor.RED);
-
- String message = s.getMessage();
-
- f.addElement(message);
-
- return (f);
- }
-
- /**
- * Returns the content length of the the html.
- *
- * @return a int.
- */
- public int getContentLength() {
- return getContent().length();
- }
-
- /**
- * Description of the Method
- *
- * @param out Description of the Parameter
- */
- public void output(PrintWriter out) {
-
- // format output -- then send to printwriter
- // otherwise we're doing way too much SSL encryption work
- out.print(getContent());
-
- }
-
- // hook all the links
- /**
- * Getter for the field content
.
- *
- * @return a {@link java.lang.String} object.
- */
- public String getContent() {
- //String makeAllAjax = "";
- // need to do this here as some of the lessons render forms after submission of an ajax form
- return (content == null) ? "" : content.toString();// + makeAllAjax;
- }
-
- /**
- * Description of the Method
- *
- * @param x Description of the Parameter
- * @return Description of the Return Value
- */
- protected static String pad(int x) {
-
- StringBuilder sb = new StringBuilder();
-
- if (x < 10) {
-
- sb.append(" ");
-
- }
-
- if (x < 100) {
-
- sb.append(" ");
-
- }
-
- sb.append(x);
-
- return (sb.toString());
- }
-
- /**
- * Description of the Method
- *
- * @param token Description of the Parameter
- * @return Description of the Return Value
- */
- protected static String convertMetachars(String token) {
-
- int mci = 0;
-
- /*
- * meta char array FIXME: Removed the conversion of whitespace " " to " " in order for
- * the html to be automatically wrapped in client browser. It is better to add line length
- * checking and only do " " conversion in lines that won't exceed screen size, say less
- * than 80 characters.
- */
- String[] metaChar = {"&", "<", ">", "\"", "\t", System.getProperty("line.separator")};
-
- String[] htmlCode = {"&", "<", ">", """, " ", " "};
-
- String replacedString = token;
- for (; mci < metaChar.length; mci += 1) {
- replacedString = replacedString.replaceAll(metaChar[mci], htmlCode[mci]);
- }
- return (replacedString);
- }
-
- /**
- * Description of the Method
- *
- * @param token Description of the Parameter
- * @return Description of the Return Value
- */
- protected static String convertMetacharsJavaCode(String token) {
- return (convertMetachars(token).replaceAll(" ", " "));
- }
-
- /**
- * Description of the Method
- *
- * @param s Description of the Parameter
- * @return Description of the Return Value
- */
- // protected abstract Element wrapForm( WebSession s );
}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/session/SequentialLessonTracker.java b/webgoat-container/src/main/java/org/owasp/webgoat/session/SequentialLessonTracker.java
deleted file mode 100644
index 07006b1b5..000000000
--- a/webgoat-container/src/main/java/org/owasp/webgoat/session/SequentialLessonTracker.java
+++ /dev/null
@@ -1,61 +0,0 @@
-
-package org.owasp.webgoat.session;
-
-import java.util.Properties;
-
-
-/**
- * SequentialLessonTracker class.
- *
- * @version $Id: $Id
- * @author dm
- */
-public class SequentialLessonTracker extends LessonTracker
-{
-
- private int currentStage = 1;
-
- /**
- * getStage.
- *
- * @return a int.
- */
- public int getStage()
- {
- return currentStage;
- }
-
- /**
- * setStage.
- *
- * @param stage a int.
- */
- public void setStage(int stage)
- {
- currentStage = stage;
- }
-
- /** {@inheritDoc} */
- protected void setProperties(Properties props, Screen screen)
- {
- super.setProperties(props, screen);
- currentStage = Integer.parseInt(props.getProperty(screen.getTitle() + ".currentStage"));
- }
-
- /** {@inheritDoc} */
- public void store(WebSession s, Screen screen, String user)
- {
- lessonProperties.setProperty(screen.getTitle() + ".currentStage", Integer.toString(currentStage));
- super.store(s, screen, user);
- }
-
- /**
- * toString.
- *
- * @return a {@link java.lang.String} object.
- */
- public String toString()
- {
- return super.toString() + " - currentStage:....... " + currentStage + "\n";
- }
-}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/session/UnauthenticatedException.java b/webgoat-container/src/main/java/org/owasp/webgoat/session/UnauthenticatedException.java
deleted file mode 100644
index cab222bb0..000000000
--- a/webgoat-container/src/main/java/org/owasp/webgoat/session/UnauthenticatedException.java
+++ /dev/null
@@ -1,41 +0,0 @@
-
-package org.owasp.webgoat.session;
-
-/**
- *************************************************************************************************
- *
- *
- * This file is part of WebGoat, an Open Web Application Security Project utility. For details,
- * please see http://www.owasp.org/
- *
- * Copyright (c) 2002 - 20014 Bruce Mayhew
- *
- * This program is free software; you can redistribute it and/or modify it under the terms of the
- * GNU General Public License as published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
- * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with this program; if
- * not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- *
- * Getting Source ==============
- *
- * Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
- * projects.
- *
- * @version $Id: $Id
- * @author dm
- */
-public class UnauthenticatedException extends Exception
-{
-
- /**
- *
- */
- private static final long serialVersionUID = 97865025446819061L;
-
-}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/session/UnauthorizedException.java b/webgoat-container/src/main/java/org/owasp/webgoat/session/UnauthorizedException.java
deleted file mode 100644
index 5ccde9f57..000000000
--- a/webgoat-container/src/main/java/org/owasp/webgoat/session/UnauthorizedException.java
+++ /dev/null
@@ -1,41 +0,0 @@
-
-package org.owasp.webgoat.session;
-
-/**
- *************************************************************************************************
- *
- *
- * This file is part of WebGoat, an Open Web Application Security Project utility. For details,
- * please see http://www.owasp.org/
- *
- * Copyright (c) 2002 - 20014 Bruce Mayhew
- *
- * This program is free software; you can redistribute it and/or modify it under the terms of the
- * GNU General Public License as published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
- * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with this program; if
- * not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- *
- * Getting Source ==============
- *
- * Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
- * projects.
- *
- * @version $Id: $Id
- * @author dm
- */
-public class UnauthorizedException extends Exception
-{
-
- /**
- *
- */
- private static final long serialVersionUID = 5245519486798464814L;
-
-}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/session/User.java b/webgoat-container/src/main/java/org/owasp/webgoat/session/User.java
deleted file mode 100644
index a1ccea6d8..000000000
--- a/webgoat-container/src/main/java/org/owasp/webgoat/session/User.java
+++ /dev/null
@@ -1,52 +0,0 @@
-package org.owasp.webgoat.session;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-
-/**
- * User class.
- *
- * @version $Id: $Id
- * @author dm
- */
-public class User {
- private String username;
- private ArrayList roles;
-
- /**
- * Constructor for User.
- *
- * @param username a {@link java.lang.String} object.
- */
- public User(String username) {
- this.username = username;
- this.roles = new ArrayList();
- }
-
- /**
- * Getter for the field username
.
- *
- * @return a {@link java.lang.String} object.
- */
- public String getUsername() {
- return username;
- }
-
- /**
- * Getter for the field roles
.
- *
- * @return a {@link java.util.Iterator} object.
- */
- public Iterator getRoles() {
- return roles.iterator();
- }
-
- /**
- * addRole.
- *
- * @param rolename a {@link java.lang.String} object.
- */
- public void addRole(String rolename) {
- roles.add(new Role(rolename));
- }
-}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/session/UserDatabase.java b/webgoat-container/src/main/java/org/owasp/webgoat/session/UserDatabase.java
index 25867223c..09e542487 100644
--- a/webgoat-container/src/main/java/org/owasp/webgoat/session/UserDatabase.java
+++ b/webgoat-container/src/main/java/org/owasp/webgoat/session/UserDatabase.java
@@ -1,9 +1,12 @@
package org.owasp.webgoat.session;
-import java.sql.*;
-import java.util.ArrayList;
-import java.util.Iterator;
import java.io.File;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
class UserDatabase {
private Connection userDB;
@@ -20,9 +23,6 @@ class UserDatabase {
private final String QUERY_ALL_ROLES_FOR_USERNAME = "SELECT rolename FROM roles, user_roles, users WHERE roles.id = user_roles.role_id AND user_roles.user_id = users.id AND users.username = ?;";
private final String QUERY_TABLE_COUNT = "SELECT count(id) AS count FROM table;";
- private final String DELETE_ALL_ROLES_FOR_USER = "DELETE FROM user_roles WHERE user_id IN (SELECT id FROM users WHERE username = ?);";
- private final String DELETE_USER = "DELETE FROM users WHERE username = ?;";
-
/**
* Constructor for UserDatabase.
*/
@@ -101,42 +101,6 @@ class UserDatabase {
return count;
}
- /**
- * getUsers.
- *
- * @return a {@link java.util.Iterator} object.
- */
- public Iterator getUsers() {
- ArrayList users = new ArrayList();
- User currentUser;
- ResultSet userResults, roleResults;
-
- try {
- open();
- Statement statement = userDB.createStatement();
- PreparedStatement rolesForUsers = userDB.prepareStatement(QUERY_ALL_ROLES_FOR_USERNAME);
-
- userResults = statement.executeQuery(QUERY_ALL_USERS);
- while (userResults.next()) {
- currentUser = new User(userResults.getString("username"));
- rolesForUsers.setString(1, currentUser.getUsername());
- roleResults = rolesForUsers.executeQuery();
- while (roleResults.next()) {
- currentUser.addRole(roleResults.getString("rolename"));
- }
- roleResults.close();
- }
- rolesForUsers.close();
- userResults.close();
- close();
- } catch (SQLException e) {
- e.printStackTrace();
- users = new ArrayList();
- }
-
- return users.iterator();
- }
-
/**
* addRoleToUser.
*
@@ -160,46 +124,6 @@ class UserDatabase {
return true;
}
- /**
- * removeUser.
- *
- * @param user a {@link org.owasp.webgoat.session.User} object.
- * @return a boolean.
- */
- public boolean removeUser(User user) {
- return removeUser(user.getUsername());
- }
-
- /**
- * removeUser.
- *
- * @param username a {@link java.lang.String} object.
- * @return a boolean.
- */
- public boolean removeUser(String username) {
- try {
- open();
-
- PreparedStatement deleteUserRoles = userDB.prepareStatement(DELETE_ALL_ROLES_FOR_USER);
- PreparedStatement deleteUser = userDB.prepareStatement(DELETE_USER);
-
- deleteUserRoles.setString(1, username);
- deleteUser.setString(1, username);
-
- deleteUserRoles.execute();
- deleteUser.execute();
-
- deleteUserRoles.close();
- deleteUser.close();
-
- close();
- } catch (SQLException e) {
- e.printStackTrace();
- return false;
- }
- return true;
- }
-
/*
* Methods to initialise the default state of the database.
*/
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/session/UserTracker.java b/webgoat-container/src/main/java/org/owasp/webgoat/session/UserTracker.java
index 554a06397..cc5f76681 100644
--- a/webgoat-container/src/main/java/org/owasp/webgoat/session/UserTracker.java
+++ b/webgoat-container/src/main/java/org/owasp/webgoat/session/UserTracker.java
@@ -1,300 +1,104 @@
package org.owasp.webgoat.session;
-import java.util.ArrayList;
-import java.util.Collection;
+import lombok.SneakyThrows;
+import org.owasp.webgoat.lessons.AbstractLesson;
+import org.owasp.webgoat.lessons.Assignment;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.util.FileCopyUtils;
+import org.springframework.util.SerializationUtils;
+
+import java.io.File;
import java.util.HashMap;
-import java.util.Iterator;
import java.util.Map;
/**
- *************************************************************************************************
- *
- *
+ * ************************************************************************************************
+ *
+ *
* This file is part of WebGoat, an Open Web Application Security Project utility. For details,
* please see http://www.owasp.org/
- *
+ *
* Copyright (c) 2002 - 20014 Bruce Mayhew
- *
+ *
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
- *
+ *
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
- *
+ *
* Getting Source ==============
- *
+ *
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
* projects.
*
* @author Bruce Mayhew WebGoat
- * @since October 29, 2003
* @version $Id: $Id
+ * @since October 29, 2003
*/
-public class UserTracker
-{
+public class UserTracker {
- private static UserTracker instance;
+ private final String webgoatHome;
+ private final String user;
+ private Map storage = new HashMap<>();
- // FIXME: persist this somehow!
+ public UserTracker(@Value("${webgoat.user.directory}") final String webgoatHome, final String user) {
+ this.webgoatHome = webgoatHome;
+ this.user = user;
+ }
- private static HashMap> storage = new HashMap>();
+ /**
+ * Returns the lesson tracker for a specific lesson if available.
+ *
+ * @param lesson the lesson
+ * @return the optional lesson tracker
+ */
+ public LessonTracker getLessonTracker(AbstractLesson lesson) {
+ LessonTracker lessonTracker = storage.get(lesson.getTitle());
+ if (lessonTracker == null) {
+ lessonTracker = new LessonTracker(lesson);
+ storage.put(lesson.getTitle(), lessonTracker);
+ }
+ return lessonTracker;
+ }
- private static UserDatabase usersDB = new UserDatabase();
+ public void assignmentSolved(AbstractLesson lesson, Assignment assignment) {
+ LessonTracker lessonTracker = getLessonTracker(lesson);
+ lessonTracker.incrementAttempts();
+ lessonTracker.assignmentSolved(assignment.getClass().getSimpleName());
+ save();
+ }
- /**
- * Constructor for the UserTracker object
- */
- private UserTracker()
- {
- }
+ public void assignmentFailed(AbstractLesson lesson) {
+ LessonTracker lessonTracker = getLessonTracker(lesson);
+ lessonTracker.incrementAttempts();
+ save();
+ }
- /**
- * Gets the completed attribute of the UserTracker object
- *
- * @param userName
- * Description of the Parameter
- * @return The completed value
- */
- public int getCompleted(String userName)
- {
+ @SneakyThrows
+ public void load() {
+ File file = new File(webgoatHome, user + ".progress");
+ if (file.exists() && file.isFile()) {
+ this.storage = (Map) SerializationUtils.deserialize(FileCopyUtils.copyToByteArray(file));
+ }
+ }
- HashMap usermap = getUserMap(userName);
+ @SneakyThrows
+ private void save() {
+ File file = new File(webgoatHome, user + ".progress");
+ FileCopyUtils.copy(SerializationUtils.serialize(this.storage), file);
+ }
- Iterator i = usermap.entrySet().iterator();
-
- int count = 0;
-
- while (i.hasNext())
- {
-
- Map.Entry entry = (Map.Entry) i.next();
-
- int value = ((Integer) entry.getValue()).intValue();
-
- if (value > 5)
- {
- count++;
- }
-
- }
-
- return count;
- }
-
- /**
- * Gets the users attribute of the UserTracker object
- *
- * @return The users value
- */
- public Collection getUsers()
- {
- return storage.keySet();
- }
-
- /**
- * getAllUsers.
- *
- * @param roleName a {@link java.lang.String} object.
- * @return a {@link java.util.Collection} object.
- */
- public Collection getAllUsers(String roleName)
- {
- synchronized (usersDB)
- {
- Collection allUsers = new ArrayList();
- try
- {
- usersDB.open();
- Iterator users = usersDB.getUsers();
- while (users.hasNext())
- {
- User user = (User) users.next();
- Iterator roles = user.getRoles();
- while (roles.hasNext())
- {
- Role role = (Role) roles.next();
- if (role.getRolename().trim().equals(roleName))
- {
- allUsers.add(user.getUsername());
- }
- }
- }
- usersDB.close();
- } catch (Exception e)
- {
- }
- return allUsers;
- }
- }
-
- /**
- * deleteUser.
- *
- * @param user a {@link java.lang.String} object.
- */
- public void deleteUser(String user)
- {
- synchronized (usersDB)
- {
- try
- {
- usersDB.open();
- Iterator users = usersDB.getUsers();
- while (users.hasNext())
- {
- User tomcatUser = (User) users.next();
- if (tomcatUser.getUsername().equals(user))
- {
- usersDB.removeUser(tomcatUser);
- // FIXME: delete all the lesson tracking property files
- break;
- }
- }
- usersDB.close();
-
- } catch (Exception e)
- {
- }
- }
- }
-
- /**
- * Gets the lessonTracker attribute of the UserTracker object
- *
- * @param screen
- * Description of the Parameter
- * @return The lessonTracker value
- * @param screen
- * Description of the Parameter
- * @param s a {@link org.owasp.webgoat.session.WebSession} object.
- */
- public LessonTracker getLessonTracker(WebSession s, Screen screen)
- {
- return getLessonTracker(s, s.getUserName(), screen);
- }
-
- /**
- * getLessonTracker.
- *
- * @param s a {@link org.owasp.webgoat.session.WebSession} object.
- * @param screen a {@link org.owasp.webgoat.session.Screen} object.
- * @param user a {@link java.lang.String} object.
- * @param screen a {@link org.owasp.webgoat.session.Screen} object.
- * @return a {@link org.owasp.webgoat.session.LessonTracker} object.
- */
- public LessonTracker getLessonTracker(WebSession s, String user, Screen screen)
- {
- HashMap usermap = getUserMap(user);
- LessonTracker tracker = (LessonTracker) usermap.get(screen.getTitle());
- if (tracker == null)
- {
- // Creates a new lesson tracker, if one does not exist on disk.
- tracker = LessonTracker.load(s, user, screen);
- usermap.put(screen.getTitle(), tracker);
- }
- // System.out.println( "User: [" + userName + "] UserTracker:getLessonTracker() LTH " +
- // tracker.hashCode() + " for " + screen );
- return tracker;
- }
-
- /**
- * Gets the status attribute of the UserTracker object
- *
- * @param screen
- * Description of the Parameter
- * @return The status value
- * @param screen
- * Description of the Parameter
- * @param s a {@link org.owasp.webgoat.session.WebSession} object.
- */
- public String getStatus(WebSession s, Screen screen)
- {
- return ("User [" + s.getUserName() + "] has accessed " + screen + " UserTracker:getStatus()LTH = " + getLessonTracker(
- s,
- screen)
- .hashCode());
- }
-
- /**
- * Gets the userMap attribute of the UserTracker object
- *
- * @param userName
- * Description of the Parameter
- * @return The userMap value
- */
- private HashMap getUserMap(String userName)
- {
-
- HashMap usermap = storage.get(userName);
-
- if (usermap == null)
- {
-
- usermap = new HashMap();
-
- storage.put(userName, usermap);
-
- }
-
- return (usermap);
- }
-
- /**
- * Description of the Method
- *
- * @return Description of the Return Value
- */
- public static synchronized UserTracker instance()
- {
-
- if (instance == null)
- {
-
- instance = new UserTracker();
-
- }
-
- return instance;
- }
-
- /**
- * Description of the Method
- *
- * @param screen
- * Description of the Parameter
- * @param screen
- * Description of the Parameter
- * @param screen
- * Description of the Parameter
- * @param screen
- * Description of the Parameter
- * @param screen
- * Description of the Parameter
- * @param screen
- * Description of the Parameter
- * @param s
- * Description of the Parameter
- */
- public void update(WebSession s, Screen screen)
- {
-
- LessonTracker tracker = getLessonTracker(s, screen);
-
- // System.out.println( "User [" + s.getUserName() + "] TRACKER: updating " + screen +
- // " LTH " + tracker.hashCode() );
- tracker.store(s, screen);
-
- HashMap usermap = getUserMap(s.getUserName());
- usermap.put(screen.getTitle(), tracker);
-
- }
+ public void reset(AbstractLesson al) {
+ getLessonTracker(al).reset();
+ save();
+ }
}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/session/ValidationException.java b/webgoat-container/src/main/java/org/owasp/webgoat/session/ValidationException.java
deleted file mode 100644
index ef025153c..000000000
--- a/webgoat-container/src/main/java/org/owasp/webgoat/session/ValidationException.java
+++ /dev/null
@@ -1,58 +0,0 @@
-
-package org.owasp.webgoat.session;
-
-/**
- *************************************************************************************************
- *
- *
- * This file is part of WebGoat, an Open Web Application Security Project utility. For details,
- * please see http://www.owasp.org/
- *
- * Copyright (c) 2002 - 20014 Bruce Mayhew
- *
- * This program is free software; you can redistribute it and/or modify it under the terms of the
- * GNU General Public License as published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
- * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with this program; if
- * not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- *
- * Getting Source ==============
- *
- * Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
- * projects.
- *
- * @version $Id: $Id
- * @author dm
- */
-public class ValidationException extends Exception
-{
-
- /**
- *
- */
- private static final long serialVersionUID = -8358754606830400708L;
-
- /**
- * Constructor for ValidationException.
- */
- public ValidationException()
- {
- super();
- }
-
- /**
- * Constructor for ValidationException.
- *
- * @param message a {@link java.lang.String} object.
- */
- public ValidationException(String message)
- {
- super(message);
- }
-}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/session/WebSession.java b/webgoat-container/src/main/java/org/owasp/webgoat/session/WebSession.java
index 157db2d89..858610b4a 100644
--- a/webgoat-container/src/main/java/org/owasp/webgoat/session/WebSession.java
+++ b/webgoat-container/src/main/java/org/owasp/webgoat/session/WebSession.java
@@ -1,251 +1,58 @@
package org.owasp.webgoat.session;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.security.Principal;
+import lombok.extern.slf4j.Slf4j;
+import org.owasp.webgoat.lessons.AbstractLesson;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.User;
+
import java.sql.Connection;
import java.sql.SQLException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.Hashtable;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Vector;
-import javax.servlet.ServletContext;
-import javax.servlet.http.Cookie;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import org.owasp.webgoat.lessons.AbstractLesson;
-import org.owasp.webgoat.lessons.Category;
-import org.owasp.webgoat.lessons.RandomLessonAdapter;
-import org.owasp.webgoat.lessons.SequentialLessonAdapter;
-import org.owasp.webgoat.lessons.model.RequestParameter;
-import org.owasp.webgoat.util.BeanProvider;
-import org.owasp.webgoat.util.LabelManager;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
/**
* *************************************************************************************************
- *
- *
+ *
+ *
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see
* http://www.owasp.org/
- *
+ *
* Copyright (c) 2002 - 20014 Bruce Mayhew
- *
+ *
* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later
* version.
- *
+ *
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License along with this program; if not, write to the Free
* Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
+ *
* Getting Source ==============
- *
+ *
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
* projects.
*
* @author Jeff Williams Aspect Security
* @author Bruce Mayhew WebGoat
- * @since October 28, 2003
* @version $Id: $Id
+ * @since October 28, 2003
*/
+@Slf4j
public class WebSession {
- final Logger logger = LoggerFactory.getLogger(WebSession.class);
-
- /**
- * Description of the Field
- */
- public final static String ADMIN = "admin";
-
- /**
- * Tomcat role for a webgoat user
- */
- public final static String WEBGOAT_USER = "ROLE_WEBGOAT_USER";
-
- /**
- * Tomcat role for a webgoat admin
- */
- public final static String WEBGOAT_ADMIN = "ROLE_WEBGOAT_ADMIN";
-
- /**
- * Description of the Field
- */
- public final static String CHALLENGE = "Challenge";
-
- /**
- * Description of the Field
- */
- public final static String COLOR = "color";
-
- /** Constant COURSE="course"
*/
- public final static String COURSE = "course";
-
- /**
- * Error screen number
- */
- public final static int ERROR = 0;
-
- /** Constant STAGE="stage"
*/
- public static final String STAGE = "stage";
-
- /**
- * session id string
- */
- public final static String JSESSION_ID = "jsessionid";
-
- /**
- * Logout parameter name
- */
- public final static String LOGOUT = "Logout";
-
- /**
- * Restart parameter name
- */
- public final static String RESTART = "Restart";
-
- /**
- * menu parameter name
- */
- public final static String MENU = "menu";
-
- /**
- * Screen parameter name
- */
- public final static String SCREEN = "Screen";
-
- /**
- * Description of the Field
- */
- public final static String SESSION = "websession";
-
- /** Constant SHOWSOURCE="ShowSource"
*/
- public final static String SHOWSOURCE = "ShowSource";
-
- /** Constant SHOWSOLUTION="ShowSolution"
*/
- public final static String SHOWSOLUTION = "ShowSolution";
-
- /** Constant SHOWHINTS="ShowHints"
*/
- public final static String SHOWHINTS = "ShowHints";
-
- /** Constant SHOW="show"
*/
- public final static String SHOW = "show";
-
- /** Constant SHOW_NEXTHINT="NextHint"
*/
- public final static String SHOW_NEXTHINT = "NextHint";
-
- /** Constant SHOW_PREVIOUSHINT="PreviousHint"
*/
- public final static String SHOW_PREVIOUSHINT = "PreviousHint";
-
- /** Constant SHOW_PARAMS="Params"
*/
- public final static String SHOW_PARAMS = "Params";
-
- /** Constant SHOW_COOKIES="Cookies"
*/
- public final static String SHOW_COOKIES = "Cookies";
-
- /** Constant SHOW_SOURCE="Source"
*/
- public final static String SHOW_SOURCE = "Source";
-
- /** Constant SHOW_SOLUTION="Solution"
*/
- public final static String SHOW_SOLUTION = "Solution";
-
- /** Constant DEBUG="debug"
*/
- public final static String DEBUG = "debug";
-
- /** Constant LANGUAGE="language"
*/
- public final static String LANGUAGE = "language";
-
- /**
- * Description of the Field
- */
- public final static int WELCOME = -1;
-
- private WebgoatContext webgoatContext;
-
- private ServletContext context = null;
-
- private Course course;
-
- private int currentScreen = WELCOME;
-
- private int previousScreen = ERROR;
-
- private int previousStage = -1;
-
- private int hintNum = -1;
-
- private boolean isAdmin = false;
-
- private boolean isHackedAdmin = false;
-
- private boolean isAuthenticated = false;
-
- private boolean isColor = false;
-
- private boolean isDebug = false;
-
- private boolean hasHackedHackableAdmin = false;
-
- private StringBuffer message = new StringBuffer("");
-
- private ParameterParser myParser;
-
- private HttpServletRequest request = null;
-
- private HttpServletResponse response = null;
-
- private String servletName;
-
- private HashMap session = new HashMap();
-
- private boolean showCookies = false;
-
- private boolean showParams = false;
-
- private boolean showRequest = false;
-
- private boolean showSource = false;
-
- private boolean showSolution = false;
-
- private boolean completedHackableAdmin = false;
-
- private int currentMenu;
-
- private String currentLanguage = null;
-
- private List cookiesOnLastRequest;
-
- private List parmsOnLastRequest;
+ private final User currentUser;
+ private final WebgoatContext webgoatContext;
+ private AbstractLesson currentLesson;
+ private UserTracker userTracker;
/**
* Constructor for the WebSession object
*
* @param webgoatContext a {@link org.owasp.webgoat.session.WebgoatContext} object.
- * @param context Description of the Parameter
*/
- public WebSession(WebgoatContext webgoatContext, ServletContext context) {
+ public WebSession(WebgoatContext webgoatContext) {
this.webgoatContext = webgoatContext;
- // initialize from web.xml
- showParams = webgoatContext.isShowParams();
- showCookies = webgoatContext.isShowCookies();
- showSource = webgoatContext.isShowSource();
- showSolution = webgoatContext.isShowSolution();
- showRequest = webgoatContext.isShowRequest();
- currentLanguage = webgoatContext.getDefaultLanguage();
- this.context = context;
-
- course = new Course();
- course.loadCourses(webgoatContext, context, "/");
+ this.currentUser = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
}
/**
@@ -268,171 +75,13 @@ public class WebSession {
DatabaseUtilities.returnConnection(s.getUserName());
}
- /**
- * Description of the Method
- *
- * @param key Description of the Parameter
- * @param value Description of the Parameter
- */
- public void add(String key, Object value) {
- session.put(key, value);
- }
-
- /**
- * Description of the Method
- */
- public void clearMessage() {
- message.setLength(0);
- }
-
- /**
- * Marks all cookies but the JSESSIONID for deletion and adds them to the response.
- */
- public void eatCookies() {
- Cookie[] cookies = request.getCookies();
-
- for (int loop = 0; loop < cookies.length; loop++) {
- if (!cookies[loop].getName().startsWith("JS")) {// skip jsessionid cookie
- cookies[loop].setMaxAge(0);// mark for deletion by browser
- response.addCookie(cookies[loop]);
- }
- }
- }
-
- /**
- * Description of the Method
- *
- * @param key Description of the Parameter
- * @return Description of the Return Value
- */
- public Object get(String key) {
- return (session.get(key));
- }
-
- /**
- * Gets the context attribute of the WebSession object
- *
- * @return The context value
- */
- public ServletContext getContext() {
- return context;
- }
-
- /**
- * getRoles.
- *
- * @return a {@link java.util.List} object.
- */
- public List getRoles() {
- List roles = new ArrayList();
-
- roles.add(AbstractLesson.USER_ROLE);
- if (isAdmin()) {
- roles.add(AbstractLesson.ADMIN_ROLE);
- }
-
- return roles;
- }
-
- /**
- * Sets the admin flag - this routine is ONLY here to allow someone a backdoor to setting the user up as an admin.
- *
- * This is also used by the WebSession to set the admin, but the method should be private
- *
- * @param state a boolean.
- */
- public void setAdmin(boolean state) {
- isAdmin = state;
-
- }
-
- /**
- * getRole.
- *
- * @return a {@link java.lang.String} object.
- */
- public String getRole() {
-
- String role = "";
- if (isAdmin()) {
- role = AbstractLesson.ADMIN_ROLE;
- } else if (isHackedAdmin()) {
- role = AbstractLesson.HACKED_ADMIN_ROLE;
- } else if (isChallenge()) {
- role = AbstractLesson.CHALLENGE_ROLE;
- } else {
- role = AbstractLesson.USER_ROLE;
- }
-
- return role;
- }
-
- /**
- * Gets the course attribute of the WebSession object
- *
- * @return The course value
- */
- public Course getCourse() {
- return course;
- }
-
- /**
- * Setter for the field course
.
- *
- * @param course a {@link org.owasp.webgoat.session.Course} object.
- */
- public void setCourse(Course course) {
- this.course = course;
- }
-
- /**
- * Gets the currentScreen attribute of the WebSession object
- *
- * @return The currentScreen value
- */
- public int getCurrentScreen() {
- return (currentScreen);
- }
-
/**
* Setter for the field currentScreen
.
*
- * @param screen a int.
+ * @param lesson current lesson
*/
- public void setCurrentScreen(int screen) {
- currentScreen = screen;
- }
-
- /**
- * getRestartLink.
- *
- * @return a {@link java.lang.String} object.
- */
- public String getRestartLink() {
- return getCurrentLesson().getLink() + "&" + RESTART + "=" + getCurrentScreen();
- }
-
- /**
- * getCurrentLink.
- *
- * @return a {@link java.lang.String} object.
- */
- public String getCurrentLink() {
- String thisLink = "attack";
- Enumeration e = request.getParameterNames();
- boolean isFirstParameter = true;
- while (e.hasMoreElements()) {
- String name = e.nextElement();
- if (isFirstParameter) {
- isFirstParameter = false;
- thisLink += "?";
- } else {
- thisLink += "&";
- }
- thisLink = thisLink + name + "=" + request.getParameter(name);
- }
-
- return thisLink;
+ public void setCurrentLesson(AbstractLesson lesson) {
+ this.currentLesson = lesson;
}
/**
@@ -441,457 +90,7 @@ public class WebSession {
* @return a {@link org.owasp.webgoat.lessons.AbstractLesson} object.
*/
public AbstractLesson getCurrentLesson() {
- return getCourse().getLesson(this, getCurrentScreen(), getRoles());
- }
-
- /**
- * getLesson.
- *
- * @param id a int.
- * @return a {@link org.owasp.webgoat.lessons.AbstractLesson} object.
- */
- public AbstractLesson getLesson(int id) {
- return getCourse().getLesson(this, id, getRoles());
- }
-
- /**
- * getLessons.
- *
- * @param category a {@link org.owasp.webgoat.lessons.Category} object.
- * @return a {@link java.util.List} object.
- */
- public List getLessons(Category category) {
- return getCourse().getLessons(this, category, getRoles());
- }
-
- /**
- * Gets the hint1 attribute of the WebSession object
- *
- * @return The hint1 value
- */
- private int getHintNum() {
- return (hintNum);
- }
-
- /**
- * getHint.
- *
- * @return a {@link java.lang.String} object.
- */
- public String getHint() {
- String hint = null;
- int hints = getCurrentLesson().getHintCount(this);
- if (getHintNum() > hints) {
- hintNum = -1;
- }
- if (getHintNum() >= 0) // FIXME
- {
- hint = getCurrentLesson().getHint(this, getHintNum());
- }
-
- return hint;
- }
-
- /**
- * getParams.
- *
- * @return a {@link java.util.List} object.
- */
- public List getParams() {
- Vector params = null;
-
- if (showParams() && getParser() != null) {
- params = new Vector();
-
- Enumeration e = getParser().getParameterNames();
-
- while ((e != null) && e.hasMoreElements()) {
- String name = (String) e.nextElement();
- String[] values = getParser().getParameterValues(name);
-
- for (int loop = 0; (values != null) && (loop < values.length); loop++) {
- params.add(new Parameter(name, values[loop]));
- // params.add( name + " -> " + values[loop] );
- }
- }
-
- Collections.sort(params);
- }
-
- return params;
- }
-
- /**
- * getCookies.
- *
- * @return a {@link java.util.List} object.
- */
- public List getCookies() {
- List cookies = null;
-
- if (showCookies()) {
- cookies = Arrays.asList(request.getCookies());
- }
-
- /*
- * List cookies = new Vector(); HttpServletRequest request = getRequest(); Cookie[] cookies =
- * request.getCookies(); if ( cookies.length == 0 ) { list.addElement( new LI( "No Cookies" ) ); } for ( int i =
- * 0; i < cookies.length; i++ ) { Cookie cookie = cookies[i]; cookies.add(cookie); //list.addElement( new LI(
- * cookie.getName() + " -> " + cookie.getValue() ) ); }
- */
- return cookies;
- }
-
- /**
- * Gets the cookie attribute of the CookieScreen object
- *
- * @return The cookie value
- * @param cookieName a {@link java.lang.String} object.
- */
- public String getCookie(String cookieName) {
- Cookie[] cookies = getRequest().getCookies();
-
- for (int i = 0; i < cookies.length; i++) {
- if (cookies[i].getName().equalsIgnoreCase(cookieName)) {
- return (cookies[i].getValue());
- }
- }
-
- return (null);
- }
-
- /**
- * getSource.
- *
- * @return a {@link java.lang.String} object.
- */
- public String getSource() {
- return "Sorry. No Java Source viewing available.";
- // return getCurrentLesson().getSource(this);
- }
-
- /**
- * getSolution.
- *
- * @return a {@link java.lang.String} object.
- */
- public String getSolution() {
- return "Sorry. No solution is available.";
- // return getCurrentLesson().getSolution(this);
- }
-
- /**
- * getInstructions.
- *
- * @return a {@link java.lang.String} object.
- */
- public String getInstructions() {
- return getCurrentLesson().getInstructions(this);
- }
-
- /**
- * Gets the message attribute of the WebSession object
- *
- * @return The message value
- */
- public String getMessage() {
- return (message.toString());
- }
-
- /**
- * Gets the parser attribute of the WebSession object
- *
- * @return The parser value
- */
- public ParameterParser getParser() {
- return (myParser);
- }
-
- /**
- * Gets the previousScreen attribute of the WebSession object
- *
- * @return The previousScreen value
- */
- public int getPreviousScreen() {
- return (previousScreen);
- }
-
- /**
- * Gets the request attribute of the WebSession object
- *
- * @return The request value
- */
- public HttpServletRequest getRequest() {
- return request;
- }
-
- /**
- * Setter for the field request
.
- *
- * @param request a {@link javax.servlet.http.HttpServletRequest} object.
- */
- public void setRequest(HttpServletRequest request) {
- this.request = request;
- }
-
- /**
- * Gets the response attribute of the WebSession object
- *
- * @return The response value
- */
- public HttpServletResponse getResponse() {
- return response;
- }
-
- /**
- * Gets the servletName attribute of the WebSession object
- *
- * @return The servletName value
- */
- public String getServletName() {
- return (servletName);
- }
-
- /**
- * Gets the sourceFile attribute of the WebSession object
- *
- * @return The sourceFile value
- * @param fileName a {@link java.lang.String} object.
- */
- public String getWebResource(String fileName) {
- // Note: doesn't work for admin path! Maybe with a ../ attack
- return (context.getRealPath(fileName));
- }
-
- /**
- * Gets the admin attribute of the WebSession object
- *
- * @return The admin value
- */
- public boolean isAdmin() {
- return (isAdmin);
- }
-
- /**
- * Gets the hackedAdmin attribute of the WebSession object
- *
- * @return The hackedAdmin value
- */
- public boolean isHackedAdmin() {
- return (isHackedAdmin);
- }
-
- /**
- * Has the user ever hacked the hackable admin
- *
- * @return The hackedAdmin value
- */
- public boolean completedHackableAdmin() {
- return (completedHackableAdmin);
- }
-
- /**
- * Gets the authenticated attribute of the WebSession object
- *
- * @return The authenticated value
- */
- public boolean isAuthenticated() {
- return (isAuthenticated);
- }
-
- private Map lessonSessions = new Hashtable();
-
- /**
- * isAuthenticatedInLesson.
- *
- * @param lesson a {@link org.owasp.webgoat.lessons.AbstractLesson} object.
- * @return a boolean.
- */
- public boolean isAuthenticatedInLesson(AbstractLesson lesson) {
- boolean authenticated = false;
-
- LessonSession lessonSession = getLessonSession(lesson);
- if (lessonSession != null) {
- authenticated = lessonSession.isAuthenticated();
- }
- // System.out.println("Authenticated for lesson " + lesson + "? " + authenticated);
-
- return authenticated;
- }
-
- /**
- * isAuthorizedInLesson.
- *
- * @param employeeId a int.
- * @param functionId a {@link java.lang.String} object.
- * @return a boolean.
- */
- public boolean isAuthorizedInLesson(int employeeId, String functionId) {
- return getCurrentLesson().isAuthorized(this, employeeId, functionId);
- }
-
- /**
- * isAuthorizedInLesson.
- *
- * @param role a {@link java.lang.String} object.
- * @param functionId a {@link java.lang.String} object.
- * @return a boolean.
- */
- public boolean isAuthorizedInLesson(String role, String functionId) {
- return getCurrentLesson().isAuthorized(this, role, functionId);
- }
-
- /**
- * getUserIdInLesson.
- *
- * @return a int.
- * @throws org.owasp.webgoat.session.ParameterNotFoundException if any.
- */
- public int getUserIdInLesson() throws ParameterNotFoundException {
- return getCurrentLesson().getUserId(this);
- }
-
- /**
- * getUserNameInLesson.
- *
- * @return a {@link java.lang.String} object.
- * @throws org.owasp.webgoat.session.ParameterNotFoundException if any.
- */
- public String getUserNameInLesson() throws ParameterNotFoundException {
- return getCurrentLesson().getUserName(this);
- }
-
- /**
- * openLessonSession.
- *
- * @param lesson a {@link org.owasp.webgoat.lessons.AbstractLesson} object.
- */
- public void openLessonSession(AbstractLesson lesson) {
- System.out.println("Opening new lesson session for lesson " + lesson);
- LessonSession lessonSession = new LessonSession();
- lessonSessions.put(lesson, lessonSession);
- }
-
- /**
- * closeLessonSession.
- *
- * @param lesson a {@link org.owasp.webgoat.lessons.AbstractLesson} object.
- */
- public void closeLessonSession(AbstractLesson lesson) {
- lessonSessions.remove(lesson);
- }
-
- /**
- * getLessonSession.
- *
- * @param lesson a {@link org.owasp.webgoat.lessons.AbstractLesson} object.
- * @return a {@link org.owasp.webgoat.session.LessonSession} object.
- */
- public LessonSession getLessonSession(AbstractLesson lesson) {
- return lessonSessions.get(lesson);
- }
-
- /**
- * Gets the challenge attribute of the WebSession object
- *
- * @return The challenge value
- */
- public boolean isChallenge() {
- if (getCurrentLesson() != null) {
- return (Category.CHALLENGE.equals(getCurrentLesson().getCategory()));
- }
- return false;
- }
-
- /**
- * Gets the color attribute of the WebSession object
- *
- * @return The color value
- */
- public boolean isColor() {
- return (isColor);
- }
-
- /**
- * Gets the screen attribute of the WebSession object
- *
- * @param value Description of the Parameter
- * @return The screen value
- */
- public boolean isScreen(int value) {
- return (getCurrentScreen() == value);
- }
-
- /**
- * Gets the user attribute of the WebSession object
- *
- * @return The user value
- */
- public boolean isUser() {
- return (!isAdmin && !isChallenge());
- }
-
- /**
- * Sets the message attribute of the WebSession object
- *
- * @param text The new message value
- */
- public void setMessage(String text) {
- message.append(" " + " * " + text);
- }
-
- /**
- * setLineBreak.
- *
- * @param text a {@link java.lang.String} object.
- */
- public void setLineBreak(String text) {
- message.append(" " + text);
- }
-
- /**
- * Description of the Method
- *
- * @return Description of the Return Value
- */
- public boolean showCookies() {
- return (showCookies);
- }
-
- /**
- * Description of the Method
- *
- * @return Description of the Return Value
- */
- public boolean showParams() {
- return (showParams);
- }
-
- /**
- * Description of the Method
- *
- * @return Description of the Return Value
- */
- public boolean showRequest() {
- return (showRequest);
- }
-
- /**
- * Description of the Method
- *
- * @return Description of the Return Value
- */
- public boolean showSource() {
- return (showSource);
- }
-
- /**
- * showSolution.
- *
- * @return a boolean.
- */
- public boolean showSolution() {
- return (showSolution);
+ return this.currentLesson;
}
/**
@@ -900,415 +99,7 @@ public class WebSession {
* @return The userName value
*/
public String getUserName() {
- HttpServletRequest request = getRequest();
- if (request == null) {
- throw new RuntimeException("Could not find the ServletRequest in the web session");
- }
- Principal principal = request.getUserPrincipal();
- if (principal == null) {
- throw new RuntimeException("Could not find the Principal in the Servlet Request");
- }
- return principal.getName();
- }
-
- /**
- * Parse parameters from the given request, handle any servlet commands, and update this session based on the
- * parameters.
- *
- * @param request Description of the Parameter
- * @param response Description of the Parameter
- * @param name Description of the Parameter
- * @throws java.io.IOException if any.
- */
- public void update(HttpServletRequest request, HttpServletResponse response, String name) throws IOException {
- String content = null;
-
- this.request = request;
- this.response = response;
- this.servletName = name;
-
- clearMessage();
- updateParser(request);
-
- // System.out.println("Current Screen 1: " + currentScreen );
- // System.out.println("Previous Screen 1: " + previousScreen );
- // FIXME: requires ?Logout=true
- // FIXME: doesn't work right -- no reauthentication
- // REMOVED - we have explicit logout now via spriing security
- /*
- * if (myParser.getRawParameter(LOGOUT, null) != null) { System.out.println("Logout " +
- * request.getUserPrincipal()); eatCookies(); request.getSession().invalidate(); currentScreen = WELCOME;
- * previousScreen = ERROR; }
- */
-
- updateScreenProperties(request);
-
- if (this.getCurrentScreen() != this.getPreviousScreen()) {
- clearScreenProperties();
- } else if (myParser.getRawParameter(STAGE, null) != null) {
- updateCurrentScreenStage();
- } else {
- content = updateCurrentScreen(content);
- }
-
- updateParameters(request);
- updateContent(response, content);
- }
-
- /**
- * Updates parameters isAdmin, isHackedAdmin, hasHackedHackableAdmin, isColor and isDebug
- *
- * @param request
- */
- private void updateParameters(HttpServletRequest request) {
- isAdmin = request.isUserInRole(WEBGOAT_ADMIN);
- isHackedAdmin = myParser.getBooleanParameter(ADMIN, isAdmin);
- if (isHackedAdmin) {
- System.out.println("Hacked admin");
- hasHackedHackableAdmin = true;
- }
- isColor = myParser.getBooleanParameter(COLOR, isColor);
- isDebug = myParser.getBooleanParameter(DEBUG, isDebug);
- }
-
- /**
- * If the content is not already set we get the response and sends it on its way
- *
- * @param response
- * @param content to send
- * @throws IOException
- */
- private void updateContent(HttpServletResponse response, String content) throws IOException {
- // System.out.println( "showParams:" + showParams );
- // System.out.println( "showSource:" + showSource );
- // System.out.println( "showSolution:" + showSolution );
- // System.out.println( "showCookies:" + showCookies );
- // System.out.println( "showRequest:" + showRequest );
- if (content != null) {
- response.setContentType("text/html");
- PrintWriter out = new PrintWriter(response.getOutputStream());
- out.print(content);
- out.flush();
- out.close();
- }
- }
-
- /**
- * Checks to see if the lesson should be restarted. Also handles parsing of "show" commands for getting hints,
- * params, cookies, source and solution.
- *
- * @param content
- * @return the updated content
- */
- private String updateCurrentScreen(String content) {
- // else update global variables for the current screen
- // Handle "restart" commands
- int lessonId = myParser.getIntParameter(RESTART, -1);
- if (lessonId != -1) {
- restartLesson(lessonId);
- }
- // if ( myParser.getBooleanParameter( RESTART, false ) )
- // {
- // getCurrentLesson().getLessonTracker( this ).getLessonProperties().setProperty(
- // CHALLENGE_STAGE, "1" );
- // }
-
- // Handle "show" commands
- String showCommand = myParser.getStringParameter(SHOW, null);
- if (showCommand != null) {
- if (showCommand.equalsIgnoreCase(SHOW_PARAMS)) {
- showParams = !showParams;
- } else if (showCommand.equalsIgnoreCase(SHOW_COOKIES)) {
- showCookies = !showCookies;
- } else if (showCommand.equalsIgnoreCase(SHOW_SOURCE)) {
- content = getSource();
- // showSource = true;
- } else if (showCommand.equalsIgnoreCase(SHOW_SOLUTION)) {
- content = getSolution();
- // showSource = true;
- } else if (showCommand.equalsIgnoreCase(SHOW_NEXTHINT)) {
- getNextHint();
- } else if (showCommand.equalsIgnoreCase(SHOW_PREVIOUSHINT)) {
- getPreviousHint();
- }
- }
- return content;
- }
-
- /**
- * Checks to see what kind of lesson we are viewing and parses the "stage" parameter accordingly. Sets the stage for
- * the lesson using setStage on the lesson object.
- */
- private void updateCurrentScreenStage() {
- AbstractLesson al = getCurrentLesson();
- if (al instanceof SequentialLessonAdapter) {
- updateSlaStage((SequentialLessonAdapter) al);
- } else if (al instanceof RandomLessonAdapter) {
- updateRlaStage((RandomLessonAdapter) al);
- }
- }
-
- /**
- * Updates the stage for a RandomLessonAdapter
- *
- * @param al
- */
- private void updateRlaStage(RandomLessonAdapter rla) {
- try {
- if (!myParser.getRawParameter(STAGE).equals("null")) {
- int currentStage = myParser.getIntParameter(STAGE) - 1;
- if (previousStage != currentStage) {
- previousStage = currentStage;
- String[] stages = rla.getStages();
- if (stages == null) {
- stages = new String[0];
- }
- if (currentStage >= 0 && currentStage < stages.length) {
- rla.setStage(this, stages[currentStage]);
- }
- }
- } else {
- rla.setStage(this, null);
- }
- } catch (ParameterNotFoundException pnfe) {
- logger.warn("ParameterNotFoundException when updating stage for RandomLessonAdapter: " + pnfe.getMessage() + " " + pnfe.getCause());
- }
- }
-
- /**
- * Updates the stage for a SequentialLessonAdapter
- *
- * @param al
- */
- private void updateSlaStage(SequentialLessonAdapter sla) {
- int stage = myParser.getIntParameter(STAGE, sla.getStage(this));
- if (stage > 0 && stage <= sla.getStageCount()) {
- sla.setStage(this, stage);
- }
- }
-
- /**
- * Eats all the cookies and resets hintNum and previousStage
- */
- private void clearScreenProperties() {
- if (webgoatContext.isDebug()) {
- setMessage("Changed to a new screen, clearing cookies and hints");
- }
- eatCookies();
- hintNum = -1;
- previousStage = -1;
- }
-
- /**
- * Updates the properties currentScreen, previousScreen and hintNum depending on which scenario is being handled.
- *
- * @param request
- */
- private void updateScreenProperties(HttpServletRequest request) {
- // There are several scenarios where we want the first lesson to be loaded
- // 1) Previous screen is Welcome - Start of the course
- // 2) After a logout and after the session has been reinitialized
- if ((this.getPreviousScreen() == WebSession.WELCOME) ||
- (getRequest().getSession(false) != null &&
- // getRequest().getSession(false).isNew() &&
- this.getCurrentScreen() == WebSession.WELCOME &&
- this.getPreviousScreen() == WebSession.ERROR)) {
- currentScreen = course.getFirstLesson().getScreenId();
- hintNum = -1;
- }
-
- // System.out.println("Current Screen 2: " + currentScreen );
- // System.out.println("Previous Screen 2: " + previousScreen );
- // update the screen variables
- previousScreen = currentScreen;
-
- try {
- // If the request is new there should be no parameters.
- // This can occur from a session timeout or a the starting of a new course.
- if (!request.getSession().isNew()) {
- currentScreen = myParser.getIntParameter(SCREEN, currentScreen);
- } else {
- if (!myParser.getRawParameter(SCREEN, "NULL").equals("NULL")) {
- this.setMessage("Session Timeout - Starting new Session.");
- }
- }
- } catch (Exception e) {
- logger.warn("Exception when updating properties in updateScreenProperties: " + e.getMessage() + " " + e.getCause());
- }
- }
-
- /**
- * Updates the labelmanager local based on the labelManager bean
- *
- * @param request
- */
- private void updateLocale(HttpServletRequest request) {
- Locale locale = request.getLocale();
- if (locale != null) {
- LabelManager labelManager = BeanProvider.getBean("labelManager", LabelManager.class);
- labelManager.setLocale(locale);
- }
- }
-
- /**
- * Creates a new parser if not created yet. Sets the request on the parser for later use.
- *
- * @param request
- */
- private void updateParser(HttpServletRequest request) {
- if (myParser == null) {
- myParser = new ParameterParser(request);
- } else {
- myParser.update(request);
- }
- }
-
- /**
- * updateLastAttackRequestInfo.
- *
- * @param request a {@link javax.servlet.http.HttpServletRequest} object.
- */
- public void updateLastAttackRequestInfo(HttpServletRequest request) {
- // store cookies
- Cookie[] cookies = request.getCookies();
- if (cookies == null) {
- this.cookiesOnLastRequest = new ArrayList();
- } else {
- this.cookiesOnLastRequest = Arrays.asList(cookies);
- }
- // store parameters
- Map parmMap = request.getParameterMap();
- logger.info("PARM MAP: " + parmMap);
- if (parmMap == null) {
- this.parmsOnLastRequest = new ArrayList();
- } else {
- this.parmsOnLastRequest = new ArrayList();
- for (String name : parmMap.keySet()) {
- String[] values = parmMap.get(name);
- String delim = "";
- StringBuffer sb = new StringBuffer();
- if (values != null && values.length > 0) {
- for (String parm : values) {
- sb.append(delim).append(parm);
- delim = ",";
- }
- }
- RequestParameter parm = new RequestParameter(name, sb.toString());
- this.parmsOnLastRequest.add(parm);
- }
- }
- }
-
- /**
- * restartLesson.
- *
- * @param lessonId a int.
- */
- public void restartLesson(int lessonId) {
- AbstractLesson al = getLesson(lessonId);
- System.out.println("Restarting lesson: " + al);
- al.restartLesson();
- al.getLessonTracker(this).setCompleted(false);
- if (al instanceof SequentialLessonAdapter) {
- SequentialLessonAdapter sla = (SequentialLessonAdapter) al;
- sla.getLessonTracker(this).setStage(1);
- } else if (al instanceof RandomLessonAdapter) {
- RandomLessonAdapter rla = (RandomLessonAdapter) al;
- rla.setStage(this, rla.getStages()[0]);
- }
- }
-
- /**
- * setHasHackableAdmin.
- *
- * @param role a {@link java.lang.String} object.
- */
- public void setHasHackableAdmin(String role) {
- hasHackedHackableAdmin = (AbstractLesson.HACKED_ADMIN_ROLE.equals(role) & hasHackedHackableAdmin);
-
- // if the user got the Admin=true parameter correct AND they accessed an admin screen
- if (hasHackedHackableAdmin) {
- completedHackableAdmin = true;
- }
- }
-
- /**
- * isDebug.
- *
- * @return Returns the isDebug.
- */
- public boolean isDebug() {
- return isDebug;
- }
-
- /**
- * getHeader.
- *
- * @param header - request header value to return
- * @return a {@link java.lang.String} object.
- */
- public String getHeader(String header) {
- return getRequest().getHeader(header);
- }
-
- /**
- * getNextHint.
- *
- * @return a {@link java.lang.String} object.
- */
- public String getNextHint() {
- String hint = null;
-
- // FIXME
- int maxHints = getCurrentLesson().getHintCount(this);
- if (hintNum < maxHints - 1) {
- hintNum++;
-
- // Hints are indexed from 0
- getCurrentLesson().getLessonTracker(this).setMaxHintLevel(getHintNum() + 1);
-
- hint = (String) getCurrentLesson().getHint(this, getHintNum());
- }
-
- return hint;
- }
-
- /**
- * getPreviousHint.
- *
- * @return a {@link java.lang.String} object.
- */
- public String getPreviousHint() {
- String hint = null;
-
- if (hintNum > 0) {
- hintNum--;
-
- // Hints are indexed from 0
- getCurrentLesson().getLessonTracker(this).setMaxHintLevel(getHintNum() + 1);
-
- hint = (String) getCurrentLesson().getHint(this, getHintNum());
- }
-
- return hint;
- }
-
- /**
- * Setter for the field currentMenu
.
- *
- * @param ranking a {@link java.lang.Integer} object.
- */
- public void setCurrentMenu(Integer ranking) {
- currentMenu = ranking.intValue();
- }
-
- /**
- * Getter for the field currentMenu
.
- *
- * @return a int.
- */
- public int getCurrentMenu() {
- return currentMenu;
+ return currentUser.getUsername();
}
/**
@@ -1319,32 +110,4 @@ public class WebSession {
public WebgoatContext getWebgoatContext() {
return webgoatContext;
}
-
- /**
- * getCurrrentLanguage.
- *
- * @return a {@link java.lang.String} object.
- */
- public String getCurrrentLanguage() {
- return currentLanguage;
- }
-
- /**
- * Getter for the field cookiesOnLastRequest
.
- *
- * @return the cookiesOnLastRequest
- */
- public List getCookiesOnLastRequest() {
- return cookiesOnLastRequest;
- }
-
- /**
- * Getter for the field parmsOnLastRequest
.
- *
- * @return the parmsOnLastRequest
- */
- public List getParmsOnLastRequest() {
- return parmsOnLastRequest;
- }
-
}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/session/WebgoatContext.java b/webgoat-container/src/main/java/org/owasp/webgoat/session/WebgoatContext.java
index 3dd30ad4b..c2e0c7e12 100644
--- a/webgoat-container/src/main/java/org/owasp/webgoat/session/WebgoatContext.java
+++ b/webgoat-container/src/main/java/org/owasp/webgoat/session/WebgoatContext.java
@@ -1,9 +1,7 @@
package org.owasp.webgoat.session;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.servlet.http.HttpServlet;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Configuration;
/**
* WebgoatContext class.
@@ -11,62 +9,15 @@ import javax.servlet.http.HttpServlet;
* @version $Id: $Id
* @author dm
*/
+@Configuration
public class WebgoatContext {
- final Logger logger = LoggerFactory.getLogger(WebgoatContext.class);
-
- /** Constant DATABASE_CONNECTION_STRING="DatabaseConnectionString"
*/
- public final static String DATABASE_CONNECTION_STRING = "DatabaseConnectionString";
-
- /** Constant DATABASE_DRIVER="DatabaseDriver"
*/
- public final static String DATABASE_DRIVER = "DatabaseDriver";
-
- /** Constant DATABASE_USER="DatabaseUser"
*/
- public final static String DATABASE_USER = "DatabaseUser";
-
- /** Constant DATABASE_PASSWORD="DatabasePassword"
*/
- public final static String DATABASE_PASSWORD = "DatabasePassword";
-
- /** Constant ENTERPRISE="Enterprise"
*/
- public final static String ENTERPRISE = "Enterprise";
-
- /** Constant CODING_EXERCISES="CodingExercises"
*/
- public final static String CODING_EXERCISES = "CodingExercises";
-
- /** Constant SHOWCOOKIES="ShowCookies"
*/
- public final static String SHOWCOOKIES = "ShowCookies";
-
- /** Constant SHOWPARAMS="ShowParams"
*/
- public final static String SHOWPARAMS = "ShowParams";
-
- /** Constant SHOWREQUEST="ShowRequest"
*/
- public final static String SHOWREQUEST = "ShowRequest";
-
- /** Constant SHOWSOURCE="ShowSource"
*/
- public final static String SHOWSOURCE = "ShowSource";
-
- /** Constant SHOWSOLUTION="ShowSolution"
*/
- public final static String SHOWSOLUTION = "ShowSolution";
-
- /** Constant SHOWHINTS="ShowHints"
*/
- public final static String SHOWHINTS = "ShowHints";
-
- /** Constant FEEDBACK_ADDRESS_HTML="FeedbackAddressHTML"
*/
- public final static String FEEDBACK_ADDRESS_HTML = "FeedbackAddressHTML";
-
- /** Constant FEEDBACK_ADDRESS="email"
*/
- public final static String FEEDBACK_ADDRESS = "email";
-
- /** Constant DEBUG="debug"
*/
- public final static String DEBUG = "debug";
-
- /** Constant DEFAULTLANGUAGE="DefaultLanguage"
*/
- public final static String DEFAULTLANGUAGE = "DefaultLanguage";
-
+ @Value("${webgoat.database.connection.string}")
private String databaseConnectionString;
private String realConnectionString = null;
+ @Value("${webgoat.database.driver}")
private String databaseDriver;
private String databaseUser;
@@ -87,58 +38,17 @@ public class WebgoatContext {
private boolean codingExercises = false;
- private String feedbackAddress = "owasp-webgoat@list.owasp.org";
+ @Value("${webgoat.feedback.address}")
+ private String feedbackAddress;
- private String feedbackAddressHTML = "owasp-webgoat@list.owasp.org ";
+ @Value("${webgoat.feedback.address.html}")
+ private String feedbackAddressHTML = "";
private boolean isDebug = false;
- private String servletName;
-
- private HttpServlet servlet;
-
+ @Value("${webgoat.default.language}")
private String defaultLanguage;
- private java.nio.file.Path pluginDirectory;
-
- /**
- * Constructor for WebgoatContext.
- *
- * @param servlet a {@link javax.servlet.http.HttpServlet} object.
- */
- public WebgoatContext(HttpServlet servlet) {
- this.servlet = servlet;
- databaseConnectionString = getParameter(servlet, DATABASE_CONNECTION_STRING);
- databaseDriver = getParameter(servlet, DATABASE_DRIVER);
- databaseUser = getParameter(servlet, DATABASE_USER);
- databasePassword = getParameter(servlet, DATABASE_PASSWORD);
-
- // initialize from web.xml
- showParams = "true".equals(getParameter(servlet, SHOWPARAMS));
- showCookies = "true".equals(getParameter(servlet, SHOWCOOKIES));
- showSource = "true".equals(getParameter(servlet, SHOWSOURCE));
- showSolution = "true".equals(getParameter(servlet, SHOWSOLUTION));
- enterprise = "true".equals(getParameter(servlet, ENTERPRISE));
- codingExercises = "true".equals(getParameter(servlet, CODING_EXERCISES));
- feedbackAddressHTML = getParameter(servlet, FEEDBACK_ADDRESS_HTML) != null ? getParameter(servlet,
- FEEDBACK_ADDRESS_HTML)
- : feedbackAddressHTML;
- feedbackAddress = getParameter(servlet, FEEDBACK_ADDRESS) != null ? getParameter(servlet, FEEDBACK_ADDRESS)
- : feedbackAddress;
- showRequest = "true".equals(getParameter(servlet, SHOWREQUEST));
- isDebug = "true".equals(getParameter(servlet, DEBUG));
- servletName = servlet.getServletName();
- defaultLanguage = getParameter(servlet, DEFAULTLANGUAGE) != null ? new String(getParameter(servlet, DEFAULTLANGUAGE)) : new String("en");
- }
-
- private String getParameter(HttpServlet servlet, String key) {
- String value = System.getenv().get(key);
- if (value == null) {
- value = servlet.getInitParameter(key);
- }
- return value;
- }
-
/**
* returns the connection string with the real path to the database
* directory inserted at the word PATH
@@ -146,17 +56,7 @@ public class WebgoatContext {
* @return The databaseConnectionString value
*/
public String getDatabaseConnectionString() {
- if (realConnectionString == null) {
- try {
- String path = servlet.getServletContext().getRealPath("/database").replace('\\', '/');
- System.out.println("PATH: " + path);
- realConnectionString = databaseConnectionString.replaceAll("PATH", path);
- System.out.println("Database Connection String: " + realConnectionString);
- } catch (Exception e) {
- logger.error("Couldn't open database: check web.xml database parameters", e);
- }
- }
- return realConnectionString;
+ return this.databaseConnectionString;
}
/**
@@ -185,7 +85,7 @@ public class WebgoatContext {
public String getDatabasePassword() {
return (databasePassword);
}
-
+
/**
* isEnterprise.
*
@@ -231,15 +131,6 @@ public class WebgoatContext {
return isDebug;
}
- /**
- * Getter for the field servletName
.
- *
- * @return a {@link java.lang.String} object.
- */
- public String getServletName() {
- return servletName;
- }
-
/**
* isShowCookies.
*
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/session/WebgoatProperties.java b/webgoat-container/src/main/java/org/owasp/webgoat/session/WebgoatProperties.java
deleted file mode 100644
index 4ba24d72a..000000000
--- a/webgoat-container/src/main/java/org/owasp/webgoat/session/WebgoatProperties.java
+++ /dev/null
@@ -1,145 +0,0 @@
-package org.owasp.webgoat.session;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.util.Properties;
-
-/**
- * *************************************************************************************************
- *
- *
- * This file is part of WebGoat, an Open Web Application Security Project
- * utility. For details, please see http://www.owasp.org/
- *
- * Copyright (c) 2002 - 20014 Bruce Mayhew
- *
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License as published by the Free Software
- * Foundation; either version 2 of the License, or (at your option) any later
- * version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * Getting Source ==============
- *
- * Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository
- * for free software projects.
- *
- * @version $Id: $Id
- * @author dm
- */
-public class WebgoatProperties extends Properties {
-
- /**
- *
- */
- private static final long serialVersionUID = 4351681705558227918L;
- final Logger logger = LoggerFactory.getLogger(WebgoatProperties.class);
-
- /**
- * Constructor for WebgoatProperties.
- *
- * @param propertiesFileName a {@link java.lang.String} object.
- * @throws java.io.IOException if any.
- */
- public WebgoatProperties(String propertiesFileName) throws IOException {
- if (propertiesFileName == null) {
- throw new IOException("Path to webgoat.properties is null, initialization must have failed");
- }
- File propertiesFile = new File(propertiesFileName);
- if (propertiesFile.exists() == false) {
- throw new IOException("Unable to locate webgoat.properties at: " + propertiesFileName);
- }
- FileInputStream in = new FileInputStream(propertiesFile);
- load(in);
- }
-
- /**
- * getIntProperty.
- *
- * @param key a {@link java.lang.String} object.
- * @param defaultValue a int.
- * @return a int.
- */
- public int getIntProperty(String key, int defaultValue) {
- int value = defaultValue;
-
- String s = getProperty(key);
- if (s != null) {
- value = Integer.parseInt(s);
- }
-
- return value;
- }
-
- /**
- * getBooleanProperty.
- *
- * @param key a {@link java.lang.String} object.
- * @param defaultValue a boolean.
- * @return a boolean.
- */
- public boolean getBooleanProperty(String key, boolean defaultValue) {
- boolean value = defaultValue;
- key = this.trimLesson(key);
-
- String s = getProperty(key);
- if (s != null) {
- if (s.equalsIgnoreCase("true")) {
- value = true;
- } else if (s.equalsIgnoreCase("yes")) {
- value = true;
- } else if (s.equalsIgnoreCase("on")) {
- value = true;
- } else if (s.equalsIgnoreCase("false")) {
- value = false;
- } else if (s.equalsIgnoreCase("no")) {
- value = false;
- } else if (s.equalsIgnoreCase("off")) {
- value = false;
- }
- }
-
- return value;
- }
-
- private String trimLesson(String lesson) {
- String result = "";
-
- if (lesson.startsWith("org.owasp.webgoat.lessons.")) {
- result = lesson.substring("org.owasp.webgoat.lessons.".length(), lesson.length());
- } else {
- result = lesson;
- }
-
- return result;
- }
-
- /**
- * main.
- *
- * @param args an array of {@link java.lang.String} objects.
- */
- public static void main(String[] args) {
- WebgoatProperties properties = null;
- try {
- properties = new WebgoatProperties("C:\\webgoat.properties");
- } catch (IOException e) {
- System.out.println("Error loading properties");
- e.printStackTrace();
- }
- System.out.println(properties.getProperty("CommandInjection.category"));
- }
-
-}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/util/BeanProvider.java b/webgoat-container/src/main/java/org/owasp/webgoat/util/BeanProvider.java
deleted file mode 100644
index 49629eaf3..000000000
--- a/webgoat-container/src/main/java/org/owasp/webgoat/util/BeanProvider.java
+++ /dev/null
@@ -1,67 +0,0 @@
-
-package org.owasp.webgoat.util;
-
-import org.springframework.beans.BeansException;
-import org.springframework.context.ApplicationContext;
-import org.springframework.context.ApplicationContextAware;
-import org.springframework.stereotype.Component;
-
-
-/**
- *************************************************************************************************
- *
- *
- * This file is part of WebGoat, an Open Web Application Security Project utility. For details,
- * please see http://www.owasp.org/
- *
- * Copyright (c) 2002 - 20014 Bruce Mayhew
- *
- * This program is free software; you can redistribute it and/or modify it under the terms of the
- * GNU General Public License as published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
- * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with this program; if
- * not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- *
- * Getting Source ==============
- *
- * Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for
- * free software projects.
- *
- * @version $Id: $Id
- * @author dm
- */
-@Component
-public class BeanProvider implements ApplicationContextAware
-{
- private static ApplicationContext ctx;
-
- /** {@inheritDoc} */
- @Override
- public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
- {
- ctx = applicationContext;
-
- }
-
- /**
- * Get access to managed beans from id.
- *
- * @param beanName
- * the id of the searched bean
- * @param beanClass
- * the type of tye searched bean
- * @param a T object.
- * @return a T object.
- */
- @SuppressWarnings("unchecked")
- public static T getBean(final String beanName, final Class beanClass)
- {
- return (T) ctx.getBean(beanName);
- }
-}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/util/HtmlEncoder.java b/webgoat-container/src/main/java/org/owasp/webgoat/util/HtmlEncoder.java
deleted file mode 100644
index 3b7dfa62d..000000000
--- a/webgoat-container/src/main/java/org/owasp/webgoat/util/HtmlEncoder.java
+++ /dev/null
@@ -1,228 +0,0 @@
-
-package org.owasp.webgoat.util;
-
-import java.util.HashMap;
-import java.util.Map;
-
-
-/**
- *************************************************************************************************
- *
- *
- * This file is part of WebGoat, an Open Web Application Security Project utility. For details,
- * please see http://www.owasp.org/
- *
- * Copyright (c) 2002 - 20014 Bruce Mayhew
- *
- * This program is free software; you can redistribute it and/or modify it under the terms of the
- * GNU General Public License as published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
- * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with this program; if
- * not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- *
- * Getting Source ==============
- *
- * Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
- * projects.
- *
- * @version $Id: $Id
- * @author dm
- */
-public class HtmlEncoder
-{
-
- static Map e2i = new HashMap();
-
- static Map i2e = new HashMap();
-
- // html entity list
- private static Object[][] entities = { { "quot", new Integer(34) }, // " - double-quote
- { "amp", new Integer(38) }, // - ampersand
- { "lt", new Integer(60) }, // - less-than
- { "gt", new Integer(62) }, // - greater-than
- { "nbsp", new Integer(160) }, // non-breaking space
- { "copy", new Integer(169) }, // - copyright
- { "reg", new Integer(174) }, // - registered trademark
- { "Agrave", new Integer(192) }, // - uppercase A, grave accent
- { "Aacute", new Integer(193) }, // - uppercase A, acute accent
- { "Acirc", new Integer(194) }, // - uppercase A, circumflex accent
- { "Atilde", new Integer(195) }, // - uppercase A, tilde
- { "Auml", new Integer(196) }, // - uppercase A, umlaut
- { "Aring", new Integer(197) }, // - uppercase A, ring
- { "AElig", new Integer(198) }, // - uppercase AE
- { "Ccedil", new Integer(199) }, // - uppercase C, cedilla
- { "Egrave", new Integer(200) }, // - uppercase E, grave accent
- { "Eacute", new Integer(201) }, // - uppercase E, acute accent
- { "Ecirc", new Integer(202) }, // - uppercase E, circumflex accent
- { "Euml", new Integer(203) }, // - uppercase E, umlaut
- { "Igrave", new Integer(204) }, // - uppercase I, grave accent
- { "Iacute", new Integer(205) }, // - uppercase I, acute accent
- { "Icirc", new Integer(206) }, // - uppercase I, circumflex accent
- { "Iuml", new Integer(207) }, // - uppercase I, umlaut
- { "ETH", new Integer(208) }, // - uppercase Eth, Icelandic
- { "Ntilde", new Integer(209) }, // - uppercase N, tilde
- { "Ograve", new Integer(210) }, // - uppercase O, grave accent
- { "Oacute", new Integer(211) }, // - uppercase O, acute accent
- { "Ocirc", new Integer(212) }, // - uppercase O, circumflex accent
- { "Otilde", new Integer(213) }, // - uppercase O, tilde
- { "Ouml", new Integer(214) }, // - uppercase O, umlaut
- { "Oslash", new Integer(216) }, // - uppercase O, slash
- { "Ugrave", new Integer(217) }, // - uppercase U, grave accent
- { "Uacute", new Integer(218) }, // - uppercase U, acute accent
- { "Ucirc", new Integer(219) }, // - uppercase U, circumflex accent
- { "Uuml", new Integer(220) }, // - uppercase U, umlaut
- { "Yacute", new Integer(221) }, // - uppercase Y, acute accent
- { "THORN", new Integer(222) }, // - uppercase THORN, Icelandic
- { "szlig", new Integer(223) }, // - lowercase sharps, German
- { "agrave", new Integer(224) }, // - lowercase a, grave accent
- { "aacute", new Integer(225) }, // - lowercase a, acute accent
- { "acirc", new Integer(226) }, // - lowercase a, circumflex accent
- { "atilde", new Integer(227) }, // - lowercase a, tilde
- { "auml", new Integer(228) }, // - lowercase a, umlaut
- { "aring", new Integer(229) }, // - lowercase a, ring
- { "aelig", new Integer(230) }, // - lowercase ae
- { "ccedil", new Integer(231) }, // - lowercase c, cedilla
- { "egrave", new Integer(232) }, // - lowercase e, grave accent
- { "eacute", new Integer(233) }, // - lowercase e, acute accent
- { "ecirc", new Integer(234) }, // - lowercase e, circumflex accent
- { "euml", new Integer(235) }, // - lowercase e, umlaut
- { "igrave", new Integer(236) }, // - lowercase i, grave accent
- { "iacute", new Integer(237) }, // - lowercase i, acute accent
- { "icirc", new Integer(238) }, // - lowercase i, circumflex accent
- { "iuml", new Integer(239) }, // - lowercase i, umlaut
- { "igrave", new Integer(236) }, // - lowercase i, grave accent
- { "iacute", new Integer(237) }, // - lowercase i, acute accent
- { "icirc", new Integer(238) }, // - lowercase i, circumflex accent
- { "iuml", new Integer(239) }, // - lowercase i, umlaut
- { "eth", new Integer(240) }, // - lowercase eth, Icelandic
- { "ntilde", new Integer(241) }, // - lowercase n, tilde
- { "ograve", new Integer(242) }, // - lowercase o, grave accent
- { "oacute", new Integer(243) }, // - lowercase o, acute accent
- { "ocirc", new Integer(244) }, // - lowercase o, circumflex accent
- { "otilde", new Integer(245) }, // - lowercase o, tilde
- { "ouml", new Integer(246) }, // - lowercase o, umlaut
- { "oslash", new Integer(248) }, // - lowercase o, slash
- { "ugrave", new Integer(249) }, // - lowercase u, grave accent
- { "uacute", new Integer(250) }, // - lowercase u, acute accent
- { "ucirc", new Integer(251) }, // - lowercase u, circumflex accent
- { "uuml", new Integer(252) }, // - lowercase u, umlaut
- { "yacute", new Integer(253) }, // - lowercase y, acute accent
- { "thorn", new Integer(254) }, // - lowercase thorn, Icelandic
- { "yuml", new Integer(255) }, // - lowercase y, umlaut
- { "euro", new Integer(8364) },// Euro symbol
- };
-
- /**
- * Initialises the mappings between entities and characters
- */
- static {
- for (int i = 0; i < entities.length; i++)
- e2i.put((String) entities[i][0], (Integer) entities[i][1]);
- for (int i = 0; i < entities.length; i++)
- i2e.put((Integer) entities[i][1], (String) entities[i][0]);
- }
-
- /**
- * Turns funky characters into HTML entity equivalents
- *
- * e.g. {@code "bread" & "butter"} = {@code "bread" &
- * "butter"}. Update: supports nearly all HTML entities, including funky
- * accents. See the source code for more detail. Adapted from
- * http://www.purpletech.com/code/src/com/purpletech/util/Utils.java.
- *
- * @param s1
- * Description of the Parameter
- * @return Description of the Return Value
- */
- public static String encode(String s1)
- {
- StringBuffer buf = new StringBuffer();
-
- int i;
- for (i = 0; i < s1.length(); ++i)
- {
- char ch = s1.charAt(i);
-
- String entity = i2e.get(new Integer((int) ch));
-
- if (entity == null)
- {
- if (((int) ch) > 128)
- {
- buf.append("" + ((int) ch) + ";");
- }
- else
- {
- buf.append(ch);
- }
- }
- else
- {
- buf.append("&" + entity + ";");
- }
- }
-
- return buf.toString();
- }
-
- /**
- * Given a string containing entity escapes, returns a string containing the actual Unicode
- * characters corresponding to the escapes. Adapted from
- * http://www.purpletech.com/code/src/com/purpletech/util/Utils.java.
- *
- * @param s1
- * Description of the Parameter
- * @return Description of the Return Value
- */
- public static String decode(String s1)
- {
- StringBuffer buf = new StringBuffer();
-
- int i;
- for (i = 0; i < s1.length(); ++i)
- {
- char ch = s1.charAt(i);
-
- if (ch == '&')
- {
- int semi = s1.indexOf(';', i + 1);
- if (semi == -1)
- {
- buf.append(ch);
- continue;
- }
- String entity = s1.substring(i + 1, semi);
- Integer iso;
- if (entity.charAt(0) == '#')
- {
- iso = new Integer(entity.substring(1));
- }
- else
- {
- iso = e2i.get(entity);
- }
- if (iso == null)
- {
- buf.append("&" + entity + ";");
- }
- else
- {
- buf.append((char) (iso.intValue()));
- }
- i = semi;
- }
- else
- {
- buf.append(ch);
- }
- }
-
- return buf.toString();
- }
-}
diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/util/WebGoatI18N.java b/webgoat-container/src/main/java/org/owasp/webgoat/util/WebGoatI18N.java
deleted file mode 100644
index 95d31a94c..000000000
--- a/webgoat-container/src/main/java/org/owasp/webgoat/util/WebGoatI18N.java
+++ /dev/null
@@ -1,93 +0,0 @@
-package org.owasp.webgoat.util;
-
-import java.util.HashMap;
-import java.util.Locale;
-import java.util.ResourceBundle;
-
-import org.owasp.webgoat.session.WebgoatContext;
-
-@Deprecated
-/**
- * WebGoatI18N class.
- *
- * @version $Id: $Id
- * @author dm
- */
-public class WebGoatI18N
-{
-
- private static HashMap labels = new HashMap();
- private static Locale currentLocale;
- private static WebGoatResourceBundleController localeController;
-
- /**
- * Constructor for WebGoatI18N.
- *
- * @param context a {@link org.owasp.webgoat.session.WebgoatContext} object.
- */
- public WebGoatI18N(WebgoatContext context)
- {
- currentLocale = new Locale(context.getDefaultLanguage());
- localeController = new WebGoatResourceBundleController(currentLocale);
- }
-
- /**
- * loadLanguage.
- *
- * @param language a {@link java.lang.String} object.
- */
- @Deprecated
- public static void loadLanguage(String language)
- {
- // Do nothing
- }
-
- /**
- * Setter for the field currentLocale
.
- *
- * @param locale a {@link java.util.Locale} object.
- */
- public static void setCurrentLocale(Locale locale)
- {
- if (!currentLocale.equals(locale))
- {
- if (!labels.containsKey(locale))
- {
- ResourceBundle resBundle = ResourceBundle.getBundle("WebGoatLabels", locale, localeController);
- labels.put(locale, resBundle);
- }
- WebGoatI18N.currentLocale = locale;
- }
- }
-
- /**
- * get.
- *
- * @param strName a {@link java.lang.String} object.
- * @return a {@link java.lang.String} object.
- */
- public static String get(String strName)
- {
- return labels.get(WebGoatI18N.currentLocale).getString(strName);
- }
-
- private static class WebGoatResourceBundleController extends ResourceBundle.Control
- {
- private Locale fallbackLocale;
-
- public WebGoatResourceBundleController(Locale l)
- {
- fallbackLocale = l;
- }
-
- @Override
- public Locale getFallbackLocale(String baseName, Locale locale)
- {
- if(! fallbackLocale.equals(locale)) {
- return fallbackLocale;
- }
- return Locale.ROOT;
- }
- }
-
-}
diff --git a/webgoat-container/src/main/resources/New Lesson Instructions.txt b/webgoat-container/src/main/resources/New Lesson Instructions.txt
deleted file mode 100644
index f861cfc82..000000000
--- a/webgoat-container/src/main/resources/New Lesson Instructions.txt
+++ /dev/null
@@ -1,193 +0,0 @@
-Detailed instructions for adding a lesson
-
-All you have to do is implement the abstract methods in LessonAdapter.
-Follow the outline below.
-
-WebGoat uses the Element Construction Set from the Jakarta project.
-You should read up on the API for ECS at
-http://jakarta.apache.org/site/downloads/downloads_ecs.cgi.
-In addition you can look at the other lessons for examples of how to use the ECS.
-
-
-
-Step 1: Set up the framework
-
-import java.util.*;
-import org.apache.ecs.*;
-import org.apache.ecs.html.*;
-
-// Add copyright text - use text from another lesson
-
-public class NewLesson extends LessonAdapter
-{
-
- protected Element createContent(WebSession s)
- {
- return( new StringElement( "Hello World" ) );
- }
-
- public String getCategory()
- {
- }
-
- protected List getHints()
- {
- }
-
- protected String getInstructions()
- {
- }
-
- protected Element getMenuItem()
- {
- }
-
- protected Integer getRanking()
- {
- }
-
- public String getTitle()
- {
- }
-}
-
-
-
-Step 2: Implement createContent
-
-Creating the content for a lesson is fairly simple. There are two main parts:
- (1) handling the input from the user's last request,
- (2) generating the next screen for the user.
-This all happens within the createContent method. Remember that each lesson
-should be handled on a single page, so you'll need to design your lesson to
-work that way. A good generic pattern for the createContent method is shown
-below:
-
-// define a constant for the field name
-private static final String INPUT = "input";
-
-protected Element createContent(WebSession s)
-{
- ElementContainer ec = new ElementContainer();
- try
- {
- // get some input from the user -- see ParameterParser
- // for details
- String userInput = s.getParser().getStringParameter(INPUT, "");
-
- // do something with the input
- // -- SQL query?
- // -- Runtime.exec?
- // -- Some other dangerous thing
-
- // generate some output -- a string and an input field
- ec.addElement(new StringElement("Enter a string: "));
- ec.addElement( new Input(Input.TEXT, INPUT, userInput) );
-
- // Tell the lesson tracker the lesson has completed.
- // This should occur when the user has 'hacked' the lesson.
- makeSuccess(s);
-
- }
- catch (Exception e)
- {
- s.setMessage("Error generating " + this.getClass().getName());
- e.printStackTrace();
- }
- return (ec);
-}
-
-ECS is quite powerful -- see the Encoding lesson for an example of how
-to use it to create a table with rows and rows of output.
-
-
-Step 3: Implement the other methods
-
-The other methods in the LessonAdapter class help the lesson plug into
-the overall WebGoat framework. They are simple and should only take a
-few minutes to implement.
-
-public String getCategory()
-{
- // The default category is "General" Only override this
- // method if you wish to create a new category or if you
- // wish this lesson to reside within a category other the
- // "General"
-
- return( "NewCategory" ); // or use an existing category
-}
-
-protected List getHints()
-{
- // Hints will be returned to the user in the order they
- // appear below. The user must click on the "next hint"
- // button before the hint will be displayed.
-
- List hints = new ArrayList();
- hints.add("A general hint to put users on the right track");
- hints.add("A hint that gives away a little piece of the problem");
- hints.add("A hint that basically gives the answer");
- return hints;
-}
-
-protected String getInstructions()
-{
- // Instructions will rendered as html and will appear below
- // the area and above the actual lesson area.
- // Instructions should provide the user with the general setup
- // and goal of the lesson.
-
- return("The text that goes at the top of the page");
-}
-
-protected Element getMenuItem()
-{
- // This is the text of the link that will appear on
- // the left hand menus under the appropriate category.
- // Their is a limited amount of horizontal space in
- // this area before wrapping will occur.
-
- return( "MyLesson" );
-}
-
-protected Integer getRanking()
-{
- // The ranking denotes the order in which the menu item
- // will appear in menu list for each category. The lowest
- // number will appear as the first lesson.
-
- return new Integer(10);
-}
-
-public String getTitle()
-{
- // The title of the lesson. This will appear above the
- // control area at the top of the page. This field will
- // be rendered as html.
-
- return ("My Lesson's Short Title");
-}
-
-
-Step 4: Build and test
-
-Once you've implemented your new lesson, you can test the lesson by
-starting the Tomcat server (within Eclipse). See the
-"readme.txt" document in the WebGoat root.
-
-
-Step 5: Create the lesson plan
-
-All WebGoat lessons have a lesson plan that describes the goals of the lesson.
-Create a lesson plan and put it in lesson_plans folder for each supported language.
-
-
-Step 6: Give back to the community
-
-If you've come up with a lesson that you think helps to teach people about
-web application security, please contribute it by sending it to the people
-who maintain the WebGoat application.
-
-Thanks!
-
-The WebGoat Team.
diff --git a/webgoat-container/src/main/resources/application.properties b/webgoat-container/src/main/resources/application.properties
new file mode 100644
index 000000000..57bb003a6
--- /dev/null
+++ b/webgoat-container/src/main/resources/application.properties
@@ -0,0 +1,34 @@
+server.error.include-stacktrace=always
+server.error.path=/error.html
+server.session.timeout=600
+server.contextPath=/WebGoat
+server.port=8080
+
+
+logging.level.org.springframework=WARN
+logging.level.org.springframework.boot.devtools=DEBUG
+logging.level.org.owasp=DEBUG
+logging.level.org.owasp.webgoat=TRACE
+
+spring.thymeleaf.cache=false
+spring.thymeleaf.content-type=text/html
+security.enable-csrf=false
+
+spring.devtools.restart.enabled=true
+
+
+webgoat.user.directory=${user.home}/.webgoat/
+webgoat.build.version=@project.version@
+webgoat.build.number=@build.number@
+webgoat.email=webgoat@owasp.org
+webgoat.emaillist=owasp-webgoat@lists.owasp.org
+webgoat.feedback.address=webgoat@owasp.org
+webgoat.feedback.address.html=webgoat@owasp.org
+webgoat.database.driver=org.hsqldb.jdbcDriver
+webgoat.database.connection.string=jdbc:hsqldb:mem:test
+# TODO_NB
+#webgoat.database.connection.string=jdbc:hsqldb:mem:${USER}
+webgoat.default.language=en
+
+
+
diff --git a/webgoat-container/src/main/resources/log4j.properties b/webgoat-container/src/main/resources/log4j.properties
deleted file mode 100644
index 2d27828df..000000000
--- a/webgoat-container/src/main/resources/log4j.properties
+++ /dev/null
@@ -1,48 +0,0 @@
-log4j.rootLogger=DEBUG, MAIN_LOG,CONSOLE
-#log4j.rootLogger=DEBUG, MAIN_LOG, ERROR_LOG
-
-# MAIN - everything gets logged here
-log4j.appender.MAIN_LOG=org.apache.log4j.RollingFileAppender
-log4j.appender.MAIN_LOG.File=${catalina.home}/logs/webgoat_main.log
-log4j.appender.MAIN_LOG.layout=org.apache.log4j.PatternLayout
-log4j.appender.MAIN_LOG.layout.ConversionPattern=%d [%t] %-5p %c %x - %m%n
-log4j.appender.MAIN_LOG.MaxFileSize=10MB
-log4j.appender.MAIN_LOG.MaxBackupIndex=5
-log4j.appender.MAIN_LOG.append=true
-
-log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
-log4j.appender.CONSOLE.Target=System.out
-log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
-log4j.appender.CONSOLE.layout.conversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %-5p - %m%n
-
-
-# a little less spring output
-log4j.category.org.springframework = INFO
-log4j.category.org.apache=INFO
-
-log4j.appender.default.out=org.apache.log4j.ConsoleAppender
-log4j.appender.default.out.threeshold=DEBUG
-log4j.appender.default.out.layout=org.apache.log4j.PatternLayout
-log4j.appender.default.out.layout.ConversionPattern=%-5p %c: %m%n
-
-# ERROR
-log4j.appender.ERROR_LOG=org.apache.log4j.RollingFileAppender
-log4j.appender.ERROR_LOG.File=${catalina.home}/logs/webgoat_error.log
-log4j.appender.ERROR_LOG.layout=org.apache.log4j.PatternLayout
-log4j.appender.ERROR_LOG.layout.ConversionPattern=%d [%t] %-5p %x - %m%n
-log4j.appender.ERROR_LOG.MaxFileSize=10MB
-log4j.appender.ERROR_LOG.MaxBackupIndex=2
-log4j.appender.ERROR_LOG.append=true
-log4j.appender.ERROR_LOG.Threshold=ERROR
-
-# PERFORMANCE
-log4j.logger.PERF_LOG=DEBUG, PERF_LOG
-log4j.appender.PERF_LOG=org.apache.log4j.RollingFileAppender
-log4j.appender.PERF_LOG.File=${catalina.home}/logs/webgoat_perf.log
-log4j.appender.PERF_LOG.layout=org.apache.log4j.PatternLayout
-log4j.appender.PERF_LOG.layout.ConversionPattern=%m%n
-log4j.appender.PERF_LOG.MaxFileSize=10MB
-log4j.appender.PERF_LOG.MaxBackupIndex=2
-log4j.appender.PERF_LOG.append=true
-log4j.additivity.PERF_LOG = false
-
diff --git a/webgoat-container/src/main/webapp/plugin_lessons/ReadMe.txt b/webgoat-container/src/main/resources/plugin_lessons/ReadMe.txt
similarity index 100%
rename from webgoat-container/src/main/webapp/plugin_lessons/ReadMe.txt
rename to webgoat-container/src/main/resources/plugin_lessons/ReadMe.txt
diff --git a/webgoat-container/src/main/webapp/WEB-INF/lib/placeholder.txt b/webgoat-container/src/main/resources/plugin_lessons/plugin_lessons_marker.txt
similarity index 100%
rename from webgoat-container/src/main/webapp/WEB-INF/lib/placeholder.txt
rename to webgoat-container/src/main/resources/plugin_lessons/plugin_lessons_marker.txt
diff --git a/webgoat-container/src/main/webapp/css/animate.css b/webgoat-container/src/main/resources/static/css/animate.css
similarity index 95%
rename from webgoat-container/src/main/webapp/css/animate.css
rename to webgoat-container/src/main/resources/static/css/animate.css
index 97f28788e..d71da17ae 100644
--- a/webgoat-container/src/main/webapp/css/animate.css
+++ b/webgoat-container/src/main/resources/static/css/animate.css
@@ -1,2744 +1,2744 @@
-@charset "UTF-8";
-
-
-/*!
-Animate.css - http://daneden.me/animate
-Licensed under the MIT license
-
-Copyright (c) 2013 Daniel Eden
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-*/
-
-.animated {
- -webkit-animation-duration: 1s;
- animation-duration: 1s;
- -webkit-animation-fill-mode: both;
- animation-fill-mode: both;
-}
-
-.animated.hinge {
- -webkit-animation-duration: 2s;
- animation-duration: 2s;
-}
-
-@-webkit-keyframes bounce {
- 0%, 20%, 50%, 80%, 100% {
- -webkit-transform: translateY(0);
- transform: translateY(0);
- }
-
- 40% {
- -webkit-transform: translateY(-30px);
- transform: translateY(-30px);
- }
-
- 60% {
- -webkit-transform: translateY(-15px);
- transform: translateY(-15px);
- }
-}
-
-@keyframes bounce {
- 0%, 20%, 50%, 80%, 100% {
- -webkit-transform: translateY(0);
- -ms-transform: translateY(0);
- transform: translateY(0);
- }
-
- 40% {
- -webkit-transform: translateY(-30px);
- -ms-transform: translateY(-30px);
- transform: translateY(-30px);
- }
-
- 60% {
- -webkit-transform: translateY(-15px);
- -ms-transform: translateY(-15px);
- transform: translateY(-15px);
- }
-}
-
-.bounce {
- -webkit-animation-name: bounce;
- animation-name: bounce;
-}
-
-@-webkit-keyframes flash {
- 0%, 50%, 100% {
- opacity: 1;
- }
-
- 25%, 75% {
- opacity: 0;
- }
-}
-
-@keyframes flash {
- 0%, 50%, 100% {
- opacity: 1;
- }
-
- 25%, 75% {
- opacity: 0;
- }
-}
-
-.flash {
- -webkit-animation-name: flash;
- animation-name: flash;
-}
-
-/* originally authored by Nick Pettit - https://github.com/nickpettit/glide */
-
-@-webkit-keyframes pulse {
- 0% {
- -webkit-transform: scale(1);
- transform: scale(1);
- }
-
- 50% {
- -webkit-transform: scale(1.1);
- transform: scale(1.1);
- }
-
- 100% {
- -webkit-transform: scale(1);
- transform: scale(1);
- }
-}
-
-@keyframes pulse {
- 0% {
- -webkit-transform: scale(1);
- -ms-transform: scale(1);
- transform: scale(1);
- }
-
- 50% {
- -webkit-transform: scale(1.1);
- -ms-transform: scale(1.1);
- transform: scale(1.1);
- }
-
- 100% {
- -webkit-transform: scale(1);
- -ms-transform: scale(1);
- transform: scale(1);
- }
-}
-
-.pulse {
- -webkit-animation-name: pulse;
- animation-name: pulse;
-}
-
-@-webkit-keyframes shake {
- 0%, 100% {
- -webkit-transform: translateX(0);
- transform: translateX(0);
- }
-
- 10%, 30%, 50%, 70%, 90% {
- -webkit-transform: translateX(-10px);
- transform: translateX(-10px);
- }
-
- 20%, 40%, 60%, 80% {
- -webkit-transform: translateX(10px);
- transform: translateX(10px);
- }
-}
-
-@keyframes shake {
- 0%, 100% {
- -webkit-transform: translateX(0);
- -ms-transform: translateX(0);
- transform: translateX(0);
- }
-
- 10%, 30%, 50%, 70%, 90% {
- -webkit-transform: translateX(-10px);
- -ms-transform: translateX(-10px);
- transform: translateX(-10px);
- }
-
- 20%, 40%, 60%, 80% {
- -webkit-transform: translateX(10px);
- -ms-transform: translateX(10px);
- transform: translateX(10px);
- }
-}
-
-.shake {
- -webkit-animation-name: shake;
- animation-name: shake;
-}
-
-@-webkit-keyframes swing {
- 20% {
- -webkit-transform: rotate(15deg);
- transform: rotate(15deg);
- }
-
- 40% {
- -webkit-transform: rotate(-10deg);
- transform: rotate(-10deg);
- }
-
- 60% {
- -webkit-transform: rotate(5deg);
- transform: rotate(5deg);
- }
-
- 80% {
- -webkit-transform: rotate(-5deg);
- transform: rotate(-5deg);
- }
-
- 100% {
- -webkit-transform: rotate(0deg);
- transform: rotate(0deg);
- }
-}
-
-@keyframes swing {
- 20% {
- -webkit-transform: rotate(15deg);
- -ms-transform: rotate(15deg);
- transform: rotate(15deg);
- }
-
- 40% {
- -webkit-transform: rotate(-10deg);
- -ms-transform: rotate(-10deg);
- transform: rotate(-10deg);
- }
-
- 60% {
- -webkit-transform: rotate(5deg);
- -ms-transform: rotate(5deg);
- transform: rotate(5deg);
- }
-
- 80% {
- -webkit-transform: rotate(-5deg);
- -ms-transform: rotate(-5deg);
- transform: rotate(-5deg);
- }
-
- 100% {
- -webkit-transform: rotate(0deg);
- -ms-transform: rotate(0deg);
- transform: rotate(0deg);
- }
-}
-
-.swing {
- -webkit-transform-origin: top center;
- -ms-transform-origin: top center;
- transform-origin: top center;
- -webkit-animation-name: swing;
- animation-name: swing;
-}
-
-@-webkit-keyframes tada {
- 0% {
- -webkit-transform: scale(1);
- transform: scale(1);
- }
-
- 10%, 20% {
- -webkit-transform: scale(0.9) rotate(-3deg);
- transform: scale(0.9) rotate(-3deg);
- }
-
- 30%, 50%, 70%, 90% {
- -webkit-transform: scale(1.1) rotate(3deg);
- transform: scale(1.1) rotate(3deg);
- }
-
- 40%, 60%, 80% {
- -webkit-transform: scale(1.1) rotate(-3deg);
- transform: scale(1.1) rotate(-3deg);
- }
-
- 100% {
- -webkit-transform: scale(1) rotate(0);
- transform: scale(1) rotate(0);
- }
-}
-
-@keyframes tada {
- 0% {
- -webkit-transform: scale(1);
- -ms-transform: scale(1);
- transform: scale(1);
- }
-
- 10%, 20% {
- -webkit-transform: scale(0.9) rotate(-3deg);
- -ms-transform: scale(0.9) rotate(-3deg);
- transform: scale(0.9) rotate(-3deg);
- }
-
- 30%, 50%, 70%, 90% {
- -webkit-transform: scale(1.1) rotate(3deg);
- -ms-transform: scale(1.1) rotate(3deg);
- transform: scale(1.1) rotate(3deg);
- }
-
- 40%, 60%, 80% {
- -webkit-transform: scale(1.1) rotate(-3deg);
- -ms-transform: scale(1.1) rotate(-3deg);
- transform: scale(1.1) rotate(-3deg);
- }
-
- 100% {
- -webkit-transform: scale(1) rotate(0);
- -ms-transform: scale(1) rotate(0);
- transform: scale(1) rotate(0);
- }
-}
-
-.tada {
- -webkit-animation-name: tada;
- animation-name: tada;
-}
-
-/* originally authored by Nick Pettit - https://github.com/nickpettit/glide */
-
-@-webkit-keyframes wobble {
- 0% {
- -webkit-transform: translateX(0%);
- transform: translateX(0%);
- }
-
- 15% {
- -webkit-transform: translateX(-25%) rotate(-5deg);
- transform: translateX(-25%) rotate(-5deg);
- }
-
- 30% {
- -webkit-transform: translateX(20%) rotate(3deg);
- transform: translateX(20%) rotate(3deg);
- }
-
- 45% {
- -webkit-transform: translateX(-15%) rotate(-3deg);
- transform: translateX(-15%) rotate(-3deg);
- }
-
- 60% {
- -webkit-transform: translateX(10%) rotate(2deg);
- transform: translateX(10%) rotate(2deg);
- }
-
- 75% {
- -webkit-transform: translateX(-5%) rotate(-1deg);
- transform: translateX(-5%) rotate(-1deg);
- }
-
- 100% {
- -webkit-transform: translateX(0%);
- transform: translateX(0%);
- }
-}
-
-@keyframes wobble {
- 0% {
- -webkit-transform: translateX(0%);
- -ms-transform: translateX(0%);
- transform: translateX(0%);
- }
-
- 15% {
- -webkit-transform: translateX(-25%) rotate(-5deg);
- -ms-transform: translateX(-25%) rotate(-5deg);
- transform: translateX(-25%) rotate(-5deg);
- }
-
- 30% {
- -webkit-transform: translateX(20%) rotate(3deg);
- -ms-transform: translateX(20%) rotate(3deg);
- transform: translateX(20%) rotate(3deg);
- }
-
- 45% {
- -webkit-transform: translateX(-15%) rotate(-3deg);
- -ms-transform: translateX(-15%) rotate(-3deg);
- transform: translateX(-15%) rotate(-3deg);
- }
-
- 60% {
- -webkit-transform: translateX(10%) rotate(2deg);
- -ms-transform: translateX(10%) rotate(2deg);
- transform: translateX(10%) rotate(2deg);
- }
-
- 75% {
- -webkit-transform: translateX(-5%) rotate(-1deg);
- -ms-transform: translateX(-5%) rotate(-1deg);
- transform: translateX(-5%) rotate(-1deg);
- }
-
- 100% {
- -webkit-transform: translateX(0%);
- -ms-transform: translateX(0%);
- transform: translateX(0%);
- }
-}
-
-.wobble {
- -webkit-animation-name: wobble;
- animation-name: wobble;
-}
-
-@-webkit-keyframes bounceIn {
- 0% {
- opacity: 0;
- -webkit-transform: scale(.3);
- transform: scale(.3);
- }
-
- 50% {
- opacity: 1;
- -webkit-transform: scale(1.05);
- transform: scale(1.05);
- }
-
- 70% {
- -webkit-transform: scale(.9);
- transform: scale(.9);
- }
-
- 100% {
- -webkit-transform: scale(1);
- transform: scale(1);
- }
-}
-
-@keyframes bounceIn {
- 0% {
- opacity: 0;
- -webkit-transform: scale(.3);
- -ms-transform: scale(.3);
- transform: scale(.3);
- }
-
- 50% {
- opacity: 1;
- -webkit-transform: scale(1.05);
- -ms-transform: scale(1.05);
- transform: scale(1.05);
- }
-
- 70% {
- -webkit-transform: scale(.9);
- -ms-transform: scale(.9);
- transform: scale(.9);
- }
-
- 100% {
- -webkit-transform: scale(1);
- -ms-transform: scale(1);
- transform: scale(1);
- }
-}
-
-.bounceIn {
- -webkit-animation-name: bounceIn;
- animation-name: bounceIn;
-}
-
-@-webkit-keyframes bounceInDown {
- 0% {
- opacity: 0;
- -webkit-transform: translateY(-2000px);
- transform: translateY(-2000px);
- }
-
- 60% {
- opacity: 1;
- -webkit-transform: translateY(30px);
- transform: translateY(30px);
- }
-
- 80% {
- -webkit-transform: translateY(-10px);
- transform: translateY(-10px);
- }
-
- 100% {
- -webkit-transform: translateY(0);
- transform: translateY(0);
- }
-}
-
-@keyframes bounceInDown {
- 0% {
- opacity: 0;
- -webkit-transform: translateY(-2000px);
- -ms-transform: translateY(-2000px);
- transform: translateY(-2000px);
- }
-
- 60% {
- opacity: 1;
- -webkit-transform: translateY(30px);
- -ms-transform: translateY(30px);
- transform: translateY(30px);
- }
-
- 80% {
- -webkit-transform: translateY(-10px);
- -ms-transform: translateY(-10px);
- transform: translateY(-10px);
- }
-
- 100% {
- -webkit-transform: translateY(0);
- -ms-transform: translateY(0);
- transform: translateY(0);
- }
-}
-
-.bounceInDown {
- -webkit-animation-name: bounceInDown;
- animation-name: bounceInDown;
-}
-
-@-webkit-keyframes bounceInLeft {
- 0% {
- opacity: 0;
- -webkit-transform: translateX(-2000px);
- transform: translateX(-2000px);
- }
-
- 60% {
- opacity: 1;
- -webkit-transform: translateX(30px);
- transform: translateX(30px);
- }
-
- 80% {
- -webkit-transform: translateX(-10px);
- transform: translateX(-10px);
- }
-
- 100% {
- -webkit-transform: translateX(0);
- transform: translateX(0);
- }
-}
-
-@keyframes bounceInLeft {
- 0% {
- opacity: 0;
- -webkit-transform: translateX(-2000px);
- -ms-transform: translateX(-2000px);
- transform: translateX(-2000px);
- }
-
- 60% {
- opacity: 1;
- -webkit-transform: translateX(30px);
- -ms-transform: translateX(30px);
- transform: translateX(30px);
- }
-
- 80% {
- -webkit-transform: translateX(-10px);
- -ms-transform: translateX(-10px);
- transform: translateX(-10px);
- }
-
- 100% {
- -webkit-transform: translateX(0);
- -ms-transform: translateX(0);
- transform: translateX(0);
- }
-}
-
-.bounceInLeft {
- -webkit-animation-name: bounceInLeft;
- animation-name: bounceInLeft;
-}
-
-@-webkit-keyframes bounceInRight {
- 0% {
- opacity: 0;
- -webkit-transform: translateX(2000px);
- transform: translateX(2000px);
- }
-
- 60% {
- opacity: 1;
- -webkit-transform: translateX(-30px);
- transform: translateX(-30px);
- }
-
- 80% {
- -webkit-transform: translateX(10px);
- transform: translateX(10px);
- }
-
- 100% {
- -webkit-transform: translateX(0);
- transform: translateX(0);
- }
-}
-
-@keyframes bounceInRight {
- 0% {
- opacity: 0;
- -webkit-transform: translateX(2000px);
- -ms-transform: translateX(2000px);
- transform: translateX(2000px);
- }
-
- 60% {
- opacity: 1;
- -webkit-transform: translateX(-30px);
- -ms-transform: translateX(-30px);
- transform: translateX(-30px);
- }
-
- 80% {
- -webkit-transform: translateX(10px);
- -ms-transform: translateX(10px);
- transform: translateX(10px);
- }
-
- 100% {
- -webkit-transform: translateX(0);
- -ms-transform: translateX(0);
- transform: translateX(0);
- }
-}
-
-.bounceInRight {
- -webkit-animation-name: bounceInRight;
- animation-name: bounceInRight;
-}
-
-@-webkit-keyframes bounceInUp {
- 0% {
- opacity: 0;
- -webkit-transform: translateY(2000px);
- transform: translateY(2000px);
- }
-
- 60% {
- opacity: 1;
- -webkit-transform: translateY(-30px);
- transform: translateY(-30px);
- }
-
- 80% {
- -webkit-transform: translateY(10px);
- transform: translateY(10px);
- }
-
- 100% {
- -webkit-transform: translateY(0);
- transform: translateY(0);
- }
-}
-
-@keyframes bounceInUp {
- 0% {
- opacity: 0;
- -webkit-transform: translateY(2000px);
- -ms-transform: translateY(2000px);
- transform: translateY(2000px);
- }
-
- 60% {
- opacity: 1;
- -webkit-transform: translateY(-30px);
- -ms-transform: translateY(-30px);
- transform: translateY(-30px);
- }
-
- 80% {
- -webkit-transform: translateY(10px);
- -ms-transform: translateY(10px);
- transform: translateY(10px);
- }
-
- 100% {
- -webkit-transform: translateY(0);
- -ms-transform: translateY(0);
- transform: translateY(0);
- }
-}
-
-.bounceInUp {
- -webkit-animation-name: bounceInUp;
- animation-name: bounceInUp;
-}
-
-@-webkit-keyframes bounceOut {
- 0% {
- -webkit-transform: scale(1);
- transform: scale(1);
- }
-
- 25% {
- -webkit-transform: scale(.95);
- transform: scale(.95);
- }
-
- 50% {
- opacity: 1;
- -webkit-transform: scale(1.1);
- transform: scale(1.1);
- }
-
- 100% {
- opacity: 0;
- -webkit-transform: scale(.3);
- transform: scale(.3);
- }
-}
-
-@keyframes bounceOut {
- 0% {
- -webkit-transform: scale(1);
- -ms-transform: scale(1);
- transform: scale(1);
- }
-
- 25% {
- -webkit-transform: scale(.95);
- -ms-transform: scale(.95);
- transform: scale(.95);
- }
-
- 50% {
- opacity: 1;
- -webkit-transform: scale(1.1);
- -ms-transform: scale(1.1);
- transform: scale(1.1);
- }
-
- 100% {
- opacity: 0;
- -webkit-transform: scale(.3);
- -ms-transform: scale(.3);
- transform: scale(.3);
- }
-}
-
-.bounceOut {
- -webkit-animation-name: bounceOut;
- animation-name: bounceOut;
-}
-
-@-webkit-keyframes bounceOutDown {
- 0% {
- -webkit-transform: translateY(0);
- transform: translateY(0);
- }
-
- 20% {
- opacity: 1;
- -webkit-transform: translateY(-20px);
- transform: translateY(-20px);
- }
-
- 100% {
- opacity: 0;
- -webkit-transform: translateY(2000px);
- transform: translateY(2000px);
- }
-}
-
-@keyframes bounceOutDown {
- 0% {
- -webkit-transform: translateY(0);
- -ms-transform: translateY(0);
- transform: translateY(0);
- }
-
- 20% {
- opacity: 1;
- -webkit-transform: translateY(-20px);
- -ms-transform: translateY(-20px);
- transform: translateY(-20px);
- }
-
- 100% {
- opacity: 0;
- -webkit-transform: translateY(2000px);
- -ms-transform: translateY(2000px);
- transform: translateY(2000px);
- }
-}
-
-.bounceOutDown {
- -webkit-animation-name: bounceOutDown;
- animation-name: bounceOutDown;
-}
-
-@-webkit-keyframes bounceOutLeft {
- 0% {
- -webkit-transform: translateX(0);
- transform: translateX(0);
- }
-
- 20% {
- opacity: 1;
- -webkit-transform: translateX(20px);
- transform: translateX(20px);
- }
-
- 100% {
- opacity: 0;
- -webkit-transform: translateX(-2000px);
- transform: translateX(-2000px);
- }
-}
-
-@keyframes bounceOutLeft {
- 0% {
- -webkit-transform: translateX(0);
- -ms-transform: translateX(0);
- transform: translateX(0);
- }
-
- 20% {
- opacity: 1;
- -webkit-transform: translateX(20px);
- -ms-transform: translateX(20px);
- transform: translateX(20px);
- }
-
- 100% {
- opacity: 0;
- -webkit-transform: translateX(-2000px);
- -ms-transform: translateX(-2000px);
- transform: translateX(-2000px);
- }
-}
-
-.bounceOutLeft {
- -webkit-animation-name: bounceOutLeft;
- animation-name: bounceOutLeft;
-}
-
-@-webkit-keyframes bounceOutRight {
- 0% {
- -webkit-transform: translateX(0);
- transform: translateX(0);
- }
-
- 20% {
- opacity: 1;
- -webkit-transform: translateX(-20px);
- transform: translateX(-20px);
- }
-
- 100% {
- opacity: 0;
- -webkit-transform: translateX(2000px);
- transform: translateX(2000px);
- }
-}
-
-@keyframes bounceOutRight {
- 0% {
- -webkit-transform: translateX(0);
- -ms-transform: translateX(0);
- transform: translateX(0);
- }
-
- 20% {
- opacity: 1;
- -webkit-transform: translateX(-20px);
- -ms-transform: translateX(-20px);
- transform: translateX(-20px);
- }
-
- 100% {
- opacity: 0;
- -webkit-transform: translateX(2000px);
- -ms-transform: translateX(2000px);
- transform: translateX(2000px);
- }
-}
-
-.bounceOutRight {
- -webkit-animation-name: bounceOutRight;
- animation-name: bounceOutRight;
-}
-
-@-webkit-keyframes bounceOutUp {
- 0% {
- -webkit-transform: translateY(0);
- transform: translateY(0);
- }
-
- 20% {
- opacity: 1;
- -webkit-transform: translateY(20px);
- transform: translateY(20px);
- }
-
- 100% {
- opacity: 0;
- -webkit-transform: translateY(-2000px);
- transform: translateY(-2000px);
- }
-}
-
-@keyframes bounceOutUp {
- 0% {
- -webkit-transform: translateY(0);
- -ms-transform: translateY(0);
- transform: translateY(0);
- }
-
- 20% {
- opacity: 1;
- -webkit-transform: translateY(20px);
- -ms-transform: translateY(20px);
- transform: translateY(20px);
- }
-
- 100% {
- opacity: 0;
- -webkit-transform: translateY(-2000px);
- -ms-transform: translateY(-2000px);
- transform: translateY(-2000px);
- }
-}
-
-.bounceOutUp {
- -webkit-animation-name: bounceOutUp;
- animation-name: bounceOutUp;
-}
-
-@-webkit-keyframes fadeIn {
- 0% {
- opacity: 0;
- }
-
- 100% {
- opacity: 1;
- }
-}
-
-@keyframes fadeIn {
- 0% {
- opacity: 0;
- }
-
- 100% {
- opacity: 1;
- }
-}
-
-.fadeIn {
- -webkit-animation-name: fadeIn;
- animation-name: fadeIn;
-}
-
-@-webkit-keyframes fadeInDown {
- 0% {
- opacity: 0;
- -webkit-transform: translateY(-20px);
- transform: translateY(-20px);
- }
-
- 100% {
- opacity: 1;
- -webkit-transform: translateY(0);
- transform: translateY(0);
- }
-}
-
-@keyframes fadeInDown {
- 0% {
- opacity: 0;
- -webkit-transform: translateY(-20px);
- -ms-transform: translateY(-20px);
- transform: translateY(-20px);
- }
-
- 100% {
- opacity: 1;
- -webkit-transform: translateY(0);
- -ms-transform: translateY(0);
- transform: translateY(0);
- }
-}
-
-.fadeInDown {
- -webkit-animation-name: fadeInDown;
- animation-name: fadeInDown;
-}
-
-@-webkit-keyframes fadeInDownBig {
- 0% {
- opacity: 0;
- -webkit-transform: translateY(-2000px);
- transform: translateY(-2000px);
- }
-
- 100% {
- opacity: 1;
- -webkit-transform: translateY(0);
- transform: translateY(0);
- }
-}
-
-@keyframes fadeInDownBig {
- 0% {
- opacity: 0;
- -webkit-transform: translateY(-2000px);
- -ms-transform: translateY(-2000px);
- transform: translateY(-2000px);
- }
-
- 100% {
- opacity: 1;
- -webkit-transform: translateY(0);
- -ms-transform: translateY(0);
- transform: translateY(0);
- }
-}
-
-.fadeInDownBig {
- -webkit-animation-name: fadeInDownBig;
- animation-name: fadeInDownBig;
-}
-
-@-webkit-keyframes fadeInLeft {
- 0% {
- opacity: 0;
- -webkit-transform: translateX(-20px);
- transform: translateX(-20px);
- }
-
- 100% {
- opacity: 1;
- -webkit-transform: translateX(0);
- transform: translateX(0);
- }
-}
-
-@keyframes fadeInLeft {
- 0% {
- opacity: 0;
- -webkit-transform: translateX(-20px);
- -ms-transform: translateX(-20px);
- transform: translateX(-20px);
- }
-
- 100% {
- opacity: 1;
- -webkit-transform: translateX(0);
- -ms-transform: translateX(0);
- transform: translateX(0);
- }
-}
-
-.fadeInLeft {
- -webkit-animation-name: fadeInLeft;
- animation-name: fadeInLeft;
-}
-
-@-webkit-keyframes fadeInLeftBig {
- 0% {
- opacity: 0;
- -webkit-transform: translateX(-2000px);
- transform: translateX(-2000px);
- }
-
- 100% {
- opacity: 1;
- -webkit-transform: translateX(0);
- transform: translateX(0);
- }
-}
-
-@keyframes fadeInLeftBig {
- 0% {
- opacity: 0;
- -webkit-transform: translateX(-2000px);
- -ms-transform: translateX(-2000px);
- transform: translateX(-2000px);
- }
-
- 100% {
- opacity: 1;
- -webkit-transform: translateX(0);
- -ms-transform: translateX(0);
- transform: translateX(0);
- }
-}
-
-.fadeInLeftBig {
- -webkit-animation-name: fadeInLeftBig;
- animation-name: fadeInLeftBig;
-}
-
-@-webkit-keyframes fadeInRight {
- 0% {
- opacity: 0;
- -webkit-transform: translateX(20px);
- transform: translateX(20px);
- }
-
- 100% {
- opacity: 1;
- -webkit-transform: translateX(0);
- transform: translateX(0);
- }
-}
-
-@keyframes fadeInRight {
- 0% {
- opacity: 0;
- -webkit-transform: translateX(20px);
- -ms-transform: translateX(20px);
- transform: translateX(20px);
- }
-
- 100% {
- opacity: 1;
- -webkit-transform: translateX(0);
- -ms-transform: translateX(0);
- transform: translateX(0);
- }
-}
-
-.fadeInRight {
- -webkit-animation-name: fadeInRight;
- animation-name: fadeInRight;
-}
-
-@-webkit-keyframes fadeInRightBig {
- 0% {
- opacity: 0;
- -webkit-transform: translateX(2000px);
- transform: translateX(2000px);
- }
-
- 100% {
- opacity: 1;
- -webkit-transform: translateX(0);
- transform: translateX(0);
- }
-}
-
-@keyframes fadeInRightBig {
- 0% {
- opacity: 0;
- -webkit-transform: translateX(2000px);
- -ms-transform: translateX(2000px);
- transform: translateX(2000px);
- }
-
- 100% {
- opacity: 1;
- -webkit-transform: translateX(0);
- -ms-transform: translateX(0);
- transform: translateX(0);
- }
-}
-
-.fadeInRightBig {
- -webkit-animation-name: fadeInRightBig;
- animation-name: fadeInRightBig;
-}
-
-@-webkit-keyframes fadeInUp {
- 0% {
- opacity: 0;
- -webkit-transform: translateY(20px);
- transform: translateY(20px);
- }
-
- 100% {
- opacity: 1;
- -webkit-transform: translateY(0);
- transform: translateY(0);
- }
-}
-
-@keyframes fadeInUp {
- 0% {
- opacity: 0;
- -webkit-transform: translateY(20px);
- -ms-transform: translateY(20px);
- transform: translateY(20px);
- }
-
- 100% {
- opacity: 1;
- -webkit-transform: translateY(0);
- -ms-transform: translateY(0);
- transform: translateY(0);
- }
-}
-
-.fadeInUp {
- -webkit-animation-name: fadeInUp;
- animation-name: fadeInUp;
-}
-
-@-webkit-keyframes fadeInUpBig {
- 0% {
- opacity: 0;
- -webkit-transform: translateY(2000px);
- transform: translateY(2000px);
- }
-
- 100% {
- opacity: 1;
- -webkit-transform: translateY(0);
- transform: translateY(0);
- }
-}
-
-@keyframes fadeInUpBig {
- 0% {
- opacity: 0;
- -webkit-transform: translateY(2000px);
- -ms-transform: translateY(2000px);
- transform: translateY(2000px);
- }
-
- 100% {
- opacity: 1;
- -webkit-transform: translateY(0);
- -ms-transform: translateY(0);
- transform: translateY(0);
- }
-}
-
-.fadeInUpBig {
- -webkit-animation-name: fadeInUpBig;
- animation-name: fadeInUpBig;
-}
-
-@-webkit-keyframes fadeOut {
- 0% {
- opacity: 1;
- }
-
- 100% {
- opacity: 0;
- }
-}
-
-@keyframes fadeOut {
- 0% {
- opacity: 1;
- }
-
- 100% {
- opacity: 0;
- }
-}
-
-.fadeOut {
- -webkit-animation-name: fadeOut;
- animation-name: fadeOut;
-}
-
-@-webkit-keyframes fadeOutDown {
- 0% {
- opacity: 1;
- -webkit-transform: translateY(0);
- transform: translateY(0);
- }
-
- 100% {
- opacity: 0;
- -webkit-transform: translateY(20px);
- transform: translateY(20px);
- }
-}
-
-@keyframes fadeOutDown {
- 0% {
- opacity: 1;
- -webkit-transform: translateY(0);
- -ms-transform: translateY(0);
- transform: translateY(0);
- }
-
- 100% {
- opacity: 0;
- -webkit-transform: translateY(20px);
- -ms-transform: translateY(20px);
- transform: translateY(20px);
- }
-}
-
-.fadeOutDown {
- -webkit-animation-name: fadeOutDown;
- animation-name: fadeOutDown;
-}
-
-@-webkit-keyframes fadeOutDownBig {
- 0% {
- opacity: 1;
- -webkit-transform: translateY(0);
- transform: translateY(0);
- }
-
- 100% {
- opacity: 0;
- -webkit-transform: translateY(2000px);
- transform: translateY(2000px);
- }
-}
-
-@keyframes fadeOutDownBig {
- 0% {
- opacity: 1;
- -webkit-transform: translateY(0);
- -ms-transform: translateY(0);
- transform: translateY(0);
- }
-
- 100% {
- opacity: 0;
- -webkit-transform: translateY(2000px);
- -ms-transform: translateY(2000px);
- transform: translateY(2000px);
- }
-}
-
-.fadeOutDownBig {
- -webkit-animation-name: fadeOutDownBig;
- animation-name: fadeOutDownBig;
-}
-
-@-webkit-keyframes fadeOutLeft {
- 0% {
- opacity: 1;
- -webkit-transform: translateX(0);
- transform: translateX(0);
- }
-
- 100% {
- opacity: 0;
- -webkit-transform: translateX(-20px);
- transform: translateX(-20px);
- }
-}
-
-@keyframes fadeOutLeft {
- 0% {
- opacity: 1;
- -webkit-transform: translateX(0);
- -ms-transform: translateX(0);
- transform: translateX(0);
- }
-
- 100% {
- opacity: 0;
- -webkit-transform: translateX(-20px);
- -ms-transform: translateX(-20px);
- transform: translateX(-20px);
- }
-}
-
-.fadeOutLeft {
- -webkit-animation-name: fadeOutLeft;
- animation-name: fadeOutLeft;
-}
-
-@-webkit-keyframes fadeOutLeftBig {
- 0% {
- opacity: 1;
- -webkit-transform: translateX(0);
- transform: translateX(0);
- }
-
- 100% {
- opacity: 0;
- -webkit-transform: translateX(-2000px);
- transform: translateX(-2000px);
- }
-}
-
-@keyframes fadeOutLeftBig {
- 0% {
- opacity: 1;
- -webkit-transform: translateX(0);
- -ms-transform: translateX(0);
- transform: translateX(0);
- }
-
- 100% {
- opacity: 0;
- -webkit-transform: translateX(-2000px);
- -ms-transform: translateX(-2000px);
- transform: translateX(-2000px);
- }
-}
-
-.fadeOutLeftBig {
- -webkit-animation-name: fadeOutLeftBig;
- animation-name: fadeOutLeftBig;
-}
-
-@-webkit-keyframes fadeOutRight {
- 0% {
- opacity: 1;
- -webkit-transform: translateX(0);
- transform: translateX(0);
- }
-
- 100% {
- opacity: 0;
- -webkit-transform: translateX(20px);
- transform: translateX(20px);
- }
-}
-
-@keyframes fadeOutRight {
- 0% {
- opacity: 1;
- -webkit-transform: translateX(0);
- -ms-transform: translateX(0);
- transform: translateX(0);
- }
-
- 100% {
- opacity: 0;
- -webkit-transform: translateX(20px);
- -ms-transform: translateX(20px);
- transform: translateX(20px);
- }
-}
-
-.fadeOutRight {
- -webkit-animation-name: fadeOutRight;
- animation-name: fadeOutRight;
-}
-
-@-webkit-keyframes fadeOutRightBig {
- 0% {
- opacity: 1;
- -webkit-transform: translateX(0);
- transform: translateX(0);
- }
-
- 100% {
- opacity: 0;
- -webkit-transform: translateX(2000px);
- transform: translateX(2000px);
- }
-}
-
-@keyframes fadeOutRightBig {
- 0% {
- opacity: 1;
- -webkit-transform: translateX(0);
- -ms-transform: translateX(0);
- transform: translateX(0);
- }
-
- 100% {
- opacity: 0;
- -webkit-transform: translateX(2000px);
- -ms-transform: translateX(2000px);
- transform: translateX(2000px);
- }
-}
-
-.fadeOutRightBig {
- -webkit-animation-name: fadeOutRightBig;
- animation-name: fadeOutRightBig;
-}
-
-@-webkit-keyframes fadeOutUp {
- 0% {
- opacity: 1;
- -webkit-transform: translateY(0);
- transform: translateY(0);
- }
-
- 100% {
- opacity: 0;
- -webkit-transform: translateY(-20px);
- transform: translateY(-20px);
- }
-}
-
-@keyframes fadeOutUp {
- 0% {
- opacity: 1;
- -webkit-transform: translateY(0);
- -ms-transform: translateY(0);
- transform: translateY(0);
- }
-
- 100% {
- opacity: 0;
- -webkit-transform: translateY(-20px);
- -ms-transform: translateY(-20px);
- transform: translateY(-20px);
- }
-}
-
-.fadeOutUp {
- -webkit-animation-name: fadeOutUp;
- animation-name: fadeOutUp;
-}
-
-@-webkit-keyframes fadeOutUpBig {
- 0% {
- opacity: 1;
- -webkit-transform: translateY(0);
- transform: translateY(0);
- }
-
- 100% {
- opacity: 0;
- -webkit-transform: translateY(-2000px);
- transform: translateY(-2000px);
- }
-}
-
-@keyframes fadeOutUpBig {
- 0% {
- opacity: 1;
- -webkit-transform: translateY(0);
- -ms-transform: translateY(0);
- transform: translateY(0);
- }
-
- 100% {
- opacity: 0;
- -webkit-transform: translateY(-2000px);
- -ms-transform: translateY(-2000px);
- transform: translateY(-2000px);
- }
-}
-
-.fadeOutUpBig {
- -webkit-animation-name: fadeOutUpBig;
- animation-name: fadeOutUpBig;
-}
-
-@-webkit-keyframes flip {
- 0% {
- -webkit-transform: perspective(400px) translateZ(0) rotateY(0) scale(1);
- transform: perspective(400px) translateZ(0) rotateY(0) scale(1);
- -webkit-animation-timing-function: ease-out;
- animation-timing-function: ease-out;
- }
-
- 40% {
- -webkit-transform: perspective(400px) translateZ(150px) rotateY(170deg) scale(1);
- transform: perspective(400px) translateZ(150px) rotateY(170deg) scale(1);
- -webkit-animation-timing-function: ease-out;
- animation-timing-function: ease-out;
- }
-
- 50% {
- -webkit-transform: perspective(400px) translateZ(150px) rotateY(190deg) scale(1);
- transform: perspective(400px) translateZ(150px) rotateY(190deg) scale(1);
- -webkit-animation-timing-function: ease-in;
- animation-timing-function: ease-in;
- }
-
- 80% {
- -webkit-transform: perspective(400px) translateZ(0) rotateY(360deg) scale(.95);
- transform: perspective(400px) translateZ(0) rotateY(360deg) scale(.95);
- -webkit-animation-timing-function: ease-in;
- animation-timing-function: ease-in;
- }
-
- 100% {
- -webkit-transform: perspective(400px) translateZ(0) rotateY(360deg) scale(1);
- transform: perspective(400px) translateZ(0) rotateY(360deg) scale(1);
- -webkit-animation-timing-function: ease-in;
- animation-timing-function: ease-in;
- }
-}
-
-@keyframes flip {
- 0% {
- -webkit-transform: perspective(400px) translateZ(0) rotateY(0) scale(1);
- -ms-transform: perspective(400px) translateZ(0) rotateY(0) scale(1);
- transform: perspective(400px) translateZ(0) rotateY(0) scale(1);
- -webkit-animation-timing-function: ease-out;
- animation-timing-function: ease-out;
- }
-
- 40% {
- -webkit-transform: perspective(400px) translateZ(150px) rotateY(170deg) scale(1);
- -ms-transform: perspective(400px) translateZ(150px) rotateY(170deg) scale(1);
- transform: perspective(400px) translateZ(150px) rotateY(170deg) scale(1);
- -webkit-animation-timing-function: ease-out;
- animation-timing-function: ease-out;
- }
-
- 50% {
- -webkit-transform: perspective(400px) translateZ(150px) rotateY(190deg) scale(1);
- -ms-transform: perspective(400px) translateZ(150px) rotateY(190deg) scale(1);
- transform: perspective(400px) translateZ(150px) rotateY(190deg) scale(1);
- -webkit-animation-timing-function: ease-in;
- animation-timing-function: ease-in;
- }
-
- 80% {
- -webkit-transform: perspective(400px) translateZ(0) rotateY(360deg) scale(.95);
- -ms-transform: perspective(400px) translateZ(0) rotateY(360deg) scale(.95);
- transform: perspective(400px) translateZ(0) rotateY(360deg) scale(.95);
- -webkit-animation-timing-function: ease-in;
- animation-timing-function: ease-in;
- }
-
- 100% {
- -webkit-transform: perspective(400px) translateZ(0) rotateY(360deg) scale(1);
- -ms-transform: perspective(400px) translateZ(0) rotateY(360deg) scale(1);
- transform: perspective(400px) translateZ(0) rotateY(360deg) scale(1);
- -webkit-animation-timing-function: ease-in;
- animation-timing-function: ease-in;
- }
-}
-
-.animated.flip {
- -webkit-backface-visibility: visible;
- -ms-backface-visibility: visible;
- backface-visibility: visible;
- -webkit-animation-name: flip;
- animation-name: flip;
-}
-
-@-webkit-keyframes flipInX {
- 0% {
- -webkit-transform: perspective(400px) rotateX(90deg);
- transform: perspective(400px) rotateX(90deg);
- opacity: 0;
- }
-
- 40% {
- -webkit-transform: perspective(400px) rotateX(-10deg);
- transform: perspective(400px) rotateX(-10deg);
- }
-
- 70% {
- -webkit-transform: perspective(400px) rotateX(10deg);
- transform: perspective(400px) rotateX(10deg);
- }
-
- 100% {
- -webkit-transform: perspective(400px) rotateX(0deg);
- transform: perspective(400px) rotateX(0deg);
- opacity: 1;
- }
-}
-
-@keyframes flipInX {
- 0% {
- -webkit-transform: perspective(400px) rotateX(90deg);
- -ms-transform: perspective(400px) rotateX(90deg);
- transform: perspective(400px) rotateX(90deg);
- opacity: 0;
- }
-
- 40% {
- -webkit-transform: perspective(400px) rotateX(-10deg);
- -ms-transform: perspective(400px) rotateX(-10deg);
- transform: perspective(400px) rotateX(-10deg);
- }
-
- 70% {
- -webkit-transform: perspective(400px) rotateX(10deg);
- -ms-transform: perspective(400px) rotateX(10deg);
- transform: perspective(400px) rotateX(10deg);
- }
-
- 100% {
- -webkit-transform: perspective(400px) rotateX(0deg);
- -ms-transform: perspective(400px) rotateX(0deg);
- transform: perspective(400px) rotateX(0deg);
- opacity: 1;
- }
-}
-
-.flipInX {
- -webkit-backface-visibility: visible !important;
- -ms-backface-visibility: visible !important;
- backface-visibility: visible !important;
- -webkit-animation-name: flipInX;
- animation-name: flipInX;
-}
-
-@-webkit-keyframes flipInY {
- 0% {
- -webkit-transform: perspective(400px) rotateY(90deg);
- transform: perspective(400px) rotateY(90deg);
- opacity: 0;
- }
-
- 40% {
- -webkit-transform: perspective(400px) rotateY(-10deg);
- transform: perspective(400px) rotateY(-10deg);
- }
-
- 70% {
- -webkit-transform: perspective(400px) rotateY(10deg);
- transform: perspective(400px) rotateY(10deg);
- }
-
- 100% {
- -webkit-transform: perspective(400px) rotateY(0deg);
- transform: perspective(400px) rotateY(0deg);
- opacity: 1;
- }
-}
-
-@keyframes flipInY {
- 0% {
- -webkit-transform: perspective(400px) rotateY(90deg);
- -ms-transform: perspective(400px) rotateY(90deg);
- transform: perspective(400px) rotateY(90deg);
- opacity: 0;
- }
-
- 40% {
- -webkit-transform: perspective(400px) rotateY(-10deg);
- -ms-transform: perspective(400px) rotateY(-10deg);
- transform: perspective(400px) rotateY(-10deg);
- }
-
- 70% {
- -webkit-transform: perspective(400px) rotateY(10deg);
- -ms-transform: perspective(400px) rotateY(10deg);
- transform: perspective(400px) rotateY(10deg);
- }
-
- 100% {
- -webkit-transform: perspective(400px) rotateY(0deg);
- -ms-transform: perspective(400px) rotateY(0deg);
- transform: perspective(400px) rotateY(0deg);
- opacity: 1;
- }
-}
-
-.flipInY {
- -webkit-backface-visibility: visible !important;
- -ms-backface-visibility: visible !important;
- backface-visibility: visible !important;
- -webkit-animation-name: flipInY;
- animation-name: flipInY;
-}
-
-@-webkit-keyframes flipOutX {
- 0% {
- -webkit-transform: perspective(400px) rotateX(0deg);
- transform: perspective(400px) rotateX(0deg);
- opacity: 1;
- }
-
- 100% {
- -webkit-transform: perspective(400px) rotateX(90deg);
- transform: perspective(400px) rotateX(90deg);
- opacity: 0;
- }
-}
-
-@keyframes flipOutX {
- 0% {
- -webkit-transform: perspective(400px) rotateX(0deg);
- -ms-transform: perspective(400px) rotateX(0deg);
- transform: perspective(400px) rotateX(0deg);
- opacity: 1;
- }
-
- 100% {
- -webkit-transform: perspective(400px) rotateX(90deg);
- -ms-transform: perspective(400px) rotateX(90deg);
- transform: perspective(400px) rotateX(90deg);
- opacity: 0;
- }
-}
-
-.flipOutX {
- -webkit-animation-name: flipOutX;
- animation-name: flipOutX;
- -webkit-backface-visibility: visible !important;
- -ms-backface-visibility: visible !important;
- backface-visibility: visible !important;
-}
-
-@-webkit-keyframes flipOutY {
- 0% {
- -webkit-transform: perspective(400px) rotateY(0deg);
- transform: perspective(400px) rotateY(0deg);
- opacity: 1;
- }
-
- 100% {
- -webkit-transform: perspective(400px) rotateY(90deg);
- transform: perspective(400px) rotateY(90deg);
- opacity: 0;
- }
-}
-
-@keyframes flipOutY {
- 0% {
- -webkit-transform: perspective(400px) rotateY(0deg);
- -ms-transform: perspective(400px) rotateY(0deg);
- transform: perspective(400px) rotateY(0deg);
- opacity: 1;
- }
-
- 100% {
- -webkit-transform: perspective(400px) rotateY(90deg);
- -ms-transform: perspective(400px) rotateY(90deg);
- transform: perspective(400px) rotateY(90deg);
- opacity: 0;
- }
-}
-
-.flipOutY {
- -webkit-backface-visibility: visible !important;
- -ms-backface-visibility: visible !important;
- backface-visibility: visible !important;
- -webkit-animation-name: flipOutY;
- animation-name: flipOutY;
-}
-
-@-webkit-keyframes lightSpeedIn {
- 0% {
- -webkit-transform: translateX(100%) skewX(-30deg);
- transform: translateX(100%) skewX(-30deg);
- opacity: 0;
- }
-
- 60% {
- -webkit-transform: translateX(-20%) skewX(30deg);
- transform: translateX(-20%) skewX(30deg);
- opacity: 1;
- }
-
- 80% {
- -webkit-transform: translateX(0%) skewX(-15deg);
- transform: translateX(0%) skewX(-15deg);
- opacity: 1;
- }
-
- 100% {
- -webkit-transform: translateX(0%) skewX(0deg);
- transform: translateX(0%) skewX(0deg);
- opacity: 1;
- }
-}
-
-@keyframes lightSpeedIn {
- 0% {
- -webkit-transform: translateX(100%) skewX(-30deg);
- -ms-transform: translateX(100%) skewX(-30deg);
- transform: translateX(100%) skewX(-30deg);
- opacity: 0;
- }
-
- 60% {
- -webkit-transform: translateX(-20%) skewX(30deg);
- -ms-transform: translateX(-20%) skewX(30deg);
- transform: translateX(-20%) skewX(30deg);
- opacity: 1;
- }
-
- 80% {
- -webkit-transform: translateX(0%) skewX(-15deg);
- -ms-transform: translateX(0%) skewX(-15deg);
- transform: translateX(0%) skewX(-15deg);
- opacity: 1;
- }
-
- 100% {
- -webkit-transform: translateX(0%) skewX(0deg);
- -ms-transform: translateX(0%) skewX(0deg);
- transform: translateX(0%) skewX(0deg);
- opacity: 1;
- }
-}
-
-.lightSpeedIn {
- -webkit-animation-name: lightSpeedIn;
- animation-name: lightSpeedIn;
- -webkit-animation-timing-function: ease-out;
- animation-timing-function: ease-out;
-}
-
-@-webkit-keyframes lightSpeedOut {
- 0% {
- -webkit-transform: translateX(0%) skewX(0deg);
- transform: translateX(0%) skewX(0deg);
- opacity: 1;
- }
-
- 100% {
- -webkit-transform: translateX(100%) skewX(-30deg);
- transform: translateX(100%) skewX(-30deg);
- opacity: 0;
- }
-}
-
-@keyframes lightSpeedOut {
- 0% {
- -webkit-transform: translateX(0%) skewX(0deg);
- -ms-transform: translateX(0%) skewX(0deg);
- transform: translateX(0%) skewX(0deg);
- opacity: 1;
- }
-
- 100% {
- -webkit-transform: translateX(100%) skewX(-30deg);
- -ms-transform: translateX(100%) skewX(-30deg);
- transform: translateX(100%) skewX(-30deg);
- opacity: 0;
- }
-}
-
-.lightSpeedOut {
- -webkit-animation-name: lightSpeedOut;
- animation-name: lightSpeedOut;
- -webkit-animation-timing-function: ease-in;
- animation-timing-function: ease-in;
-}
-
-@-webkit-keyframes rotateIn {
- 0% {
- -webkit-transform-origin: center center;
- transform-origin: center center;
- -webkit-transform: rotate(-200deg);
- transform: rotate(-200deg);
- opacity: 0;
- }
-
- 100% {
- -webkit-transform-origin: center center;
- transform-origin: center center;
- -webkit-transform: rotate(0);
- transform: rotate(0);
- opacity: 1;
- }
-}
-
-@keyframes rotateIn {
- 0% {
- -webkit-transform-origin: center center;
- -ms-transform-origin: center center;
- transform-origin: center center;
- -webkit-transform: rotate(-200deg);
- -ms-transform: rotate(-200deg);
- transform: rotate(-200deg);
- opacity: 0;
- }
-
- 100% {
- -webkit-transform-origin: center center;
- -ms-transform-origin: center center;
- transform-origin: center center;
- -webkit-transform: rotate(0);
- -ms-transform: rotate(0);
- transform: rotate(0);
- opacity: 1;
- }
-}
-
-.rotateIn {
- -webkit-animation-name: rotateIn;
- animation-name: rotateIn;
-}
-
-@-webkit-keyframes rotateInDownLeft {
- 0% {
- -webkit-transform-origin: left bottom;
- transform-origin: left bottom;
- -webkit-transform: rotate(-90deg);
- transform: rotate(-90deg);
- opacity: 0;
- }
-
- 100% {
- -webkit-transform-origin: left bottom;
- transform-origin: left bottom;
- -webkit-transform: rotate(0);
- transform: rotate(0);
- opacity: 1;
- }
-}
-
-@keyframes rotateInDownLeft {
- 0% {
- -webkit-transform-origin: left bottom;
- -ms-transform-origin: left bottom;
- transform-origin: left bottom;
- -webkit-transform: rotate(-90deg);
- -ms-transform: rotate(-90deg);
- transform: rotate(-90deg);
- opacity: 0;
- }
-
- 100% {
- -webkit-transform-origin: left bottom;
- -ms-transform-origin: left bottom;
- transform-origin: left bottom;
- -webkit-transform: rotate(0);
- -ms-transform: rotate(0);
- transform: rotate(0);
- opacity: 1;
- }
-}
-
-.rotateInDownLeft {
- -webkit-animation-name: rotateInDownLeft;
- animation-name: rotateInDownLeft;
-}
-
-@-webkit-keyframes rotateInDownRight {
- 0% {
- -webkit-transform-origin: right bottom;
- transform-origin: right bottom;
- -webkit-transform: rotate(90deg);
- transform: rotate(90deg);
- opacity: 0;
- }
-
- 100% {
- -webkit-transform-origin: right bottom;
- transform-origin: right bottom;
- -webkit-transform: rotate(0);
- transform: rotate(0);
- opacity: 1;
- }
-}
-
-@keyframes rotateInDownRight {
- 0% {
- -webkit-transform-origin: right bottom;
- -ms-transform-origin: right bottom;
- transform-origin: right bottom;
- -webkit-transform: rotate(90deg);
- -ms-transform: rotate(90deg);
- transform: rotate(90deg);
- opacity: 0;
- }
-
- 100% {
- -webkit-transform-origin: right bottom;
- -ms-transform-origin: right bottom;
- transform-origin: right bottom;
- -webkit-transform: rotate(0);
- -ms-transform: rotate(0);
- transform: rotate(0);
- opacity: 1;
- }
-}
-
-.rotateInDownRight {
- -webkit-animation-name: rotateInDownRight;
- animation-name: rotateInDownRight;
-}
-
-@-webkit-keyframes rotateInUpLeft {
- 0% {
- -webkit-transform-origin: left bottom;
- transform-origin: left bottom;
- -webkit-transform: rotate(90deg);
- transform: rotate(90deg);
- opacity: 0;
- }
-
- 100% {
- -webkit-transform-origin: left bottom;
- transform-origin: left bottom;
- -webkit-transform: rotate(0);
- transform: rotate(0);
- opacity: 1;
- }
-}
-
-@keyframes rotateInUpLeft {
- 0% {
- -webkit-transform-origin: left bottom;
- -ms-transform-origin: left bottom;
- transform-origin: left bottom;
- -webkit-transform: rotate(90deg);
- -ms-transform: rotate(90deg);
- transform: rotate(90deg);
- opacity: 0;
- }
-
- 100% {
- -webkit-transform-origin: left bottom;
- -ms-transform-origin: left bottom;
- transform-origin: left bottom;
- -webkit-transform: rotate(0);
- -ms-transform: rotate(0);
- transform: rotate(0);
- opacity: 1;
- }
-}
-
-.rotateInUpLeft {
- -webkit-animation-name: rotateInUpLeft;
- animation-name: rotateInUpLeft;
-}
-
-@-webkit-keyframes rotateInUpRight {
- 0% {
- -webkit-transform-origin: right bottom;
- transform-origin: right bottom;
- -webkit-transform: rotate(-90deg);
- transform: rotate(-90deg);
- opacity: 0;
- }
-
- 100% {
- -webkit-transform-origin: right bottom;
- transform-origin: right bottom;
- -webkit-transform: rotate(0);
- transform: rotate(0);
- opacity: 1;
- }
-}
-
-@keyframes rotateInUpRight {
- 0% {
- -webkit-transform-origin: right bottom;
- -ms-transform-origin: right bottom;
- transform-origin: right bottom;
- -webkit-transform: rotate(-90deg);
- -ms-transform: rotate(-90deg);
- transform: rotate(-90deg);
- opacity: 0;
- }
-
- 100% {
- -webkit-transform-origin: right bottom;
- -ms-transform-origin: right bottom;
- transform-origin: right bottom;
- -webkit-transform: rotate(0);
- -ms-transform: rotate(0);
- transform: rotate(0);
- opacity: 1;
- }
-}
-
-.rotateInUpRight {
- -webkit-animation-name: rotateInUpRight;
- animation-name: rotateInUpRight;
-}
-
-@-webkit-keyframes rotateOut {
- 0% {
- -webkit-transform-origin: center center;
- transform-origin: center center;
- -webkit-transform: rotate(0);
- transform: rotate(0);
- opacity: 1;
- }
-
- 100% {
- -webkit-transform-origin: center center;
- transform-origin: center center;
- -webkit-transform: rotate(200deg);
- transform: rotate(200deg);
- opacity: 0;
- }
-}
-
-@keyframes rotateOut {
- 0% {
- -webkit-transform-origin: center center;
- -ms-transform-origin: center center;
- transform-origin: center center;
- -webkit-transform: rotate(0);
- -ms-transform: rotate(0);
- transform: rotate(0);
- opacity: 1;
- }
-
- 100% {
- -webkit-transform-origin: center center;
- -ms-transform-origin: center center;
- transform-origin: center center;
- -webkit-transform: rotate(200deg);
- -ms-transform: rotate(200deg);
- transform: rotate(200deg);
- opacity: 0;
- }
-}
-
-.rotateOut {
- -webkit-animation-name: rotateOut;
- animation-name: rotateOut;
-}
-
-@-webkit-keyframes rotateOutDownLeft {
- 0% {
- -webkit-transform-origin: left bottom;
- transform-origin: left bottom;
- -webkit-transform: rotate(0);
- transform: rotate(0);
- opacity: 1;
- }
-
- 100% {
- -webkit-transform-origin: left bottom;
- transform-origin: left bottom;
- -webkit-transform: rotate(90deg);
- transform: rotate(90deg);
- opacity: 0;
- }
-}
-
-@keyframes rotateOutDownLeft {
- 0% {
- -webkit-transform-origin: left bottom;
- -ms-transform-origin: left bottom;
- transform-origin: left bottom;
- -webkit-transform: rotate(0);
- -ms-transform: rotate(0);
- transform: rotate(0);
- opacity: 1;
- }
-
- 100% {
- -webkit-transform-origin: left bottom;
- -ms-transform-origin: left bottom;
- transform-origin: left bottom;
- -webkit-transform: rotate(90deg);
- -ms-transform: rotate(90deg);
- transform: rotate(90deg);
- opacity: 0;
- }
-}
-
-.rotateOutDownLeft {
- -webkit-animation-name: rotateOutDownLeft;
- animation-name: rotateOutDownLeft;
-}
-
-@-webkit-keyframes rotateOutDownRight {
- 0% {
- -webkit-transform-origin: right bottom;
- transform-origin: right bottom;
- -webkit-transform: rotate(0);
- transform: rotate(0);
- opacity: 1;
- }
-
- 100% {
- -webkit-transform-origin: right bottom;
- transform-origin: right bottom;
- -webkit-transform: rotate(-90deg);
- transform: rotate(-90deg);
- opacity: 0;
- }
-}
-
-@keyframes rotateOutDownRight {
- 0% {
- -webkit-transform-origin: right bottom;
- -ms-transform-origin: right bottom;
- transform-origin: right bottom;
- -webkit-transform: rotate(0);
- -ms-transform: rotate(0);
- transform: rotate(0);
- opacity: 1;
- }
-
- 100% {
- -webkit-transform-origin: right bottom;
- -ms-transform-origin: right bottom;
- transform-origin: right bottom;
- -webkit-transform: rotate(-90deg);
- -ms-transform: rotate(-90deg);
- transform: rotate(-90deg);
- opacity: 0;
- }
-}
-
-.rotateOutDownRight {
- -webkit-animation-name: rotateOutDownRight;
- animation-name: rotateOutDownRight;
-}
-
-@-webkit-keyframes rotateOutUpLeft {
- 0% {
- -webkit-transform-origin: left bottom;
- transform-origin: left bottom;
- -webkit-transform: rotate(0);
- transform: rotate(0);
- opacity: 1;
- }
-
- 100% {
- -webkit-transform-origin: left bottom;
- transform-origin: left bottom;
- -webkit-transform: rotate(-90deg);
- transform: rotate(-90deg);
- opacity: 0;
- }
-}
-
-@keyframes rotateOutUpLeft {
- 0% {
- -webkit-transform-origin: left bottom;
- -ms-transform-origin: left bottom;
- transform-origin: left bottom;
- -webkit-transform: rotate(0);
- -ms-transform: rotate(0);
- transform: rotate(0);
- opacity: 1;
- }
-
- 100% {
- -webkit-transform-origin: left bottom;
- -ms-transform-origin: left bottom;
- transform-origin: left bottom;
- -webkit-transform: rotate(-90deg);
- -ms-transform: rotate(-90deg);
- transform: rotate(-90deg);
- opacity: 0;
- }
-}
-
-.rotateOutUpLeft {
- -webkit-animation-name: rotateOutUpLeft;
- animation-name: rotateOutUpLeft;
-}
-
-@-webkit-keyframes rotateOutUpRight {
- 0% {
- -webkit-transform-origin: right bottom;
- transform-origin: right bottom;
- -webkit-transform: rotate(0);
- transform: rotate(0);
- opacity: 1;
- }
-
- 100% {
- -webkit-transform-origin: right bottom;
- transform-origin: right bottom;
- -webkit-transform: rotate(90deg);
- transform: rotate(90deg);
- opacity: 0;
- }
-}
-
-@keyframes rotateOutUpRight {
- 0% {
- -webkit-transform-origin: right bottom;
- -ms-transform-origin: right bottom;
- transform-origin: right bottom;
- -webkit-transform: rotate(0);
- -ms-transform: rotate(0);
- transform: rotate(0);
- opacity: 1;
- }
-
- 100% {
- -webkit-transform-origin: right bottom;
- -ms-transform-origin: right bottom;
- transform-origin: right bottom;
- -webkit-transform: rotate(90deg);
- -ms-transform: rotate(90deg);
- transform: rotate(90deg);
- opacity: 0;
- }
-}
-
-.rotateOutUpRight {
- -webkit-animation-name: rotateOutUpRight;
- animation-name: rotateOutUpRight;
-}
-
-@-webkit-keyframes slideInDown {
- 0% {
- opacity: 0;
- -webkit-transform: translateY(-2000px);
- transform: translateY(-2000px);
- }
-
- 100% {
- -webkit-transform: translateY(0);
- transform: translateY(0);
- }
-}
-
-@keyframes slideInDown {
- 0% {
- opacity: 0;
- -webkit-transform: translateY(-2000px);
- -ms-transform: translateY(-2000px);
- transform: translateY(-2000px);
- }
-
- 100% {
- -webkit-transform: translateY(0);
- -ms-transform: translateY(0);
- transform: translateY(0);
- }
-}
-
-.slideInDown {
- -webkit-animation-name: slideInDown;
- animation-name: slideInDown;
-}
-
-@-webkit-keyframes slideInLeft {
- 0% {
- opacity: 0;
- -webkit-transform: translateX(-2000px);
- transform: translateX(-2000px);
- }
-
- 100% {
- -webkit-transform: translateX(0);
- transform: translateX(0);
- }
-}
-
-@keyframes slideInLeft {
- 0% {
- opacity: 0;
- -webkit-transform: translateX(-2000px);
- -ms-transform: translateX(-2000px);
- transform: translateX(-2000px);
- }
-
- 100% {
- -webkit-transform: translateX(0);
- -ms-transform: translateX(0);
- transform: translateX(0);
- }
-}
-
-.slideInLeft {
- -webkit-animation-name: slideInLeft;
- animation-name: slideInLeft;
-}
-
-@-webkit-keyframes slideInRight {
- 0% {
- opacity: 0;
- -webkit-transform: translateX(2000px);
- transform: translateX(2000px);
- }
-
- 100% {
- -webkit-transform: translateX(0);
- transform: translateX(0);
- }
-}
-
-@keyframes slideInRight {
- 0% {
- opacity: 0;
- -webkit-transform: translateX(2000px);
- -ms-transform: translateX(2000px);
- transform: translateX(2000px);
- }
-
- 100% {
- -webkit-transform: translateX(0);
- -ms-transform: translateX(0);
- transform: translateX(0);
- }
-}
-
-.slideInRight {
- -webkit-animation-name: slideInRight;
- animation-name: slideInRight;
-}
-
-@-webkit-keyframes slideOutLeft {
- 0% {
- -webkit-transform: translateX(0);
- transform: translateX(0);
- }
-
- 100% {
- opacity: 0;
- -webkit-transform: translateX(-2000px);
- transform: translateX(-2000px);
- }
-}
-
-@keyframes slideOutLeft {
- 0% {
- -webkit-transform: translateX(0);
- -ms-transform: translateX(0);
- transform: translateX(0);
- }
-
- 100% {
- opacity: 0;
- -webkit-transform: translateX(-2000px);
- -ms-transform: translateX(-2000px);
- transform: translateX(-2000px);
- }
-}
-
-.slideOutLeft {
- -webkit-animation-name: slideOutLeft;
- animation-name: slideOutLeft;
-}
-
-@-webkit-keyframes slideOutRight {
- 0% {
- -webkit-transform: translateX(0);
- transform: translateX(0);
- }
-
- 100% {
- opacity: 0;
- -webkit-transform: translateX(2000px);
- transform: translateX(2000px);
- }
-}
-
-@keyframes slideOutRight {
- 0% {
- -webkit-transform: translateX(0);
- -ms-transform: translateX(0);
- transform: translateX(0);
- }
-
- 100% {
- opacity: 0;
- -webkit-transform: translateX(2000px);
- -ms-transform: translateX(2000px);
- transform: translateX(2000px);
- }
-}
-
-.slideOutRight {
- -webkit-animation-name: slideOutRight;
- animation-name: slideOutRight;
-}
-
-@-webkit-keyframes slideOutUp {
- 0% {
- -webkit-transform: translateY(0);
- transform: translateY(0);
- }
-
- 100% {
- opacity: 0;
- -webkit-transform: translateY(-2000px);
- transform: translateY(-2000px);
- }
-}
-
-@keyframes slideOutUp {
- 0% {
- -webkit-transform: translateY(0);
- -ms-transform: translateY(0);
- transform: translateY(0);
- }
-
- 100% {
- opacity: 0;
- -webkit-transform: translateY(-2000px);
- -ms-transform: translateY(-2000px);
- transform: translateY(-2000px);
- }
-}
-
-.slideOutUp {
- -webkit-animation-name: slideOutUp;
- animation-name: slideOutUp;
-}
-
-@-webkit-keyframes hinge {
- 0% {
- -webkit-transform: rotate(0);
- transform: rotate(0);
- -webkit-transform-origin: top left;
- transform-origin: top left;
- -webkit-animation-timing-function: ease-in-out;
- animation-timing-function: ease-in-out;
- }
-
- 20%, 60% {
- -webkit-transform: rotate(80deg);
- transform: rotate(80deg);
- -webkit-transform-origin: top left;
- transform-origin: top left;
- -webkit-animation-timing-function: ease-in-out;
- animation-timing-function: ease-in-out;
- }
-
- 40% {
- -webkit-transform: rotate(60deg);
- transform: rotate(60deg);
- -webkit-transform-origin: top left;
- transform-origin: top left;
- -webkit-animation-timing-function: ease-in-out;
- animation-timing-function: ease-in-out;
- }
-
- 80% {
- -webkit-transform: rotate(60deg) translateY(0);
- transform: rotate(60deg) translateY(0);
- opacity: 1;
- -webkit-transform-origin: top left;
- transform-origin: top left;
- -webkit-animation-timing-function: ease-in-out;
- animation-timing-function: ease-in-out;
- }
-
- 100% {
- -webkit-transform: translateY(700px);
- transform: translateY(700px);
- opacity: 0;
- }
-}
-
-@keyframes hinge {
- 0% {
- -webkit-transform: rotate(0);
- -ms-transform: rotate(0);
- transform: rotate(0);
- -webkit-transform-origin: top left;
- -ms-transform-origin: top left;
- transform-origin: top left;
- -webkit-animation-timing-function: ease-in-out;
- animation-timing-function: ease-in-out;
- }
-
- 20%, 60% {
- -webkit-transform: rotate(80deg);
- -ms-transform: rotate(80deg);
- transform: rotate(80deg);
- -webkit-transform-origin: top left;
- -ms-transform-origin: top left;
- transform-origin: top left;
- -webkit-animation-timing-function: ease-in-out;
- animation-timing-function: ease-in-out;
- }
-
- 40% {
- -webkit-transform: rotate(60deg);
- -ms-transform: rotate(60deg);
- transform: rotate(60deg);
- -webkit-transform-origin: top left;
- -ms-transform-origin: top left;
- transform-origin: top left;
- -webkit-animation-timing-function: ease-in-out;
- animation-timing-function: ease-in-out;
- }
-
- 80% {
- -webkit-transform: rotate(60deg) translateY(0);
- -ms-transform: rotate(60deg) translateY(0);
- transform: rotate(60deg) translateY(0);
- opacity: 1;
- -webkit-transform-origin: top left;
- -ms-transform-origin: top left;
- transform-origin: top left;
- -webkit-animation-timing-function: ease-in-out;
- animation-timing-function: ease-in-out;
- }
-
- 100% {
- -webkit-transform: translateY(700px);
- -ms-transform: translateY(700px);
- transform: translateY(700px);
- opacity: 0;
- }
-}
-
-.hinge {
- -webkit-animation-name: hinge;
- animation-name: hinge;
-}
-
-/* originally authored by Nick Pettit - https://github.com/nickpettit/glide */
-
-@-webkit-keyframes rollIn {
- 0% {
- opacity: 0;
- -webkit-transform: translateX(-100%) rotate(-120deg);
- transform: translateX(-100%) rotate(-120deg);
- }
-
- 100% {
- opacity: 1;
- -webkit-transform: translateX(0px) rotate(0deg);
- transform: translateX(0px) rotate(0deg);
- }
-}
-
-@keyframes rollIn {
- 0% {
- opacity: 0;
- -webkit-transform: translateX(-100%) rotate(-120deg);
- -ms-transform: translateX(-100%) rotate(-120deg);
- transform: translateX(-100%) rotate(-120deg);
- }
-
- 100% {
- opacity: 1;
- -webkit-transform: translateX(0px) rotate(0deg);
- -ms-transform: translateX(0px) rotate(0deg);
- transform: translateX(0px) rotate(0deg);
- }
-}
-
-.rollIn {
- -webkit-animation-name: rollIn;
- animation-name: rollIn;
-}
-
-/* originally authored by Nick Pettit - https://github.com/nickpettit/glide */
-
-@-webkit-keyframes rollOut {
- 0% {
- opacity: 1;
- -webkit-transform: translateX(0px) rotate(0deg);
- transform: translateX(0px) rotate(0deg);
- }
-
- 100% {
- opacity: 0;
- -webkit-transform: translateX(100%) rotate(120deg);
- transform: translateX(100%) rotate(120deg);
- }
-}
-
-@keyframes rollOut {
- 0% {
- opacity: 1;
- -webkit-transform: translateX(0px) rotate(0deg);
- -ms-transform: translateX(0px) rotate(0deg);
- transform: translateX(0px) rotate(0deg);
- }
-
- 100% {
- opacity: 0;
- -webkit-transform: translateX(100%) rotate(120deg);
- -ms-transform: translateX(100%) rotate(120deg);
- transform: translateX(100%) rotate(120deg);
- }
-}
-
-.rollOut {
- -webkit-animation-name: rollOut;
- animation-name: rollOut;
+@charset "UTF-8";
+
+
+/*!
+Animate.css - http://daneden.me/animate
+Licensed under the MIT license
+
+Copyright (c) 2013 Daniel Eden
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+.animated {
+ -webkit-animation-duration: 1s;
+ animation-duration: 1s;
+ -webkit-animation-fill-mode: both;
+ animation-fill-mode: both;
+}
+
+.animated.hinge {
+ -webkit-animation-duration: 2s;
+ animation-duration: 2s;
+}
+
+@-webkit-keyframes bounce {
+ 0%, 20%, 50%, 80%, 100% {
+ -webkit-transform: translateY(0);
+ transform: translateY(0);
+ }
+
+ 40% {
+ -webkit-transform: translateY(-30px);
+ transform: translateY(-30px);
+ }
+
+ 60% {
+ -webkit-transform: translateY(-15px);
+ transform: translateY(-15px);
+ }
+}
+
+@keyframes bounce {
+ 0%, 20%, 50%, 80%, 100% {
+ -webkit-transform: translateY(0);
+ -ms-transform: translateY(0);
+ transform: translateY(0);
+ }
+
+ 40% {
+ -webkit-transform: translateY(-30px);
+ -ms-transform: translateY(-30px);
+ transform: translateY(-30px);
+ }
+
+ 60% {
+ -webkit-transform: translateY(-15px);
+ -ms-transform: translateY(-15px);
+ transform: translateY(-15px);
+ }
+}
+
+.bounce {
+ -webkit-animation-name: bounce;
+ animation-name: bounce;
+}
+
+@-webkit-keyframes flash {
+ 0%, 50%, 100% {
+ opacity: 1;
+ }
+
+ 25%, 75% {
+ opacity: 0;
+ }
+}
+
+@keyframes flash {
+ 0%, 50%, 100% {
+ opacity: 1;
+ }
+
+ 25%, 75% {
+ opacity: 0;
+ }
+}
+
+.flash {
+ -webkit-animation-name: flash;
+ animation-name: flash;
+}
+
+/* originally authored by Nick Pettit - https://github.com/nickpettit/glide */
+
+@-webkit-keyframes pulse {
+ 0% {
+ -webkit-transform: scale(1);
+ transform: scale(1);
+ }
+
+ 50% {
+ -webkit-transform: scale(1.1);
+ transform: scale(1.1);
+ }
+
+ 100% {
+ -webkit-transform: scale(1);
+ transform: scale(1);
+ }
+}
+
+@keyframes pulse {
+ 0% {
+ -webkit-transform: scale(1);
+ -ms-transform: scale(1);
+ transform: scale(1);
+ }
+
+ 50% {
+ -webkit-transform: scale(1.1);
+ -ms-transform: scale(1.1);
+ transform: scale(1.1);
+ }
+
+ 100% {
+ -webkit-transform: scale(1);
+ -ms-transform: scale(1);
+ transform: scale(1);
+ }
+}
+
+.pulse {
+ -webkit-animation-name: pulse;
+ animation-name: pulse;
+}
+
+@-webkit-keyframes shake {
+ 0%, 100% {
+ -webkit-transform: translateX(0);
+ transform: translateX(0);
+ }
+
+ 10%, 30%, 50%, 70%, 90% {
+ -webkit-transform: translateX(-10px);
+ transform: translateX(-10px);
+ }
+
+ 20%, 40%, 60%, 80% {
+ -webkit-transform: translateX(10px);
+ transform: translateX(10px);
+ }
+}
+
+@keyframes shake {
+ 0%, 100% {
+ -webkit-transform: translateX(0);
+ -ms-transform: translateX(0);
+ transform: translateX(0);
+ }
+
+ 10%, 30%, 50%, 70%, 90% {
+ -webkit-transform: translateX(-10px);
+ -ms-transform: translateX(-10px);
+ transform: translateX(-10px);
+ }
+
+ 20%, 40%, 60%, 80% {
+ -webkit-transform: translateX(10px);
+ -ms-transform: translateX(10px);
+ transform: translateX(10px);
+ }
+}
+
+.shake {
+ -webkit-animation-name: shake;
+ animation-name: shake;
+}
+
+@-webkit-keyframes swing {
+ 20% {
+ -webkit-transform: rotate(15deg);
+ transform: rotate(15deg);
+ }
+
+ 40% {
+ -webkit-transform: rotate(-10deg);
+ transform: rotate(-10deg);
+ }
+
+ 60% {
+ -webkit-transform: rotate(5deg);
+ transform: rotate(5deg);
+ }
+
+ 80% {
+ -webkit-transform: rotate(-5deg);
+ transform: rotate(-5deg);
+ }
+
+ 100% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+}
+
+@keyframes swing {
+ 20% {
+ -webkit-transform: rotate(15deg);
+ -ms-transform: rotate(15deg);
+ transform: rotate(15deg);
+ }
+
+ 40% {
+ -webkit-transform: rotate(-10deg);
+ -ms-transform: rotate(-10deg);
+ transform: rotate(-10deg);
+ }
+
+ 60% {
+ -webkit-transform: rotate(5deg);
+ -ms-transform: rotate(5deg);
+ transform: rotate(5deg);
+ }
+
+ 80% {
+ -webkit-transform: rotate(-5deg);
+ -ms-transform: rotate(-5deg);
+ transform: rotate(-5deg);
+ }
+
+ 100% {
+ -webkit-transform: rotate(0deg);
+ -ms-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+}
+
+.swing {
+ -webkit-transform-origin: top center;
+ -ms-transform-origin: top center;
+ transform-origin: top center;
+ -webkit-animation-name: swing;
+ animation-name: swing;
+}
+
+@-webkit-keyframes tada {
+ 0% {
+ -webkit-transform: scale(1);
+ transform: scale(1);
+ }
+
+ 10%, 20% {
+ -webkit-transform: scale(0.9) rotate(-3deg);
+ transform: scale(0.9) rotate(-3deg);
+ }
+
+ 30%, 50%, 70%, 90% {
+ -webkit-transform: scale(1.1) rotate(3deg);
+ transform: scale(1.1) rotate(3deg);
+ }
+
+ 40%, 60%, 80% {
+ -webkit-transform: scale(1.1) rotate(-3deg);
+ transform: scale(1.1) rotate(-3deg);
+ }
+
+ 100% {
+ -webkit-transform: scale(1) rotate(0);
+ transform: scale(1) rotate(0);
+ }
+}
+
+@keyframes tada {
+ 0% {
+ -webkit-transform: scale(1);
+ -ms-transform: scale(1);
+ transform: scale(1);
+ }
+
+ 10%, 20% {
+ -webkit-transform: scale(0.9) rotate(-3deg);
+ -ms-transform: scale(0.9) rotate(-3deg);
+ transform: scale(0.9) rotate(-3deg);
+ }
+
+ 30%, 50%, 70%, 90% {
+ -webkit-transform: scale(1.1) rotate(3deg);
+ -ms-transform: scale(1.1) rotate(3deg);
+ transform: scale(1.1) rotate(3deg);
+ }
+
+ 40%, 60%, 80% {
+ -webkit-transform: scale(1.1) rotate(-3deg);
+ -ms-transform: scale(1.1) rotate(-3deg);
+ transform: scale(1.1) rotate(-3deg);
+ }
+
+ 100% {
+ -webkit-transform: scale(1) rotate(0);
+ -ms-transform: scale(1) rotate(0);
+ transform: scale(1) rotate(0);
+ }
+}
+
+.tada {
+ -webkit-animation-name: tada;
+ animation-name: tada;
+}
+
+/* originally authored by Nick Pettit - https://github.com/nickpettit/glide */
+
+@-webkit-keyframes wobble {
+ 0% {
+ -webkit-transform: translateX(0%);
+ transform: translateX(0%);
+ }
+
+ 15% {
+ -webkit-transform: translateX(-25%) rotate(-5deg);
+ transform: translateX(-25%) rotate(-5deg);
+ }
+
+ 30% {
+ -webkit-transform: translateX(20%) rotate(3deg);
+ transform: translateX(20%) rotate(3deg);
+ }
+
+ 45% {
+ -webkit-transform: translateX(-15%) rotate(-3deg);
+ transform: translateX(-15%) rotate(-3deg);
+ }
+
+ 60% {
+ -webkit-transform: translateX(10%) rotate(2deg);
+ transform: translateX(10%) rotate(2deg);
+ }
+
+ 75% {
+ -webkit-transform: translateX(-5%) rotate(-1deg);
+ transform: translateX(-5%) rotate(-1deg);
+ }
+
+ 100% {
+ -webkit-transform: translateX(0%);
+ transform: translateX(0%);
+ }
+}
+
+@keyframes wobble {
+ 0% {
+ -webkit-transform: translateX(0%);
+ -ms-transform: translateX(0%);
+ transform: translateX(0%);
+ }
+
+ 15% {
+ -webkit-transform: translateX(-25%) rotate(-5deg);
+ -ms-transform: translateX(-25%) rotate(-5deg);
+ transform: translateX(-25%) rotate(-5deg);
+ }
+
+ 30% {
+ -webkit-transform: translateX(20%) rotate(3deg);
+ -ms-transform: translateX(20%) rotate(3deg);
+ transform: translateX(20%) rotate(3deg);
+ }
+
+ 45% {
+ -webkit-transform: translateX(-15%) rotate(-3deg);
+ -ms-transform: translateX(-15%) rotate(-3deg);
+ transform: translateX(-15%) rotate(-3deg);
+ }
+
+ 60% {
+ -webkit-transform: translateX(10%) rotate(2deg);
+ -ms-transform: translateX(10%) rotate(2deg);
+ transform: translateX(10%) rotate(2deg);
+ }
+
+ 75% {
+ -webkit-transform: translateX(-5%) rotate(-1deg);
+ -ms-transform: translateX(-5%) rotate(-1deg);
+ transform: translateX(-5%) rotate(-1deg);
+ }
+
+ 100% {
+ -webkit-transform: translateX(0%);
+ -ms-transform: translateX(0%);
+ transform: translateX(0%);
+ }
+}
+
+.wobble {
+ -webkit-animation-name: wobble;
+ animation-name: wobble;
+}
+
+@-webkit-keyframes bounceIn {
+ 0% {
+ opacity: 0;
+ -webkit-transform: scale(.3);
+ transform: scale(.3);
+ }
+
+ 50% {
+ opacity: 1;
+ -webkit-transform: scale(1.05);
+ transform: scale(1.05);
+ }
+
+ 70% {
+ -webkit-transform: scale(.9);
+ transform: scale(.9);
+ }
+
+ 100% {
+ -webkit-transform: scale(1);
+ transform: scale(1);
+ }
+}
+
+@keyframes bounceIn {
+ 0% {
+ opacity: 0;
+ -webkit-transform: scale(.3);
+ -ms-transform: scale(.3);
+ transform: scale(.3);
+ }
+
+ 50% {
+ opacity: 1;
+ -webkit-transform: scale(1.05);
+ -ms-transform: scale(1.05);
+ transform: scale(1.05);
+ }
+
+ 70% {
+ -webkit-transform: scale(.9);
+ -ms-transform: scale(.9);
+ transform: scale(.9);
+ }
+
+ 100% {
+ -webkit-transform: scale(1);
+ -ms-transform: scale(1);
+ transform: scale(1);
+ }
+}
+
+.bounceIn {
+ -webkit-animation-name: bounceIn;
+ animation-name: bounceIn;
+}
+
+@-webkit-keyframes bounceInDown {
+ 0% {
+ opacity: 0;
+ -webkit-transform: translateY(-2000px);
+ transform: translateY(-2000px);
+ }
+
+ 60% {
+ opacity: 1;
+ -webkit-transform: translateY(30px);
+ transform: translateY(30px);
+ }
+
+ 80% {
+ -webkit-transform: translateY(-10px);
+ transform: translateY(-10px);
+ }
+
+ 100% {
+ -webkit-transform: translateY(0);
+ transform: translateY(0);
+ }
+}
+
+@keyframes bounceInDown {
+ 0% {
+ opacity: 0;
+ -webkit-transform: translateY(-2000px);
+ -ms-transform: translateY(-2000px);
+ transform: translateY(-2000px);
+ }
+
+ 60% {
+ opacity: 1;
+ -webkit-transform: translateY(30px);
+ -ms-transform: translateY(30px);
+ transform: translateY(30px);
+ }
+
+ 80% {
+ -webkit-transform: translateY(-10px);
+ -ms-transform: translateY(-10px);
+ transform: translateY(-10px);
+ }
+
+ 100% {
+ -webkit-transform: translateY(0);
+ -ms-transform: translateY(0);
+ transform: translateY(0);
+ }
+}
+
+.bounceInDown {
+ -webkit-animation-name: bounceInDown;
+ animation-name: bounceInDown;
+}
+
+@-webkit-keyframes bounceInLeft {
+ 0% {
+ opacity: 0;
+ -webkit-transform: translateX(-2000px);
+ transform: translateX(-2000px);
+ }
+
+ 60% {
+ opacity: 1;
+ -webkit-transform: translateX(30px);
+ transform: translateX(30px);
+ }
+
+ 80% {
+ -webkit-transform: translateX(-10px);
+ transform: translateX(-10px);
+ }
+
+ 100% {
+ -webkit-transform: translateX(0);
+ transform: translateX(0);
+ }
+}
+
+@keyframes bounceInLeft {
+ 0% {
+ opacity: 0;
+ -webkit-transform: translateX(-2000px);
+ -ms-transform: translateX(-2000px);
+ transform: translateX(-2000px);
+ }
+
+ 60% {
+ opacity: 1;
+ -webkit-transform: translateX(30px);
+ -ms-transform: translateX(30px);
+ transform: translateX(30px);
+ }
+
+ 80% {
+ -webkit-transform: translateX(-10px);
+ -ms-transform: translateX(-10px);
+ transform: translateX(-10px);
+ }
+
+ 100% {
+ -webkit-transform: translateX(0);
+ -ms-transform: translateX(0);
+ transform: translateX(0);
+ }
+}
+
+.bounceInLeft {
+ -webkit-animation-name: bounceInLeft;
+ animation-name: bounceInLeft;
+}
+
+@-webkit-keyframes bounceInRight {
+ 0% {
+ opacity: 0;
+ -webkit-transform: translateX(2000px);
+ transform: translateX(2000px);
+ }
+
+ 60% {
+ opacity: 1;
+ -webkit-transform: translateX(-30px);
+ transform: translateX(-30px);
+ }
+
+ 80% {
+ -webkit-transform: translateX(10px);
+ transform: translateX(10px);
+ }
+
+ 100% {
+ -webkit-transform: translateX(0);
+ transform: translateX(0);
+ }
+}
+
+@keyframes bounceInRight {
+ 0% {
+ opacity: 0;
+ -webkit-transform: translateX(2000px);
+ -ms-transform: translateX(2000px);
+ transform: translateX(2000px);
+ }
+
+ 60% {
+ opacity: 1;
+ -webkit-transform: translateX(-30px);
+ -ms-transform: translateX(-30px);
+ transform: translateX(-30px);
+ }
+
+ 80% {
+ -webkit-transform: translateX(10px);
+ -ms-transform: translateX(10px);
+ transform: translateX(10px);
+ }
+
+ 100% {
+ -webkit-transform: translateX(0);
+ -ms-transform: translateX(0);
+ transform: translateX(0);
+ }
+}
+
+.bounceInRight {
+ -webkit-animation-name: bounceInRight;
+ animation-name: bounceInRight;
+}
+
+@-webkit-keyframes bounceInUp {
+ 0% {
+ opacity: 0;
+ -webkit-transform: translateY(2000px);
+ transform: translateY(2000px);
+ }
+
+ 60% {
+ opacity: 1;
+ -webkit-transform: translateY(-30px);
+ transform: translateY(-30px);
+ }
+
+ 80% {
+ -webkit-transform: translateY(10px);
+ transform: translateY(10px);
+ }
+
+ 100% {
+ -webkit-transform: translateY(0);
+ transform: translateY(0);
+ }
+}
+
+@keyframes bounceInUp {
+ 0% {
+ opacity: 0;
+ -webkit-transform: translateY(2000px);
+ -ms-transform: translateY(2000px);
+ transform: translateY(2000px);
+ }
+
+ 60% {
+ opacity: 1;
+ -webkit-transform: translateY(-30px);
+ -ms-transform: translateY(-30px);
+ transform: translateY(-30px);
+ }
+
+ 80% {
+ -webkit-transform: translateY(10px);
+ -ms-transform: translateY(10px);
+ transform: translateY(10px);
+ }
+
+ 100% {
+ -webkit-transform: translateY(0);
+ -ms-transform: translateY(0);
+ transform: translateY(0);
+ }
+}
+
+.bounceInUp {
+ -webkit-animation-name: bounceInUp;
+ animation-name: bounceInUp;
+}
+
+@-webkit-keyframes bounceOut {
+ 0% {
+ -webkit-transform: scale(1);
+ transform: scale(1);
+ }
+
+ 25% {
+ -webkit-transform: scale(.95);
+ transform: scale(.95);
+ }
+
+ 50% {
+ opacity: 1;
+ -webkit-transform: scale(1.1);
+ transform: scale(1.1);
+ }
+
+ 100% {
+ opacity: 0;
+ -webkit-transform: scale(.3);
+ transform: scale(.3);
+ }
+}
+
+@keyframes bounceOut {
+ 0% {
+ -webkit-transform: scale(1);
+ -ms-transform: scale(1);
+ transform: scale(1);
+ }
+
+ 25% {
+ -webkit-transform: scale(.95);
+ -ms-transform: scale(.95);
+ transform: scale(.95);
+ }
+
+ 50% {
+ opacity: 1;
+ -webkit-transform: scale(1.1);
+ -ms-transform: scale(1.1);
+ transform: scale(1.1);
+ }
+
+ 100% {
+ opacity: 0;
+ -webkit-transform: scale(.3);
+ -ms-transform: scale(.3);
+ transform: scale(.3);
+ }
+}
+
+.bounceOut {
+ -webkit-animation-name: bounceOut;
+ animation-name: bounceOut;
+}
+
+@-webkit-keyframes bounceOutDown {
+ 0% {
+ -webkit-transform: translateY(0);
+ transform: translateY(0);
+ }
+
+ 20% {
+ opacity: 1;
+ -webkit-transform: translateY(-20px);
+ transform: translateY(-20px);
+ }
+
+ 100% {
+ opacity: 0;
+ -webkit-transform: translateY(2000px);
+ transform: translateY(2000px);
+ }
+}
+
+@keyframes bounceOutDown {
+ 0% {
+ -webkit-transform: translateY(0);
+ -ms-transform: translateY(0);
+ transform: translateY(0);
+ }
+
+ 20% {
+ opacity: 1;
+ -webkit-transform: translateY(-20px);
+ -ms-transform: translateY(-20px);
+ transform: translateY(-20px);
+ }
+
+ 100% {
+ opacity: 0;
+ -webkit-transform: translateY(2000px);
+ -ms-transform: translateY(2000px);
+ transform: translateY(2000px);
+ }
+}
+
+.bounceOutDown {
+ -webkit-animation-name: bounceOutDown;
+ animation-name: bounceOutDown;
+}
+
+@-webkit-keyframes bounceOutLeft {
+ 0% {
+ -webkit-transform: translateX(0);
+ transform: translateX(0);
+ }
+
+ 20% {
+ opacity: 1;
+ -webkit-transform: translateX(20px);
+ transform: translateX(20px);
+ }
+
+ 100% {
+ opacity: 0;
+ -webkit-transform: translateX(-2000px);
+ transform: translateX(-2000px);
+ }
+}
+
+@keyframes bounceOutLeft {
+ 0% {
+ -webkit-transform: translateX(0);
+ -ms-transform: translateX(0);
+ transform: translateX(0);
+ }
+
+ 20% {
+ opacity: 1;
+ -webkit-transform: translateX(20px);
+ -ms-transform: translateX(20px);
+ transform: translateX(20px);
+ }
+
+ 100% {
+ opacity: 0;
+ -webkit-transform: translateX(-2000px);
+ -ms-transform: translateX(-2000px);
+ transform: translateX(-2000px);
+ }
+}
+
+.bounceOutLeft {
+ -webkit-animation-name: bounceOutLeft;
+ animation-name: bounceOutLeft;
+}
+
+@-webkit-keyframes bounceOutRight {
+ 0% {
+ -webkit-transform: translateX(0);
+ transform: translateX(0);
+ }
+
+ 20% {
+ opacity: 1;
+ -webkit-transform: translateX(-20px);
+ transform: translateX(-20px);
+ }
+
+ 100% {
+ opacity: 0;
+ -webkit-transform: translateX(2000px);
+ transform: translateX(2000px);
+ }
+}
+
+@keyframes bounceOutRight {
+ 0% {
+ -webkit-transform: translateX(0);
+ -ms-transform: translateX(0);
+ transform: translateX(0);
+ }
+
+ 20% {
+ opacity: 1;
+ -webkit-transform: translateX(-20px);
+ -ms-transform: translateX(-20px);
+ transform: translateX(-20px);
+ }
+
+ 100% {
+ opacity: 0;
+ -webkit-transform: translateX(2000px);
+ -ms-transform: translateX(2000px);
+ transform: translateX(2000px);
+ }
+}
+
+.bounceOutRight {
+ -webkit-animation-name: bounceOutRight;
+ animation-name: bounceOutRight;
+}
+
+@-webkit-keyframes bounceOutUp {
+ 0% {
+ -webkit-transform: translateY(0);
+ transform: translateY(0);
+ }
+
+ 20% {
+ opacity: 1;
+ -webkit-transform: translateY(20px);
+ transform: translateY(20px);
+ }
+
+ 100% {
+ opacity: 0;
+ -webkit-transform: translateY(-2000px);
+ transform: translateY(-2000px);
+ }
+}
+
+@keyframes bounceOutUp {
+ 0% {
+ -webkit-transform: translateY(0);
+ -ms-transform: translateY(0);
+ transform: translateY(0);
+ }
+
+ 20% {
+ opacity: 1;
+ -webkit-transform: translateY(20px);
+ -ms-transform: translateY(20px);
+ transform: translateY(20px);
+ }
+
+ 100% {
+ opacity: 0;
+ -webkit-transform: translateY(-2000px);
+ -ms-transform: translateY(-2000px);
+ transform: translateY(-2000px);
+ }
+}
+
+.bounceOutUp {
+ -webkit-animation-name: bounceOutUp;
+ animation-name: bounceOutUp;
+}
+
+@-webkit-keyframes fadeIn {
+ 0% {
+ opacity: 0;
+ }
+
+ 100% {
+ opacity: 1;
+ }
+}
+
+@keyframes fadeIn {
+ 0% {
+ opacity: 0;
+ }
+
+ 100% {
+ opacity: 1;
+ }
+}
+
+.fadeIn {
+ -webkit-animation-name: fadeIn;
+ animation-name: fadeIn;
+}
+
+@-webkit-keyframes fadeInDown {
+ 0% {
+ opacity: 0;
+ -webkit-transform: translateY(-20px);
+ transform: translateY(-20px);
+ }
+
+ 100% {
+ opacity: 1;
+ -webkit-transform: translateY(0);
+ transform: translateY(0);
+ }
+}
+
+@keyframes fadeInDown {
+ 0% {
+ opacity: 0;
+ -webkit-transform: translateY(-20px);
+ -ms-transform: translateY(-20px);
+ transform: translateY(-20px);
+ }
+
+ 100% {
+ opacity: 1;
+ -webkit-transform: translateY(0);
+ -ms-transform: translateY(0);
+ transform: translateY(0);
+ }
+}
+
+.fadeInDown {
+ -webkit-animation-name: fadeInDown;
+ animation-name: fadeInDown;
+}
+
+@-webkit-keyframes fadeInDownBig {
+ 0% {
+ opacity: 0;
+ -webkit-transform: translateY(-2000px);
+ transform: translateY(-2000px);
+ }
+
+ 100% {
+ opacity: 1;
+ -webkit-transform: translateY(0);
+ transform: translateY(0);
+ }
+}
+
+@keyframes fadeInDownBig {
+ 0% {
+ opacity: 0;
+ -webkit-transform: translateY(-2000px);
+ -ms-transform: translateY(-2000px);
+ transform: translateY(-2000px);
+ }
+
+ 100% {
+ opacity: 1;
+ -webkit-transform: translateY(0);
+ -ms-transform: translateY(0);
+ transform: translateY(0);
+ }
+}
+
+.fadeInDownBig {
+ -webkit-animation-name: fadeInDownBig;
+ animation-name: fadeInDownBig;
+}
+
+@-webkit-keyframes fadeInLeft {
+ 0% {
+ opacity: 0;
+ -webkit-transform: translateX(-20px);
+ transform: translateX(-20px);
+ }
+
+ 100% {
+ opacity: 1;
+ -webkit-transform: translateX(0);
+ transform: translateX(0);
+ }
+}
+
+@keyframes fadeInLeft {
+ 0% {
+ opacity: 0;
+ -webkit-transform: translateX(-20px);
+ -ms-transform: translateX(-20px);
+ transform: translateX(-20px);
+ }
+
+ 100% {
+ opacity: 1;
+ -webkit-transform: translateX(0);
+ -ms-transform: translateX(0);
+ transform: translateX(0);
+ }
+}
+
+.fadeInLeft {
+ -webkit-animation-name: fadeInLeft;
+ animation-name: fadeInLeft;
+}
+
+@-webkit-keyframes fadeInLeftBig {
+ 0% {
+ opacity: 0;
+ -webkit-transform: translateX(-2000px);
+ transform: translateX(-2000px);
+ }
+
+ 100% {
+ opacity: 1;
+ -webkit-transform: translateX(0);
+ transform: translateX(0);
+ }
+}
+
+@keyframes fadeInLeftBig {
+ 0% {
+ opacity: 0;
+ -webkit-transform: translateX(-2000px);
+ -ms-transform: translateX(-2000px);
+ transform: translateX(-2000px);
+ }
+
+ 100% {
+ opacity: 1;
+ -webkit-transform: translateX(0);
+ -ms-transform: translateX(0);
+ transform: translateX(0);
+ }
+}
+
+.fadeInLeftBig {
+ -webkit-animation-name: fadeInLeftBig;
+ animation-name: fadeInLeftBig;
+}
+
+@-webkit-keyframes fadeInRight {
+ 0% {
+ opacity: 0;
+ -webkit-transform: translateX(20px);
+ transform: translateX(20px);
+ }
+
+ 100% {
+ opacity: 1;
+ -webkit-transform: translateX(0);
+ transform: translateX(0);
+ }
+}
+
+@keyframes fadeInRight {
+ 0% {
+ opacity: 0;
+ -webkit-transform: translateX(20px);
+ -ms-transform: translateX(20px);
+ transform: translateX(20px);
+ }
+
+ 100% {
+ opacity: 1;
+ -webkit-transform: translateX(0);
+ -ms-transform: translateX(0);
+ transform: translateX(0);
+ }
+}
+
+.fadeInRight {
+ -webkit-animation-name: fadeInRight;
+ animation-name: fadeInRight;
+}
+
+@-webkit-keyframes fadeInRightBig {
+ 0% {
+ opacity: 0;
+ -webkit-transform: translateX(2000px);
+ transform: translateX(2000px);
+ }
+
+ 100% {
+ opacity: 1;
+ -webkit-transform: translateX(0);
+ transform: translateX(0);
+ }
+}
+
+@keyframes fadeInRightBig {
+ 0% {
+ opacity: 0;
+ -webkit-transform: translateX(2000px);
+ -ms-transform: translateX(2000px);
+ transform: translateX(2000px);
+ }
+
+ 100% {
+ opacity: 1;
+ -webkit-transform: translateX(0);
+ -ms-transform: translateX(0);
+ transform: translateX(0);
+ }
+}
+
+.fadeInRightBig {
+ -webkit-animation-name: fadeInRightBig;
+ animation-name: fadeInRightBig;
+}
+
+@-webkit-keyframes fadeInUp {
+ 0% {
+ opacity: 0;
+ -webkit-transform: translateY(20px);
+ transform: translateY(20px);
+ }
+
+ 100% {
+ opacity: 1;
+ -webkit-transform: translateY(0);
+ transform: translateY(0);
+ }
+}
+
+@keyframes fadeInUp {
+ 0% {
+ opacity: 0;
+ -webkit-transform: translateY(20px);
+ -ms-transform: translateY(20px);
+ transform: translateY(20px);
+ }
+
+ 100% {
+ opacity: 1;
+ -webkit-transform: translateY(0);
+ -ms-transform: translateY(0);
+ transform: translateY(0);
+ }
+}
+
+.fadeInUp {
+ -webkit-animation-name: fadeInUp;
+ animation-name: fadeInUp;
+}
+
+@-webkit-keyframes fadeInUpBig {
+ 0% {
+ opacity: 0;
+ -webkit-transform: translateY(2000px);
+ transform: translateY(2000px);
+ }
+
+ 100% {
+ opacity: 1;
+ -webkit-transform: translateY(0);
+ transform: translateY(0);
+ }
+}
+
+@keyframes fadeInUpBig {
+ 0% {
+ opacity: 0;
+ -webkit-transform: translateY(2000px);
+ -ms-transform: translateY(2000px);
+ transform: translateY(2000px);
+ }
+
+ 100% {
+ opacity: 1;
+ -webkit-transform: translateY(0);
+ -ms-transform: translateY(0);
+ transform: translateY(0);
+ }
+}
+
+.fadeInUpBig {
+ -webkit-animation-name: fadeInUpBig;
+ animation-name: fadeInUpBig;
+}
+
+@-webkit-keyframes fadeOut {
+ 0% {
+ opacity: 1;
+ }
+
+ 100% {
+ opacity: 0;
+ }
+}
+
+@keyframes fadeOut {
+ 0% {
+ opacity: 1;
+ }
+
+ 100% {
+ opacity: 0;
+ }
+}
+
+.fadeOut {
+ -webkit-animation-name: fadeOut;
+ animation-name: fadeOut;
+}
+
+@-webkit-keyframes fadeOutDown {
+ 0% {
+ opacity: 1;
+ -webkit-transform: translateY(0);
+ transform: translateY(0);
+ }
+
+ 100% {
+ opacity: 0;
+ -webkit-transform: translateY(20px);
+ transform: translateY(20px);
+ }
+}
+
+@keyframes fadeOutDown {
+ 0% {
+ opacity: 1;
+ -webkit-transform: translateY(0);
+ -ms-transform: translateY(0);
+ transform: translateY(0);
+ }
+
+ 100% {
+ opacity: 0;
+ -webkit-transform: translateY(20px);
+ -ms-transform: translateY(20px);
+ transform: translateY(20px);
+ }
+}
+
+.fadeOutDown {
+ -webkit-animation-name: fadeOutDown;
+ animation-name: fadeOutDown;
+}
+
+@-webkit-keyframes fadeOutDownBig {
+ 0% {
+ opacity: 1;
+ -webkit-transform: translateY(0);
+ transform: translateY(0);
+ }
+
+ 100% {
+ opacity: 0;
+ -webkit-transform: translateY(2000px);
+ transform: translateY(2000px);
+ }
+}
+
+@keyframes fadeOutDownBig {
+ 0% {
+ opacity: 1;
+ -webkit-transform: translateY(0);
+ -ms-transform: translateY(0);
+ transform: translateY(0);
+ }
+
+ 100% {
+ opacity: 0;
+ -webkit-transform: translateY(2000px);
+ -ms-transform: translateY(2000px);
+ transform: translateY(2000px);
+ }
+}
+
+.fadeOutDownBig {
+ -webkit-animation-name: fadeOutDownBig;
+ animation-name: fadeOutDownBig;
+}
+
+@-webkit-keyframes fadeOutLeft {
+ 0% {
+ opacity: 1;
+ -webkit-transform: translateX(0);
+ transform: translateX(0);
+ }
+
+ 100% {
+ opacity: 0;
+ -webkit-transform: translateX(-20px);
+ transform: translateX(-20px);
+ }
+}
+
+@keyframes fadeOutLeft {
+ 0% {
+ opacity: 1;
+ -webkit-transform: translateX(0);
+ -ms-transform: translateX(0);
+ transform: translateX(0);
+ }
+
+ 100% {
+ opacity: 0;
+ -webkit-transform: translateX(-20px);
+ -ms-transform: translateX(-20px);
+ transform: translateX(-20px);
+ }
+}
+
+.fadeOutLeft {
+ -webkit-animation-name: fadeOutLeft;
+ animation-name: fadeOutLeft;
+}
+
+@-webkit-keyframes fadeOutLeftBig {
+ 0% {
+ opacity: 1;
+ -webkit-transform: translateX(0);
+ transform: translateX(0);
+ }
+
+ 100% {
+ opacity: 0;
+ -webkit-transform: translateX(-2000px);
+ transform: translateX(-2000px);
+ }
+}
+
+@keyframes fadeOutLeftBig {
+ 0% {
+ opacity: 1;
+ -webkit-transform: translateX(0);
+ -ms-transform: translateX(0);
+ transform: translateX(0);
+ }
+
+ 100% {
+ opacity: 0;
+ -webkit-transform: translateX(-2000px);
+ -ms-transform: translateX(-2000px);
+ transform: translateX(-2000px);
+ }
+}
+
+.fadeOutLeftBig {
+ -webkit-animation-name: fadeOutLeftBig;
+ animation-name: fadeOutLeftBig;
+}
+
+@-webkit-keyframes fadeOutRight {
+ 0% {
+ opacity: 1;
+ -webkit-transform: translateX(0);
+ transform: translateX(0);
+ }
+
+ 100% {
+ opacity: 0;
+ -webkit-transform: translateX(20px);
+ transform: translateX(20px);
+ }
+}
+
+@keyframes fadeOutRight {
+ 0% {
+ opacity: 1;
+ -webkit-transform: translateX(0);
+ -ms-transform: translateX(0);
+ transform: translateX(0);
+ }
+
+ 100% {
+ opacity: 0;
+ -webkit-transform: translateX(20px);
+ -ms-transform: translateX(20px);
+ transform: translateX(20px);
+ }
+}
+
+.fadeOutRight {
+ -webkit-animation-name: fadeOutRight;
+ animation-name: fadeOutRight;
+}
+
+@-webkit-keyframes fadeOutRightBig {
+ 0% {
+ opacity: 1;
+ -webkit-transform: translateX(0);
+ transform: translateX(0);
+ }
+
+ 100% {
+ opacity: 0;
+ -webkit-transform: translateX(2000px);
+ transform: translateX(2000px);
+ }
+}
+
+@keyframes fadeOutRightBig {
+ 0% {
+ opacity: 1;
+ -webkit-transform: translateX(0);
+ -ms-transform: translateX(0);
+ transform: translateX(0);
+ }
+
+ 100% {
+ opacity: 0;
+ -webkit-transform: translateX(2000px);
+ -ms-transform: translateX(2000px);
+ transform: translateX(2000px);
+ }
+}
+
+.fadeOutRightBig {
+ -webkit-animation-name: fadeOutRightBig;
+ animation-name: fadeOutRightBig;
+}
+
+@-webkit-keyframes fadeOutUp {
+ 0% {
+ opacity: 1;
+ -webkit-transform: translateY(0);
+ transform: translateY(0);
+ }
+
+ 100% {
+ opacity: 0;
+ -webkit-transform: translateY(-20px);
+ transform: translateY(-20px);
+ }
+}
+
+@keyframes fadeOutUp {
+ 0% {
+ opacity: 1;
+ -webkit-transform: translateY(0);
+ -ms-transform: translateY(0);
+ transform: translateY(0);
+ }
+
+ 100% {
+ opacity: 0;
+ -webkit-transform: translateY(-20px);
+ -ms-transform: translateY(-20px);
+ transform: translateY(-20px);
+ }
+}
+
+.fadeOutUp {
+ -webkit-animation-name: fadeOutUp;
+ animation-name: fadeOutUp;
+}
+
+@-webkit-keyframes fadeOutUpBig {
+ 0% {
+ opacity: 1;
+ -webkit-transform: translateY(0);
+ transform: translateY(0);
+ }
+
+ 100% {
+ opacity: 0;
+ -webkit-transform: translateY(-2000px);
+ transform: translateY(-2000px);
+ }
+}
+
+@keyframes fadeOutUpBig {
+ 0% {
+ opacity: 1;
+ -webkit-transform: translateY(0);
+ -ms-transform: translateY(0);
+ transform: translateY(0);
+ }
+
+ 100% {
+ opacity: 0;
+ -webkit-transform: translateY(-2000px);
+ -ms-transform: translateY(-2000px);
+ transform: translateY(-2000px);
+ }
+}
+
+.fadeOutUpBig {
+ -webkit-animation-name: fadeOutUpBig;
+ animation-name: fadeOutUpBig;
+}
+
+@-webkit-keyframes flip {
+ 0% {
+ -webkit-transform: perspective(400px) translateZ(0) rotateY(0) scale(1);
+ transform: perspective(400px) translateZ(0) rotateY(0) scale(1);
+ -webkit-animation-timing-function: ease-out;
+ animation-timing-function: ease-out;
+ }
+
+ 40% {
+ -webkit-transform: perspective(400px) translateZ(150px) rotateY(170deg) scale(1);
+ transform: perspective(400px) translateZ(150px) rotateY(170deg) scale(1);
+ -webkit-animation-timing-function: ease-out;
+ animation-timing-function: ease-out;
+ }
+
+ 50% {
+ -webkit-transform: perspective(400px) translateZ(150px) rotateY(190deg) scale(1);
+ transform: perspective(400px) translateZ(150px) rotateY(190deg) scale(1);
+ -webkit-animation-timing-function: ease-in;
+ animation-timing-function: ease-in;
+ }
+
+ 80% {
+ -webkit-transform: perspective(400px) translateZ(0) rotateY(360deg) scale(.95);
+ transform: perspective(400px) translateZ(0) rotateY(360deg) scale(.95);
+ -webkit-animation-timing-function: ease-in;
+ animation-timing-function: ease-in;
+ }
+
+ 100% {
+ -webkit-transform: perspective(400px) translateZ(0) rotateY(360deg) scale(1);
+ transform: perspective(400px) translateZ(0) rotateY(360deg) scale(1);
+ -webkit-animation-timing-function: ease-in;
+ animation-timing-function: ease-in;
+ }
+}
+
+@keyframes flip {
+ 0% {
+ -webkit-transform: perspective(400px) translateZ(0) rotateY(0) scale(1);
+ -ms-transform: perspective(400px) translateZ(0) rotateY(0) scale(1);
+ transform: perspective(400px) translateZ(0) rotateY(0) scale(1);
+ -webkit-animation-timing-function: ease-out;
+ animation-timing-function: ease-out;
+ }
+
+ 40% {
+ -webkit-transform: perspective(400px) translateZ(150px) rotateY(170deg) scale(1);
+ -ms-transform: perspective(400px) translateZ(150px) rotateY(170deg) scale(1);
+ transform: perspective(400px) translateZ(150px) rotateY(170deg) scale(1);
+ -webkit-animation-timing-function: ease-out;
+ animation-timing-function: ease-out;
+ }
+
+ 50% {
+ -webkit-transform: perspective(400px) translateZ(150px) rotateY(190deg) scale(1);
+ -ms-transform: perspective(400px) translateZ(150px) rotateY(190deg) scale(1);
+ transform: perspective(400px) translateZ(150px) rotateY(190deg) scale(1);
+ -webkit-animation-timing-function: ease-in;
+ animation-timing-function: ease-in;
+ }
+
+ 80% {
+ -webkit-transform: perspective(400px) translateZ(0) rotateY(360deg) scale(.95);
+ -ms-transform: perspective(400px) translateZ(0) rotateY(360deg) scale(.95);
+ transform: perspective(400px) translateZ(0) rotateY(360deg) scale(.95);
+ -webkit-animation-timing-function: ease-in;
+ animation-timing-function: ease-in;
+ }
+
+ 100% {
+ -webkit-transform: perspective(400px) translateZ(0) rotateY(360deg) scale(1);
+ -ms-transform: perspective(400px) translateZ(0) rotateY(360deg) scale(1);
+ transform: perspective(400px) translateZ(0) rotateY(360deg) scale(1);
+ -webkit-animation-timing-function: ease-in;
+ animation-timing-function: ease-in;
+ }
+}
+
+.animated.flip {
+ -webkit-backface-visibility: visible;
+ -ms-backface-visibility: visible;
+ backface-visibility: visible;
+ -webkit-animation-name: flip;
+ animation-name: flip;
+}
+
+@-webkit-keyframes flipInX {
+ 0% {
+ -webkit-transform: perspective(400px) rotateX(90deg);
+ transform: perspective(400px) rotateX(90deg);
+ opacity: 0;
+ }
+
+ 40% {
+ -webkit-transform: perspective(400px) rotateX(-10deg);
+ transform: perspective(400px) rotateX(-10deg);
+ }
+
+ 70% {
+ -webkit-transform: perspective(400px) rotateX(10deg);
+ transform: perspective(400px) rotateX(10deg);
+ }
+
+ 100% {
+ -webkit-transform: perspective(400px) rotateX(0deg);
+ transform: perspective(400px) rotateX(0deg);
+ opacity: 1;
+ }
+}
+
+@keyframes flipInX {
+ 0% {
+ -webkit-transform: perspective(400px) rotateX(90deg);
+ -ms-transform: perspective(400px) rotateX(90deg);
+ transform: perspective(400px) rotateX(90deg);
+ opacity: 0;
+ }
+
+ 40% {
+ -webkit-transform: perspective(400px) rotateX(-10deg);
+ -ms-transform: perspective(400px) rotateX(-10deg);
+ transform: perspective(400px) rotateX(-10deg);
+ }
+
+ 70% {
+ -webkit-transform: perspective(400px) rotateX(10deg);
+ -ms-transform: perspective(400px) rotateX(10deg);
+ transform: perspective(400px) rotateX(10deg);
+ }
+
+ 100% {
+ -webkit-transform: perspective(400px) rotateX(0deg);
+ -ms-transform: perspective(400px) rotateX(0deg);
+ transform: perspective(400px) rotateX(0deg);
+ opacity: 1;
+ }
+}
+
+.flipInX {
+ -webkit-backface-visibility: visible !important;
+ -ms-backface-visibility: visible !important;
+ backface-visibility: visible !important;
+ -webkit-animation-name: flipInX;
+ animation-name: flipInX;
+}
+
+@-webkit-keyframes flipInY {
+ 0% {
+ -webkit-transform: perspective(400px) rotateY(90deg);
+ transform: perspective(400px) rotateY(90deg);
+ opacity: 0;
+ }
+
+ 40% {
+ -webkit-transform: perspective(400px) rotateY(-10deg);
+ transform: perspective(400px) rotateY(-10deg);
+ }
+
+ 70% {
+ -webkit-transform: perspective(400px) rotateY(10deg);
+ transform: perspective(400px) rotateY(10deg);
+ }
+
+ 100% {
+ -webkit-transform: perspective(400px) rotateY(0deg);
+ transform: perspective(400px) rotateY(0deg);
+ opacity: 1;
+ }
+}
+
+@keyframes flipInY {
+ 0% {
+ -webkit-transform: perspective(400px) rotateY(90deg);
+ -ms-transform: perspective(400px) rotateY(90deg);
+ transform: perspective(400px) rotateY(90deg);
+ opacity: 0;
+ }
+
+ 40% {
+ -webkit-transform: perspective(400px) rotateY(-10deg);
+ -ms-transform: perspective(400px) rotateY(-10deg);
+ transform: perspective(400px) rotateY(-10deg);
+ }
+
+ 70% {
+ -webkit-transform: perspective(400px) rotateY(10deg);
+ -ms-transform: perspective(400px) rotateY(10deg);
+ transform: perspective(400px) rotateY(10deg);
+ }
+
+ 100% {
+ -webkit-transform: perspective(400px) rotateY(0deg);
+ -ms-transform: perspective(400px) rotateY(0deg);
+ transform: perspective(400px) rotateY(0deg);
+ opacity: 1;
+ }
+}
+
+.flipInY {
+ -webkit-backface-visibility: visible !important;
+ -ms-backface-visibility: visible !important;
+ backface-visibility: visible !important;
+ -webkit-animation-name: flipInY;
+ animation-name: flipInY;
+}
+
+@-webkit-keyframes flipOutX {
+ 0% {
+ -webkit-transform: perspective(400px) rotateX(0deg);
+ transform: perspective(400px) rotateX(0deg);
+ opacity: 1;
+ }
+
+ 100% {
+ -webkit-transform: perspective(400px) rotateX(90deg);
+ transform: perspective(400px) rotateX(90deg);
+ opacity: 0;
+ }
+}
+
+@keyframes flipOutX {
+ 0% {
+ -webkit-transform: perspective(400px) rotateX(0deg);
+ -ms-transform: perspective(400px) rotateX(0deg);
+ transform: perspective(400px) rotateX(0deg);
+ opacity: 1;
+ }
+
+ 100% {
+ -webkit-transform: perspective(400px) rotateX(90deg);
+ -ms-transform: perspective(400px) rotateX(90deg);
+ transform: perspective(400px) rotateX(90deg);
+ opacity: 0;
+ }
+}
+
+.flipOutX {
+ -webkit-animation-name: flipOutX;
+ animation-name: flipOutX;
+ -webkit-backface-visibility: visible !important;
+ -ms-backface-visibility: visible !important;
+ backface-visibility: visible !important;
+}
+
+@-webkit-keyframes flipOutY {
+ 0% {
+ -webkit-transform: perspective(400px) rotateY(0deg);
+ transform: perspective(400px) rotateY(0deg);
+ opacity: 1;
+ }
+
+ 100% {
+ -webkit-transform: perspective(400px) rotateY(90deg);
+ transform: perspective(400px) rotateY(90deg);
+ opacity: 0;
+ }
+}
+
+@keyframes flipOutY {
+ 0% {
+ -webkit-transform: perspective(400px) rotateY(0deg);
+ -ms-transform: perspective(400px) rotateY(0deg);
+ transform: perspective(400px) rotateY(0deg);
+ opacity: 1;
+ }
+
+ 100% {
+ -webkit-transform: perspective(400px) rotateY(90deg);
+ -ms-transform: perspective(400px) rotateY(90deg);
+ transform: perspective(400px) rotateY(90deg);
+ opacity: 0;
+ }
+}
+
+.flipOutY {
+ -webkit-backface-visibility: visible !important;
+ -ms-backface-visibility: visible !important;
+ backface-visibility: visible !important;
+ -webkit-animation-name: flipOutY;
+ animation-name: flipOutY;
+}
+
+@-webkit-keyframes lightSpeedIn {
+ 0% {
+ -webkit-transform: translateX(100%) skewX(-30deg);
+ transform: translateX(100%) skewX(-30deg);
+ opacity: 0;
+ }
+
+ 60% {
+ -webkit-transform: translateX(-20%) skewX(30deg);
+ transform: translateX(-20%) skewX(30deg);
+ opacity: 1;
+ }
+
+ 80% {
+ -webkit-transform: translateX(0%) skewX(-15deg);
+ transform: translateX(0%) skewX(-15deg);
+ opacity: 1;
+ }
+
+ 100% {
+ -webkit-transform: translateX(0%) skewX(0deg);
+ transform: translateX(0%) skewX(0deg);
+ opacity: 1;
+ }
+}
+
+@keyframes lightSpeedIn {
+ 0% {
+ -webkit-transform: translateX(100%) skewX(-30deg);
+ -ms-transform: translateX(100%) skewX(-30deg);
+ transform: translateX(100%) skewX(-30deg);
+ opacity: 0;
+ }
+
+ 60% {
+ -webkit-transform: translateX(-20%) skewX(30deg);
+ -ms-transform: translateX(-20%) skewX(30deg);
+ transform: translateX(-20%) skewX(30deg);
+ opacity: 1;
+ }
+
+ 80% {
+ -webkit-transform: translateX(0%) skewX(-15deg);
+ -ms-transform: translateX(0%) skewX(-15deg);
+ transform: translateX(0%) skewX(-15deg);
+ opacity: 1;
+ }
+
+ 100% {
+ -webkit-transform: translateX(0%) skewX(0deg);
+ -ms-transform: translateX(0%) skewX(0deg);
+ transform: translateX(0%) skewX(0deg);
+ opacity: 1;
+ }
+}
+
+.lightSpeedIn {
+ -webkit-animation-name: lightSpeedIn;
+ animation-name: lightSpeedIn;
+ -webkit-animation-timing-function: ease-out;
+ animation-timing-function: ease-out;
+}
+
+@-webkit-keyframes lightSpeedOut {
+ 0% {
+ -webkit-transform: translateX(0%) skewX(0deg);
+ transform: translateX(0%) skewX(0deg);
+ opacity: 1;
+ }
+
+ 100% {
+ -webkit-transform: translateX(100%) skewX(-30deg);
+ transform: translateX(100%) skewX(-30deg);
+ opacity: 0;
+ }
+}
+
+@keyframes lightSpeedOut {
+ 0% {
+ -webkit-transform: translateX(0%) skewX(0deg);
+ -ms-transform: translateX(0%) skewX(0deg);
+ transform: translateX(0%) skewX(0deg);
+ opacity: 1;
+ }
+
+ 100% {
+ -webkit-transform: translateX(100%) skewX(-30deg);
+ -ms-transform: translateX(100%) skewX(-30deg);
+ transform: translateX(100%) skewX(-30deg);
+ opacity: 0;
+ }
+}
+
+.lightSpeedOut {
+ -webkit-animation-name: lightSpeedOut;
+ animation-name: lightSpeedOut;
+ -webkit-animation-timing-function: ease-in;
+ animation-timing-function: ease-in;
+}
+
+@-webkit-keyframes rotateIn {
+ 0% {
+ -webkit-transform-origin: center center;
+ transform-origin: center center;
+ -webkit-transform: rotate(-200deg);
+ transform: rotate(-200deg);
+ opacity: 0;
+ }
+
+ 100% {
+ -webkit-transform-origin: center center;
+ transform-origin: center center;
+ -webkit-transform: rotate(0);
+ transform: rotate(0);
+ opacity: 1;
+ }
+}
+
+@keyframes rotateIn {
+ 0% {
+ -webkit-transform-origin: center center;
+ -ms-transform-origin: center center;
+ transform-origin: center center;
+ -webkit-transform: rotate(-200deg);
+ -ms-transform: rotate(-200deg);
+ transform: rotate(-200deg);
+ opacity: 0;
+ }
+
+ 100% {
+ -webkit-transform-origin: center center;
+ -ms-transform-origin: center center;
+ transform-origin: center center;
+ -webkit-transform: rotate(0);
+ -ms-transform: rotate(0);
+ transform: rotate(0);
+ opacity: 1;
+ }
+}
+
+.rotateIn {
+ -webkit-animation-name: rotateIn;
+ animation-name: rotateIn;
+}
+
+@-webkit-keyframes rotateInDownLeft {
+ 0% {
+ -webkit-transform-origin: left bottom;
+ transform-origin: left bottom;
+ -webkit-transform: rotate(-90deg);
+ transform: rotate(-90deg);
+ opacity: 0;
+ }
+
+ 100% {
+ -webkit-transform-origin: left bottom;
+ transform-origin: left bottom;
+ -webkit-transform: rotate(0);
+ transform: rotate(0);
+ opacity: 1;
+ }
+}
+
+@keyframes rotateInDownLeft {
+ 0% {
+ -webkit-transform-origin: left bottom;
+ -ms-transform-origin: left bottom;
+ transform-origin: left bottom;
+ -webkit-transform: rotate(-90deg);
+ -ms-transform: rotate(-90deg);
+ transform: rotate(-90deg);
+ opacity: 0;
+ }
+
+ 100% {
+ -webkit-transform-origin: left bottom;
+ -ms-transform-origin: left bottom;
+ transform-origin: left bottom;
+ -webkit-transform: rotate(0);
+ -ms-transform: rotate(0);
+ transform: rotate(0);
+ opacity: 1;
+ }
+}
+
+.rotateInDownLeft {
+ -webkit-animation-name: rotateInDownLeft;
+ animation-name: rotateInDownLeft;
+}
+
+@-webkit-keyframes rotateInDownRight {
+ 0% {
+ -webkit-transform-origin: right bottom;
+ transform-origin: right bottom;
+ -webkit-transform: rotate(90deg);
+ transform: rotate(90deg);
+ opacity: 0;
+ }
+
+ 100% {
+ -webkit-transform-origin: right bottom;
+ transform-origin: right bottom;
+ -webkit-transform: rotate(0);
+ transform: rotate(0);
+ opacity: 1;
+ }
+}
+
+@keyframes rotateInDownRight {
+ 0% {
+ -webkit-transform-origin: right bottom;
+ -ms-transform-origin: right bottom;
+ transform-origin: right bottom;
+ -webkit-transform: rotate(90deg);
+ -ms-transform: rotate(90deg);
+ transform: rotate(90deg);
+ opacity: 0;
+ }
+
+ 100% {
+ -webkit-transform-origin: right bottom;
+ -ms-transform-origin: right bottom;
+ transform-origin: right bottom;
+ -webkit-transform: rotate(0);
+ -ms-transform: rotate(0);
+ transform: rotate(0);
+ opacity: 1;
+ }
+}
+
+.rotateInDownRight {
+ -webkit-animation-name: rotateInDownRight;
+ animation-name: rotateInDownRight;
+}
+
+@-webkit-keyframes rotateInUpLeft {
+ 0% {
+ -webkit-transform-origin: left bottom;
+ transform-origin: left bottom;
+ -webkit-transform: rotate(90deg);
+ transform: rotate(90deg);
+ opacity: 0;
+ }
+
+ 100% {
+ -webkit-transform-origin: left bottom;
+ transform-origin: left bottom;
+ -webkit-transform: rotate(0);
+ transform: rotate(0);
+ opacity: 1;
+ }
+}
+
+@keyframes rotateInUpLeft {
+ 0% {
+ -webkit-transform-origin: left bottom;
+ -ms-transform-origin: left bottom;
+ transform-origin: left bottom;
+ -webkit-transform: rotate(90deg);
+ -ms-transform: rotate(90deg);
+ transform: rotate(90deg);
+ opacity: 0;
+ }
+
+ 100% {
+ -webkit-transform-origin: left bottom;
+ -ms-transform-origin: left bottom;
+ transform-origin: left bottom;
+ -webkit-transform: rotate(0);
+ -ms-transform: rotate(0);
+ transform: rotate(0);
+ opacity: 1;
+ }
+}
+
+.rotateInUpLeft {
+ -webkit-animation-name: rotateInUpLeft;
+ animation-name: rotateInUpLeft;
+}
+
+@-webkit-keyframes rotateInUpRight {
+ 0% {
+ -webkit-transform-origin: right bottom;
+ transform-origin: right bottom;
+ -webkit-transform: rotate(-90deg);
+ transform: rotate(-90deg);
+ opacity: 0;
+ }
+
+ 100% {
+ -webkit-transform-origin: right bottom;
+ transform-origin: right bottom;
+ -webkit-transform: rotate(0);
+ transform: rotate(0);
+ opacity: 1;
+ }
+}
+
+@keyframes rotateInUpRight {
+ 0% {
+ -webkit-transform-origin: right bottom;
+ -ms-transform-origin: right bottom;
+ transform-origin: right bottom;
+ -webkit-transform: rotate(-90deg);
+ -ms-transform: rotate(-90deg);
+ transform: rotate(-90deg);
+ opacity: 0;
+ }
+
+ 100% {
+ -webkit-transform-origin: right bottom;
+ -ms-transform-origin: right bottom;
+ transform-origin: right bottom;
+ -webkit-transform: rotate(0);
+ -ms-transform: rotate(0);
+ transform: rotate(0);
+ opacity: 1;
+ }
+}
+
+.rotateInUpRight {
+ -webkit-animation-name: rotateInUpRight;
+ animation-name: rotateInUpRight;
+}
+
+@-webkit-keyframes rotateOut {
+ 0% {
+ -webkit-transform-origin: center center;
+ transform-origin: center center;
+ -webkit-transform: rotate(0);
+ transform: rotate(0);
+ opacity: 1;
+ }
+
+ 100% {
+ -webkit-transform-origin: center center;
+ transform-origin: center center;
+ -webkit-transform: rotate(200deg);
+ transform: rotate(200deg);
+ opacity: 0;
+ }
+}
+
+@keyframes rotateOut {
+ 0% {
+ -webkit-transform-origin: center center;
+ -ms-transform-origin: center center;
+ transform-origin: center center;
+ -webkit-transform: rotate(0);
+ -ms-transform: rotate(0);
+ transform: rotate(0);
+ opacity: 1;
+ }
+
+ 100% {
+ -webkit-transform-origin: center center;
+ -ms-transform-origin: center center;
+ transform-origin: center center;
+ -webkit-transform: rotate(200deg);
+ -ms-transform: rotate(200deg);
+ transform: rotate(200deg);
+ opacity: 0;
+ }
+}
+
+.rotateOut {
+ -webkit-animation-name: rotateOut;
+ animation-name: rotateOut;
+}
+
+@-webkit-keyframes rotateOutDownLeft {
+ 0% {
+ -webkit-transform-origin: left bottom;
+ transform-origin: left bottom;
+ -webkit-transform: rotate(0);
+ transform: rotate(0);
+ opacity: 1;
+ }
+
+ 100% {
+ -webkit-transform-origin: left bottom;
+ transform-origin: left bottom;
+ -webkit-transform: rotate(90deg);
+ transform: rotate(90deg);
+ opacity: 0;
+ }
+}
+
+@keyframes rotateOutDownLeft {
+ 0% {
+ -webkit-transform-origin: left bottom;
+ -ms-transform-origin: left bottom;
+ transform-origin: left bottom;
+ -webkit-transform: rotate(0);
+ -ms-transform: rotate(0);
+ transform: rotate(0);
+ opacity: 1;
+ }
+
+ 100% {
+ -webkit-transform-origin: left bottom;
+ -ms-transform-origin: left bottom;
+ transform-origin: left bottom;
+ -webkit-transform: rotate(90deg);
+ -ms-transform: rotate(90deg);
+ transform: rotate(90deg);
+ opacity: 0;
+ }
+}
+
+.rotateOutDownLeft {
+ -webkit-animation-name: rotateOutDownLeft;
+ animation-name: rotateOutDownLeft;
+}
+
+@-webkit-keyframes rotateOutDownRight {
+ 0% {
+ -webkit-transform-origin: right bottom;
+ transform-origin: right bottom;
+ -webkit-transform: rotate(0);
+ transform: rotate(0);
+ opacity: 1;
+ }
+
+ 100% {
+ -webkit-transform-origin: right bottom;
+ transform-origin: right bottom;
+ -webkit-transform: rotate(-90deg);
+ transform: rotate(-90deg);
+ opacity: 0;
+ }
+}
+
+@keyframes rotateOutDownRight {
+ 0% {
+ -webkit-transform-origin: right bottom;
+ -ms-transform-origin: right bottom;
+ transform-origin: right bottom;
+ -webkit-transform: rotate(0);
+ -ms-transform: rotate(0);
+ transform: rotate(0);
+ opacity: 1;
+ }
+
+ 100% {
+ -webkit-transform-origin: right bottom;
+ -ms-transform-origin: right bottom;
+ transform-origin: right bottom;
+ -webkit-transform: rotate(-90deg);
+ -ms-transform: rotate(-90deg);
+ transform: rotate(-90deg);
+ opacity: 0;
+ }
+}
+
+.rotateOutDownRight {
+ -webkit-animation-name: rotateOutDownRight;
+ animation-name: rotateOutDownRight;
+}
+
+@-webkit-keyframes rotateOutUpLeft {
+ 0% {
+ -webkit-transform-origin: left bottom;
+ transform-origin: left bottom;
+ -webkit-transform: rotate(0);
+ transform: rotate(0);
+ opacity: 1;
+ }
+
+ 100% {
+ -webkit-transform-origin: left bottom;
+ transform-origin: left bottom;
+ -webkit-transform: rotate(-90deg);
+ transform: rotate(-90deg);
+ opacity: 0;
+ }
+}
+
+@keyframes rotateOutUpLeft {
+ 0% {
+ -webkit-transform-origin: left bottom;
+ -ms-transform-origin: left bottom;
+ transform-origin: left bottom;
+ -webkit-transform: rotate(0);
+ -ms-transform: rotate(0);
+ transform: rotate(0);
+ opacity: 1;
+ }
+
+ 100% {
+ -webkit-transform-origin: left bottom;
+ -ms-transform-origin: left bottom;
+ transform-origin: left bottom;
+ -webkit-transform: rotate(-90deg);
+ -ms-transform: rotate(-90deg);
+ transform: rotate(-90deg);
+ opacity: 0;
+ }
+}
+
+.rotateOutUpLeft {
+ -webkit-animation-name: rotateOutUpLeft;
+ animation-name: rotateOutUpLeft;
+}
+
+@-webkit-keyframes rotateOutUpRight {
+ 0% {
+ -webkit-transform-origin: right bottom;
+ transform-origin: right bottom;
+ -webkit-transform: rotate(0);
+ transform: rotate(0);
+ opacity: 1;
+ }
+
+ 100% {
+ -webkit-transform-origin: right bottom;
+ transform-origin: right bottom;
+ -webkit-transform: rotate(90deg);
+ transform: rotate(90deg);
+ opacity: 0;
+ }
+}
+
+@keyframes rotateOutUpRight {
+ 0% {
+ -webkit-transform-origin: right bottom;
+ -ms-transform-origin: right bottom;
+ transform-origin: right bottom;
+ -webkit-transform: rotate(0);
+ -ms-transform: rotate(0);
+ transform: rotate(0);
+ opacity: 1;
+ }
+
+ 100% {
+ -webkit-transform-origin: right bottom;
+ -ms-transform-origin: right bottom;
+ transform-origin: right bottom;
+ -webkit-transform: rotate(90deg);
+ -ms-transform: rotate(90deg);
+ transform: rotate(90deg);
+ opacity: 0;
+ }
+}
+
+.rotateOutUpRight {
+ -webkit-animation-name: rotateOutUpRight;
+ animation-name: rotateOutUpRight;
+}
+
+@-webkit-keyframes slideInDown {
+ 0% {
+ opacity: 0;
+ -webkit-transform: translateY(-2000px);
+ transform: translateY(-2000px);
+ }
+
+ 100% {
+ -webkit-transform: translateY(0);
+ transform: translateY(0);
+ }
+}
+
+@keyframes slideInDown {
+ 0% {
+ opacity: 0;
+ -webkit-transform: translateY(-2000px);
+ -ms-transform: translateY(-2000px);
+ transform: translateY(-2000px);
+ }
+
+ 100% {
+ -webkit-transform: translateY(0);
+ -ms-transform: translateY(0);
+ transform: translateY(0);
+ }
+}
+
+.slideInDown {
+ -webkit-animation-name: slideInDown;
+ animation-name: slideInDown;
+}
+
+@-webkit-keyframes slideInLeft {
+ 0% {
+ opacity: 0;
+ -webkit-transform: translateX(-2000px);
+ transform: translateX(-2000px);
+ }
+
+ 100% {
+ -webkit-transform: translateX(0);
+ transform: translateX(0);
+ }
+}
+
+@keyframes slideInLeft {
+ 0% {
+ opacity: 0;
+ -webkit-transform: translateX(-2000px);
+ -ms-transform: translateX(-2000px);
+ transform: translateX(-2000px);
+ }
+
+ 100% {
+ -webkit-transform: translateX(0);
+ -ms-transform: translateX(0);
+ transform: translateX(0);
+ }
+}
+
+.slideInLeft {
+ -webkit-animation-name: slideInLeft;
+ animation-name: slideInLeft;
+}
+
+@-webkit-keyframes slideInRight {
+ 0% {
+ opacity: 0;
+ -webkit-transform: translateX(2000px);
+ transform: translateX(2000px);
+ }
+
+ 100% {
+ -webkit-transform: translateX(0);
+ transform: translateX(0);
+ }
+}
+
+@keyframes slideInRight {
+ 0% {
+ opacity: 0;
+ -webkit-transform: translateX(2000px);
+ -ms-transform: translateX(2000px);
+ transform: translateX(2000px);
+ }
+
+ 100% {
+ -webkit-transform: translateX(0);
+ -ms-transform: translateX(0);
+ transform: translateX(0);
+ }
+}
+
+.slideInRight {
+ -webkit-animation-name: slideInRight;
+ animation-name: slideInRight;
+}
+
+@-webkit-keyframes slideOutLeft {
+ 0% {
+ -webkit-transform: translateX(0);
+ transform: translateX(0);
+ }
+
+ 100% {
+ opacity: 0;
+ -webkit-transform: translateX(-2000px);
+ transform: translateX(-2000px);
+ }
+}
+
+@keyframes slideOutLeft {
+ 0% {
+ -webkit-transform: translateX(0);
+ -ms-transform: translateX(0);
+ transform: translateX(0);
+ }
+
+ 100% {
+ opacity: 0;
+ -webkit-transform: translateX(-2000px);
+ -ms-transform: translateX(-2000px);
+ transform: translateX(-2000px);
+ }
+}
+
+.slideOutLeft {
+ -webkit-animation-name: slideOutLeft;
+ animation-name: slideOutLeft;
+}
+
+@-webkit-keyframes slideOutRight {
+ 0% {
+ -webkit-transform: translateX(0);
+ transform: translateX(0);
+ }
+
+ 100% {
+ opacity: 0;
+ -webkit-transform: translateX(2000px);
+ transform: translateX(2000px);
+ }
+}
+
+@keyframes slideOutRight {
+ 0% {
+ -webkit-transform: translateX(0);
+ -ms-transform: translateX(0);
+ transform: translateX(0);
+ }
+
+ 100% {
+ opacity: 0;
+ -webkit-transform: translateX(2000px);
+ -ms-transform: translateX(2000px);
+ transform: translateX(2000px);
+ }
+}
+
+.slideOutRight {
+ -webkit-animation-name: slideOutRight;
+ animation-name: slideOutRight;
+}
+
+@-webkit-keyframes slideOutUp {
+ 0% {
+ -webkit-transform: translateY(0);
+ transform: translateY(0);
+ }
+
+ 100% {
+ opacity: 0;
+ -webkit-transform: translateY(-2000px);
+ transform: translateY(-2000px);
+ }
+}
+
+@keyframes slideOutUp {
+ 0% {
+ -webkit-transform: translateY(0);
+ -ms-transform: translateY(0);
+ transform: translateY(0);
+ }
+
+ 100% {
+ opacity: 0;
+ -webkit-transform: translateY(-2000px);
+ -ms-transform: translateY(-2000px);
+ transform: translateY(-2000px);
+ }
+}
+
+.slideOutUp {
+ -webkit-animation-name: slideOutUp;
+ animation-name: slideOutUp;
+}
+
+@-webkit-keyframes hinge {
+ 0% {
+ -webkit-transform: rotate(0);
+ transform: rotate(0);
+ -webkit-transform-origin: top left;
+ transform-origin: top left;
+ -webkit-animation-timing-function: ease-in-out;
+ animation-timing-function: ease-in-out;
+ }
+
+ 20%, 60% {
+ -webkit-transform: rotate(80deg);
+ transform: rotate(80deg);
+ -webkit-transform-origin: top left;
+ transform-origin: top left;
+ -webkit-animation-timing-function: ease-in-out;
+ animation-timing-function: ease-in-out;
+ }
+
+ 40% {
+ -webkit-transform: rotate(60deg);
+ transform: rotate(60deg);
+ -webkit-transform-origin: top left;
+ transform-origin: top left;
+ -webkit-animation-timing-function: ease-in-out;
+ animation-timing-function: ease-in-out;
+ }
+
+ 80% {
+ -webkit-transform: rotate(60deg) translateY(0);
+ transform: rotate(60deg) translateY(0);
+ opacity: 1;
+ -webkit-transform-origin: top left;
+ transform-origin: top left;
+ -webkit-animation-timing-function: ease-in-out;
+ animation-timing-function: ease-in-out;
+ }
+
+ 100% {
+ -webkit-transform: translateY(700px);
+ transform: translateY(700px);
+ opacity: 0;
+ }
+}
+
+@keyframes hinge {
+ 0% {
+ -webkit-transform: rotate(0);
+ -ms-transform: rotate(0);
+ transform: rotate(0);
+ -webkit-transform-origin: top left;
+ -ms-transform-origin: top left;
+ transform-origin: top left;
+ -webkit-animation-timing-function: ease-in-out;
+ animation-timing-function: ease-in-out;
+ }
+
+ 20%, 60% {
+ -webkit-transform: rotate(80deg);
+ -ms-transform: rotate(80deg);
+ transform: rotate(80deg);
+ -webkit-transform-origin: top left;
+ -ms-transform-origin: top left;
+ transform-origin: top left;
+ -webkit-animation-timing-function: ease-in-out;
+ animation-timing-function: ease-in-out;
+ }
+
+ 40% {
+ -webkit-transform: rotate(60deg);
+ -ms-transform: rotate(60deg);
+ transform: rotate(60deg);
+ -webkit-transform-origin: top left;
+ -ms-transform-origin: top left;
+ transform-origin: top left;
+ -webkit-animation-timing-function: ease-in-out;
+ animation-timing-function: ease-in-out;
+ }
+
+ 80% {
+ -webkit-transform: rotate(60deg) translateY(0);
+ -ms-transform: rotate(60deg) translateY(0);
+ transform: rotate(60deg) translateY(0);
+ opacity: 1;
+ -webkit-transform-origin: top left;
+ -ms-transform-origin: top left;
+ transform-origin: top left;
+ -webkit-animation-timing-function: ease-in-out;
+ animation-timing-function: ease-in-out;
+ }
+
+ 100% {
+ -webkit-transform: translateY(700px);
+ -ms-transform: translateY(700px);
+ transform: translateY(700px);
+ opacity: 0;
+ }
+}
+
+.hinge {
+ -webkit-animation-name: hinge;
+ animation-name: hinge;
+}
+
+/* originally authored by Nick Pettit - https://github.com/nickpettit/glide */
+
+@-webkit-keyframes rollIn {
+ 0% {
+ opacity: 0;
+ -webkit-transform: translateX(-100%) rotate(-120deg);
+ transform: translateX(-100%) rotate(-120deg);
+ }
+
+ 100% {
+ opacity: 1;
+ -webkit-transform: translateX(0px) rotate(0deg);
+ transform: translateX(0px) rotate(0deg);
+ }
+}
+
+@keyframes rollIn {
+ 0% {
+ opacity: 0;
+ -webkit-transform: translateX(-100%) rotate(-120deg);
+ -ms-transform: translateX(-100%) rotate(-120deg);
+ transform: translateX(-100%) rotate(-120deg);
+ }
+
+ 100% {
+ opacity: 1;
+ -webkit-transform: translateX(0px) rotate(0deg);
+ -ms-transform: translateX(0px) rotate(0deg);
+ transform: translateX(0px) rotate(0deg);
+ }
+}
+
+.rollIn {
+ -webkit-animation-name: rollIn;
+ animation-name: rollIn;
+}
+
+/* originally authored by Nick Pettit - https://github.com/nickpettit/glide */
+
+@-webkit-keyframes rollOut {
+ 0% {
+ opacity: 1;
+ -webkit-transform: translateX(0px) rotate(0deg);
+ transform: translateX(0px) rotate(0deg);
+ }
+
+ 100% {
+ opacity: 0;
+ -webkit-transform: translateX(100%) rotate(120deg);
+ transform: translateX(100%) rotate(120deg);
+ }
+}
+
+@keyframes rollOut {
+ 0% {
+ opacity: 1;
+ -webkit-transform: translateX(0px) rotate(0deg);
+ -ms-transform: translateX(0px) rotate(0deg);
+ transform: translateX(0px) rotate(0deg);
+ }
+
+ 100% {
+ opacity: 0;
+ -webkit-transform: translateX(100%) rotate(120deg);
+ -ms-transform: translateX(100%) rotate(120deg);
+ transform: translateX(100%) rotate(120deg);
+ }
+}
+
+.rollOut {
+ -webkit-animation-name: rollOut;
+ animation-name: rollOut;
}
\ No newline at end of file
diff --git a/webgoat-container/src/main/webapp/css/font-awesome.min.css b/webgoat-container/src/main/resources/static/css/font-awesome.min.css
similarity index 100%
rename from webgoat-container/src/main/webapp/css/font-awesome.min.css
rename to webgoat-container/src/main/resources/static/css/font-awesome.min.css
diff --git a/webgoat-container/src/main/webapp/css/img/logo.png b/webgoat-container/src/main/resources/static/css/img/logo.png
similarity index 100%
rename from webgoat-container/src/main/webapp/css/img/logo.png
rename to webgoat-container/src/main/resources/static/css/img/logo.png
diff --git a/webgoat-container/src/main/webapp/css/img/logoBG.jpg b/webgoat-container/src/main/resources/static/css/img/logoBG.jpg
similarity index 100%
rename from webgoat-container/src/main/webapp/css/img/logoBG.jpg
rename to webgoat-container/src/main/resources/static/css/img/logoBG.jpg
diff --git a/webgoat-container/src/main/webapp/css/img/webBg.png b/webgoat-container/src/main/resources/static/css/img/webBg.png
similarity index 100%
rename from webgoat-container/src/main/webapp/css/img/webBg.png
rename to webgoat-container/src/main/resources/static/css/img/webBg.png
diff --git a/webgoat-container/src/main/webapp/css/layers.css b/webgoat-container/src/main/resources/static/css/layers.css
similarity index 99%
rename from webgoat-container/src/main/webapp/css/layers.css
rename to webgoat-container/src/main/resources/static/css/layers.css
index 99d09863f..a5081db2b 100644
--- a/webgoat-container/src/main/webapp/css/layers.css
+++ b/webgoat-container/src/main/resources/static/css/layers.css
@@ -1,2 +1,2 @@
-#lesson-title {position:absolute;left:94px;top:75px;width:690px;height:22px;z-index:1;float: right;font-size: 20px;color: #FFFFFF;}
-#hMenuBar {position:absolute;left:245px;top:108px;width:538px;height:22px;z-index:2;}
+#lesson-title {position:absolute;left:94px;top:75px;width:690px;height:22px;z-index:1;float: right;font-size: 20px;color: #FFFFFF;}
+#hMenuBar {position:absolute;left:245px;top:108px;width:538px;height:22px;z-index:2;}
diff --git a/webgoat-container/src/main/webapp/css/lesson.css b/webgoat-container/src/main/resources/static/css/lesson.css
similarity index 98%
rename from webgoat-container/src/main/webapp/css/lesson.css
rename to webgoat-container/src/main/resources/static/css/lesson.css
index ba0229b96..06174eecd 100644
--- a/webgoat-container/src/main/webapp/css/lesson.css
+++ b/webgoat-container/src/main/resources/static/css/lesson.css
@@ -1,11 +1,11 @@
-body.page {color: #000000;font-family: Verdana, Tahoma, sans-serif;font-size: 8pt;}
-td {font-family: Verdana, Tahoma, sans-serif;font-size: 8pt; }
-tr {font-family: Verdana, Tahoma, sans-serif;}
-span {font-family: Verdana, Tahoma, sans-serif;}
-.f8-0 {font-size: 8pt;font-family: Verdana, Tahoma, sans-serif;}
-.f8-1 {font-size: 8pt;font-family: Verdana, Tahoma, sans-serif;}
-.div_tree {padding-left:10px;overflow:visible;}
-.report_tree_link {width:100%;font-size: 8pt;font-family: Verdana, Tahoma, sans-serif;margin-left:2px;padding-right:2px;margin-top:2px;border-spacing:0px;}
-.form_link {font-size: 8pt;font-family: Verdana, Tahoma, sans-serif;font-weight: bold;}
-.report_title {font-size: 8pt;font-family: Verdana, Tahoma, sans-serif;border: 1px solid #afafaf;background-color: #cfcfef;margin-top:3px;margin-bottom:3px;margin-left:1px;padding:3px;font-weight: bold;}
+body.page {color: #000000;font-family: Verdana, Tahoma, sans-serif;font-size: 8pt;}
+td {font-family: Verdana, Tahoma, sans-serif;font-size: 8pt; }
+tr {font-family: Verdana, Tahoma, sans-serif;}
+span {font-family: Verdana, Tahoma, sans-serif;}
+.f8-0 {font-size: 8pt;font-family: Verdana, Tahoma, sans-serif;}
+.f8-1 {font-size: 8pt;font-family: Verdana, Tahoma, sans-serif;}
+.div_tree {padding-left:10px;overflow:visible;}
+.report_tree_link {width:100%;font-size: 8pt;font-family: Verdana, Tahoma, sans-serif;margin-left:2px;padding-right:2px;margin-top:2px;border-spacing:0px;}
+.form_link {font-size: 8pt;font-family: Verdana, Tahoma, sans-serif;font-weight: bold;}
+.report_title {font-size: 8pt;font-family: Verdana, Tahoma, sans-serif;border: 1px solid #afafaf;background-color: #cfcfef;margin-top:3px;margin-bottom:3px;margin-left:1px;padding:3px;font-weight: bold;}
.middle {vertical-align:middle;}
\ No newline at end of file
diff --git a/webgoat-container/src/main/webapp/css/main.css b/webgoat-container/src/main/resources/static/css/main.css
similarity index 95%
rename from webgoat-container/src/main/webapp/css/main.css
rename to webgoat-container/src/main/resources/static/css/main.css
index c05467ad1..ee0ae7e94 100644
--- a/webgoat-container/src/main/webapp/css/main.css
+++ b/webgoat-container/src/main/resources/static/css/main.css
@@ -657,12 +657,17 @@ fieldset[disabled] .btn-warning.active {
}
.modal .modal-body.modal-scroll {
max-height: 375px;
- overflow-y: auto;
+ overflow-y: scroll auto;
}
#about-modal {
opacity: 95%;
}
+
+.modal-header {
+ border-bottom:none !important
+}
+
/* ==========================================================================
Media Queries
========================================================================== */
@@ -793,7 +798,7 @@ cookie-container {
.sidebar {
width: 240px;
/*height: 100%;*/
- background: #222;
+ background: #fff;
position: absolute;
-webkit-transition: all 0.3s ease-in-out;
-moz-transition: all 0.3s ease-in-out;
@@ -804,7 +809,7 @@ cookie-container {
}
#menu-container {
- overflow-y:scroll;
+ overflow-y:scroll auto;
overflow-x:hidden;
}
@@ -829,7 +834,9 @@ cookie-container {
#menu-container ul li a {
- color: #aeb2b7;
+ /*color: #aeb2b7;*/
+ color: #222;
+ font-weight:bold;
text-decoration: none;
display: block;
padding: 5px 0 5px 15px;
@@ -845,7 +852,8 @@ cookie-container {
display: inline-block;
}
#menu-container ul ul li {
- background: #333;
+ /*background: #333;*/
+ background: #aaa;
margin-bottom: 0;
margin-left: 0;
margin-right: 0;
@@ -855,7 +863,8 @@ cookie-container {
font-size: 11px;
padding-top: 5px;
padding-bottom: 5px;
- color: #aeb2b7;
+ /*color: #aeb2b7;*/
+ color: #fff;
margin-left:8px;
}
#menu-container ul li a i {
@@ -885,7 +894,7 @@ cookie-container {
}
#menu-container ul li.selected, #menu-container li a.selected {
- background-color: #555;
+ background-color: ##aaa;
}
#menu-container ul li.stage {
@@ -893,17 +902,47 @@ cookie-container {
}
#menu-container li.selected, #menu-container a.selected {
- color:white;
+ color:#fff;
+ font-weight:550;
}
#menu-container ul ul.lessonsAndStages.keepOpen {
display: block
}
+/* General View Controls */
+.show-next-page:hover {
+ cursor:pointer;
+}
+
+.show-prev-page {
+ margin-right: 10px;
+}
+
+.show-prev-page:hover {
+ cursor:pointer;
+}
+
+.attack-feedback {
+ font-weight:800;
+}
+
+.attack-output {
+ border-top: 1px solid #ccc;
+}
+
/* HINTS */
#lesson-hint-container {
display: none;
}
+
+#lesson-hint {
+ background-color: #ccc;
+ border-radius: 4px;
+ border-color: #999;
+ margin-top:4px;
+}
+
#hintsViewTop{
display: none;
background-color: #eee;
@@ -925,4 +964,13 @@ cookie-container {
.help-button {
margin-right:4px;
+}
+
+/* ATTACK DISPLAY */
+
+.attack-container {
+ background-color: #f1f1f1;
+ border: 2px solid #a66;
+ border-radius: 12px;
+ padding: 7px;
}
\ No newline at end of file
diff --git a/webgoat-container/src/main/webapp/css/menu.css b/webgoat-container/src/main/resources/static/css/menu.css
similarity index 98%
rename from webgoat-container/src/main/webapp/css/menu.css
rename to webgoat-container/src/main/resources/static/css/menu.css
index 0436f5aeb..93b4aa59b 100644
--- a/webgoat-container/src/main/webapp/css/menu.css
+++ b/webgoat-container/src/main/resources/static/css/menu.css
@@ -1,11 +1,11 @@
-.pviimenudiv td {font-family: "Trebuchet MS", Arial, sans-serif; font-size: 10px}
-.pviimenudiv p {font-family: "Trebuchet MS", Arial, sans-serif; font-size: 10px; margin-top: 12px; margin-bottom: 6px}
-.pviimenudiv b {font-family: Verdana, Arial, Helvetica, sans-serif; font-style: normal; color: #666666}
-.pviimenudiv a:link {color: #333333; text-decoration: underline}
-.pviimenudiv a:visited {color: #0066FF; text-decoration: underline}
-.pviimenudiv a:hover {color: red; text-decoration: underline}
-.pviimenudiv a:active {color: #0066FF; text-decoration: underline}
-.pviimenudivstage a:link {color: #333333; font-size: 9px; display: block; margin-left: 2em; }
-.pviimenudivstage a:visited {color: #0066FF; font-size: 9px; display: block; margin-left: 2em; }
-.pviimenudivstage a:hover {color: red; font-size: 9px; display: block; margin-left: 2em; }
-.pviimenudivstage a:active {color: #0066FF; font-size: 9px; display: block; margin-left: 2em; }
+.pviimenudiv td {font-family: "Trebuchet MS", Arial, sans-serif; font-size: 10px}
+.pviimenudiv p {font-family: "Trebuchet MS", Arial, sans-serif; font-size: 10px; margin-top: 12px; margin-bottom: 6px}
+.pviimenudiv b {font-family: Verdana, Arial, Helvetica, sans-serif; font-style: normal; color: #666666}
+.pviimenudiv a:link {color: #333333; text-decoration: underline}
+.pviimenudiv a:visited {color: #0066FF; text-decoration: underline}
+.pviimenudiv a:hover {color: red; text-decoration: underline}
+.pviimenudiv a:active {color: #0066FF; text-decoration: underline}
+.pviimenudivstage a:link {color: #333333; font-size: 9px; display: block; margin-left: 2em; }
+.pviimenudivstage a:visited {color: #0066FF; font-size: 9px; display: block; margin-left: 2em; }
+.pviimenudivstage a:hover {color: red; font-size: 9px; display: block; margin-left: 2em; }
+.pviimenudivstage a:active {color: #0066FF; font-size: 9px; display: block; margin-left: 2em; }
diff --git a/webgoat-container/src/main/webapp/css/webgoat.css b/webgoat-container/src/main/resources/static/css/webgoat.css
similarity index 92%
rename from webgoat-container/src/main/webapp/css/webgoat.css
rename to webgoat-container/src/main/resources/static/css/webgoat.css
index dd61f086b..7c66701ab 100644
--- a/webgoat-container/src/main/webapp/css/webgoat.css
+++ b/webgoat-container/src/main/resources/static/css/webgoat.css
@@ -1,305 +1,305 @@
-/*
-body{
- min-width: 800px;
- font-family: Arial,sans-serif;
- color: #333333;
- line-height: 1.166;
- margin: 0px;
- padding: 0px;
-}
-
-a:link, a:visited, a:hover {
- color: #666666;
- text-decoration: none;
-}
-
-a:hover {
- text-decoration: underline;
- color: red;
-}
-
-h1, h2, h3, h4, h5, h6 {
- font-family: Arial,sans-serif;
- margin: 0px;
- padding: 0px;
-}
-
-h1{
- font-family: Verdana,Arial,sans-serif;
- font-size: 120%;
- color: #333333;
-}
-
-h2{
- font-size: 114%;
- color: #333333;
-}
-
-h3{
- font-size: 100%;
- color: #334d55;
-}
-
-h4{
- font-size: 100%;
- font-weight: normal;
- color: #333333;
-}
-
-h5{
- font-size: 100%;
- color: #334d55;
-}
-*/
-ul{
- list-style-type: square;
-}
-
-ul ul{
- list-style-type: disc;
-}
-
-ul ul ul{
- list-style-type: none;
-}
-
-#navBar{
- margin: 0 79% 0 0;
- padding: 0px;
- background-color: #999999;
-}
-
-#twoCol{
- margin: 0;
- padding-left: 13px;
-}
-
-#siteName{
- margin: 0px;
- padding: 0px 0px 10px 10px;
-}
-
-#lessonName{
- padding: 5px 0px 10px 10px;
-}
-
-#globalNav{
- color: #cccccc;
- padding: 0px 10px;
- white-space: nowrap;
-}
-
-#globalNav img{
- display: block;
-}
-
-#globalNav a {
- font-size: 10px;
- padding: 0px 4px 0px 0px;
-}
-
-.lessonContent{
- padding: 10px 10px 10px 10px;
- font-size: 10px;
-}
-
-.lessonText h3{
- padding: 30px 0px 5px 0px;
- text-align: center;
-}
-
-.lessonText img{
- float: left;
- padding: 0px 10px 0px 0px;
- margin: 0 5px 5px 0;
-}
-
-#bottom{
- color: #999999;
- clear: both;
- font-size: 10px;
- padding-top: 5px;
-}
-
-#navBar ul a:link, #navBar ul a:visited {}
-
-#navBar ul {
- list-style: none;
- margin: 0;
- padding: 0;
-}
-
-/* hack to fix IE/Win's broken rendering of block-level anchors in lists */
-#navBar li {}
-
-/* fix for browsers that don't need the hack */
-html>body #navBar li {}
-
-#top{
- height:136px;
- background-image: url(img/header/header.jpg);
- width: 800px;
-}
-
-#top_challenge{
- height:136px;
- width: 800px;
-}
-
-#topLinks{
- position: relative;
- margin: 0px;
- padding: 0px;
- font-size: small;
-}
-
-#topLinks h3{
- padding: 10px 0px 2px 10px;
-}
-
-#topLinks a:link{
- padding: 2px 0px 2px 10px;
- width: 100%;
- voice-family:inherit;
- width: auto;
-}
-
-#topLinks a:visited{
- border-top: 1px solid #cccccc;
- padding: 2px 0px 2px 10px;
-}
-
-#topLinks a:hover{
- background-color: #FFFFFF;
- padding: 5px 2px 2px 10px;
-}
-
-#menuSpacer {
- float: left;
- width: 225px;
-}
-
-#lessonArea {
- float: right;
- width: 540px;
- height: 100%;
- padding: 10px;
-}
-#lessonAreaTop {
- float: right;
- width: 540px;
- height: 15px;
- padding: 10px;
-}
-
-#wrap {
- width: 800px;
- word-wrap:break-word; /* Fixes IE wrapping issue */
-}
-
-#topRight {
- position:absolute;
- left:380px;
- top:0px;
- width:400px;
- height:23px;
- z-index:3;
- float: right;
-}
-
-#topLeft {
- position:absolute;
- left:100px;
- top:0px;
- width:400px;
- height:23px;
- z-index:3;
- float: right;
-}
-#topRightInner {
- position:absolute;
- left:450px;
- top:10px;
- width:300px;
- height:23px;
- z-index:4;
- float: right;
-}
-
-.info {
- color: red;
- font-weight: bold;
-}
-
-#reset {
- text-align: right;
- font-weight: bold;
- float: right;
- display: inline;
- margin-bottom: 10px;
-}
-
-#training {
- text-align: left;
- font-weight: bold;
- display: inline;
- float: left;
- margin-bottom: 10px;
-
-}
-
-#training_wrap {
- width: 540px;
-}
-
-#hint{}
-#parameter{}
-#cookie{}
-#message{
- margin-bottom: 20px;
- margin-top: 10px;
-}
-
-#lessonPlans {
- border: 1px solid #000000;
- background-color: #FFFFFF;
- margin: 15px;
- padding: 25px;
- padding-bottom: 75px;
-}
-
-#credits {
- float: right;
-}
-
-#start {
- height: 370px;
- width: 700px;
- padding: 10px 50px 10px 50px;
- font-size: 15px;
-}
-#warning {
- border: 1px solid #666666;
- padding: 10px;
- font-size: 10px;
- color: #FF3300;
- width: 600px;
- margin-left: 100px;
- margin-right: 100px;
-}
-#team {
- width: 580px;
- margin-right: 50px;
- margin-left: 50px;
- padding-top: 5px;
- padding-right: 10px;
- padding-bottom: 5px;
- padding-left: 10px;
-}
-.style1 {
- font-size: 11px;
- font-weight: bold;
-}
-.style2 {
- font-size: 10px;
-}
+/*
+body{
+ min-width: 800px;
+ font-family: Arial,sans-serif;
+ color: #333333;
+ line-height: 1.166;
+ margin: 0px;
+ padding: 0px;
+}
+
+a:link, a:visited, a:hover {
+ color: #666666;
+ text-decoration: none;
+}
+
+a:hover {
+ text-decoration: underline;
+ color: red;
+}
+
+h1, h2, h3, h4, h5, h6 {
+ font-family: Arial,sans-serif;
+ margin: 0px;
+ padding: 0px;
+}
+
+h1{
+ font-family: Verdana,Arial,sans-serif;
+ font-size: 120%;
+ color: #333333;
+}
+
+h2{
+ font-size: 114%;
+ color: #333333;
+}
+
+h3{
+ font-size: 100%;
+ color: #334d55;
+}
+
+h4{
+ font-size: 100%;
+ font-weight: normal;
+ color: #333333;
+}
+
+h5{
+ font-size: 100%;
+ color: #334d55;
+}
+*/
+ul{
+ list-style-type: square;
+}
+
+ul ul{
+ list-style-type: disc;
+}
+
+ul ul ul{
+ list-style-type: none;
+}
+
+#navBar{
+ margin: 0 79% 0 0;
+ padding: 0px;
+ background-color: #999999;
+}
+
+#twoCol{
+ margin: 0;
+ padding-left: 13px;
+}
+
+#siteName{
+ margin: 0px;
+ padding: 0px 0px 10px 10px;
+}
+
+#lessonName{
+ padding: 5px 0px 10px 10px;
+}
+
+#globalNav{
+ color: #cccccc;
+ padding: 0px 10px;
+ white-space: nowrap;
+}
+
+#globalNav img{
+ display: block;
+}
+
+#globalNav a {
+ font-size: 10px;
+ padding: 0px 4px 0px 0px;
+}
+
+.lessonContent{
+ padding: 10px 10px 10px 10px;
+ font-size: 10px;
+}
+
+.lessonText h3{
+ padding: 30px 0px 5px 0px;
+ text-align: center;
+}
+
+.lessonText img{
+ float: left;
+ padding: 0px 10px 0px 0px;
+ margin: 0 5px 5px 0;
+}
+
+#bottom{
+ color: #999999;
+ clear: both;
+ font-size: 10px;
+ padding-top: 5px;
+}
+
+#navBar ul a:link, #navBar ul a:visited {}
+
+#navBar ul {
+ list-style: none;
+ margin: 0;
+ padding: 0;
+}
+
+/* hack to fix IE/Win's broken rendering of block-level anchors in lists */
+#navBar li {}
+
+/* fix for browsers that don't need the hack */
+html>body #navBar li {}
+
+#top{
+ height:136px;
+ background-image: url(img/header/header.jpg);
+ width: 800px;
+}
+
+#top_challenge{
+ height:136px;
+ width: 800px;
+}
+
+#topLinks{
+ position: relative;
+ margin: 0px;
+ padding: 0px;
+ font-size: small;
+}
+
+#topLinks h3{
+ padding: 10px 0px 2px 10px;
+}
+
+#topLinks a:link{
+ padding: 2px 0px 2px 10px;
+ width: 100%;
+ voice-family:inherit;
+ width: auto;
+}
+
+#topLinks a:visited{
+ border-top: 1px solid #cccccc;
+ padding: 2px 0px 2px 10px;
+}
+
+#topLinks a:hover{
+ background-color: #FFFFFF;
+ padding: 5px 2px 2px 10px;
+}
+
+#menuSpacer {
+ float: left;
+ width: 225px;
+}
+
+#lessonArea {
+ float: right;
+ width: 540px;
+ height: 100%;
+ padding: 10px;
+}
+#lessonAreaTop {
+ float: right;
+ width: 540px;
+ height: 15px;
+ padding: 10px;
+}
+
+#wrap {
+ width: 800px;
+ word-wrap:break-word; /* Fixes IE wrapping issue */
+}
+
+#topRight {
+ position:absolute;
+ left:380px;
+ top:0px;
+ width:400px;
+ height:23px;
+ z-index:3;
+ float: right;
+}
+
+#topLeft {
+ position:absolute;
+ left:100px;
+ top:0px;
+ width:400px;
+ height:23px;
+ z-index:3;
+ float: right;
+}
+#topRightInner {
+ position:absolute;
+ left:450px;
+ top:10px;
+ width:300px;
+ height:23px;
+ z-index:4;
+ float: right;
+}
+
+.info {
+ color: red;
+ font-weight: bold;
+}
+
+#reset {
+ text-align: right;
+ font-weight: bold;
+ float: right;
+ display: inline;
+ margin-bottom: 10px;
+}
+
+#training {
+ text-align: left;
+ font-weight: bold;
+ display: inline;
+ float: left;
+ margin-bottom: 10px;
+
+}
+
+#training_wrap {
+ width: 540px;
+}
+
+#hint{}
+#parameter{}
+#cookie{}
+#message{
+ margin-bottom: 20px;
+ margin-top: 10px;
+}
+
+#lessonPlans {
+ border: 1px solid #000000;
+ background-color: #FFFFFF;
+ margin: 15px;
+ padding: 25px;
+ padding-bottom: 75px;
+}
+
+#credits {
+ float: right;
+}
+
+#start {
+ height: 370px;
+ width: 700px;
+ padding: 10px 50px 10px 50px;
+ font-size: 15px;
+}
+#warning {
+ border: 1px solid #666666;
+ padding: 10px;
+ font-size: 10px;
+ color: #FF3300;
+ width: 600px;
+ margin-left: 100px;
+ margin-right: 100px;
+}
+#team {
+ width: 580px;
+ margin-right: 50px;
+ margin-left: 50px;
+ padding-top: 5px;
+ padding-right: 10px;
+ padding-bottom: 5px;
+ padding-left: 10px;
+}
+.style1 {
+ font-size: 11px;
+ font-weight: bold;
+}
+.style2 {
+ font-size: 10px;
+}
diff --git a/webgoat-container/src/main/webapp/fonts/FontAwesome.otf b/webgoat-container/src/main/resources/static/fonts/FontAwesome.otf
similarity index 100%
rename from webgoat-container/src/main/webapp/fonts/FontAwesome.otf
rename to webgoat-container/src/main/resources/static/fonts/FontAwesome.otf
diff --git a/webgoat-container/src/main/webapp/fonts/fontawesome-webfont.eot b/webgoat-container/src/main/resources/static/fonts/fontawesome-webfont.eot
similarity index 100%
rename from webgoat-container/src/main/webapp/fonts/fontawesome-webfont.eot
rename to webgoat-container/src/main/resources/static/fonts/fontawesome-webfont.eot
diff --git a/webgoat-container/src/main/webapp/fonts/fontawesome-webfont.svg b/webgoat-container/src/main/resources/static/fonts/fontawesome-webfont.svg
similarity index 100%
rename from webgoat-container/src/main/webapp/fonts/fontawesome-webfont.svg
rename to webgoat-container/src/main/resources/static/fonts/fontawesome-webfont.svg
diff --git a/webgoat-container/src/main/webapp/fonts/fontawesome-webfont.ttf b/webgoat-container/src/main/resources/static/fonts/fontawesome-webfont.ttf
similarity index 100%
rename from webgoat-container/src/main/webapp/fonts/fontawesome-webfont.ttf
rename to webgoat-container/src/main/resources/static/fonts/fontawesome-webfont.ttf
diff --git a/webgoat-container/src/main/webapp/fonts/fontawesome-webfont.woff b/webgoat-container/src/main/resources/static/fonts/fontawesome-webfont.woff
similarity index 100%
rename from webgoat-container/src/main/webapp/fonts/fontawesome-webfont.woff
rename to webgoat-container/src/main/resources/static/fonts/fontawesome-webfont.woff
diff --git a/webgoat-container/src/main/webapp/images/WebGoatFinancial/banklogo.jpg b/webgoat-container/src/main/resources/static/images/WebGoatFinancial/banklogo.jpg
similarity index 100%
rename from webgoat-container/src/main/webapp/images/WebGoatFinancial/banklogo.jpg
rename to webgoat-container/src/main/resources/static/images/WebGoatFinancial/banklogo.jpg
diff --git a/webgoat-container/src/main/webapp/images/buttons/catStarted.jpg b/webgoat-container/src/main/resources/static/images/buttons/catStarted.jpg
similarity index 100%
rename from webgoat-container/src/main/webapp/images/buttons/catStarted.jpg
rename to webgoat-container/src/main/resources/static/images/buttons/catStarted.jpg
diff --git a/webgoat-container/src/main/webapp/images/buttons/cookies.jpg b/webgoat-container/src/main/resources/static/images/buttons/cookies.jpg
similarity index 100%
rename from webgoat-container/src/main/webapp/images/buttons/cookies.jpg
rename to webgoat-container/src/main/resources/static/images/buttons/cookies.jpg
diff --git a/webgoat-container/src/main/webapp/images/buttons/cookiesOver.jpg b/webgoat-container/src/main/resources/static/images/buttons/cookiesOver.jpg
similarity index 100%
rename from webgoat-container/src/main/webapp/images/buttons/cookiesOver.jpg
rename to webgoat-container/src/main/resources/static/images/buttons/cookiesOver.jpg
diff --git a/webgoat-container/src/main/webapp/images/buttons/help.jpg b/webgoat-container/src/main/resources/static/images/buttons/help.jpg
similarity index 100%
rename from webgoat-container/src/main/webapp/images/buttons/help.jpg
rename to webgoat-container/src/main/resources/static/images/buttons/help.jpg
diff --git a/webgoat-container/src/main/webapp/images/buttons/helpOver.jpg b/webgoat-container/src/main/resources/static/images/buttons/helpOver.jpg
similarity index 100%
rename from webgoat-container/src/main/webapp/images/buttons/helpOver.jpg
rename to webgoat-container/src/main/resources/static/images/buttons/helpOver.jpg
diff --git a/webgoat-container/src/main/webapp/images/buttons/hint.jpg b/webgoat-container/src/main/resources/static/images/buttons/hint.jpg
similarity index 100%
rename from webgoat-container/src/main/webapp/images/buttons/hint.jpg
rename to webgoat-container/src/main/resources/static/images/buttons/hint.jpg
diff --git a/webgoat-container/src/main/webapp/images/buttons/hintLeft.jpg b/webgoat-container/src/main/resources/static/images/buttons/hintLeft.jpg
similarity index 100%
rename from webgoat-container/src/main/webapp/images/buttons/hintLeft.jpg
rename to webgoat-container/src/main/resources/static/images/buttons/hintLeft.jpg
diff --git a/webgoat-container/src/main/webapp/images/buttons/hintLeftOver.jpg b/webgoat-container/src/main/resources/static/images/buttons/hintLeftOver.jpg
similarity index 100%
rename from webgoat-container/src/main/webapp/images/buttons/hintLeftOver.jpg
rename to webgoat-container/src/main/resources/static/images/buttons/hintLeftOver.jpg
diff --git a/webgoat-container/src/main/webapp/images/buttons/hintOver.jpg b/webgoat-container/src/main/resources/static/images/buttons/hintOver.jpg
similarity index 100%
rename from webgoat-container/src/main/webapp/images/buttons/hintOver.jpg
rename to webgoat-container/src/main/resources/static/images/buttons/hintOver.jpg
diff --git a/webgoat-container/src/main/webapp/images/buttons/hintRight.jpg b/webgoat-container/src/main/resources/static/images/buttons/hintRight.jpg
similarity index 100%
rename from webgoat-container/src/main/webapp/images/buttons/hintRight.jpg
rename to webgoat-container/src/main/resources/static/images/buttons/hintRight.jpg
diff --git a/webgoat-container/src/main/webapp/images/buttons/hintRightOver.jpg b/webgoat-container/src/main/resources/static/images/buttons/hintRightOver.jpg
similarity index 100%
rename from webgoat-container/src/main/webapp/images/buttons/hintRightOver.jpg
rename to webgoat-container/src/main/resources/static/images/buttons/hintRightOver.jpg
diff --git a/webgoat-container/src/main/webapp/images/buttons/html.jpg b/webgoat-container/src/main/resources/static/images/buttons/html.jpg
similarity index 100%
rename from webgoat-container/src/main/webapp/images/buttons/html.jpg
rename to webgoat-container/src/main/resources/static/images/buttons/html.jpg
diff --git a/webgoat-container/src/main/webapp/images/buttons/htmlOver.jpg b/webgoat-container/src/main/resources/static/images/buttons/htmlOver.jpg
similarity index 100%
rename from webgoat-container/src/main/webapp/images/buttons/htmlOver.jpg
rename to webgoat-container/src/main/resources/static/images/buttons/htmlOver.jpg
diff --git a/webgoat-container/src/main/webapp/images/buttons/java.jpg b/webgoat-container/src/main/resources/static/images/buttons/java.jpg
similarity index 100%
rename from webgoat-container/src/main/webapp/images/buttons/java.jpg
rename to webgoat-container/src/main/resources/static/images/buttons/java.jpg
diff --git a/webgoat-container/src/main/webapp/images/buttons/javaOver.jpg b/webgoat-container/src/main/resources/static/images/buttons/javaOver.jpg
similarity index 100%
rename from webgoat-container/src/main/webapp/images/buttons/javaOver.jpg
rename to webgoat-container/src/main/resources/static/images/buttons/javaOver.jpg
diff --git a/webgoat-container/src/main/webapp/images/buttons/lessonComplete.jpg b/webgoat-container/src/main/resources/static/images/buttons/lessonComplete.jpg
similarity index 100%
rename from webgoat-container/src/main/webapp/images/buttons/lessonComplete.jpg
rename to webgoat-container/src/main/resources/static/images/buttons/lessonComplete.jpg
diff --git a/webgoat-container/src/main/webapp/images/buttons/logout.jpg b/webgoat-container/src/main/resources/static/images/buttons/logout.jpg
similarity index 100%
rename from webgoat-container/src/main/webapp/images/buttons/logout.jpg
rename to webgoat-container/src/main/resources/static/images/buttons/logout.jpg
diff --git a/webgoat-container/src/main/webapp/images/buttons/logoutOver.jpg b/webgoat-container/src/main/resources/static/images/buttons/logoutOver.jpg
similarity index 100%
rename from webgoat-container/src/main/webapp/images/buttons/logoutOver.jpg
rename to webgoat-container/src/main/resources/static/images/buttons/logoutOver.jpg
diff --git a/webgoat-container/src/main/webapp/images/buttons/params.jpg b/webgoat-container/src/main/resources/static/images/buttons/params.jpg
similarity index 100%
rename from webgoat-container/src/main/webapp/images/buttons/params.jpg
rename to webgoat-container/src/main/resources/static/images/buttons/params.jpg
diff --git a/webgoat-container/src/main/webapp/images/buttons/paramsOver.jpg b/webgoat-container/src/main/resources/static/images/buttons/paramsOver.jpg
similarity index 100%
rename from webgoat-container/src/main/webapp/images/buttons/paramsOver.jpg
rename to webgoat-container/src/main/resources/static/images/buttons/paramsOver.jpg
diff --git a/webgoat-container/src/main/webapp/images/buttons/plans.jpg b/webgoat-container/src/main/resources/static/images/buttons/plans.jpg
similarity index 100%
rename from webgoat-container/src/main/webapp/images/buttons/plans.jpg
rename to webgoat-container/src/main/resources/static/images/buttons/plans.jpg
diff --git a/webgoat-container/src/main/webapp/images/buttons/plansOver.jpg b/webgoat-container/src/main/resources/static/images/buttons/plansOver.jpg
similarity index 100%
rename from webgoat-container/src/main/webapp/images/buttons/plansOver.jpg
rename to webgoat-container/src/main/resources/static/images/buttons/plansOver.jpg
diff --git a/webgoat-container/src/main/webapp/images/buttons/solutions.jpg b/webgoat-container/src/main/resources/static/images/buttons/solutions.jpg
similarity index 100%
rename from webgoat-container/src/main/webapp/images/buttons/solutions.jpg
rename to webgoat-container/src/main/resources/static/images/buttons/solutions.jpg
diff --git a/webgoat-container/src/main/webapp/images/buttons/solutionsOver.jpg b/webgoat-container/src/main/resources/static/images/buttons/solutionsOver.jpg
similarity index 100%
rename from webgoat-container/src/main/webapp/images/buttons/solutionsOver.jpg
rename to webgoat-container/src/main/resources/static/images/buttons/solutionsOver.jpg
diff --git a/webgoat-container/src/main/webapp/images/header/header.jpg b/webgoat-container/src/main/resources/static/images/header/header.jpg
similarity index 100%
rename from webgoat-container/src/main/webapp/images/header/header.jpg
rename to webgoat-container/src/main/resources/static/images/header/header.jpg
diff --git a/webgoat-container/src/main/webapp/images/header/header_ASP.jpg b/webgoat-container/src/main/resources/static/images/header/header_ASP.jpg
similarity index 100%
rename from webgoat-container/src/main/webapp/images/header/header_ASP.jpg
rename to webgoat-container/src/main/resources/static/images/header/header_ASP.jpg
diff --git a/webgoat-container/src/main/webapp/images/header/header_CShrp.jpg b/webgoat-container/src/main/resources/static/images/header/header_CShrp.jpg
similarity index 100%
rename from webgoat-container/src/main/webapp/images/header/header_CShrp.jpg
rename to webgoat-container/src/main/resources/static/images/header/header_CShrp.jpg
diff --git a/webgoat-container/src/main/webapp/images/header/header_coldFusion.jpg b/webgoat-container/src/main/resources/static/images/header/header_coldFusion.jpg
similarity index 100%
rename from webgoat-container/src/main/webapp/images/header/header_coldFusion.jpg
rename to webgoat-container/src/main/resources/static/images/header/header_coldFusion.jpg
diff --git a/webgoat-container/src/main/webapp/images/header/header_dotNet.jpg b/webgoat-container/src/main/resources/static/images/header/header_dotNet.jpg
similarity index 100%
rename from webgoat-container/src/main/webapp/images/header/header_dotNet.jpg
rename to webgoat-container/src/main/resources/static/images/header/header_dotNet.jpg
diff --git a/webgoat-container/src/main/webapp/images/icons/rightArrow.jpg b/webgoat-container/src/main/resources/static/images/icons/rightArrow.jpg
similarity index 100%
rename from webgoat-container/src/main/webapp/images/icons/rightArrow.jpg
rename to webgoat-container/src/main/resources/static/images/icons/rightArrow.jpg
diff --git a/webgoat-container/src/main/webapp/images/introduction/HowToUse_2.jpg b/webgoat-container/src/main/resources/static/images/introduction/HowToUse_2.jpg
similarity index 100%
rename from webgoat-container/src/main/webapp/images/introduction/HowToUse_2.jpg
rename to webgoat-container/src/main/resources/static/images/introduction/HowToUse_2.jpg
diff --git a/webgoat-container/src/main/webapp/images/introduction/HowToUse_3.jpg b/webgoat-container/src/main/resources/static/images/introduction/HowToUse_3.jpg
similarity index 100%
rename from webgoat-container/src/main/webapp/images/introduction/HowToUse_3.jpg
rename to webgoat-container/src/main/resources/static/images/introduction/HowToUse_3.jpg
diff --git a/webgoat-container/src/main/webapp/images/introduction/UsefulTools-ZAP.png b/webgoat-container/src/main/resources/static/images/introduction/UsefulTools-ZAP.png
similarity index 100%
rename from webgoat-container/src/main/webapp/images/introduction/UsefulTools-ZAP.png
rename to webgoat-container/src/main/resources/static/images/introduction/UsefulTools-ZAP.png
diff --git a/webgoat-container/src/main/webapp/images/introduction/UsefulTools-ZAP_1.png b/webgoat-container/src/main/resources/static/images/introduction/UsefulTools-ZAP_1.png
similarity index 100%
rename from webgoat-container/src/main/webapp/images/introduction/UsefulTools-ZAP_1.png
rename to webgoat-container/src/main/resources/static/images/introduction/UsefulTools-ZAP_1.png
diff --git a/webgoat-container/src/main/webapp/images/introduction/interface.png b/webgoat-container/src/main/resources/static/images/introduction/interface.png
similarity index 100%
rename from webgoat-container/src/main/webapp/images/introduction/interface.png
rename to webgoat-container/src/main/resources/static/images/introduction/interface.png
diff --git a/webgoat-container/src/main/webapp/images/introduction/wireshark.png b/webgoat-container/src/main/resources/static/images/introduction/wireshark.png
similarity index 100%
rename from webgoat-container/src/main/webapp/images/introduction/wireshark.png
rename to webgoat-container/src/main/resources/static/images/introduction/wireshark.png
diff --git a/webgoat-container/src/main/webapp/images/logo.png b/webgoat-container/src/main/resources/static/images/logo.png
similarity index 100%
rename from webgoat-container/src/main/webapp/images/logo.png
rename to webgoat-container/src/main/resources/static/images/logo.png
diff --git a/webgoat-container/src/main/webapp/images/logos/aspect.jpg b/webgoat-container/src/main/resources/static/images/logos/aspect.jpg
similarity index 100%
rename from webgoat-container/src/main/webapp/images/logos/aspect.jpg
rename to webgoat-container/src/main/resources/static/images/logos/aspect.jpg
diff --git a/webgoat-container/src/main/webapp/images/logos/macadamian.gif b/webgoat-container/src/main/resources/static/images/logos/macadamian.gif
similarity index 100%
rename from webgoat-container/src/main/webapp/images/logos/macadamian.gif
rename to webgoat-container/src/main/resources/static/images/logos/macadamian.gif
diff --git a/webgoat-container/src/main/webapp/images/logos/mandiant.png b/webgoat-container/src/main/resources/static/images/logos/mandiant.png
similarity index 100%
rename from webgoat-container/src/main/webapp/images/logos/mandiant.png
rename to webgoat-container/src/main/resources/static/images/logos/mandiant.png
diff --git a/webgoat-container/src/main/webapp/images/logos/ounce.jpg b/webgoat-container/src/main/resources/static/images/logos/ounce.jpg
similarity index 100%
rename from webgoat-container/src/main/webapp/images/logos/ounce.jpg
rename to webgoat-container/src/main/resources/static/images/logos/ounce.jpg
diff --git a/webgoat-container/src/main/webapp/images/logos/owasp.jpg b/webgoat-container/src/main/resources/static/images/logos/owasp.jpg
similarity index 100%
rename from webgoat-container/src/main/webapp/images/logos/owasp.jpg
rename to webgoat-container/src/main/resources/static/images/logos/owasp.jpg
diff --git a/webgoat-container/src/main/webapp/images/logos/parasoft.jpg b/webgoat-container/src/main/resources/static/images/logos/parasoft.jpg
similarity index 100%
rename from webgoat-container/src/main/webapp/images/logos/parasoft.jpg
rename to webgoat-container/src/main/resources/static/images/logos/parasoft.jpg
diff --git a/webgoat-container/src/main/webapp/images/logos/sages.png b/webgoat-container/src/main/resources/static/images/logos/sages.png
similarity index 100%
rename from webgoat-container/src/main/webapp/images/logos/sages.png
rename to webgoat-container/src/main/resources/static/images/logos/sages.png
diff --git a/webgoat-container/src/main/webapp/images/logos/seleucus.png b/webgoat-container/src/main/resources/static/images/logos/seleucus.png
similarity index 100%
rename from webgoat-container/src/main/webapp/images/logos/seleucus.png
rename to webgoat-container/src/main/resources/static/images/logos/seleucus.png
diff --git a/webgoat-container/src/main/webapp/images/logos/softwaresecured.gif b/webgoat-container/src/main/resources/static/images/logos/softwaresecured.gif
similarity index 100%
rename from webgoat-container/src/main/webapp/images/logos/softwaresecured.gif
rename to webgoat-container/src/main/resources/static/images/logos/softwaresecured.gif
diff --git a/webgoat-container/src/main/webapp/images/logos/zionsecurity.gif b/webgoat-container/src/main/resources/static/images/logos/zionsecurity.gif
similarity index 100%
rename from webgoat-container/src/main/webapp/images/logos/zionsecurity.gif
rename to webgoat-container/src/main/resources/static/images/logos/zionsecurity.gif
diff --git a/webgoat-container/src/main/webapp/images/menu_images/1x1.gif b/webgoat-container/src/main/resources/static/images/menu_images/1x1.gif
similarity index 100%
rename from webgoat-container/src/main/webapp/images/menu_images/1x1.gif
rename to webgoat-container/src/main/resources/static/images/menu_images/1x1.gif
diff --git a/webgoat-container/src/main/webapp/images/webBg.png b/webgoat-container/src/main/resources/static/images/webBg.png
similarity index 100%
rename from webgoat-container/src/main/webapp/images/webBg.png
rename to webgoat-container/src/main/resources/static/images/webBg.png
diff --git a/webgoat-container/src/main/webapp/js/DOMXSS_backup.js b/webgoat-container/src/main/resources/static/js/DOMXSS_backup.js
similarity index 96%
rename from webgoat-container/src/main/webapp/js/DOMXSS_backup.js
rename to webgoat-container/src/main/resources/static/js/DOMXSS_backup.js
index 9ddb31a10..2229cdbd3 100644
--- a/webgoat-container/src/main/webapp/js/DOMXSS_backup.js
+++ b/webgoat-container/src/main/resources/static/js/DOMXSS_backup.js
@@ -1,5 +1,5 @@
-function displayGreeting(name) {
- if (name != ''){
- document.getElementById("greeting").innerHTML="Hello, " + name+ "!";
- }
+function displayGreeting(name) {
+ if (name != ''){
+ document.getElementById("greeting").innerHTML="Hello, " + name+ "!";
+ }
}
\ No newline at end of file
diff --git a/webgoat-container/src/main/webapp/js/application.js b/webgoat-container/src/main/resources/static/js/application.js
similarity index 96%
rename from webgoat-container/src/main/webapp/js/application.js
rename to webgoat-container/src/main/resources/static/js/application.js
index 0bf45e4aa..7a955728c 100644
--- a/webgoat-container/src/main/webapp/js/application.js
+++ b/webgoat-container/src/main/resources/static/js/application.js
@@ -1,226 +1,226 @@
-var app = function() {
-
- var init = function() {
-
- tooltips();
- toggleMenuLeft();
- toggleMenuRight();
- // menu is handled by angular
- //menu();
- togglePanel();
- sideBarLeftInit();
- window.onresize = function(){
- sideBarLeftInit();
- }
- closePanel();
- };
-
- var tooltips = function() {
- $('#toggle-left').tooltip();
- $('.right_nav_button').tooltip({'placement': 'bottom'});
- };
-
- var togglePanel = function() {
- $('.actions > .fa-chevron-down').click(function() {
- $(this).parent().parent().next().slideToggle('fast');
- $(this).toggleClass('fa-chevron-down fa-chevron-up');
- });
-
- };
-
- var toggleMenuLeft = function() {
- $('#toggle-left').bind('click', function(e) {
- if (!$('.sidebarRight').hasClass('.sidebar-toggle-right')) {
- $('.sidebarRight').removeClass('sidebar-toggle-right');
- $('.main-content-wrapper').removeClass('main-content-toggle-right');
- }
- $('.sidebar').toggleClass('sidebar-toggle');
- $('.main-content-wrapper').toggleClass('main-content-toggle-left');
- e.stopPropagation();
- });
- };
-
- var toggleMenuRight = function() {
- $('#toggle-right').bind('click', function(e) {
-
- if (!$('.sidebar').hasClass('.sidebar-toggle')) {
- $('.sidebar').addClass('sidebar-toggle');
- $('.main-content-wrapper').addClass('main-content-toggle-left');
- }
-
- $('.sidebarRight').toggleClass('sidebar-toggle-right animated bounceInRight');
- $('.main-content-wrapper').toggleClass('main-content-toggle-right');
-
- if ( $(window).width() < 660 ) {
- $('.sidebar').removeClass('sidebar-toggle');
- $('.main-content-wrapper').removeClass('main-content-toggle-left main-content-toggle-right');
- };
-
- e.stopPropagation();
- });
- };
-
- var closePanel = function() {
- $('.actions > .fa-times').click(function() {
- $(this).parent().parent().parent().fadeOut();
- });
-
- }
-
- /*
- var menu = function() {
- $("#leftside-navigation .sub-menu a").click(function(e) {
- $("#leftside-navigation ul ul").slideUp();
- if (!$(this).next().is(":visible")) {
- $(this).next().slideDown();
- }
- e.stopPropagation();
- });
- };
- */
- //End functions
-
- //Dashboard functions
- var timer = function() {
- $('.timer').countTo();
- };
-
-
- //Vector Maps
- var map = function() {
- $('#map').vectorMap({
- map: 'world_mill_en',
- backgroundColor: 'transparent',
- regionStyle: {
- initial: {
- fill: '#1ABC9C',
- },
- hover: {
- "fill-opacity": 0.8
- }
- },
- markerStyle: {
- initial: {
- r: 10
- },
- hover: {
- r: 12,
- stroke: 'rgba(255,255,255,0.8)',
- "stroke-width": 3
- }
- },
- markers: [{
- latLng: [27.9881, 86.9253],
- name: '36 Employees',
- style: {
- fill: '#E84C3D',
- stroke: 'rgba(255,255,255,0.7)',
- "stroke-width": 3
- }
- }, {
- latLng: [48.8582, 2.2945],
- name: '58 Employees',
- style: {
- fill: '#E84C3D',
- stroke: 'rgba(255,255,255,0.7)',
- "stroke-width": 3
- }
- }, {
- latLng: [-40.6892, -74.0444],
- name: '109 Employees',
- style: {
- fill: '#E84C3D',
- stroke: 'rgba(255,255,255,0.7)',
- "stroke-width": 3
- }
- }, {
- latLng: [34.05, -118.25],
- name: '85 Employees ',
- style: {
- fill: '#E84C3D',
- stroke: 'rgba(255,255,255,0.7)',
- "stroke-width": 3
- }
- }]
- });
-
- };
-
- var weather = function() {
- var icons = new Skycons({
- "color": "white"
- });
-
- icons.set("clear-day", Skycons.CLEAR_DAY);
- icons.set("clear-night", Skycons.CLEAR_NIGHT);
- icons.set("partly-cloudy-day", Skycons.PARTLY_CLOUDY_DAY);
- icons.set("partly-cloudy-night", Skycons.PARTLY_CLOUDY_NIGHT);
- icons.set("cloudy", Skycons.CLOUDY);
- icons.set("rain", Skycons.RAIN);
- icons.set("sleet", Skycons.SLEET);
- icons.set("snow", Skycons.SNOW);
- icons.set("wind", Skycons.WIND);
- icons.set("fog", Skycons.FOG);
-
- icons.play();
- }
-
- //morris pie chart
- var morrisPie = function() {
-
- Morris.Donut({
- element: 'donut-example',
- data: [{
- label: "Chrome",
- value: 73
- }, {
- label: "Firefox",
- value: 71
- }, {
- label: "Safari",
- value: 69
- }, {
- label: "Internet Explorer",
- value: 40
- }, {
- label: "Opera",
- value: 20
- }, {
- label: "Android Browser",
- value: 10
- }
-
- ],
- colors: [
- '#1abc9c',
- '#293949',
- '#e84c3d',
- '#3598db',
- '#2dcc70',
- '#f1c40f'
- ]
- });
- }
-
- //Sliders
- var sliders = function() {
- $('.slider-span').slider()
- };
-
- var sideBarLeftInit = function(){
- $("#leftside-navigation").css("height", (window.innerHeight-80)+"px");
- };
-
- //return functions
- return {
- init: init,
- timer: timer,
- map: map,
- sliders: sliders,
- weather: weather,
- morrisPie: morrisPie,
- sideBarLeftInit:sideBarLeftInit
- };
-}();
-
-
+var app = function() {
+
+ var init = function() {
+
+ tooltips();
+ toggleMenuLeft();
+ toggleMenuRight();
+ // menu is handled by angular
+ //menu();
+ togglePanel();
+ sideBarLeftInit();
+ window.onresize = function(){
+ sideBarLeftInit();
+ }
+ closePanel();
+ };
+
+ var tooltips = function() {
+ $('#toggle-left').tooltip();
+ $('.right_nav_button').tooltip({'placement': 'bottom'});
+ };
+
+ var togglePanel = function() {
+ $('.actions > .fa-chevron-down').click(function() {
+ $(this).parent().parent().next().slideToggle('fast');
+ $(this).toggleClass('fa-chevron-down fa-chevron-up');
+ });
+
+ };
+
+ var toggleMenuLeft = function() {
+ $('#toggle-left').bind('click', function(e) {
+ if (!$('.sidebarRight').hasClass('.sidebar-toggle-right')) {
+ $('.sidebarRight').removeClass('sidebar-toggle-right');
+ $('.main-content-wrapper').removeClass('main-content-toggle-right');
+ }
+ $('.sidebar').toggleClass('sidebar-toggle');
+ $('.main-content-wrapper').toggleClass('main-content-toggle-left');
+ e.stopPropagation();
+ });
+ };
+
+ var toggleMenuRight = function() {
+ $('#toggle-right').bind('click', function(e) {
+
+ if (!$('.sidebar').hasClass('.sidebar-toggle')) {
+ $('.sidebar').addClass('sidebar-toggle');
+ $('.main-content-wrapper').addClass('main-content-toggle-left');
+ }
+
+ $('.sidebarRight').toggleClass('sidebar-toggle-right animated bounceInRight');
+ $('.main-content-wrapper').toggleClass('main-content-toggle-right');
+
+ if ( $(window).width() < 660 ) {
+ $('.sidebar').removeClass('sidebar-toggle');
+ $('.main-content-wrapper').removeClass('main-content-toggle-left main-content-toggle-right');
+ };
+
+ e.stopPropagation();
+ });
+ };
+
+ var closePanel = function() {
+ $('.actions > .fa-times').click(function() {
+ $(this).parent().parent().parent().fadeOut();
+ });
+
+ }
+
+ /*
+ var menu = function() {
+ $("#leftside-navigation .sub-menu a").click(function(e) {
+ $("#leftside-navigation ul ul").slideUp();
+ if (!$(this).next().is(":visible")) {
+ $(this).next().slideDown();
+ }
+ e.stopPropagation();
+ });
+ };
+ */
+ //End functions
+
+ //Dashboard functions
+ var timer = function() {
+ $('.timer').countTo();
+ };
+
+
+ //Vector Maps
+ var map = function() {
+ $('#map').vectorMap({
+ map: 'world_mill_en',
+ backgroundColor: 'transparent',
+ regionStyle: {
+ initial: {
+ fill: '#1ABC9C',
+ },
+ hover: {
+ "fill-opacity": 0.8
+ }
+ },
+ markerStyle: {
+ initial: {
+ r: 10
+ },
+ hover: {
+ r: 12,
+ stroke: 'rgba(255,255,255,0.8)',
+ "stroke-width": 3
+ }
+ },
+ markers: [{
+ latLng: [27.9881, 86.9253],
+ name: '36 Employees',
+ style: {
+ fill: '#E84C3D',
+ stroke: 'rgba(255,255,255,0.7)',
+ "stroke-width": 3
+ }
+ }, {
+ latLng: [48.8582, 2.2945],
+ name: '58 Employees',
+ style: {
+ fill: '#E84C3D',
+ stroke: 'rgba(255,255,255,0.7)',
+ "stroke-width": 3
+ }
+ }, {
+ latLng: [-40.6892, -74.0444],
+ name: '109 Employees',
+ style: {
+ fill: '#E84C3D',
+ stroke: 'rgba(255,255,255,0.7)',
+ "stroke-width": 3
+ }
+ }, {
+ latLng: [34.05, -118.25],
+ name: '85 Employees ',
+ style: {
+ fill: '#E84C3D',
+ stroke: 'rgba(255,255,255,0.7)',
+ "stroke-width": 3
+ }
+ }]
+ });
+
+ };
+
+ var weather = function() {
+ var icons = new Skycons({
+ "color": "white"
+ });
+
+ icons.set("clear-day", Skycons.CLEAR_DAY);
+ icons.set("clear-night", Skycons.CLEAR_NIGHT);
+ icons.set("partly-cloudy-day", Skycons.PARTLY_CLOUDY_DAY);
+ icons.set("partly-cloudy-night", Skycons.PARTLY_CLOUDY_NIGHT);
+ icons.set("cloudy", Skycons.CLOUDY);
+ icons.set("rain", Skycons.RAIN);
+ icons.set("sleet", Skycons.SLEET);
+ icons.set("snow", Skycons.SNOW);
+ icons.set("wind", Skycons.WIND);
+ icons.set("fog", Skycons.FOG);
+
+ icons.play();
+ }
+
+ //morris pie chart
+ var morrisPie = function() {
+
+ Morris.Donut({
+ element: 'donut-example',
+ data: [{
+ label: "Chrome",
+ value: 73
+ }, {
+ label: "Firefox",
+ value: 71
+ }, {
+ label: "Safari",
+ value: 69
+ }, {
+ label: "Internet Explorer",
+ value: 40
+ }, {
+ label: "Opera",
+ value: 20
+ }, {
+ label: "Android Browser",
+ value: 10
+ }
+
+ ],
+ colors: [
+ '#1abc9c',
+ '#293949',
+ '#e84c3d',
+ '#3598db',
+ '#2dcc70',
+ '#f1c40f'
+ ]
+ });
+ }
+
+ //Sliders
+ var sliders = function() {
+ $('.slider-span').slider()
+ };
+
+ var sideBarLeftInit = function(){
+ $("#leftside-navigation").css("height", (window.innerHeight-80)+"px");
+ };
+
+ //return functions
+ return {
+ init: init,
+ timer: timer,
+ map: map,
+ sliders: sliders,
+ weather: weather,
+ morrisPie: morrisPie,
+ sideBarLeftInit:sideBarLeftInit
+ };
+}();
+
+
diff --git a/webgoat-container/src/main/webapp/js/backbone/backbone-edge.js b/webgoat-container/src/main/resources/static/js/backbone/backbone-edge.js
similarity index 100%
rename from webgoat-container/src/main/webapp/js/backbone/backbone-edge.js
rename to webgoat-container/src/main/resources/static/js/backbone/backbone-edge.js
diff --git a/webgoat-container/src/main/webapp/js/backbone/backbone-min.js b/webgoat-container/src/main/resources/static/js/backbone/backbone-min.js
similarity index 100%
rename from webgoat-container/src/main/webapp/js/backbone/backbone-min.js
rename to webgoat-container/src/main/resources/static/js/backbone/backbone-min.js
diff --git a/webgoat-container/src/main/webapp/js/backbone/backbone.js b/webgoat-container/src/main/resources/static/js/backbone/backbone.js
similarity index 100%
rename from webgoat-container/src/main/webapp/js/backbone/backbone.js
rename to webgoat-container/src/main/resources/static/js/backbone/backbone.js
diff --git a/webgoat-container/src/main/webapp/js/backbone/underscore-min.js b/webgoat-container/src/main/resources/static/js/backbone/underscore-min.js
similarity index 100%
rename from webgoat-container/src/main/webapp/js/backbone/underscore-min.js
rename to webgoat-container/src/main/resources/static/js/backbone/underscore-min.js
diff --git a/webgoat-container/src/main/webapp/js/backbone/underscore.js b/webgoat-container/src/main/resources/static/js/backbone/underscore.js
similarity index 100%
rename from webgoat-container/src/main/webapp/js/backbone/underscore.js
rename to webgoat-container/src/main/resources/static/js/backbone/underscore.js
diff --git a/webgoat-container/src/main/webapp/js/goatApp/controller/LessonController.js b/webgoat-container/src/main/resources/static/js/goatApp/controller/LessonController.js
similarity index 74%
rename from webgoat-container/src/main/webapp/js/goatApp/controller/LessonController.js
rename to webgoat-container/src/main/resources/static/js/goatApp/controller/LessonController.js
index bc072b979..3f77f1f54 100644
--- a/webgoat-container/src/main/webapp/js/goatApp/controller/LessonController.js
+++ b/webgoat-container/src/main/resources/static/js/goatApp/controller/LessonController.js
@@ -11,6 +11,7 @@ define(['jquery',
'goatApp/view/CookieView',
'goatApp/view/ParamView',
'goatApp/model/ParamModel',
+ 'goatApp/view/DeveloperControlsView',
'goatApp/support/GoatUtils',
'goatApp/view/UserAndInfoView',
'goatApp/view/MenuButtonView',
@@ -32,6 +33,7 @@ define(['jquery',
CookieView,
ParamView,
ParamModel,
+ DeveloperControlsView,
GoatUtils,
UserAndInfoView,
MenuButtonView,
@@ -48,7 +50,8 @@ define(['jquery',
this.lessonContent = new LessonContentModel();
this.lessonProgressModel = new LessonProgressModel();
this.lessonProgressView = new LessonProgressView(this.lessonProgressModel);
- this.lessonView = options.lessonView;
+ this.lessonContentView = options.lessonContentView;
+ this.developerControlsView = new DeveloperControlsView();
_.extend(Controller.prototype,Backbone.Events);
@@ -58,36 +61,20 @@ define(['jquery',
this.menuButtonView = new MenuButtonView();
};
- this.loadLesson = function(scr,menu,stage,num) {
+ this.loadLesson = function(name) {
this.titleView = new TitleView();
this.helpsLoaded = {};
- if (typeof(scr) == "undefined") {
- scr = null;
- }
- if (typeof(menu) == "undefined") {
- menu = null;
- }
- if (typeof(stage) == "undefined") {
- stage = null;
- }
- if (typeof(num) == "undefined") {
- num = null;
+ if (typeof(name) === 'undefined' || name === null) {
+ //TODO: implement lesson not found or return to welcome page?
}
this.lessonContent.loadData({
- 'scr': scr,
- 'menu': menu,
- 'stage': stage,
- 'num': num,
+ 'name':name
});
this.planView = {};
this.solutionView = {};
this.sourceView = {};
this.lessonHintView = {};
- this.scr = scr;
- this.menu = menu;
- this.stage = stage;
- this.num = num;
- console.log("Lesson loading initiated")
+ this.name = name;
};
this.onInfoLoaded = function() {
@@ -95,28 +82,37 @@ define(['jquery',
hasPlan:this.lessonInfoModel.get('hasPlan'),
hasSolution:this.lessonInfoModel.get('hasSolution'),
hasSource:this.lessonInfoModel.get('hasSource'),
- hasHints:(this.lessonInfoModel.get('numberHints') > 0),
+ hasHints:(this.lessonInfoModel.get('numberHints') > 0)
+ //hasAttack:this.lessonInfo.get('hasAttack') // TODO: add attack options
});
- this.listenTo(this.helpControlsView,'plan:show',this.hideShowHelps);
- this.listenTo(this.helpControlsView,'solution:show',this.hideShowHelps);
- this.listenTo(this.helpControlsView,'hints:show',this.onShowHints)
+ this.listenTo(this.helpControlsView,'hints:show',this.showHints);
+ this.listenTo(this.helpControlsView,'attack:show',this.hideShowAttack);
+ this.listenTo(this.helpControlsView,'solution:show',this.hideShowHelps);
this.listenTo(this.helpControlsView,'source:show',this.hideShowHelps);
this.listenTo(this.helpControlsView,'lesson:restart',this.restartLesson);
+ this.listenTo(this.developerControlsView, 'dev:labels', this.restartLesson);
+ this.listenTo(this.lessonContentView, 'lesson:complete', this.updateMenu)
+
+ this.listenTo(this,'hints:show',this.onShowHints);
this.helpControlsView.render();
this.titleView.render(this.lessonInfoModel.get('lessonTitle'));
};
+ this.updateMenu = function() {
+ this.trigger('menu:reload')
+ };
+
this.onContentLoaded = function(loadHelps) {
this.lessonInfoModel = new LessonInfoModel();
this.listenTo(this.lessonInfoModel,'info:loaded',this.onInfoLoaded);
if (loadHelps) {
this.helpControlsView = null;
- this.lessonView.model = this.lessonContent;
- this.lessonView.render();
+ this.lessonContentView.model = this.lessonContent;
+ this.lessonContentView.render();
this.planView = new PlanView();
this.solutionView = new SolutionView();
@@ -134,7 +130,7 @@ define(['jquery',
$('.lesson-help').hide();
}
- this.trigger('menu:reload');
+ //this.trigger('menu:reload');
this.lessonProgressModel.completed();
};
@@ -171,29 +167,31 @@ define(['jquery',
}
};
- this.onShowHints = function() {
+ this.showHints = function() {
this.lessonHintView.render();
+ //this.lessonHintView.
+ };
+
+ this.hideShowAttack = function (options) { // will likely expand this to encompass
+ if (options.show) {
+ $('#attack-container').show();
+ $('#attack-container div.modal-header button.close, #about-modal div.modal-footer button').unbind('click').on('click', function() {
+ $('#attack-container').hide(200);
+ });
+ if (this.lessonInfoModel.get('numberHints') > 0) {
+
+ this.lessonContentView.$el.find('#show-hints-button').unbind().on('click',_.bind(this.showHints,this)).show();
+ }
+ }
};
this.restartLesson = function() {
var self=this;
- var fragment = "attack/" + self.scr + "/" + self.menu;
- console.log("Navigating to " + fragment);
- // Avoiding the trigger event - handle - navigate loop by
- // loading the lesson explicitly (after executing the restart
- // servlet).
- goatRouter.navigate(fragment);
- // Resetting the user's lesson state (assuming a single browser
- // and session per user).
$.ajax({
url:'service/restartlesson.mvc',
method:'GET'
- }).done(function() {
- //Log shows warning, see https://bugzilla.mozilla.org/show_bug.cgi?id=884693
-
- // Explicitly loading the lesson instead of triggering an
- // event in goatRouter.navigate().
- self.loadLesson(self.scr,self.menu);
+ }).done(function(lessonLink) {
+ self.loadLesson(self.name);
});
};
diff --git a/webgoat-container/src/main/webapp/js/goatApp/controller/MenuController.js b/webgoat-container/src/main/resources/static/js/goatApp/controller/MenuController.js
similarity index 100%
rename from webgoat-container/src/main/webapp/js/goatApp/controller/MenuController.js
rename to webgoat-container/src/main/resources/static/js/goatApp/controller/MenuController.js
diff --git a/webgoat-container/src/main/webapp/js/goatApp/goatApp.js b/webgoat-container/src/main/resources/static/js/goatApp/goatApp.js
similarity index 100%
rename from webgoat-container/src/main/webapp/js/goatApp/goatApp.js
rename to webgoat-container/src/main/resources/static/js/goatApp/goatApp.js
diff --git a/webgoat-container/src/main/webapp/js/goatApp/model/CookieCollection.js b/webgoat-container/src/main/resources/static/js/goatApp/model/CookieCollection.js
similarity index 100%
rename from webgoat-container/src/main/webapp/js/goatApp/model/CookieCollection.js
rename to webgoat-container/src/main/resources/static/js/goatApp/model/CookieCollection.js
diff --git a/webgoat-container/src/main/webapp/js/goatApp/model/CookieModel.js b/webgoat-container/src/main/resources/static/js/goatApp/model/CookieModel.js
similarity index 100%
rename from webgoat-container/src/main/webapp/js/goatApp/model/CookieModel.js
rename to webgoat-container/src/main/resources/static/js/goatApp/model/CookieModel.js
diff --git a/webgoat-container/src/main/webapp/js/goatApp/model/HTMLContentModel.js b/webgoat-container/src/main/resources/static/js/goatApp/model/HTMLContentModel.js
similarity index 93%
rename from webgoat-container/src/main/webapp/js/goatApp/model/HTMLContentModel.js
rename to webgoat-container/src/main/resources/static/js/goatApp/model/HTMLContentModel.js
index fd5ac05f5..3bfb43eb3 100644
--- a/webgoat-container/src/main/webapp/js/goatApp/model/HTMLContentModel.js
+++ b/webgoat-container/src/main/resources/static/js/goatApp/model/HTMLContentModel.js
@@ -3,7 +3,6 @@ define(['jquery',
'backbone'],
function($,_,Backbone) {
return Backbone.Model.extend({
- //url:'service/lessonplan.mvc',
fetch: function (options) {
options = options || {};
return Backbone.Model.prototype.fetch.call(this, _.extend({ dataType: "html"}, options));
diff --git a/webgoat-container/src/main/webapp/js/goatApp/model/HintCollection.js b/webgoat-container/src/main/resources/static/js/goatApp/model/HintCollection.js
similarity index 100%
rename from webgoat-container/src/main/webapp/js/goatApp/model/HintCollection.js
rename to webgoat-container/src/main/resources/static/js/goatApp/model/HintCollection.js
diff --git a/webgoat-container/src/main/webapp/js/goatApp/model/HintModel.js b/webgoat-container/src/main/resources/static/js/goatApp/model/HintModel.js
similarity index 100%
rename from webgoat-container/src/main/webapp/js/goatApp/model/HintModel.js
rename to webgoat-container/src/main/resources/static/js/goatApp/model/HintModel.js
diff --git a/webgoat-container/src/main/webapp/js/goatApp/model/LabelDebugModel.js b/webgoat-container/src/main/resources/static/js/goatApp/model/LabelDebugModel.js
similarity index 100%
rename from webgoat-container/src/main/webapp/js/goatApp/model/LabelDebugModel.js
rename to webgoat-container/src/main/resources/static/js/goatApp/model/LabelDebugModel.js
diff --git a/webgoat-container/src/main/webapp/js/goatApp/model/LessonContentModel.js b/webgoat-container/src/main/resources/static/js/goatApp/model/LessonContentModel.js
similarity index 57%
rename from webgoat-container/src/main/webapp/js/goatApp/model/LessonContentModel.js
rename to webgoat-container/src/main/resources/static/js/goatApp/model/LessonContentModel.js
index d4923640d..60ca65a36 100644
--- a/webgoat-container/src/main/webapp/js/goatApp/model/LessonContentModel.js
+++ b/webgoat-container/src/main/resources/static/js/goatApp/model/LessonContentModel.js
@@ -14,24 +14,25 @@ define(['jquery',
selectedItem:null
},
initialize: function (options) {
- this.scrParam = null;
- this.menuParam = null;
- this.stageParam = null;
- this.numParam = null;
- this.baseUrlRoot = 'attack';
+ //this.scrParam = null;
+ //this.menuParam = null;
+ //this.stageParam = null;
+ //this.numParam = null;
+ //this.baseUrlRoot = '';
},
loadData: function(options) {
- this.urlRoot = this.baseUrlRoot + "?Screen=" + options.scr + '&menu=' + options.menu;
- if (options.stage != null) {
- this.urlRoot += '&stage=' + options.stage;
- }
- if (options.num != null) {
- this.urlRoot += '&Num=' + options.num;
- }
- this.set('menuParam', options.menu);
- this.set('scrParam', options.scr);
- this.set('stageParam', options.stage)
- this.set('numParam', options.num)
+ this.urlRoot = _.escape(encodeURIComponent(options.name)) + '.lesson'
+// if (options.stage != null) {
+// this.urlRoot += '&stage=' + options.stage;
+// }
+// if (options.num != null) {
+// this.urlRoot += '&Num=' + options.num;
+// }
+ //TODO - is below needed anymore?
+// this.set('menuParam', options.menu);
+// this.set('scrParam', options.scr);
+// this.set('stageParam', options.stage);
+// this.set('numParam', options.num);
var self = this;
this.fetch().done(function(data) {
self.setContent(data);
diff --git a/webgoat-container/src/main/webapp/js/goatApp/model/LessonInfoModel.js b/webgoat-container/src/main/resources/static/js/goatApp/model/LessonInfoModel.js
similarity index 100%
rename from webgoat-container/src/main/webapp/js/goatApp/model/LessonInfoModel.js
rename to webgoat-container/src/main/resources/static/js/goatApp/model/LessonInfoModel.js
diff --git a/webgoat-container/src/main/webapp/js/goatApp/model/LessonPlanModel.js b/webgoat-container/src/main/resources/static/js/goatApp/model/LessonPlanModel.js
similarity index 100%
rename from webgoat-container/src/main/webapp/js/goatApp/model/LessonPlanModel.js
rename to webgoat-container/src/main/resources/static/js/goatApp/model/LessonPlanModel.js
diff --git a/webgoat-container/src/main/webapp/js/goatApp/model/LessonProgressModel.js b/webgoat-container/src/main/resources/static/js/goatApp/model/LessonProgressModel.js
similarity index 100%
rename from webgoat-container/src/main/webapp/js/goatApp/model/LessonProgressModel.js
rename to webgoat-container/src/main/resources/static/js/goatApp/model/LessonProgressModel.js
diff --git a/webgoat-container/src/main/webapp/js/goatApp/model/MenuCollection.js b/webgoat-container/src/main/resources/static/js/goatApp/model/MenuCollection.js
similarity index 100%
rename from webgoat-container/src/main/webapp/js/goatApp/model/MenuCollection.js
rename to webgoat-container/src/main/resources/static/js/goatApp/model/MenuCollection.js
diff --git a/webgoat-container/src/main/webapp/js/goatApp/model/MenuData.js b/webgoat-container/src/main/resources/static/js/goatApp/model/MenuData.js
similarity index 100%
rename from webgoat-container/src/main/webapp/js/goatApp/model/MenuData.js
rename to webgoat-container/src/main/resources/static/js/goatApp/model/MenuData.js
diff --git a/webgoat-container/src/main/webapp/js/goatApp/model/MenuModel.js b/webgoat-container/src/main/resources/static/js/goatApp/model/MenuModel.js
similarity index 100%
rename from webgoat-container/src/main/webapp/js/goatApp/model/MenuModel.js
rename to webgoat-container/src/main/resources/static/js/goatApp/model/MenuModel.js
diff --git a/webgoat-container/src/main/webapp/js/goatApp/model/ParamModel.js b/webgoat-container/src/main/resources/static/js/goatApp/model/ParamModel.js
similarity index 100%
rename from webgoat-container/src/main/webapp/js/goatApp/model/ParamModel.js
rename to webgoat-container/src/main/resources/static/js/goatApp/model/ParamModel.js
diff --git a/webgoat-container/src/main/webapp/js/goatApp/model/PluginReloadModel.js b/webgoat-container/src/main/resources/static/js/goatApp/model/PluginReloadModel.js
similarity index 100%
rename from webgoat-container/src/main/webapp/js/goatApp/model/PluginReloadModel.js
rename to webgoat-container/src/main/resources/static/js/goatApp/model/PluginReloadModel.js
diff --git a/webgoat-container/src/main/webapp/js/goatApp/model/SolutionModel.js b/webgoat-container/src/main/resources/static/js/goatApp/model/SolutionModel.js
similarity index 100%
rename from webgoat-container/src/main/webapp/js/goatApp/model/SolutionModel.js
rename to webgoat-container/src/main/resources/static/js/goatApp/model/SolutionModel.js
diff --git a/webgoat-container/src/main/webapp/js/goatApp/model/SourceModel.js b/webgoat-container/src/main/resources/static/js/goatApp/model/SourceModel.js
similarity index 100%
rename from webgoat-container/src/main/webapp/js/goatApp/model/SourceModel.js
rename to webgoat-container/src/main/resources/static/js/goatApp/model/SourceModel.js
diff --git a/webgoat-container/src/main/resources/static/js/goatApp/support/CustomGoat.js b/webgoat-container/src/main/resources/static/js/goatApp/support/CustomGoat.js
new file mode 100644
index 000000000..c296939cb
--- /dev/null
+++ b/webgoat-container/src/main/resources/static/js/goatApp/support/CustomGoat.js
@@ -0,0 +1,24 @@
+define(['jquery',
+ 'underscore',
+ 'backbone',
+ 'libs/jquery.form'
+ ],
+ function($,
+ _,
+ Backbone,
+ JQueryForm) {
+ var customGoat = {
+
+ getFlights:function() {
+ var fromField = $('#travelFrom');
+ var toField = $('#travelTo');
+ var xml = '' +
+ '' +
+ ' ' + fromField.value() + ' ' +
+ ' ';
+ return xml;
+ },
+ }
+
+ return customGoat;
+ });
\ No newline at end of file
diff --git a/webgoat-container/src/main/webapp/js/goatApp/support/GoatUtils.js b/webgoat-container/src/main/resources/static/js/goatApp/support/GoatUtils.js
similarity index 100%
rename from webgoat-container/src/main/webapp/js/goatApp/support/GoatUtils.js
rename to webgoat-container/src/main/resources/static/js/goatApp/support/GoatUtils.js
diff --git a/webgoat-container/src/main/webapp/js/goatApp/support/goatConstants.js b/webgoat-container/src/main/resources/static/js/goatApp/support/goatConstants.js
similarity index 100%
rename from webgoat-container/src/main/webapp/js/goatApp/support/goatConstants.js
rename to webgoat-container/src/main/resources/static/js/goatApp/support/goatConstants.js
diff --git a/webgoat-container/src/main/webapp/js/goatApp/view/CookieView.js b/webgoat-container/src/main/resources/static/js/goatApp/view/CookieView.js
similarity index 100%
rename from webgoat-container/src/main/webapp/js/goatApp/view/CookieView.js
rename to webgoat-container/src/main/resources/static/js/goatApp/view/CookieView.js
diff --git a/webgoat-container/src/main/webapp/js/goatApp/view/DeveloperControlsView.js b/webgoat-container/src/main/resources/static/js/goatApp/view/DeveloperControlsView.js
similarity index 96%
rename from webgoat-container/src/main/webapp/js/goatApp/view/DeveloperControlsView.js
rename to webgoat-container/src/main/resources/static/js/goatApp/view/DeveloperControlsView.js
index ddd8b9f2d..42d383f52 100644
--- a/webgoat-container/src/main/webapp/js/goatApp/view/DeveloperControlsView.js
+++ b/webgoat-container/src/main/resources/static/js/goatApp/view/DeveloperControlsView.js
@@ -11,7 +11,7 @@ function(
LabelDebugModel) {
return Backbone.View.extend({
el: '#developer-controls',
-
+
onControlClick: function(model) {
$('#' + model.id).find('td').text('Loading...');
model.load();
@@ -24,7 +24,7 @@ function(
onLabelsLoaded: function(model) {
this.models[1] = model;
this.render();
- Backbone.history.loadUrl(Backbone.history.getFragment());
+ this.trigger('dev:labels')
},
initialize: function(options) {
diff --git a/webgoat-container/src/main/webapp/js/goatApp/view/GoatRouter.js b/webgoat-container/src/main/resources/static/js/goatApp/view/GoatRouter.js
similarity index 61%
rename from webgoat-container/src/main/webapp/js/goatApp/view/GoatRouter.js
rename to webgoat-container/src/main/resources/static/js/goatApp/view/GoatRouter.js
index 1d9e7ad94..2a6079e2c 100644
--- a/webgoat-container/src/main/webapp/js/goatApp/view/GoatRouter.js
+++ b/webgoat-container/src/main/resources/static/js/goatApp/view/GoatRouter.js
@@ -15,20 +15,20 @@ define(['jquery',
MenuView,
DeveloperControlsView) {
- var lessonView = new LessonContentView();
+ var lessonContentView = new LessonContentView();
var menuView = new MenuView();
var developerControlsView = new DeveloperControlsView();
var GoatAppRouter = Backbone.Router.extend({
routes: {
'welcome':'welcomeRoute',
- 'attack/:scr/:menu':'attackRoute',
- 'attack/:scr/:menu/:stage':'attackRoute',
- 'attack/:scr/:menu/*stage/:num':'attackRoute',
+ 'lesson/:name':'lessonRoute'
+ //'attack/:scr/:menu/:stage':'attackRoute',
+ //'attack/:scr/:menu/*stage/:num':'attackRoute',
},
lessonController: new LessonController({
- lessonView: lessonView
+ lessonContentView: lessonContentView
}),
menuController: new MenuController({
@@ -39,17 +39,23 @@ define(['jquery',
goatRouter = new GoatAppRouter();
this.lessonController.start();
// this.menuController.initMenu();
+ webgoat = {};
+ webgoat.customjs = {};
- goatRouter.on('route:attackRoute', function(scr,menu,stage,num) {
- this.lessonController.loadLesson(scr,menu,stage,num);
- this.menuController.updateMenu(scr,menu);
+// goatRouter.on('route:attackRoute', function(scr,menu,stage,num) {
+// this.lessonController.loadLesson(scr,menu,stage,num);
+// this.menuController.updateMenu(scr,menu);
+// });
+ goatRouter.on('route:lessonRoute', function(name) {
+ this.lessonController.loadLesson(name);
+ //TODO - update menu code from below
+ this.menuController.updateMenu(name);
});
+
goatRouter.on('route:welcomeRoute', function() {
this.lessonController.loadWelcome();
});
- goatRouter.on("route", function(route, params) {
-
- });
+ goatRouter.on("route", function(route, params) {});
Backbone.history.start();
this.listenTo(this.lessonController, 'menu:reload',this.reloadMenu)
diff --git a/webgoat-container/src/main/webapp/js/goatApp/view/HelpControlsView.js b/webgoat-container/src/main/resources/static/js/goatApp/view/HelpControlsView.js
similarity index 77%
rename from webgoat-container/src/main/webapp/js/goatApp/view/HelpControlsView.js
rename to webgoat-container/src/main/resources/static/js/goatApp/view/HelpControlsView.js
index 2a3e6da6b..b29220224 100644
--- a/webgoat-container/src/main/webapp/js/goatApp/view/HelpControlsView.js
+++ b/webgoat-container/src/main/resources/static/js/goatApp/view/HelpControlsView.js
@@ -26,20 +26,25 @@ function($,_,Backbone) {
if (this.hasSource) {
this.$el.find('#show-source-button').unbind().on('click',_.bind(this.showSource,this)).show();
}
+ if (this.hasHints) {
+ this.$el.find('#show-hints-button').unbind().on('click',this.showHints.bind(this)).show();
+ }
if (this.hasSolution) {
this.$el.find('#show-solution-button').unbind().on('click',_.bind(this.showSolution,this)).show();
}
- if (this.hasPlan) {
- this.$el.find('#show-plan-button').unbind().on('click',_.bind(this.showPlan,this)).show();
- }
- if (this.hasHints) {
- this.$el.find('#show-hints-button').unbind().on('click',_.bind(this.showHints,this)).show();
+ if (true) { //FIXME: change to this.hasAttack
+ this.$el.find('#show-attack-button').unbind().on('click',_.bind(this.showAttack,this)).show();
}
+
this.$el.find('#restart-lesson-button').unbind().on('click',_.bind(this.restartLesson,this)).show();
//this.$el.append(this.helpButtons.restartLesson);
},
+ showHints: function() {
+ this.trigger('hints:show','hint');
+ },
+
showSource: function() {
this.trigger('source:show','source');
},
@@ -48,13 +53,10 @@ function($,_,Backbone) {
this.trigger('solution:show','solution');
},
- showPlan: function() {
- this.trigger('plan:show','plan');
+ showAttack: function() {
+ this.trigger('attack:show',{show:true});
},
- showHints: function() {
- this.trigger('hints:show','hints');
- },
restartLesson: function() {
this.trigger('lesson:restart');
}
diff --git a/webgoat-container/src/main/webapp/js/goatApp/view/HelpView.js b/webgoat-container/src/main/resources/static/js/goatApp/view/HelpView.js
similarity index 100%
rename from webgoat-container/src/main/webapp/js/goatApp/view/HelpView.js
rename to webgoat-container/src/main/resources/static/js/goatApp/view/HelpView.js
diff --git a/webgoat-container/src/main/webapp/js/goatApp/view/HintView.js b/webgoat-container/src/main/resources/static/js/goatApp/view/HintView.js
similarity index 82%
rename from webgoat-container/src/main/webapp/js/goatApp/view/HintView.js
rename to webgoat-container/src/main/resources/static/js/goatApp/view/HintView.js
index cbe18e601..564acde68 100644
--- a/webgoat-container/src/main/webapp/js/goatApp/view/HintView.js
+++ b/webgoat-container/src/main/resources/static/js/goatApp/view/HintView.js
@@ -19,13 +19,27 @@ function($,
this.hideHints();
},
+ isVisible: function() {
+ return this.$el.is(':visible');
+ },
+
+ toggleLabel: function() {
+ if (this.isVisible()) {
+ $('show-hints-button').text('Hide hints');
+ } else {
+ $('show-hints-button').text('Show hints');
+ }
+ },
+
render:function() {
- if (this.$el.is(':visible')) {
+ if (this.isVisible()) {
this.$el.hide(350);
} else {
this.$el.show(350);
}
-
+
+ this.toggleLabel()
+
if (this.collection.length > 0) {
this.hideShowPrevNextButtons();
}
diff --git a/webgoat-container/src/main/resources/static/js/goatApp/view/LessonContentView.js b/webgoat-container/src/main/resources/static/js/goatApp/view/LessonContentView.js
new file mode 100644
index 000000000..7f69e36e5
--- /dev/null
+++ b/webgoat-container/src/main/resources/static/js/goatApp/view/LessonContentView.js
@@ -0,0 +1,198 @@
+//LessonContentView
+define(['jquery',
+ 'underscore',
+ 'backbone',
+ 'libs/jquery.form'],
+ function(
+ $,
+ _,
+ Backbone,
+ JQueryForm) {
+ return Backbone.View.extend({
+ el:'#lesson-content-wrapper', //TODO << get this fixed up in DOM
+
+ initialize: function(options) {
+ options = options || {};
+ },
+
+ /* initial renering */
+ render: function() {
+ this.$el.find('.lesson-content').html(this.model.get('content'));
+ this.$el.find('.attack-feedback').hide();
+ this.$el.find('.attack-output').hide();
+ this.makeFormsAjax();
+ //this.ajaxifyAttackHref();
+ $(window).scrollTop(0); //work-around til we get the scroll down sorted out
+ this.initPagination();
+ },
+
+ initPagination: function() {
+ //get basic pagination info
+ this.currentPage = 0;
+ this.$contentPages = this.$el.find('.lesson-page-wrapper');
+ this.numPages = this.$contentPages.length;
+
+ //
+ this.addPaginationControls();
+ if (this.numPages > 1) {
+ //no animation on init
+ this.$contentPages.hide();
+ this.$el.find(this.$contentPages[this.currentPage]).show();
+ this.showNextPageButton();
+ this.hidePrevPageButton();
+ } else if (this.numPages === 1) {
+ this.hideNextPageButton();
+ this.hidePrevPageButton();
+ }
+ },
+
+ makeFormsAjax: function () {
+ this.$form = $('form.attack-form');
+ // turn off standard submit
+ var self = this;
+ // each submit handled per form
+ this.$form.each( function() {
+ $(this).submit(self.onFormSubmit.bind(self));
+ });
+ },
+
+ /* form submission handling */
+ onFormSubmit: function (e) {
+ var curForm = e.currentTarget; // the form from which the
+ var self = this;
+ // TODO custom Data prep for submission
+ var prepareDataFunctionName = $(curForm).attr('prepareData');
+ var submitData = (typeof webgoat.customjs[prepareDataFunctionName] === 'function') ? webgoat.customjs[prepareDataFunctionName]() : this.$form.serialize();
+ // var submitData = this.$form.serialize();
+ this.$curFeedback = $(curForm).closest('.attack-container').find('.attack-feedback');
+ this.$curOutput = $(curForm).closest('.atatck-container').find('.attack-output');
+ var formUrl = $(curForm).attr('action');
+ var formMethod = $(curForm).attr('method');
+ var contentType = ($(curForm).attr('contentType')) ? $(curForm).attr('contentType') : 'application/x-www-form-urlencoded; charset=UTF-8';
+ $.ajax({
+ //data:submitData,
+ url:formUrl,
+ method:formMethod,
+ contentType:contentType,
+ data: submitData
+ }).then(self.onSuccessResponse.bind(self), self.onErrorResponse.bind(self));
+ return false;
+ },
+
+ onSuccessResponse: function(data) {
+ console.log(data);
+ this.renderFeedback(data.feedback);
+
+ this.renderOutput(data.output || "");
+ if (data.lessonCompleted) {
+ this.trigger('lesson:complete');
+ }
+ return false;
+ },
+
+ onErrorResponse: function (a,b,c) {
+ console.error(a);
+ console.error(b);
+ console.error(c);
+ return false;
+ },
+
+ ajaxifyAttackHref: function() { // rewrite any links with hrefs point to relative attack URLs
+ var self = this;
+ // instruct in template to have links returned with the attack-link class
+ $('a.attack-link').submit(function(event){
+ $.get(this.action, "json").then(self.onSuccessResponse, self.onErrorResponse);
+ });
+ },
+
+ renderFeedback: function(feedback) {
+ this.$curFeedback.html(feedback || "");
+ this.$curFeedback.show(400)
+
+ },
+
+ renderOutput: function(output) {
+ this.$curOutput.html(output || "");
+ this.$curOutput.show(400)
+ },
+
+ /* create, show & hide pagination controls */
+
+ addPaginationControls: function() {
+ var pagingControlsDiv;
+ this.$el.html();
+ //prev
+ var prevPageButton = $('',{class:'glyphicon-class glyphicon glyphicon-circle-arrow-left show-prev-page'});
+ prevPageButton.unbind().on('click',this.decrementPageView.bind(this));
+ //next
+ var nextPageButton = $('',{class:'glyphicon-class glyphicon glyphicon-circle-arrow-right show-next-page'});
+ nextPageButton.unbind().on('click',this.incrementPageView.bind(this));
+ //add to DOM
+ if (this.$el.find('#lesson-page-controls').length < 1) {
+ pagingControlsDiv = $('',{class:'panel-body', id:'lesson-page-controls'});
+ pagingControlsDiv.append(prevPageButton);
+ pagingControlsDiv.append(nextPageButton);
+ this.$el.append(pagingControlsDiv);
+ }
+
+ },
+
+ showPrevPageButton: function() {
+ $('span.glyphicon-class.glyphicon.glyphicon-circle-arrow-left.show-prev-page').show();
+ },
+
+ hidePrevPageButton: function() {
+ $('span.glyphicon-class.glyphicon.glyphicon-circle-arrow-left.show-prev-page').hide();
+ },
+
+ showNextPageButton: function() {
+ $('span.glyphicon-class.glyphicon.glyphicon-circle-arrow-right.show-next-page').show();
+ },
+
+ hideNextPageButton: function() {
+ $('span.glyphicon-class.glyphicon.glyphicon-circle-arrow-right.show-next-page').hide();
+ },
+
+ /* increment, decrement & display handlers */
+ incrementPageView: function() {
+ if (this.currentPage < this.numPages -1) {
+ this.currentPage++;
+ this.showCurContentPage(true);
+ }
+
+ if (this.currentPage > 0) {
+ this.showPrevPageButton();
+ }
+
+ if (this.currentPage >= this.numPages -1) {
+ this.hideNextPageButton();
+ this.showPrevPageButton;
+ }
+ },
+
+ decrementPageView: function() {
+ if (this.currentPage > 0) {
+ this.currentPage--;
+ this.showCurContentPage(false);
+ }
+
+ if (this.currentPage < this.numPages -1) {
+ this.showNextPageButton();
+ }
+
+ if (this.currentPage == 0) {
+ this.hidePrevPageButton();
+ this.showNextPageButton()
+ }
+
+ },
+
+ showCurContentPage: function(isIncrement) {
+ this.$contentPages.hide();
+ this.$el.find(this.$contentPages[this.currentPage]).show();
+ }
+
+ });
+
+
+});
diff --git a/webgoat-container/src/main/webapp/js/goatApp/view/LessonProgressView.js b/webgoat-container/src/main/resources/static/js/goatApp/view/LessonProgressView.js
similarity index 100%
rename from webgoat-container/src/main/webapp/js/goatApp/view/LessonProgressView.js
rename to webgoat-container/src/main/resources/static/js/goatApp/view/LessonProgressView.js
diff --git a/webgoat-container/src/main/webapp/js/goatApp/view/MenuButtonView.js b/webgoat-container/src/main/resources/static/js/goatApp/view/MenuButtonView.js
similarity index 100%
rename from webgoat-container/src/main/webapp/js/goatApp/view/MenuButtonView.js
rename to webgoat-container/src/main/resources/static/js/goatApp/view/MenuButtonView.js
diff --git a/webgoat-container/src/main/webapp/js/goatApp/view/MenuItemView.js b/webgoat-container/src/main/resources/static/js/goatApp/view/MenuItemView.js
similarity index 100%
rename from webgoat-container/src/main/webapp/js/goatApp/view/MenuItemView.js
rename to webgoat-container/src/main/resources/static/js/goatApp/view/MenuItemView.js
diff --git a/webgoat-container/src/main/webapp/js/goatApp/view/MenuStageView.js b/webgoat-container/src/main/resources/static/js/goatApp/view/MenuStageView.js
similarity index 100%
rename from webgoat-container/src/main/webapp/js/goatApp/view/MenuStageView.js
rename to webgoat-container/src/main/resources/static/js/goatApp/view/MenuStageView.js
diff --git a/webgoat-container/src/main/webapp/js/goatApp/view/MenuView.js b/webgoat-container/src/main/resources/static/js/goatApp/view/MenuView.js
similarity index 100%
rename from webgoat-container/src/main/webapp/js/goatApp/view/MenuView.js
rename to webgoat-container/src/main/resources/static/js/goatApp/view/MenuView.js
diff --git a/webgoat-container/src/main/webapp/js/goatApp/view/ParamView.js b/webgoat-container/src/main/resources/static/js/goatApp/view/ParamView.js
similarity index 100%
rename from webgoat-container/src/main/webapp/js/goatApp/view/ParamView.js
rename to webgoat-container/src/main/resources/static/js/goatApp/view/ParamView.js
diff --git a/webgoat-container/src/main/webapp/js/goatApp/view/PlanView.js b/webgoat-container/src/main/resources/static/js/goatApp/view/PlanView.js
similarity index 100%
rename from webgoat-container/src/main/webapp/js/goatApp/view/PlanView.js
rename to webgoat-container/src/main/resources/static/js/goatApp/view/PlanView.js
diff --git a/webgoat-container/src/main/webapp/js/goatApp/view/SolutionView.js b/webgoat-container/src/main/resources/static/js/goatApp/view/SolutionView.js
similarity index 100%
rename from webgoat-container/src/main/webapp/js/goatApp/view/SolutionView.js
rename to webgoat-container/src/main/resources/static/js/goatApp/view/SolutionView.js
diff --git a/webgoat-container/src/main/webapp/js/goatApp/view/SourceView.js b/webgoat-container/src/main/resources/static/js/goatApp/view/SourceView.js
similarity index 100%
rename from webgoat-container/src/main/webapp/js/goatApp/view/SourceView.js
rename to webgoat-container/src/main/resources/static/js/goatApp/view/SourceView.js
diff --git a/webgoat-container/src/main/webapp/js/goatApp/view/TitleView.js b/webgoat-container/src/main/resources/static/js/goatApp/view/TitleView.js
similarity index 100%
rename from webgoat-container/src/main/webapp/js/goatApp/view/TitleView.js
rename to webgoat-container/src/main/resources/static/js/goatApp/view/TitleView.js
diff --git a/webgoat-container/src/main/webapp/js/goatApp/view/UserAndInfoView.js b/webgoat-container/src/main/resources/static/js/goatApp/view/UserAndInfoView.js
similarity index 100%
rename from webgoat-container/src/main/webapp/js/goatApp/view/UserAndInfoView.js
rename to webgoat-container/src/main/resources/static/js/goatApp/view/UserAndInfoView.js
diff --git a/webgoat-container/src/main/webapp/js/html5shiv.js b/webgoat-container/src/main/resources/static/js/html5shiv.js
similarity index 99%
rename from webgoat-container/src/main/webapp/js/html5shiv.js
rename to webgoat-container/src/main/resources/static/js/html5shiv.js
index e2e00155b..448cebd79 100644
--- a/webgoat-container/src/main/webapp/js/html5shiv.js
+++ b/webgoat-container/src/main/resources/static/js/html5shiv.js
@@ -1,8 +1,8 @@
-/*
- HTML5 Shiv v3.7.0 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed
-*/
-(function(l,f){function m(){var a=e.elements;return"string"==typeof a?a.split(" "):a}function i(a){var b=n[a[o]];b||(b={},h++,a[o]=h,n[h]=b);return b}function p(a,b,c){b||(b=f);if(g)return b.createElement(a);c||(c=i(b));b=c.cache[a]?c.cache[a].cloneNode():r.test(a)?(c.cache[a]=c.createElem(a)).cloneNode():c.createElem(a);return b.canHaveChildren&&!s.test(a)?c.frag.appendChild(b):b}function t(a,b){if(!b.cache)b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag();
-a.createElement=function(c){return!e.shivMethods?b.createElem(c):p(c,a,b)};a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+m().join().replace(/[\w\-]+/g,function(a){b.createElem(a);b.frag.createElement(a);return'c("'+a+'")'})+");return n}")(e,b.frag)}function q(a){a||(a=f);var b=i(a);if(e.shivCSS&&!j&&!b.hasCSS){var c,d=a;c=d.createElement("p");d=d.getElementsByTagName("head")[0]||d.documentElement;c.innerHTML="x";
-c=d.insertBefore(c.lastChild,d.firstChild);b.hasCSS=!!c}g||t(a,b);return a}var k=l.html5||{},s=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,r=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,j,o="_html5shiv",h=0,n={},g;(function(){try{var a=f.createElement("a");a.innerHTML="
";j="hidden"in a;var b;if(!(b=1==a.childNodes.length)){f.createElement("a");var c=f.createDocumentFragment();b="undefined"==typeof c.cloneNode||
-"undefined"==typeof c.createDocumentFragment||"undefined"==typeof c.createElement}g=b}catch(d){g=j=!0}})();var e={elements:k.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output progress section summary template time video",version:"3.7.0",shivCSS:!1!==k.shivCSS,supportsUnknownElements:g,shivMethods:!1!==k.shivMethods,type:"default",shivDocument:q,createElement:p,createDocumentFragment:function(a,b){a||(a=f);
-if(g)return a.createDocumentFragment();for(var b=b||i(a),c=b.frag.cloneNode(),d=0,e=m(),h=e.length;d
article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}";
+c=d.insertBefore(c.lastChild,d.firstChild);b.hasCSS=!!c}g||t(a,b);return a}var k=l.html5||{},s=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,r=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,j,o="_html5shiv",h=0,n={},g;(function(){try{var a=f.createElement("a");a.innerHTML=" ";j="hidden"in a;var b;if(!(b=1==a.childNodes.length)){f.createElement("a");var c=f.createDocumentFragment();b="undefined"==typeof c.cloneNode||
+"undefined"==typeof c.createDocumentFragment||"undefined"==typeof c.createElement}g=b}catch(d){g=j=!0}})();var e={elements:k.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output progress section summary template time video",version:"3.7.0",shivCSS:!1!==k.shivCSS,supportsUnknownElements:g,shivMethods:!1!==k.shivMethods,type:"default",shivDocument:q,createElement:p,createDocumentFragment:function(a,b){a||(a=f);
+if(g)return a.createDocumentFragment();for(var b=b||i(a),c=b.frag.cloneNode(),d=0,e=m(),h=e.length;d'+
- ''+
- ''+
- ' ')
- .insertBefore(this.element)
- .append(this.element);
- this.id = this.element.data('slider-id')||options.id;
- if (this.id) {
- this.picker[0].id = this.id;
- }
-
- if (typeof Modernizr !== 'undefined' && Modernizr.touch) {
- this.touchCapable = true;
- }
-
- var tooltip = this.element.data('slider-tooltip')||options.tooltip;
-
- this.tooltip = this.picker.find('.tooltip');
- this.tooltipInner = this.tooltip.find('div.tooltip-inner');
-
- this.orientation = this.element.data('slider-orientation')||options.orientation;
- switch(this.orientation) {
- case 'vertical':
- this.picker.addClass('slider-vertical');
- this.stylePos = 'top';
- this.mousePos = 'pageY';
- this.sizePos = 'offsetHeight';
- this.tooltip.addClass('right')[0].style.left = '100%';
- break;
- default:
- this.picker
- .addClass('slider-horizontal')
- .css('width', this.element.outerWidth());
- this.orientation = 'horizontal';
- this.stylePos = 'left';
- this.mousePos = 'pageX';
- this.sizePos = 'offsetWidth';
- this.tooltip.addClass('top')[0].style.top = -this.tooltip.outerHeight() - 14 + 'px';
- break;
- }
-
- this.min = this.element.data('slider-min')||options.min;
- this.max = this.element.data('slider-max')||options.max;
- this.step = this.element.data('slider-step')||options.step;
- this.value = this.element.data('slider-value')||options.value;
- if (this.value[1]) {
- this.range = true;
- }
-
- this.selection = this.element.data('slider-selection')||options.selection;
- this.selectionEl = this.picker.find('.slider-selection');
- if (this.selection === 'none') {
- this.selectionEl.addClass('hide');
- }
- this.selectionElStyle = this.selectionEl[0].style;
-
-
- this.handle1 = this.picker.find('.slider-handle:first');
- this.handle1Stype = this.handle1[0].style;
- this.handle2 = this.picker.find('.slider-handle:last');
- this.handle2Stype = this.handle2[0].style;
-
- var handle = this.element.data('slider-handle')||options.handle;
- switch(handle) {
- case 'round':
- this.handle1.addClass('round');
- this.handle2.addClass('round');
- break
- case 'triangle':
- this.handle1.addClass('triangle');
- this.handle2.addClass('triangle');
- break
- }
-
- if (this.range) {
- this.value[0] = Math.max(this.min, Math.min(this.max, this.value[0]));
- this.value[1] = Math.max(this.min, Math.min(this.max, this.value[1]));
- } else {
- this.value = [ Math.max(this.min, Math.min(this.max, this.value))];
- this.handle2.addClass('hide');
- if (this.selection == 'after') {
- this.value[1] = this.max;
- } else {
- this.value[1] = this.min;
- }
- }
- this.diff = this.max - this.min;
- this.percentage = [
- (this.value[0]-this.min)*100/this.diff,
- (this.value[1]-this.min)*100/this.diff,
- this.step*100/this.diff
- ];
-
- this.offset = this.picker.offset();
- this.size = this.picker[0][this.sizePos];
-
- this.formater = options.formater;
-
- this.layout();
-
- if (this.touchCapable) {
- // Touch: Bind touch events:
- this.picker.on({
- touchstart: $.proxy(this.mousedown, this)
- });
- } else {
- this.picker.on({
- mousedown: $.proxy(this.mousedown, this)
- });
- }
-
- if (tooltip === 'show') {
- this.picker.on({
- mouseenter: $.proxy(this.showTooltip, this),
- mouseleave: $.proxy(this.hideTooltip, this)
- });
- } else {
- this.tooltip.addClass('hide');
- }
- };
-
- Slider.prototype = {
- constructor: Slider,
-
- over: false,
- inDrag: false,
-
- showTooltip: function(){
- this.tooltip.addClass('in');
- //var left = Math.round(this.percent*this.width);
- //this.tooltip.css('left', left - this.tooltip.outerWidth()/2);
- this.over = true;
- },
-
- hideTooltip: function(){
- if (this.inDrag === false) {
- this.tooltip.removeClass('in');
- }
- this.over = false;
- },
-
- layout: function(){
- this.handle1Stype[this.stylePos] = this.percentage[0]+'%';
- this.handle2Stype[this.stylePos] = this.percentage[1]+'%';
- if (this.orientation == 'vertical') {
- this.selectionElStyle.top = Math.min(this.percentage[0], this.percentage[1]) +'%';
- this.selectionElStyle.height = Math.abs(this.percentage[0] - this.percentage[1]) +'%';
- } else {
- this.selectionElStyle.left = Math.min(this.percentage[0], this.percentage[1]) +'%';
- this.selectionElStyle.width = Math.abs(this.percentage[0] - this.percentage[1]) +'%';
- }
- if (this.range) {
- this.tooltipInner.text(
- this.formater(this.value[0]) +
- ' : ' +
- this.formater(this.value[1])
- );
- this.tooltip[0].style[this.stylePos] = this.size * (this.percentage[0] + (this.percentage[1] - this.percentage[0])/2)/100 - (this.orientation === 'vertical' ? this.tooltip.outerHeight()/2 : this.tooltip.outerWidth()/2) +'px';
- } else {
- this.tooltipInner.text(
- this.formater(this.value[0])
- );
- this.tooltip[0].style[this.stylePos] = this.size * this.percentage[0]/100 - (this.orientation === 'vertical' ? this.tooltip.outerHeight()/2 : this.tooltip.outerWidth()/2) +'px';
- }
- },
-
- mousedown: function(ev) {
-
- // Touch: Get the original event:
- if (this.touchCapable && ev.type === 'touchstart') {
- ev = ev.originalEvent;
- }
-
- this.offset = this.picker.offset();
- this.size = this.picker[0][this.sizePos];
-
- var percentage = this.getPercentage(ev);
-
- if (this.range) {
- var diff1 = Math.abs(this.percentage[0] - percentage);
- var diff2 = Math.abs(this.percentage[1] - percentage);
- this.dragged = (diff1 < diff2) ? 0 : 1;
- } else {
- this.dragged = 0;
- }
-
- this.percentage[this.dragged] = percentage;
- this.layout();
-
- if (this.touchCapable) {
- // Touch: Bind touch events:
- $(document).on({
- touchmove: $.proxy(this.mousemove, this),
- touchend: $.proxy(this.mouseup, this)
- });
- } else {
- $(document).on({
- mousemove: $.proxy(this.mousemove, this),
- mouseup: $.proxy(this.mouseup, this)
- });
- }
-
- this.inDrag = true;
- var val = this.calculateValue();
- this.element.trigger({
- type: 'slideStart',
- value: val
- }).trigger({
- type: 'slide',
- value: val
- });
- return false;
- },
-
- mousemove: function(ev) {
-
- // Touch: Get the original event:
- if (this.touchCapable && ev.type === 'touchmove') {
- ev = ev.originalEvent;
- }
-
- var percentage = this.getPercentage(ev);
- if (this.range) {
- if (this.dragged === 0 && this.percentage[1] < percentage) {
- this.percentage[0] = this.percentage[1];
- this.dragged = 1;
- } else if (this.dragged === 1 && this.percentage[0] > percentage) {
- this.percentage[1] = this.percentage[0];
- this.dragged = 0;
- }
- }
- this.percentage[this.dragged] = percentage;
- this.layout();
- var val = this.calculateValue();
- this.element
- .trigger({
- type: 'slide',
- value: val
- })
- .data('value', val)
- .prop('value', val);
- return false;
- },
-
- mouseup: function(ev) {
- if (this.touchCapable) {
- // Touch: Bind touch events:
- $(document).off({
- touchmove: this.mousemove,
- touchend: this.mouseup
- });
- } else {
- $(document).off({
- mousemove: this.mousemove,
- mouseup: this.mouseup
- });
- }
-
- this.inDrag = false;
- if (this.over == false) {
- this.hideTooltip();
- }
- this.element;
- var val = this.calculateValue();
- this.element
- .trigger({
- type: 'slideStop',
- value: val
- })
- .data('value', val)
- .prop('value', val);
- return false;
- },
-
- calculateValue: function() {
- var val;
- if (this.range) {
- val = [
- (this.min + Math.round((this.diff * this.percentage[0]/100)/this.step)*this.step),
- (this.min + Math.round((this.diff * this.percentage[1]/100)/this.step)*this.step)
- ];
- this.value = val;
- } else {
- val = (this.min + Math.round((this.diff * this.percentage[0]/100)/this.step)*this.step);
- this.value = [val, this.value[1]];
- }
- return val;
- },
-
- getPercentage: function(ev) {
- if (this.touchCapable) {
- ev = ev.touches[0];
- }
- var percentage = (ev[this.mousePos] - this.offset[this.stylePos])*100/this.size;
- percentage = Math.round(percentage/this.percentage[2])*this.percentage[2];
- return Math.max(0, Math.min(100, percentage));
- },
-
- getValue: function() {
- if (this.range) {
- return this.value;
- }
- return this.value[0];
- },
-
- setValue: function(val) {
- this.value = val;
-
- if (this.range) {
- this.value[0] = Math.max(this.min, Math.min(this.max, this.value[0]));
- this.value[1] = Math.max(this.min, Math.min(this.max, this.value[1]));
- } else {
- this.value = [ Math.max(this.min, Math.min(this.max, this.value))];
- this.handle2.addClass('hide');
- if (this.selection == 'after') {
- this.value[1] = this.max;
- } else {
- this.value[1] = this.min;
- }
- }
- this.diff = this.max - this.min;
- this.percentage = [
- (this.value[0]-this.min)*100/this.diff,
- (this.value[1]-this.min)*100/this.diff,
- this.step*100/this.diff
- ];
- this.layout();
- }
- };
-
- $.fn.slider = function ( option, val ) {
- return this.each(function () {
- var $this = $(this),
- data = $this.data('slider'),
- options = typeof option === 'object' && option;
- if (!data) {
- $this.data('slider', (data = new Slider(this, $.extend({}, $.fn.slider.defaults,options))));
- }
- if (typeof option == 'string') {
- data[option](val);
- }
- })
- };
-
- $.fn.slider.defaults = {
- min: 0,
- max: 10,
- step: 1,
- orientation: 'horizontal',
- value: 5,
- selection: 'before',
- tooltip: 'show',
- handle: 'round',
- formater: function(value) {
- return value;
- }
- };
-
- $.fn.slider.Constructor = Slider;
-
+/* =========================================================
+ * bootstrap-slider.js v2.0.0
+ * http://www.eyecon.ro/bootstrap-slider
+ * =========================================================
+ * Copyright 2012 Stefan Petre
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================= */
+
+!function( $ ) {
+
+ var Slider = function(element, options) {
+ this.element = $(element);
+ this.picker = $('')
+ .insertBefore(this.element)
+ .append(this.element);
+ this.id = this.element.data('slider-id')||options.id;
+ if (this.id) {
+ this.picker[0].id = this.id;
+ }
+
+ if (typeof Modernizr !== 'undefined' && Modernizr.touch) {
+ this.touchCapable = true;
+ }
+
+ var tooltip = this.element.data('slider-tooltip')||options.tooltip;
+
+ this.tooltip = this.picker.find('.tooltip');
+ this.tooltipInner = this.tooltip.find('div.tooltip-inner');
+
+ this.orientation = this.element.data('slider-orientation')||options.orientation;
+ switch(this.orientation) {
+ case 'vertical':
+ this.picker.addClass('slider-vertical');
+ this.stylePos = 'top';
+ this.mousePos = 'pageY';
+ this.sizePos = 'offsetHeight';
+ this.tooltip.addClass('right')[0].style.left = '100%';
+ break;
+ default:
+ this.picker
+ .addClass('slider-horizontal')
+ .css('width', this.element.outerWidth());
+ this.orientation = 'horizontal';
+ this.stylePos = 'left';
+ this.mousePos = 'pageX';
+ this.sizePos = 'offsetWidth';
+ this.tooltip.addClass('top')[0].style.top = -this.tooltip.outerHeight() - 14 + 'px';
+ break;
+ }
+
+ this.min = this.element.data('slider-min')||options.min;
+ this.max = this.element.data('slider-max')||options.max;
+ this.step = this.element.data('slider-step')||options.step;
+ this.value = this.element.data('slider-value')||options.value;
+ if (this.value[1]) {
+ this.range = true;
+ }
+
+ this.selection = this.element.data('slider-selection')||options.selection;
+ this.selectionEl = this.picker.find('.slider-selection');
+ if (this.selection === 'none') {
+ this.selectionEl.addClass('hide');
+ }
+ this.selectionElStyle = this.selectionEl[0].style;
+
+
+ this.handle1 = this.picker.find('.slider-handle:first');
+ this.handle1Stype = this.handle1[0].style;
+ this.handle2 = this.picker.find('.slider-handle:last');
+ this.handle2Stype = this.handle2[0].style;
+
+ var handle = this.element.data('slider-handle')||options.handle;
+ switch(handle) {
+ case 'round':
+ this.handle1.addClass('round');
+ this.handle2.addClass('round');
+ break
+ case 'triangle':
+ this.handle1.addClass('triangle');
+ this.handle2.addClass('triangle');
+ break
+ }
+
+ if (this.range) {
+ this.value[0] = Math.max(this.min, Math.min(this.max, this.value[0]));
+ this.value[1] = Math.max(this.min, Math.min(this.max, this.value[1]));
+ } else {
+ this.value = [ Math.max(this.min, Math.min(this.max, this.value))];
+ this.handle2.addClass('hide');
+ if (this.selection == 'after') {
+ this.value[1] = this.max;
+ } else {
+ this.value[1] = this.min;
+ }
+ }
+ this.diff = this.max - this.min;
+ this.percentage = [
+ (this.value[0]-this.min)*100/this.diff,
+ (this.value[1]-this.min)*100/this.diff,
+ this.step*100/this.diff
+ ];
+
+ this.offset = this.picker.offset();
+ this.size = this.picker[0][this.sizePos];
+
+ this.formater = options.formater;
+
+ this.layout();
+
+ if (this.touchCapable) {
+ // Touch: Bind touch events:
+ this.picker.on({
+ touchstart: $.proxy(this.mousedown, this)
+ });
+ } else {
+ this.picker.on({
+ mousedown: $.proxy(this.mousedown, this)
+ });
+ }
+
+ if (tooltip === 'show') {
+ this.picker.on({
+ mouseenter: $.proxy(this.showTooltip, this),
+ mouseleave: $.proxy(this.hideTooltip, this)
+ });
+ } else {
+ this.tooltip.addClass('hide');
+ }
+ };
+
+ Slider.prototype = {
+ constructor: Slider,
+
+ over: false,
+ inDrag: false,
+
+ showTooltip: function(){
+ this.tooltip.addClass('in');
+ //var left = Math.round(this.percent*this.width);
+ //this.tooltip.css('left', left - this.tooltip.outerWidth()/2);
+ this.over = true;
+ },
+
+ hideTooltip: function(){
+ if (this.inDrag === false) {
+ this.tooltip.removeClass('in');
+ }
+ this.over = false;
+ },
+
+ layout: function(){
+ this.handle1Stype[this.stylePos] = this.percentage[0]+'%';
+ this.handle2Stype[this.stylePos] = this.percentage[1]+'%';
+ if (this.orientation == 'vertical') {
+ this.selectionElStyle.top = Math.min(this.percentage[0], this.percentage[1]) +'%';
+ this.selectionElStyle.height = Math.abs(this.percentage[0] - this.percentage[1]) +'%';
+ } else {
+ this.selectionElStyle.left = Math.min(this.percentage[0], this.percentage[1]) +'%';
+ this.selectionElStyle.width = Math.abs(this.percentage[0] - this.percentage[1]) +'%';
+ }
+ if (this.range) {
+ this.tooltipInner.text(
+ this.formater(this.value[0]) +
+ ' : ' +
+ this.formater(this.value[1])
+ );
+ this.tooltip[0].style[this.stylePos] = this.size * (this.percentage[0] + (this.percentage[1] - this.percentage[0])/2)/100 - (this.orientation === 'vertical' ? this.tooltip.outerHeight()/2 : this.tooltip.outerWidth()/2) +'px';
+ } else {
+ this.tooltipInner.text(
+ this.formater(this.value[0])
+ );
+ this.tooltip[0].style[this.stylePos] = this.size * this.percentage[0]/100 - (this.orientation === 'vertical' ? this.tooltip.outerHeight()/2 : this.tooltip.outerWidth()/2) +'px';
+ }
+ },
+
+ mousedown: function(ev) {
+
+ // Touch: Get the original event:
+ if (this.touchCapable && ev.type === 'touchstart') {
+ ev = ev.originalEvent;
+ }
+
+ this.offset = this.picker.offset();
+ this.size = this.picker[0][this.sizePos];
+
+ var percentage = this.getPercentage(ev);
+
+ if (this.range) {
+ var diff1 = Math.abs(this.percentage[0] - percentage);
+ var diff2 = Math.abs(this.percentage[1] - percentage);
+ this.dragged = (diff1 < diff2) ? 0 : 1;
+ } else {
+ this.dragged = 0;
+ }
+
+ this.percentage[this.dragged] = percentage;
+ this.layout();
+
+ if (this.touchCapable) {
+ // Touch: Bind touch events:
+ $(document).on({
+ touchmove: $.proxy(this.mousemove, this),
+ touchend: $.proxy(this.mouseup, this)
+ });
+ } else {
+ $(document).on({
+ mousemove: $.proxy(this.mousemove, this),
+ mouseup: $.proxy(this.mouseup, this)
+ });
+ }
+
+ this.inDrag = true;
+ var val = this.calculateValue();
+ this.element.trigger({
+ type: 'slideStart',
+ value: val
+ }).trigger({
+ type: 'slide',
+ value: val
+ });
+ return false;
+ },
+
+ mousemove: function(ev) {
+
+ // Touch: Get the original event:
+ if (this.touchCapable && ev.type === 'touchmove') {
+ ev = ev.originalEvent;
+ }
+
+ var percentage = this.getPercentage(ev);
+ if (this.range) {
+ if (this.dragged === 0 && this.percentage[1] < percentage) {
+ this.percentage[0] = this.percentage[1];
+ this.dragged = 1;
+ } else if (this.dragged === 1 && this.percentage[0] > percentage) {
+ this.percentage[1] = this.percentage[0];
+ this.dragged = 0;
+ }
+ }
+ this.percentage[this.dragged] = percentage;
+ this.layout();
+ var val = this.calculateValue();
+ this.element
+ .trigger({
+ type: 'slide',
+ value: val
+ })
+ .data('value', val)
+ .prop('value', val);
+ return false;
+ },
+
+ mouseup: function(ev) {
+ if (this.touchCapable) {
+ // Touch: Bind touch events:
+ $(document).off({
+ touchmove: this.mousemove,
+ touchend: this.mouseup
+ });
+ } else {
+ $(document).off({
+ mousemove: this.mousemove,
+ mouseup: this.mouseup
+ });
+ }
+
+ this.inDrag = false;
+ if (this.over == false) {
+ this.hideTooltip();
+ }
+ this.element;
+ var val = this.calculateValue();
+ this.element
+ .trigger({
+ type: 'slideStop',
+ value: val
+ })
+ .data('value', val)
+ .prop('value', val);
+ return false;
+ },
+
+ calculateValue: function() {
+ var val;
+ if (this.range) {
+ val = [
+ (this.min + Math.round((this.diff * this.percentage[0]/100)/this.step)*this.step),
+ (this.min + Math.round((this.diff * this.percentage[1]/100)/this.step)*this.step)
+ ];
+ this.value = val;
+ } else {
+ val = (this.min + Math.round((this.diff * this.percentage[0]/100)/this.step)*this.step);
+ this.value = [val, this.value[1]];
+ }
+ return val;
+ },
+
+ getPercentage: function(ev) {
+ if (this.touchCapable) {
+ ev = ev.touches[0];
+ }
+ var percentage = (ev[this.mousePos] - this.offset[this.stylePos])*100/this.size;
+ percentage = Math.round(percentage/this.percentage[2])*this.percentage[2];
+ return Math.max(0, Math.min(100, percentage));
+ },
+
+ getValue: function() {
+ if (this.range) {
+ return this.value;
+ }
+ return this.value[0];
+ },
+
+ setValue: function(val) {
+ this.value = val;
+
+ if (this.range) {
+ this.value[0] = Math.max(this.min, Math.min(this.max, this.value[0]));
+ this.value[1] = Math.max(this.min, Math.min(this.max, this.value[1]));
+ } else {
+ this.value = [ Math.max(this.min, Math.min(this.max, this.value))];
+ this.handle2.addClass('hide');
+ if (this.selection == 'after') {
+ this.value[1] = this.max;
+ } else {
+ this.value[1] = this.min;
+ }
+ }
+ this.diff = this.max - this.min;
+ this.percentage = [
+ (this.value[0]-this.min)*100/this.diff,
+ (this.value[1]-this.min)*100/this.diff,
+ this.step*100/this.diff
+ ];
+ this.layout();
+ }
+ };
+
+ $.fn.slider = function ( option, val ) {
+ return this.each(function () {
+ var $this = $(this),
+ data = $this.data('slider'),
+ options = typeof option === 'object' && option;
+ if (!data) {
+ $this.data('slider', (data = new Slider(this, $.extend({}, $.fn.slider.defaults,options))));
+ }
+ if (typeof option == 'string') {
+ data[option](val);
+ }
+ })
+ };
+
+ $.fn.slider.defaults = {
+ min: 0,
+ max: 10,
+ step: 1,
+ orientation: 'horizontal',
+ value: 5,
+ selection: 'before',
+ tooltip: 'show',
+ handle: 'round',
+ formater: function(value) {
+ return value;
+ }
+ };
+
+ $.fn.slider.Constructor = Slider;
+
}( window.jQuery );
\ No newline at end of file
diff --git a/webgoat-container/src/main/webapp/plugins/bootstrap-wysihtml5/css/bootstrap-wysihtml5.css b/webgoat-container/src/main/resources/static/plugins/bootstrap-wysihtml5/css/bootstrap-wysihtml5.css
similarity index 100%
rename from webgoat-container/src/main/webapp/plugins/bootstrap-wysihtml5/css/bootstrap-wysihtml5.css
rename to webgoat-container/src/main/resources/static/plugins/bootstrap-wysihtml5/css/bootstrap-wysihtml5.css
diff --git a/webgoat-container/src/main/webapp/plugins/bootstrap-wysihtml5/css/bootstrap3-wysiwyg5-color.css b/webgoat-container/src/main/resources/static/plugins/bootstrap-wysihtml5/css/bootstrap3-wysiwyg5-color.css
similarity index 100%
rename from webgoat-container/src/main/webapp/plugins/bootstrap-wysihtml5/css/bootstrap3-wysiwyg5-color.css
rename to webgoat-container/src/main/resources/static/plugins/bootstrap-wysihtml5/css/bootstrap3-wysiwyg5-color.css
diff --git a/webgoat-container/src/main/webapp/plugins/bootstrap-wysihtml5/js/bootstrap3-wysihtml5.js b/webgoat-container/src/main/resources/static/plugins/bootstrap-wysihtml5/js/bootstrap3-wysihtml5.js
similarity index 100%
rename from webgoat-container/src/main/webapp/plugins/bootstrap-wysihtml5/js/bootstrap3-wysihtml5.js
rename to webgoat-container/src/main/resources/static/plugins/bootstrap-wysihtml5/js/bootstrap3-wysihtml5.js
diff --git a/webgoat-container/src/main/webapp/plugins/bootstrap-wysihtml5/js/wysihtml5-0.3.0.js b/webgoat-container/src/main/resources/static/plugins/bootstrap-wysihtml5/js/wysihtml5-0.3.0.js
similarity index 97%
rename from webgoat-container/src/main/webapp/plugins/bootstrap-wysihtml5/js/wysihtml5-0.3.0.js
rename to webgoat-container/src/main/resources/static/plugins/bootstrap-wysihtml5/js/wysihtml5-0.3.0.js
index 7afa8f781..6bce5112a 100644
--- a/webgoat-container/src/main/webapp/plugins/bootstrap-wysihtml5/js/wysihtml5-0.3.0.js
+++ b/webgoat-container/src/main/resources/static/plugins/bootstrap-wysihtml5/js/wysihtml5-0.3.0.js
@@ -1,9523 +1,9523 @@
-/**
- * @license wysihtml5 v0.3.0
- * https://github.com/xing/wysihtml5
- *
- * Author: Christopher Blum (https://github.com/tiff)
- *
- * Copyright (C) 2012 XING AG
- * Licensed under the MIT license (MIT)
- *
- */
-var wysihtml5 = {
- version: "0.3.0",
-
- // namespaces
- commands: {},
- dom: {},
- quirks: {},
- toolbar: {},
- lang: {},
- selection: {},
- views: {},
-
- INVISIBLE_SPACE: "\uFEFF",
-
- EMPTY_FUNCTION: function() {},
-
- ELEMENT_NODE: 1,
- TEXT_NODE: 3,
-
- BACKSPACE_KEY: 8,
- ENTER_KEY: 13,
- ESCAPE_KEY: 27,
- SPACE_KEY: 32,
- DELETE_KEY: 46
-};/**
- * @license Rangy, a cross-browser JavaScript range and selection library
- * http://code.google.com/p/rangy/
- *
- * Copyright 2011, Tim Down
- * Licensed under the MIT license.
- * Version: 1.2.2
- * Build date: 13 November 2011
- */
-window['rangy'] = (function() {
-
-
- var OBJECT = "object", FUNCTION = "function", UNDEFINED = "undefined";
-
- var domRangeProperties = ["startContainer", "startOffset", "endContainer", "endOffset", "collapsed",
- "commonAncestorContainer", "START_TO_START", "START_TO_END", "END_TO_START", "END_TO_END"];
-
- var domRangeMethods = ["setStart", "setStartBefore", "setStartAfter", "setEnd", "setEndBefore",
- "setEndAfter", "collapse", "selectNode", "selectNodeContents", "compareBoundaryPoints", "deleteContents",
- "extractContents", "cloneContents", "insertNode", "surroundContents", "cloneRange", "toString", "detach"];
-
- var textRangeProperties = ["boundingHeight", "boundingLeft", "boundingTop", "boundingWidth", "htmlText", "text"];
-
- // Subset of TextRange's full set of methods that we're interested in
- var textRangeMethods = ["collapse", "compareEndPoints", "duplicate", "getBookmark", "moveToBookmark",
- "moveToElementText", "parentElement", "pasteHTML", "select", "setEndPoint", "getBoundingClientRect"];
-
- /*----------------------------------------------------------------------------------------------------------------*/
-
- // Trio of functions taken from Peter Michaux's article:
- // http://peter.michaux.ca/articles/feature-detection-state-of-the-art-browser-scripting
- function isHostMethod(o, p) {
- var t = typeof o[p];
- return t == FUNCTION || (!!(t == OBJECT && o[p])) || t == "unknown";
- }
-
- function isHostObject(o, p) {
- return !!(typeof o[p] == OBJECT && o[p]);
- }
-
- function isHostProperty(o, p) {
- return typeof o[p] != UNDEFINED;
- }
-
- // Creates a convenience function to save verbose repeated calls to tests functions
- function createMultiplePropertyTest(testFunc) {
- return function(o, props) {
- var i = props.length;
- while (i--) {
- if (!testFunc(o, props[i])) {
- return false;
- }
- }
- return true;
- };
- }
-
- // Next trio of functions are a convenience to save verbose repeated calls to previous two functions
- var areHostMethods = createMultiplePropertyTest(isHostMethod);
- var areHostObjects = createMultiplePropertyTest(isHostObject);
- var areHostProperties = createMultiplePropertyTest(isHostProperty);
-
- function isTextRange(range) {
- return range && areHostMethods(range, textRangeMethods) && areHostProperties(range, textRangeProperties);
- }
-
- var api = {
- version: "1.2.2",
- initialized: false,
- supported: true,
-
- util: {
- isHostMethod: isHostMethod,
- isHostObject: isHostObject,
- isHostProperty: isHostProperty,
- areHostMethods: areHostMethods,
- areHostObjects: areHostObjects,
- areHostProperties: areHostProperties,
- isTextRange: isTextRange
- },
-
- features: {},
-
- modules: {},
- config: {
- alertOnWarn: false,
- preferTextRange: false
- }
- };
-
- function fail(reason) {
- window.alert("Rangy not supported in your browser. Reason: " + reason);
- api.initialized = true;
- api.supported = false;
- }
-
- api.fail = fail;
-
- function warn(msg) {
- var warningMessage = "Rangy warning: " + msg;
- if (api.config.alertOnWarn) {
- window.alert(warningMessage);
- } else if (typeof window.console != UNDEFINED && typeof window.console.log != UNDEFINED) {
- window.console.log(warningMessage);
- }
- }
-
- api.warn = warn;
-
- if ({}.hasOwnProperty) {
- api.util.extend = function(o, props) {
- for (var i in props) {
- if (props.hasOwnProperty(i)) {
- o[i] = props[i];
- }
- }
- };
- } else {
- fail("hasOwnProperty not supported");
- }
-
- var initListeners = [];
- var moduleInitializers = [];
-
- // Initialization
- function init() {
- if (api.initialized) {
- return;
- }
- var testRange;
- var implementsDomRange = false, implementsTextRange = false;
-
- // First, perform basic feature tests
-
- if (isHostMethod(document, "createRange")) {
- testRange = document.createRange();
- if (areHostMethods(testRange, domRangeMethods) && areHostProperties(testRange, domRangeProperties)) {
- implementsDomRange = true;
- }
- testRange.detach();
- }
-
- var body = isHostObject(document, "body") ? document.body : document.getElementsByTagName("body")[0];
-
- if (body && isHostMethod(body, "createTextRange")) {
- testRange = body.createTextRange();
- if (isTextRange(testRange)) {
- implementsTextRange = true;
- }
- }
-
- if (!implementsDomRange && !implementsTextRange) {
- fail("Neither Range nor TextRange are implemented");
- }
-
- api.initialized = true;
- api.features = {
- implementsDomRange: implementsDomRange,
- implementsTextRange: implementsTextRange
- };
-
- // Initialize modules and call init listeners
- var allListeners = moduleInitializers.concat(initListeners);
- for (var i = 0, len = allListeners.length; i < len; ++i) {
- try {
- allListeners[i](api);
- } catch (ex) {
- if (isHostObject(window, "console") && isHostMethod(window.console, "log")) {
- window.console.log("Init listener threw an exception. Continuing.", ex);
- }
-
- }
- }
- }
-
- // Allow external scripts to initialize this library in case it's loaded after the document has loaded
- api.init = init;
-
- // Execute listener immediately if already initialized
- api.addInitListener = function(listener) {
- if (api.initialized) {
- listener(api);
- } else {
- initListeners.push(listener);
- }
- };
-
- var createMissingNativeApiListeners = [];
-
- api.addCreateMissingNativeApiListener = function(listener) {
- createMissingNativeApiListeners.push(listener);
- };
-
- function createMissingNativeApi(win) {
- win = win || window;
- init();
-
- // Notify listeners
- for (var i = 0, len = createMissingNativeApiListeners.length; i < len; ++i) {
- createMissingNativeApiListeners[i](win);
- }
- }
-
- api.createMissingNativeApi = createMissingNativeApi;
-
- /**
- * @constructor
- */
- function Module(name) {
- this.name = name;
- this.initialized = false;
- this.supported = false;
- }
-
- Module.prototype.fail = function(reason) {
- this.initialized = true;
- this.supported = false;
-
- throw new Error("Module '" + this.name + "' failed to load: " + reason);
- };
-
- Module.prototype.warn = function(msg) {
- api.warn("Module " + this.name + ": " + msg);
- };
-
- Module.prototype.createError = function(msg) {
- return new Error("Error in Rangy " + this.name + " module: " + msg);
- };
-
- api.createModule = function(name, initFunc) {
- var module = new Module(name);
- api.modules[name] = module;
-
- moduleInitializers.push(function(api) {
- initFunc(api, module);
- module.initialized = true;
- module.supported = true;
- });
- };
-
- api.requireModules = function(modules) {
- for (var i = 0, len = modules.length, module, moduleName; i < len; ++i) {
- moduleName = modules[i];
- module = api.modules[moduleName];
- if (!module || !(module instanceof Module)) {
- throw new Error("Module '" + moduleName + "' not found");
- }
- if (!module.supported) {
- throw new Error("Module '" + moduleName + "' not supported");
- }
- }
- };
-
- /*----------------------------------------------------------------------------------------------------------------*/
-
- // Wait for document to load before running tests
-
- var docReady = false;
-
- var loadHandler = function(e) {
-
- if (!docReady) {
- docReady = true;
- if (!api.initialized) {
- init();
- }
- }
- };
-
- // Test whether we have window and document objects that we will need
- if (typeof window == UNDEFINED) {
- fail("No window found");
- return;
- }
- if (typeof document == UNDEFINED) {
- fail("No document found");
- return;
- }
-
- if (isHostMethod(document, "addEventListener")) {
- document.addEventListener("DOMContentLoaded", loadHandler, false);
- }
-
- // Add a fallback in case the DOMContentLoaded event isn't supported
- if (isHostMethod(window, "addEventListener")) {
- window.addEventListener("load", loadHandler, false);
- } else if (isHostMethod(window, "attachEvent")) {
- window.attachEvent("onload", loadHandler);
- } else {
- fail("Window does not have required addEventListener or attachEvent method");
- }
-
- return api;
-})();
-rangy.createModule("DomUtil", function(api, module) {
-
- var UNDEF = "undefined";
- var util = api.util;
-
- // Perform feature tests
- if (!util.areHostMethods(document, ["createDocumentFragment", "createElement", "createTextNode"])) {
- module.fail("document missing a Node creation method");
- }
-
- if (!util.isHostMethod(document, "getElementsByTagName")) {
- module.fail("document missing getElementsByTagName method");
- }
-
- var el = document.createElement("div");
- if (!util.areHostMethods(el, ["insertBefore", "appendChild", "cloneNode"] ||
- !util.areHostObjects(el, ["previousSibling", "nextSibling", "childNodes", "parentNode"]))) {
- module.fail("Incomplete Element implementation");
- }
-
- // innerHTML is required for Range's createContextualFragment method
- if (!util.isHostProperty(el, "innerHTML")) {
- module.fail("Element is missing innerHTML property");
- }
-
- var textNode = document.createTextNode("test");
- if (!util.areHostMethods(textNode, ["splitText", "deleteData", "insertData", "appendData", "cloneNode"] ||
- !util.areHostObjects(el, ["previousSibling", "nextSibling", "childNodes", "parentNode"]) ||
- !util.areHostProperties(textNode, ["data"]))) {
- module.fail("Incomplete Text Node implementation");
- }
-
- /*----------------------------------------------------------------------------------------------------------------*/
-
- // Removed use of indexOf because of a bizarre bug in Opera that is thrown in one of the Acid3 tests. I haven't been
- // able to replicate it outside of the test. The bug is that indexOf returns -1 when called on an Array that
- // contains just the document as a single element and the value searched for is the document.
- var arrayContains = /*Array.prototype.indexOf ?
- function(arr, val) {
- return arr.indexOf(val) > -1;
- }:*/
-
- function(arr, val) {
- var i = arr.length;
- while (i--) {
- if (arr[i] === val) {
- return true;
- }
- }
- return false;
- };
-
- // Opera 11 puts HTML elements in the null namespace, it seems, and IE 7 has undefined namespaceURI
- function isHtmlNamespace(node) {
- var ns;
- return typeof node.namespaceURI == UNDEF || ((ns = node.namespaceURI) === null || ns == "http://www.w3.org/1999/xhtml");
- }
-
- function parentElement(node) {
- var parent = node.parentNode;
- return (parent.nodeType == 1) ? parent : null;
- }
-
- function getNodeIndex(node) {
- var i = 0;
- while( (node = node.previousSibling) ) {
- i++;
- }
- return i;
- }
-
- function getNodeLength(node) {
- var childNodes;
- return isCharacterDataNode(node) ? node.length : ((childNodes = node.childNodes) ? childNodes.length : 0);
- }
-
- function getCommonAncestor(node1, node2) {
- var ancestors = [], n;
- for (n = node1; n; n = n.parentNode) {
- ancestors.push(n);
- }
-
- for (n = node2; n; n = n.parentNode) {
- if (arrayContains(ancestors, n)) {
- return n;
- }
- }
-
- return null;
- }
-
- function isAncestorOf(ancestor, descendant, selfIsAncestor) {
- var n = selfIsAncestor ? descendant : descendant.parentNode;
- while (n) {
- if (n === ancestor) {
- return true;
- } else {
- n = n.parentNode;
- }
- }
- return false;
- }
-
- function getClosestAncestorIn(node, ancestor, selfIsAncestor) {
- var p, n = selfIsAncestor ? node : node.parentNode;
- while (n) {
- p = n.parentNode;
- if (p === ancestor) {
- return n;
- }
- n = p;
- }
- return null;
- }
-
- function isCharacterDataNode(node) {
- var t = node.nodeType;
- return t == 3 || t == 4 || t == 8 ; // Text, CDataSection or Comment
- }
-
- function insertAfter(node, precedingNode) {
- var nextNode = precedingNode.nextSibling, parent = precedingNode.parentNode;
- if (nextNode) {
- parent.insertBefore(node, nextNode);
- } else {
- parent.appendChild(node);
- }
- return node;
- }
-
- // Note that we cannot use splitText() because it is bugridden in IE 9.
- function splitDataNode(node, index) {
- var newNode = node.cloneNode(false);
- newNode.deleteData(0, index);
- node.deleteData(index, node.length - index);
- insertAfter(newNode, node);
- return newNode;
- }
-
- function getDocument(node) {
- if (node.nodeType == 9) {
- return node;
- } else if (typeof node.ownerDocument != UNDEF) {
- return node.ownerDocument;
- } else if (typeof node.document != UNDEF) {
- return node.document;
- } else if (node.parentNode) {
- return getDocument(node.parentNode);
- } else {
- throw new Error("getDocument: no document found for node");
- }
- }
-
- function getWindow(node) {
- var doc = getDocument(node);
- if (typeof doc.defaultView != UNDEF) {
- return doc.defaultView;
- } else if (typeof doc.parentWindow != UNDEF) {
- return doc.parentWindow;
- } else {
- throw new Error("Cannot get a window object for node");
- }
- }
-
- function getIframeDocument(iframeEl) {
- if (typeof iframeEl.contentDocument != UNDEF) {
- return iframeEl.contentDocument;
- } else if (typeof iframeEl.contentWindow != UNDEF) {
- return iframeEl.contentWindow.document;
- } else {
- throw new Error("getIframeWindow: No Document object found for iframe element");
- }
- }
-
- function getIframeWindow(iframeEl) {
- if (typeof iframeEl.contentWindow != UNDEF) {
- return iframeEl.contentWindow;
- } else if (typeof iframeEl.contentDocument != UNDEF) {
- return iframeEl.contentDocument.defaultView;
- } else {
- throw new Error("getIframeWindow: No Window object found for iframe element");
- }
- }
-
- function getBody(doc) {
- return util.isHostObject(doc, "body") ? doc.body : doc.getElementsByTagName("body")[0];
- }
-
- function getRootContainer(node) {
- var parent;
- while ( (parent = node.parentNode) ) {
- node = parent;
- }
- return node;
- }
-
- function comparePoints(nodeA, offsetA, nodeB, offsetB) {
- // See http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-Comparing
- var nodeC, root, childA, childB, n;
- if (nodeA == nodeB) {
-
- // Case 1: nodes are the same
- return offsetA === offsetB ? 0 : (offsetA < offsetB) ? -1 : 1;
- } else if ( (nodeC = getClosestAncestorIn(nodeB, nodeA, true)) ) {
-
- // Case 2: node C (container B or an ancestor) is a child node of A
- return offsetA <= getNodeIndex(nodeC) ? -1 : 1;
- } else if ( (nodeC = getClosestAncestorIn(nodeA, nodeB, true)) ) {
-
- // Case 3: node C (container A or an ancestor) is a child node of B
- return getNodeIndex(nodeC) < offsetB ? -1 : 1;
- } else {
-
- // Case 4: containers are siblings or descendants of siblings
- root = getCommonAncestor(nodeA, nodeB);
- childA = (nodeA === root) ? root : getClosestAncestorIn(nodeA, root, true);
- childB = (nodeB === root) ? root : getClosestAncestorIn(nodeB, root, true);
-
- if (childA === childB) {
- // This shouldn't be possible
-
- throw new Error("comparePoints got to case 4 and childA and childB are the same!");
- } else {
- n = root.firstChild;
- while (n) {
- if (n === childA) {
- return -1;
- } else if (n === childB) {
- return 1;
- }
- n = n.nextSibling;
- }
- throw new Error("Should not be here!");
- }
- }
- }
-
- function fragmentFromNodeChildren(node) {
- var fragment = getDocument(node).createDocumentFragment(), child;
- while ( (child = node.firstChild) ) {
- fragment.appendChild(child);
- }
- return fragment;
- }
-
- function inspectNode(node) {
- if (!node) {
- return "[No node]";
- }
- if (isCharacterDataNode(node)) {
- return '"' + node.data + '"';
- } else if (node.nodeType == 1) {
- var idAttr = node.id ? ' id="' + node.id + '"' : "";
- return "<" + node.nodeName + idAttr + ">[" + node.childNodes.length + "]";
- } else {
- return node.nodeName;
- }
- }
-
- /**
- * @constructor
- */
- function NodeIterator(root) {
- this.root = root;
- this._next = root;
- }
-
- NodeIterator.prototype = {
- _current: null,
-
- hasNext: function() {
- return !!this._next;
- },
-
- next: function() {
- var n = this._current = this._next;
- var child, next;
- if (this._current) {
- child = n.firstChild;
- if (child) {
- this._next = child;
- } else {
- next = null;
- while ((n !== this.root) && !(next = n.nextSibling)) {
- n = n.parentNode;
- }
- this._next = next;
- }
- }
- return this._current;
- },
-
- detach: function() {
- this._current = this._next = this.root = null;
- }
- };
-
- function createIterator(root) {
- return new NodeIterator(root);
- }
-
- /**
- * @constructor
- */
- function DomPosition(node, offset) {
- this.node = node;
- this.offset = offset;
- }
-
- DomPosition.prototype = {
- equals: function(pos) {
- return this.node === pos.node & this.offset == pos.offset;
- },
-
- inspect: function() {
- return "[DomPosition(" + inspectNode(this.node) + ":" + this.offset + ")]";
- }
- };
-
- /**
- * @constructor
- */
- function DOMException(codeName) {
- this.code = this[codeName];
- this.codeName = codeName;
- this.message = "DOMException: " + this.codeName;
- }
-
- DOMException.prototype = {
- INDEX_SIZE_ERR: 1,
- HIERARCHY_REQUEST_ERR: 3,
- WRONG_DOCUMENT_ERR: 4,
- NO_MODIFICATION_ALLOWED_ERR: 7,
- NOT_FOUND_ERR: 8,
- NOT_SUPPORTED_ERR: 9,
- INVALID_STATE_ERR: 11
- };
-
- DOMException.prototype.toString = function() {
- return this.message;
- };
-
- api.dom = {
- arrayContains: arrayContains,
- isHtmlNamespace: isHtmlNamespace,
- parentElement: parentElement,
- getNodeIndex: getNodeIndex,
- getNodeLength: getNodeLength,
- getCommonAncestor: getCommonAncestor,
- isAncestorOf: isAncestorOf,
- getClosestAncestorIn: getClosestAncestorIn,
- isCharacterDataNode: isCharacterDataNode,
- insertAfter: insertAfter,
- splitDataNode: splitDataNode,
- getDocument: getDocument,
- getWindow: getWindow,
- getIframeWindow: getIframeWindow,
- getIframeDocument: getIframeDocument,
- getBody: getBody,
- getRootContainer: getRootContainer,
- comparePoints: comparePoints,
- inspectNode: inspectNode,
- fragmentFromNodeChildren: fragmentFromNodeChildren,
- createIterator: createIterator,
- DomPosition: DomPosition
- };
-
- api.DOMException = DOMException;
-});rangy.createModule("DomRange", function(api, module) {
- api.requireModules( ["DomUtil"] );
-
-
- var dom = api.dom;
- var DomPosition = dom.DomPosition;
- var DOMException = api.DOMException;
-
- /*----------------------------------------------------------------------------------------------------------------*/
-
- // Utility functions
-
- function isNonTextPartiallySelected(node, range) {
- return (node.nodeType != 3) &&
- (dom.isAncestorOf(node, range.startContainer, true) || dom.isAncestorOf(node, range.endContainer, true));
- }
-
- function getRangeDocument(range) {
- return dom.getDocument(range.startContainer);
- }
-
- function dispatchEvent(range, type, args) {
- var listeners = range._listeners[type];
- if (listeners) {
- for (var i = 0, len = listeners.length; i < len; ++i) {
- listeners[i].call(range, {target: range, args: args});
- }
- }
- }
-
- function getBoundaryBeforeNode(node) {
- return new DomPosition(node.parentNode, dom.getNodeIndex(node));
- }
-
- function getBoundaryAfterNode(node) {
- return new DomPosition(node.parentNode, dom.getNodeIndex(node) + 1);
- }
-
- function insertNodeAtPosition(node, n, o) {
- var firstNodeInserted = node.nodeType == 11 ? node.firstChild : node;
- if (dom.isCharacterDataNode(n)) {
- if (o == n.length) {
- dom.insertAfter(node, n);
- } else {
- n.parentNode.insertBefore(node, o == 0 ? n : dom.splitDataNode(n, o));
- }
- } else if (o >= n.childNodes.length) {
- n.appendChild(node);
- } else {
- n.insertBefore(node, n.childNodes[o]);
- }
- return firstNodeInserted;
- }
-
- function cloneSubtree(iterator) {
- var partiallySelected;
- for (var node, frag = getRangeDocument(iterator.range).createDocumentFragment(), subIterator; node = iterator.next(); ) {
- partiallySelected = iterator.isPartiallySelectedSubtree();
-
- node = node.cloneNode(!partiallySelected);
- if (partiallySelected) {
- subIterator = iterator.getSubtreeIterator();
- node.appendChild(cloneSubtree(subIterator));
- subIterator.detach(true);
- }
-
- if (node.nodeType == 10) { // DocumentType
- throw new DOMException("HIERARCHY_REQUEST_ERR");
- }
- frag.appendChild(node);
- }
- return frag;
- }
-
- function iterateSubtree(rangeIterator, func, iteratorState) {
- var it, n;
- iteratorState = iteratorState || { stop: false };
- for (var node, subRangeIterator; node = rangeIterator.next(); ) {
- //log.debug("iterateSubtree, partially selected: " + rangeIterator.isPartiallySelectedSubtree(), nodeToString(node));
- if (rangeIterator.isPartiallySelectedSubtree()) {
- // The node is partially selected by the Range, so we can use a new RangeIterator on the portion of the
- // node selected by the Range.
- if (func(node) === false) {
- iteratorState.stop = true;
- return;
- } else {
- subRangeIterator = rangeIterator.getSubtreeIterator();
- iterateSubtree(subRangeIterator, func, iteratorState);
- subRangeIterator.detach(true);
- if (iteratorState.stop) {
- return;
- }
- }
- } else {
- // The whole node is selected, so we can use efficient DOM iteration to iterate over the node and its
- // descendant
- it = dom.createIterator(node);
- while ( (n = it.next()) ) {
- if (func(n) === false) {
- iteratorState.stop = true;
- return;
- }
- }
- }
- }
- }
-
- function deleteSubtree(iterator) {
- var subIterator;
- while (iterator.next()) {
- if (iterator.isPartiallySelectedSubtree()) {
- subIterator = iterator.getSubtreeIterator();
- deleteSubtree(subIterator);
- subIterator.detach(true);
- } else {
- iterator.remove();
- }
- }
- }
-
- function extractSubtree(iterator) {
-
- for (var node, frag = getRangeDocument(iterator.range).createDocumentFragment(), subIterator; node = iterator.next(); ) {
-
-
- if (iterator.isPartiallySelectedSubtree()) {
- node = node.cloneNode(false);
- subIterator = iterator.getSubtreeIterator();
- node.appendChild(extractSubtree(subIterator));
- subIterator.detach(true);
- } else {
- iterator.remove();
- }
- if (node.nodeType == 10) { // DocumentType
- throw new DOMException("HIERARCHY_REQUEST_ERR");
- }
- frag.appendChild(node);
- }
- return frag;
- }
-
- function getNodesInRange(range, nodeTypes, filter) {
- //log.info("getNodesInRange, " + nodeTypes.join(","));
- var filterNodeTypes = !!(nodeTypes && nodeTypes.length), regex;
- var filterExists = !!filter;
- if (filterNodeTypes) {
- regex = new RegExp("^(" + nodeTypes.join("|") + ")$");
- }
-
- var nodes = [];
- iterateSubtree(new RangeIterator(range, false), function(node) {
- if ((!filterNodeTypes || regex.test(node.nodeType)) && (!filterExists || filter(node))) {
- nodes.push(node);
- }
- });
- return nodes;
- }
-
- function inspect(range) {
- var name = (typeof range.getName == "undefined") ? "Range" : range.getName();
- return "[" + name + "(" + dom.inspectNode(range.startContainer) + ":" + range.startOffset + ", " +
- dom.inspectNode(range.endContainer) + ":" + range.endOffset + ")]";
- }
-
- /*----------------------------------------------------------------------------------------------------------------*/
-
- // RangeIterator code partially borrows from IERange by Tim Ryan (http://github.com/timcameronryan/IERange)
-
- /**
- * @constructor
- */
- function RangeIterator(range, clonePartiallySelectedTextNodes) {
- this.range = range;
- this.clonePartiallySelectedTextNodes = clonePartiallySelectedTextNodes;
-
-
-
- if (!range.collapsed) {
- this.sc = range.startContainer;
- this.so = range.startOffset;
- this.ec = range.endContainer;
- this.eo = range.endOffset;
- var root = range.commonAncestorContainer;
-
- if (this.sc === this.ec && dom.isCharacterDataNode(this.sc)) {
- this.isSingleCharacterDataNode = true;
- this._first = this._last = this._next = this.sc;
- } else {
- this._first = this._next = (this.sc === root && !dom.isCharacterDataNode(this.sc)) ?
- this.sc.childNodes[this.so] : dom.getClosestAncestorIn(this.sc, root, true);
- this._last = (this.ec === root && !dom.isCharacterDataNode(this.ec)) ?
- this.ec.childNodes[this.eo - 1] : dom.getClosestAncestorIn(this.ec, root, true);
- }
-
- }
- }
-
- RangeIterator.prototype = {
- _current: null,
- _next: null,
- _first: null,
- _last: null,
- isSingleCharacterDataNode: false,
-
- reset: function() {
- this._current = null;
- this._next = this._first;
- },
-
- hasNext: function() {
- return !!this._next;
- },
-
- next: function() {
- // Move to next node
- var current = this._current = this._next;
- if (current) {
- this._next = (current !== this._last) ? current.nextSibling : null;
-
- // Check for partially selected text nodes
- if (dom.isCharacterDataNode(current) && this.clonePartiallySelectedTextNodes) {
- if (current === this.ec) {
-
- (current = current.cloneNode(true)).deleteData(this.eo, current.length - this.eo);
- }
- if (this._current === this.sc) {
-
- (current = current.cloneNode(true)).deleteData(0, this.so);
- }
- }
- }
-
- return current;
- },
-
- remove: function() {
- var current = this._current, start, end;
-
- if (dom.isCharacterDataNode(current) && (current === this.sc || current === this.ec)) {
- start = (current === this.sc) ? this.so : 0;
- end = (current === this.ec) ? this.eo : current.length;
- if (start != end) {
- current.deleteData(start, end - start);
- }
- } else {
- if (current.parentNode) {
- current.parentNode.removeChild(current);
- } else {
-
- }
- }
- },
-
- // Checks if the current node is partially selected
- isPartiallySelectedSubtree: function() {
- var current = this._current;
- return isNonTextPartiallySelected(current, this.range);
- },
-
- getSubtreeIterator: function() {
- var subRange;
- if (this.isSingleCharacterDataNode) {
- subRange = this.range.cloneRange();
- subRange.collapse();
- } else {
- subRange = new Range(getRangeDocument(this.range));
- var current = this._current;
- var startContainer = current, startOffset = 0, endContainer = current, endOffset = dom.getNodeLength(current);
-
- if (dom.isAncestorOf(current, this.sc, true)) {
- startContainer = this.sc;
- startOffset = this.so;
- }
- if (dom.isAncestorOf(current, this.ec, true)) {
- endContainer = this.ec;
- endOffset = this.eo;
- }
-
- updateBoundaries(subRange, startContainer, startOffset, endContainer, endOffset);
- }
- return new RangeIterator(subRange, this.clonePartiallySelectedTextNodes);
- },
-
- detach: function(detachRange) {
- if (detachRange) {
- this.range.detach();
- }
- this.range = this._current = this._next = this._first = this._last = this.sc = this.so = this.ec = this.eo = null;
- }
- };
-
- /*----------------------------------------------------------------------------------------------------------------*/
-
- // Exceptions
-
- /**
- * @constructor
- */
- function RangeException(codeName) {
- this.code = this[codeName];
- this.codeName = codeName;
- this.message = "RangeException: " + this.codeName;
- }
-
- RangeException.prototype = {
- BAD_BOUNDARYPOINTS_ERR: 1,
- INVALID_NODE_TYPE_ERR: 2
- };
-
- RangeException.prototype.toString = function() {
- return this.message;
- };
-
- /*----------------------------------------------------------------------------------------------------------------*/
-
- /**
- * Currently iterates through all nodes in the range on creation until I think of a decent way to do it
- * TODO: Look into making this a proper iterator, not requiring preloading everything first
- * @constructor
- */
- function RangeNodeIterator(range, nodeTypes, filter) {
- this.nodes = getNodesInRange(range, nodeTypes, filter);
- this._next = this.nodes[0];
- this._position = 0;
- }
-
- RangeNodeIterator.prototype = {
- _current: null,
-
- hasNext: function() {
- return !!this._next;
- },
-
- next: function() {
- this._current = this._next;
- this._next = this.nodes[ ++this._position ];
- return this._current;
- },
-
- detach: function() {
- this._current = this._next = this.nodes = null;
- }
- };
-
- var beforeAfterNodeTypes = [1, 3, 4, 5, 7, 8, 10];
- var rootContainerNodeTypes = [2, 9, 11];
- var readonlyNodeTypes = [5, 6, 10, 12];
- var insertableNodeTypes = [1, 3, 4, 5, 7, 8, 10, 11];
- var surroundNodeTypes = [1, 3, 4, 5, 7, 8];
-
- function createAncestorFinder(nodeTypes) {
- return function(node, selfIsAncestor) {
- var t, n = selfIsAncestor ? node : node.parentNode;
- while (n) {
- t = n.nodeType;
- if (dom.arrayContains(nodeTypes, t)) {
- return n;
- }
- n = n.parentNode;
- }
- return null;
- };
- }
-
- var getRootContainer = dom.getRootContainer;
- var getDocumentOrFragmentContainer = createAncestorFinder( [9, 11] );
- var getReadonlyAncestor = createAncestorFinder(readonlyNodeTypes);
- var getDocTypeNotationEntityAncestor = createAncestorFinder( [6, 10, 12] );
-
- function assertNoDocTypeNotationEntityAncestor(node, allowSelf) {
- if (getDocTypeNotationEntityAncestor(node, allowSelf)) {
- throw new RangeException("INVALID_NODE_TYPE_ERR");
- }
- }
-
- function assertNotDetached(range) {
- if (!range.startContainer) {
- throw new DOMException("INVALID_STATE_ERR");
- }
- }
-
- function assertValidNodeType(node, invalidTypes) {
- if (!dom.arrayContains(invalidTypes, node.nodeType)) {
- throw new RangeException("INVALID_NODE_TYPE_ERR");
- }
- }
-
- function assertValidOffset(node, offset) {
- if (offset < 0 || offset > (dom.isCharacterDataNode(node) ? node.length : node.childNodes.length)) {
- throw new DOMException("INDEX_SIZE_ERR");
- }
- }
-
- function assertSameDocumentOrFragment(node1, node2) {
- if (getDocumentOrFragmentContainer(node1, true) !== getDocumentOrFragmentContainer(node2, true)) {
- throw new DOMException("WRONG_DOCUMENT_ERR");
- }
- }
-
- function assertNodeNotReadOnly(node) {
- if (getReadonlyAncestor(node, true)) {
- throw new DOMException("NO_MODIFICATION_ALLOWED_ERR");
- }
- }
-
- function assertNode(node, codeName) {
- if (!node) {
- throw new DOMException(codeName);
- }
- }
-
- function isOrphan(node) {
- return !dom.arrayContains(rootContainerNodeTypes, node.nodeType) && !getDocumentOrFragmentContainer(node, true);
- }
-
- function isValidOffset(node, offset) {
- return offset <= (dom.isCharacterDataNode(node) ? node.length : node.childNodes.length);
- }
-
- function assertRangeValid(range) {
- assertNotDetached(range);
- if (isOrphan(range.startContainer) || isOrphan(range.endContainer) ||
- !isValidOffset(range.startContainer, range.startOffset) ||
- !isValidOffset(range.endContainer, range.endOffset)) {
- throw new Error("Range error: Range is no longer valid after DOM mutation (" + range.inspect() + ")");
- }
- }
-
- /*----------------------------------------------------------------------------------------------------------------*/
-
- // Test the browser's innerHTML support to decide how to implement createContextualFragment
- var styleEl = document.createElement("style");
- var htmlParsingConforms = false;
- try {
- styleEl.innerHTML = "x ";
- htmlParsingConforms = (styleEl.firstChild.nodeType == 3); // Opera incorrectly creates an element node
- } catch (e) {
- // IE 6 and 7 throw
- }
-
- api.features.htmlParsingConforms = htmlParsingConforms;
-
- var createContextualFragment = htmlParsingConforms ?
-
- // Implementation as per HTML parsing spec, trusting in the browser's implementation of innerHTML. See
- // discussion and base code for this implementation at issue 67.
- // Spec: http://html5.org/specs/dom-parsing.html#extensions-to-the-range-interface
- // Thanks to Aleks Williams.
- function(fragmentStr) {
- // "Let node the context object's start's node."
- var node = this.startContainer;
- var doc = dom.getDocument(node);
-
- // "If the context object's start's node is null, raise an INVALID_STATE_ERR
- // exception and abort these steps."
- if (!node) {
- throw new DOMException("INVALID_STATE_ERR");
- }
-
- // "Let element be as follows, depending on node's interface:"
- // Document, Document Fragment: null
- var el = null;
-
- // "Element: node"
- if (node.nodeType == 1) {
- el = node;
-
- // "Text, Comment: node's parentElement"
- } else if (dom.isCharacterDataNode(node)) {
- el = dom.parentElement(node);
- }
-
- // "If either element is null or element's ownerDocument is an HTML document
- // and element's local name is "html" and element's namespace is the HTML
- // namespace"
- if (el === null || (
- el.nodeName == "HTML"
- && dom.isHtmlNamespace(dom.getDocument(el).documentElement)
- && dom.isHtmlNamespace(el)
- )) {
-
- // "let element be a new Element with "body" as its local name and the HTML
- // namespace as its namespace.""
- el = doc.createElement("body");
- } else {
- el = el.cloneNode(false);
- }
-
- // "If the node's document is an HTML document: Invoke the HTML fragment parsing algorithm."
- // "If the node's document is an XML document: Invoke the XML fragment parsing algorithm."
- // "In either case, the algorithm must be invoked with fragment as the input
- // and element as the context element."
- el.innerHTML = fragmentStr;
-
- // "If this raises an exception, then abort these steps. Otherwise, let new
- // children be the nodes returned."
-
- // "Let fragment be a new DocumentFragment."
- // "Append all new children to fragment."
- // "Return fragment."
- return dom.fragmentFromNodeChildren(el);
- } :
-
- // In this case, innerHTML cannot be trusted, so fall back to a simpler, non-conformant implementation that
- // previous versions of Rangy used (with the exception of using a body element rather than a div)
- function(fragmentStr) {
- assertNotDetached(this);
- var doc = getRangeDocument(this);
- var el = doc.createElement("body");
- el.innerHTML = fragmentStr;
-
- return dom.fragmentFromNodeChildren(el);
- };
-
- /*----------------------------------------------------------------------------------------------------------------*/
-
- var rangeProperties = ["startContainer", "startOffset", "endContainer", "endOffset", "collapsed",
- "commonAncestorContainer"];
-
- var s2s = 0, s2e = 1, e2e = 2, e2s = 3;
- var n_b = 0, n_a = 1, n_b_a = 2, n_i = 3;
-
- function RangePrototype() {}
-
- RangePrototype.prototype = {
- attachListener: function(type, listener) {
- this._listeners[type].push(listener);
- },
-
- compareBoundaryPoints: function(how, range) {
- assertRangeValid(this);
- assertSameDocumentOrFragment(this.startContainer, range.startContainer);
-
- var nodeA, offsetA, nodeB, offsetB;
- var prefixA = (how == e2s || how == s2s) ? "start" : "end";
- var prefixB = (how == s2e || how == s2s) ? "start" : "end";
- nodeA = this[prefixA + "Container"];
- offsetA = this[prefixA + "Offset"];
- nodeB = range[prefixB + "Container"];
- offsetB = range[prefixB + "Offset"];
- return dom.comparePoints(nodeA, offsetA, nodeB, offsetB);
- },
-
- insertNode: function(node) {
- assertRangeValid(this);
- assertValidNodeType(node, insertableNodeTypes);
- assertNodeNotReadOnly(this.startContainer);
-
- if (dom.isAncestorOf(node, this.startContainer, true)) {
- throw new DOMException("HIERARCHY_REQUEST_ERR");
- }
-
- // No check for whether the container of the start of the Range is of a type that does not allow
- // children of the type of node: the browser's DOM implementation should do this for us when we attempt
- // to add the node
-
- var firstNodeInserted = insertNodeAtPosition(node, this.startContainer, this.startOffset);
- this.setStartBefore(firstNodeInserted);
- },
-
- cloneContents: function() {
- assertRangeValid(this);
-
- var clone, frag;
- if (this.collapsed) {
- return getRangeDocument(this).createDocumentFragment();
- } else {
- if (this.startContainer === this.endContainer && dom.isCharacterDataNode(this.startContainer)) {
- clone = this.startContainer.cloneNode(true);
- clone.data = clone.data.slice(this.startOffset, this.endOffset);
- frag = getRangeDocument(this).createDocumentFragment();
- frag.appendChild(clone);
- return frag;
- } else {
- var iterator = new RangeIterator(this, true);
- clone = cloneSubtree(iterator);
- iterator.detach();
- }
- return clone;
- }
- },
-
- canSurroundContents: function() {
- assertRangeValid(this);
- assertNodeNotReadOnly(this.startContainer);
- assertNodeNotReadOnly(this.endContainer);
-
- // Check if the contents can be surrounded. Specifically, this means whether the range partially selects
- // no non-text nodes.
- var iterator = new RangeIterator(this, true);
- var boundariesInvalid = (iterator._first && (isNonTextPartiallySelected(iterator._first, this)) ||
- (iterator._last && isNonTextPartiallySelected(iterator._last, this)));
- iterator.detach();
- return !boundariesInvalid;
- },
-
- surroundContents: function(node) {
- assertValidNodeType(node, surroundNodeTypes);
-
- if (!this.canSurroundContents()) {
- throw new RangeException("BAD_BOUNDARYPOINTS_ERR");
- }
-
- // Extract the contents
- var content = this.extractContents();
-
- // Clear the children of the node
- if (node.hasChildNodes()) {
- while (node.lastChild) {
- node.removeChild(node.lastChild);
- }
- }
-
- // Insert the new node and add the extracted contents
- insertNodeAtPosition(node, this.startContainer, this.startOffset);
- node.appendChild(content);
-
- this.selectNode(node);
- },
-
- cloneRange: function() {
- assertRangeValid(this);
- var range = new Range(getRangeDocument(this));
- var i = rangeProperties.length, prop;
- while (i--) {
- prop = rangeProperties[i];
- range[prop] = this[prop];
- }
- return range;
- },
-
- toString: function() {
- assertRangeValid(this);
- var sc = this.startContainer;
- if (sc === this.endContainer && dom.isCharacterDataNode(sc)) {
- return (sc.nodeType == 3 || sc.nodeType == 4) ? sc.data.slice(this.startOffset, this.endOffset) : "";
- } else {
- var textBits = [], iterator = new RangeIterator(this, true);
-
- iterateSubtree(iterator, function(node) {
- // Accept only text or CDATA nodes, not comments
-
- if (node.nodeType == 3 || node.nodeType == 4) {
- textBits.push(node.data);
- }
- });
- iterator.detach();
- return textBits.join("");
- }
- },
-
- // The methods below are all non-standard. The following batch were introduced by Mozilla but have since
- // been removed from Mozilla.
-
- compareNode: function(node) {
- assertRangeValid(this);
-
- var parent = node.parentNode;
- var nodeIndex = dom.getNodeIndex(node);
-
- if (!parent) {
- throw new DOMException("NOT_FOUND_ERR");
- }
-
- var startComparison = this.comparePoint(parent, nodeIndex),
- endComparison = this.comparePoint(parent, nodeIndex + 1);
-
- if (startComparison < 0) { // Node starts before
- return (endComparison > 0) ? n_b_a : n_b;
- } else {
- return (endComparison > 0) ? n_a : n_i;
- }
- },
-
- comparePoint: function(node, offset) {
- assertRangeValid(this);
- assertNode(node, "HIERARCHY_REQUEST_ERR");
- assertSameDocumentOrFragment(node, this.startContainer);
-
- if (dom.comparePoints(node, offset, this.startContainer, this.startOffset) < 0) {
- return -1;
- } else if (dom.comparePoints(node, offset, this.endContainer, this.endOffset) > 0) {
- return 1;
- }
- return 0;
- },
-
- createContextualFragment: createContextualFragment,
-
- toHtml: function() {
- assertRangeValid(this);
- var container = getRangeDocument(this).createElement("div");
- container.appendChild(this.cloneContents());
- return container.innerHTML;
- },
-
- // touchingIsIntersecting determines whether this method considers a node that borders a range intersects
- // with it (as in WebKit) or not (as in Gecko pre-1.9, and the default)
- intersectsNode: function(node, touchingIsIntersecting) {
- assertRangeValid(this);
- assertNode(node, "NOT_FOUND_ERR");
- if (dom.getDocument(node) !== getRangeDocument(this)) {
- return false;
- }
-
- var parent = node.parentNode, offset = dom.getNodeIndex(node);
- assertNode(parent, "NOT_FOUND_ERR");
-
- var startComparison = dom.comparePoints(parent, offset, this.endContainer, this.endOffset),
- endComparison = dom.comparePoints(parent, offset + 1, this.startContainer, this.startOffset);
-
- return touchingIsIntersecting ? startComparison <= 0 && endComparison >= 0 : startComparison < 0 && endComparison > 0;
- },
-
-
- isPointInRange: function(node, offset) {
- assertRangeValid(this);
- assertNode(node, "HIERARCHY_REQUEST_ERR");
- assertSameDocumentOrFragment(node, this.startContainer);
-
- return (dom.comparePoints(node, offset, this.startContainer, this.startOffset) >= 0) &&
- (dom.comparePoints(node, offset, this.endContainer, this.endOffset) <= 0);
- },
-
- // The methods below are non-standard and invented by me.
-
- // Sharing a boundary start-to-end or end-to-start does not count as intersection.
- intersectsRange: function(range, touchingIsIntersecting) {
- assertRangeValid(this);
-
- if (getRangeDocument(range) != getRangeDocument(this)) {
- throw new DOMException("WRONG_DOCUMENT_ERR");
- }
-
- var startComparison = dom.comparePoints(this.startContainer, this.startOffset, range.endContainer, range.endOffset),
- endComparison = dom.comparePoints(this.endContainer, this.endOffset, range.startContainer, range.startOffset);
-
- return touchingIsIntersecting ? startComparison <= 0 && endComparison >= 0 : startComparison < 0 && endComparison > 0;
- },
-
- intersection: function(range) {
- if (this.intersectsRange(range)) {
- var startComparison = dom.comparePoints(this.startContainer, this.startOffset, range.startContainer, range.startOffset),
- endComparison = dom.comparePoints(this.endContainer, this.endOffset, range.endContainer, range.endOffset);
-
- var intersectionRange = this.cloneRange();
-
- if (startComparison == -1) {
- intersectionRange.setStart(range.startContainer, range.startOffset);
- }
- if (endComparison == 1) {
- intersectionRange.setEnd(range.endContainer, range.endOffset);
- }
- return intersectionRange;
- }
- return null;
- },
-
- union: function(range) {
- if (this.intersectsRange(range, true)) {
- var unionRange = this.cloneRange();
- if (dom.comparePoints(range.startContainer, range.startOffset, this.startContainer, this.startOffset) == -1) {
- unionRange.setStart(range.startContainer, range.startOffset);
- }
- if (dom.comparePoints(range.endContainer, range.endOffset, this.endContainer, this.endOffset) == 1) {
- unionRange.setEnd(range.endContainer, range.endOffset);
- }
- return unionRange;
- } else {
- throw new RangeException("Ranges do not intersect");
- }
- },
-
- containsNode: function(node, allowPartial) {
- if (allowPartial) {
- return this.intersectsNode(node, false);
- } else {
- return this.compareNode(node) == n_i;
- }
- },
-
- containsNodeContents: function(node) {
- return this.comparePoint(node, 0) >= 0 && this.comparePoint(node, dom.getNodeLength(node)) <= 0;
- },
-
- containsRange: function(range) {
- return this.intersection(range).equals(range);
- },
-
- containsNodeText: function(node) {
- var nodeRange = this.cloneRange();
- nodeRange.selectNode(node);
- var textNodes = nodeRange.getNodes([3]);
- if (textNodes.length > 0) {
- nodeRange.setStart(textNodes[0], 0);
- var lastTextNode = textNodes.pop();
- nodeRange.setEnd(lastTextNode, lastTextNode.length);
- var contains = this.containsRange(nodeRange);
- nodeRange.detach();
- return contains;
- } else {
- return this.containsNodeContents(node);
- }
- },
-
- createNodeIterator: function(nodeTypes, filter) {
- assertRangeValid(this);
- return new RangeNodeIterator(this, nodeTypes, filter);
- },
-
- getNodes: function(nodeTypes, filter) {
- assertRangeValid(this);
- return getNodesInRange(this, nodeTypes, filter);
- },
-
- getDocument: function() {
- return getRangeDocument(this);
- },
-
- collapseBefore: function(node) {
- assertNotDetached(this);
-
- this.setEndBefore(node);
- this.collapse(false);
- },
-
- collapseAfter: function(node) {
- assertNotDetached(this);
-
- this.setStartAfter(node);
- this.collapse(true);
- },
-
- getName: function() {
- return "DomRange";
- },
-
- equals: function(range) {
- return Range.rangesEqual(this, range);
- },
-
- inspect: function() {
- return inspect(this);
- }
- };
-
- function copyComparisonConstantsToObject(obj) {
- obj.START_TO_START = s2s;
- obj.START_TO_END = s2e;
- obj.END_TO_END = e2e;
- obj.END_TO_START = e2s;
-
- obj.NODE_BEFORE = n_b;
- obj.NODE_AFTER = n_a;
- obj.NODE_BEFORE_AND_AFTER = n_b_a;
- obj.NODE_INSIDE = n_i;
- }
-
- function copyComparisonConstants(constructor) {
- copyComparisonConstantsToObject(constructor);
- copyComparisonConstantsToObject(constructor.prototype);
- }
-
- function createRangeContentRemover(remover, boundaryUpdater) {
- return function() {
- assertRangeValid(this);
-
- var sc = this.startContainer, so = this.startOffset, root = this.commonAncestorContainer;
-
- var iterator = new RangeIterator(this, true);
-
- // Work out where to position the range after content removal
- var node, boundary;
- if (sc !== root) {
- node = dom.getClosestAncestorIn(sc, root, true);
- boundary = getBoundaryAfterNode(node);
- sc = boundary.node;
- so = boundary.offset;
- }
-
- // Check none of the range is read-only
- iterateSubtree(iterator, assertNodeNotReadOnly);
-
- iterator.reset();
-
- // Remove the content
- var returnValue = remover(iterator);
- iterator.detach();
-
- // Move to the new position
- boundaryUpdater(this, sc, so, sc, so);
-
- return returnValue;
- };
- }
-
- function createPrototypeRange(constructor, boundaryUpdater, detacher) {
- function createBeforeAfterNodeSetter(isBefore, isStart) {
- return function(node) {
- assertNotDetached(this);
- assertValidNodeType(node, beforeAfterNodeTypes);
- assertValidNodeType(getRootContainer(node), rootContainerNodeTypes);
-
- var boundary = (isBefore ? getBoundaryBeforeNode : getBoundaryAfterNode)(node);
- (isStart ? setRangeStart : setRangeEnd)(this, boundary.node, boundary.offset);
- };
- }
-
- function setRangeStart(range, node, offset) {
- var ec = range.endContainer, eo = range.endOffset;
- if (node !== range.startContainer || offset !== range.startOffset) {
- // Check the root containers of the range and the new boundary, and also check whether the new boundary
- // is after the current end. In either case, collapse the range to the new position
- if (getRootContainer(node) != getRootContainer(ec) || dom.comparePoints(node, offset, ec, eo) == 1) {
- ec = node;
- eo = offset;
- }
- boundaryUpdater(range, node, offset, ec, eo);
- }
- }
-
- function setRangeEnd(range, node, offset) {
- var sc = range.startContainer, so = range.startOffset;
- if (node !== range.endContainer || offset !== range.endOffset) {
- // Check the root containers of the range and the new boundary, and also check whether the new boundary
- // is after the current end. In either case, collapse the range to the new position
- if (getRootContainer(node) != getRootContainer(sc) || dom.comparePoints(node, offset, sc, so) == -1) {
- sc = node;
- so = offset;
- }
- boundaryUpdater(range, sc, so, node, offset);
- }
- }
-
- function setRangeStartAndEnd(range, node, offset) {
- if (node !== range.startContainer || offset !== range.startOffset || node !== range.endContainer || offset !== range.endOffset) {
- boundaryUpdater(range, node, offset, node, offset);
- }
- }
-
- constructor.prototype = new RangePrototype();
-
- api.util.extend(constructor.prototype, {
- setStart: function(node, offset) {
- assertNotDetached(this);
- assertNoDocTypeNotationEntityAncestor(node, true);
- assertValidOffset(node, offset);
-
- setRangeStart(this, node, offset);
- },
-
- setEnd: function(node, offset) {
- assertNotDetached(this);
- assertNoDocTypeNotationEntityAncestor(node, true);
- assertValidOffset(node, offset);
-
- setRangeEnd(this, node, offset);
- },
-
- setStartBefore: createBeforeAfterNodeSetter(true, true),
- setStartAfter: createBeforeAfterNodeSetter(false, true),
- setEndBefore: createBeforeAfterNodeSetter(true, false),
- setEndAfter: createBeforeAfterNodeSetter(false, false),
-
- collapse: function(isStart) {
- assertRangeValid(this);
- if (isStart) {
- boundaryUpdater(this, this.startContainer, this.startOffset, this.startContainer, this.startOffset);
- } else {
- boundaryUpdater(this, this.endContainer, this.endOffset, this.endContainer, this.endOffset);
- }
- },
-
- selectNodeContents: function(node) {
- // This doesn't seem well specified: the spec talks only about selecting the node's contents, which
- // could be taken to mean only its children. However, browsers implement this the same as selectNode for
- // text nodes, so I shall do likewise
- assertNotDetached(this);
- assertNoDocTypeNotationEntityAncestor(node, true);
-
- boundaryUpdater(this, node, 0, node, dom.getNodeLength(node));
- },
-
- selectNode: function(node) {
- assertNotDetached(this);
- assertNoDocTypeNotationEntityAncestor(node, false);
- assertValidNodeType(node, beforeAfterNodeTypes);
-
- var start = getBoundaryBeforeNode(node), end = getBoundaryAfterNode(node);
- boundaryUpdater(this, start.node, start.offset, end.node, end.offset);
- },
-
- extractContents: createRangeContentRemover(extractSubtree, boundaryUpdater),
-
- deleteContents: createRangeContentRemover(deleteSubtree, boundaryUpdater),
-
- canSurroundContents: function() {
- assertRangeValid(this);
- assertNodeNotReadOnly(this.startContainer);
- assertNodeNotReadOnly(this.endContainer);
-
- // Check if the contents can be surrounded. Specifically, this means whether the range partially selects
- // no non-text nodes.
- var iterator = new RangeIterator(this, true);
- var boundariesInvalid = (iterator._first && (isNonTextPartiallySelected(iterator._first, this)) ||
- (iterator._last && isNonTextPartiallySelected(iterator._last, this)));
- iterator.detach();
- return !boundariesInvalid;
- },
-
- detach: function() {
- detacher(this);
- },
-
- splitBoundaries: function() {
- assertRangeValid(this);
-
-
- var sc = this.startContainer, so = this.startOffset, ec = this.endContainer, eo = this.endOffset;
- var startEndSame = (sc === ec);
-
- if (dom.isCharacterDataNode(ec) && eo > 0 && eo < ec.length) {
- dom.splitDataNode(ec, eo);
-
- }
-
- if (dom.isCharacterDataNode(sc) && so > 0 && so < sc.length) {
-
- sc = dom.splitDataNode(sc, so);
- if (startEndSame) {
- eo -= so;
- ec = sc;
- } else if (ec == sc.parentNode && eo >= dom.getNodeIndex(sc)) {
- eo++;
- }
- so = 0;
-
- }
- boundaryUpdater(this, sc, so, ec, eo);
- },
-
- normalizeBoundaries: function() {
- assertRangeValid(this);
-
- var sc = this.startContainer, so = this.startOffset, ec = this.endContainer, eo = this.endOffset;
-
- var mergeForward = function(node) {
- var sibling = node.nextSibling;
- if (sibling && sibling.nodeType == node.nodeType) {
- ec = node;
- eo = node.length;
- node.appendData(sibling.data);
- sibling.parentNode.removeChild(sibling);
- }
- };
-
- var mergeBackward = function(node) {
- var sibling = node.previousSibling;
- if (sibling && sibling.nodeType == node.nodeType) {
- sc = node;
- var nodeLength = node.length;
- so = sibling.length;
- node.insertData(0, sibling.data);
- sibling.parentNode.removeChild(sibling);
- if (sc == ec) {
- eo += so;
- ec = sc;
- } else if (ec == node.parentNode) {
- var nodeIndex = dom.getNodeIndex(node);
- if (eo == nodeIndex) {
- ec = node;
- eo = nodeLength;
- } else if (eo > nodeIndex) {
- eo--;
- }
- }
- }
- };
-
- var normalizeStart = true;
-
- if (dom.isCharacterDataNode(ec)) {
- if (ec.length == eo) {
- mergeForward(ec);
- }
- } else {
- if (eo > 0) {
- var endNode = ec.childNodes[eo - 1];
- if (endNode && dom.isCharacterDataNode(endNode)) {
- mergeForward(endNode);
- }
- }
- normalizeStart = !this.collapsed;
- }
-
- if (normalizeStart) {
- if (dom.isCharacterDataNode(sc)) {
- if (so == 0) {
- mergeBackward(sc);
- }
- } else {
- if (so < sc.childNodes.length) {
- var startNode = sc.childNodes[so];
- if (startNode && dom.isCharacterDataNode(startNode)) {
- mergeBackward(startNode);
- }
- }
- }
- } else {
- sc = ec;
- so = eo;
- }
-
- boundaryUpdater(this, sc, so, ec, eo);
- },
-
- collapseToPoint: function(node, offset) {
- assertNotDetached(this);
-
- assertNoDocTypeNotationEntityAncestor(node, true);
- assertValidOffset(node, offset);
-
- setRangeStartAndEnd(this, node, offset);
- }
- });
-
- copyComparisonConstants(constructor);
- }
-
- /*----------------------------------------------------------------------------------------------------------------*/
-
- // Updates commonAncestorContainer and collapsed after boundary change
- function updateCollapsedAndCommonAncestor(range) {
- range.collapsed = (range.startContainer === range.endContainer && range.startOffset === range.endOffset);
- range.commonAncestorContainer = range.collapsed ?
- range.startContainer : dom.getCommonAncestor(range.startContainer, range.endContainer);
- }
-
- function updateBoundaries(range, startContainer, startOffset, endContainer, endOffset) {
- var startMoved = (range.startContainer !== startContainer || range.startOffset !== startOffset);
- var endMoved = (range.endContainer !== endContainer || range.endOffset !== endOffset);
-
- range.startContainer = startContainer;
- range.startOffset = startOffset;
- range.endContainer = endContainer;
- range.endOffset = endOffset;
-
- updateCollapsedAndCommonAncestor(range);
- dispatchEvent(range, "boundarychange", {startMoved: startMoved, endMoved: endMoved});
- }
-
- function detach(range) {
- assertNotDetached(range);
- range.startContainer = range.startOffset = range.endContainer = range.endOffset = null;
- range.collapsed = range.commonAncestorContainer = null;
- dispatchEvent(range, "detach", null);
- range._listeners = null;
- }
-
- /**
- * @constructor
- */
- function Range(doc) {
- this.startContainer = doc;
- this.startOffset = 0;
- this.endContainer = doc;
- this.endOffset = 0;
- this._listeners = {
- boundarychange: [],
- detach: []
- };
- updateCollapsedAndCommonAncestor(this);
- }
-
- createPrototypeRange(Range, updateBoundaries, detach);
-
- api.rangePrototype = RangePrototype.prototype;
-
- Range.rangeProperties = rangeProperties;
- Range.RangeIterator = RangeIterator;
- Range.copyComparisonConstants = copyComparisonConstants;
- Range.createPrototypeRange = createPrototypeRange;
- Range.inspect = inspect;
- Range.getRangeDocument = getRangeDocument;
- Range.rangesEqual = function(r1, r2) {
- return r1.startContainer === r2.startContainer &&
- r1.startOffset === r2.startOffset &&
- r1.endContainer === r2.endContainer &&
- r1.endOffset === r2.endOffset;
- };
-
- api.DomRange = Range;
- api.RangeException = RangeException;
-});rangy.createModule("WrappedRange", function(api, module) {
- api.requireModules( ["DomUtil", "DomRange"] );
-
- /**
- * @constructor
- */
- var WrappedRange;
- var dom = api.dom;
- var DomPosition = dom.DomPosition;
- var DomRange = api.DomRange;
-
-
-
- /*----------------------------------------------------------------------------------------------------------------*/
-
- /*
- This is a workaround for a bug where IE returns the wrong container element from the TextRange's parentElement()
- method. For example, in the following (where pipes denote the selection boundaries):
-
-
-
- var range = document.selection.createRange();
- alert(range.parentElement().id); // Should alert "ul" but alerts "b"
-
- This method returns the common ancestor node of the following:
- - the parentElement() of the textRange
- - the parentElement() of the textRange after calling collapse(true)
- - the parentElement() of the textRange after calling collapse(false)
- */
- function getTextRangeContainerElement(textRange) {
- var parentEl = textRange.parentElement();
-
- var range = textRange.duplicate();
- range.collapse(true);
- var startEl = range.parentElement();
- range = textRange.duplicate();
- range.collapse(false);
- var endEl = range.parentElement();
- var startEndContainer = (startEl == endEl) ? startEl : dom.getCommonAncestor(startEl, endEl);
-
- return startEndContainer == parentEl ? startEndContainer : dom.getCommonAncestor(parentEl, startEndContainer);
- }
-
- function textRangeIsCollapsed(textRange) {
- return textRange.compareEndPoints("StartToEnd", textRange) == 0;
- }
-
- // Gets the boundary of a TextRange expressed as a node and an offset within that node. This function started out as
- // an improved version of code found in Tim Cameron Ryan's IERange (http://code.google.com/p/ierange/) but has
- // grown, fixing problems with line breaks in preformatted text, adding workaround for IE TextRange bugs, handling
- // for inputs and images, plus optimizations.
- function getTextRangeBoundaryPosition(textRange, wholeRangeContainerElement, isStart, isCollapsed) {
- var workingRange = textRange.duplicate();
-
- workingRange.collapse(isStart);
- var containerElement = workingRange.parentElement();
-
- // Sometimes collapsing a TextRange that's at the start of a text node can move it into the previous node, so
- // check for that
- // TODO: Find out when. Workaround for wholeRangeContainerElement may break this
- if (!dom.isAncestorOf(wholeRangeContainerElement, containerElement, true)) {
- containerElement = wholeRangeContainerElement;
-
- }
-
-
-
- // Deal with nodes that cannot "contain rich HTML markup". In practice, this means form inputs, images and
- // similar. See http://msdn.microsoft.com/en-us/library/aa703950%28VS.85%29.aspx
- if (!containerElement.canHaveHTML) {
- return new DomPosition(containerElement.parentNode, dom.getNodeIndex(containerElement));
- }
-
- var workingNode = dom.getDocument(containerElement).createElement("span");
- var comparison, workingComparisonType = isStart ? "StartToStart" : "StartToEnd";
- var previousNode, nextNode, boundaryPosition, boundaryNode;
-
- // Move the working range through the container's children, starting at the end and working backwards, until the
- // working range reaches or goes past the boundary we're interested in
- do {
- containerElement.insertBefore(workingNode, workingNode.previousSibling);
- workingRange.moveToElementText(workingNode);
- } while ( (comparison = workingRange.compareEndPoints(workingComparisonType, textRange)) > 0 &&
- workingNode.previousSibling);
-
- // We've now reached or gone past the boundary of the text range we're interested in
- // so have identified the node we want
- boundaryNode = workingNode.nextSibling;
-
- if (comparison == -1 && boundaryNode && dom.isCharacterDataNode(boundaryNode)) {
- // This is a character data node (text, comment, cdata). The working range is collapsed at the start of the
- // node containing the text range's boundary, so we move the end of the working range to the boundary point
- // and measure the length of its text to get the boundary's offset within the node.
- workingRange.setEndPoint(isStart ? "EndToStart" : "EndToEnd", textRange);
-
-
- var offset;
-
- if (/[\r\n]/.test(boundaryNode.data)) {
- /*
- For the particular case of a boundary within a text node containing line breaks (within a element,
- for example), we need a slightly complicated approach to get the boundary's offset in IE. The facts:
-
- - Each line break is represented as \r in the text node's data/nodeValue properties
- - Each line break is represented as \r\n in the TextRange's 'text' property
- - The 'text' property of the TextRange does not contain trailing line breaks
-
- To get round the problem presented by the final fact above, we can use the fact that TextRange's
- moveStart() and moveEnd() methods return the actual number of characters moved, which is not necessarily
- the same as the number of characters it was instructed to move. The simplest approach is to use this to
- store the characters moved when moving both the start and end of the range to the start of the document
- body and subtracting the start offset from the end offset (the "move-negative-gazillion" method).
- However, this is extremely slow when the document is large and the range is near the end of it. Clearly
- doing the mirror image (i.e. moving the range boundaries to the end of the document) has the same
- problem.
-
- Another approach that works is to use moveStart() to move the start boundary of the range up to the end
- boundary one character at a time and incrementing a counter with the value returned by the moveStart()
- call. However, the check for whether the start boundary has reached the end boundary is expensive, so
- this method is slow (although unlike "move-negative-gazillion" is largely unaffected by the location of
- the range within the document).
-
- The method below is a hybrid of the two methods above. It uses the fact that a string containing the
- TextRange's 'text' property with each \r\n converted to a single \r character cannot be longer than the
- text of the TextRange, so the start of the range is moved that length initially and then a character at
- a time to make up for any trailing line breaks not contained in the 'text' property. This has good
- performance in most situations compared to the previous two methods.
- */
- var tempRange = workingRange.duplicate();
- var rangeLength = tempRange.text.replace(/\r\n/g, "\r").length;
-
- offset = tempRange.moveStart("character", rangeLength);
- while ( (comparison = tempRange.compareEndPoints("StartToEnd", tempRange)) == -1) {
- offset++;
- tempRange.moveStart("character", 1);
- }
- } else {
- offset = workingRange.text.length;
- }
- boundaryPosition = new DomPosition(boundaryNode, offset);
- } else {
-
-
- // If the boundary immediately follows a character data node and this is the end boundary, we should favour
- // a position within that, and likewise for a start boundary preceding a character data node
- previousNode = (isCollapsed || !isStart) && workingNode.previousSibling;
- nextNode = (isCollapsed || isStart) && workingNode.nextSibling;
-
-
-
- if (nextNode && dom.isCharacterDataNode(nextNode)) {
- boundaryPosition = new DomPosition(nextNode, 0);
- } else if (previousNode && dom.isCharacterDataNode(previousNode)) {
- boundaryPosition = new DomPosition(previousNode, previousNode.length);
- } else {
- boundaryPosition = new DomPosition(containerElement, dom.getNodeIndex(workingNode));
- }
- }
-
- // Clean up
- workingNode.parentNode.removeChild(workingNode);
-
- return boundaryPosition;
- }
-
- // Returns a TextRange representing the boundary of a TextRange expressed as a node and an offset within that node.
- // This function started out as an optimized version of code found in Tim Cameron Ryan's IERange
- // (http://code.google.com/p/ierange/)
- function createBoundaryTextRange(boundaryPosition, isStart) {
- var boundaryNode, boundaryParent, boundaryOffset = boundaryPosition.offset;
- var doc = dom.getDocument(boundaryPosition.node);
- var workingNode, childNodes, workingRange = doc.body.createTextRange();
- var nodeIsDataNode = dom.isCharacterDataNode(boundaryPosition.node);
-
- if (nodeIsDataNode) {
- boundaryNode = boundaryPosition.node;
- boundaryParent = boundaryNode.parentNode;
- } else {
- childNodes = boundaryPosition.node.childNodes;
- boundaryNode = (boundaryOffset < childNodes.length) ? childNodes[boundaryOffset] : null;
- boundaryParent = boundaryPosition.node;
- }
-
- // Position the range immediately before the node containing the boundary
- workingNode = doc.createElement("span");
-
- // Making the working element non-empty element persuades IE to consider the TextRange boundary to be within the
- // element rather than immediately before or after it, which is what we want
- workingNode.innerHTML = "feff;";
-
- // insertBefore is supposed to work like appendChild if the second parameter is null. However, a bug report
- // for IERange suggests that it can crash the browser: http://code.google.com/p/ierange/issues/detail?id=12
- if (boundaryNode) {
- boundaryParent.insertBefore(workingNode, boundaryNode);
- } else {
- boundaryParent.appendChild(workingNode);
- }
-
- workingRange.moveToElementText(workingNode);
- workingRange.collapse(!isStart);
-
- // Clean up
- boundaryParent.removeChild(workingNode);
-
- // Move the working range to the text offset, if required
- if (nodeIsDataNode) {
- workingRange[isStart ? "moveStart" : "moveEnd"]("character", boundaryOffset);
- }
-
- return workingRange;
- }
-
- /*----------------------------------------------------------------------------------------------------------------*/
-
- if (api.features.implementsDomRange && (!api.features.implementsTextRange || !api.config.preferTextRange)) {
- // This is a wrapper around the browser's native DOM Range. It has two aims:
- // - Provide workarounds for specific browser bugs
- // - provide convenient extensions, which are inherited from Rangy's DomRange
-
- (function() {
- var rangeProto;
- var rangeProperties = DomRange.rangeProperties;
- var canSetRangeStartAfterEnd;
-
- function updateRangeProperties(range) {
- var i = rangeProperties.length, prop;
- while (i--) {
- prop = rangeProperties[i];
- range[prop] = range.nativeRange[prop];
- }
- }
-
- function updateNativeRange(range, startContainer, startOffset, endContainer,endOffset) {
- var startMoved = (range.startContainer !== startContainer || range.startOffset != startOffset);
- var endMoved = (range.endContainer !== endContainer || range.endOffset != endOffset);
-
- // Always set both boundaries for the benefit of IE9 (see issue 35)
- if (startMoved || endMoved) {
- range.setEnd(endContainer, endOffset);
- range.setStart(startContainer, startOffset);
- }
- }
-
- function detach(range) {
- range.nativeRange.detach();
- range.detached = true;
- var i = rangeProperties.length, prop;
- while (i--) {
- prop = rangeProperties[i];
- range[prop] = null;
- }
- }
-
- var createBeforeAfterNodeSetter;
-
- WrappedRange = function(range) {
- if (!range) {
- throw new Error("Range must be specified");
- }
- this.nativeRange = range;
- updateRangeProperties(this);
- };
-
- DomRange.createPrototypeRange(WrappedRange, updateNativeRange, detach);
-
- rangeProto = WrappedRange.prototype;
-
- rangeProto.selectNode = function(node) {
- this.nativeRange.selectNode(node);
- updateRangeProperties(this);
- };
-
- rangeProto.deleteContents = function() {
- this.nativeRange.deleteContents();
- updateRangeProperties(this);
- };
-
- rangeProto.extractContents = function() {
- var frag = this.nativeRange.extractContents();
- updateRangeProperties(this);
- return frag;
- };
-
- rangeProto.cloneContents = function() {
- return this.nativeRange.cloneContents();
- };
-
- // TODO: Until I can find a way to programmatically trigger the Firefox bug (apparently long-standing, still
- // present in 3.6.8) that throws "Index or size is negative or greater than the allowed amount" for
- // insertNode in some circumstances, all browsers will have to use the Rangy's own implementation of
- // insertNode, which works but is almost certainly slower than the native implementation.
-/*
- rangeProto.insertNode = function(node) {
- this.nativeRange.insertNode(node);
- updateRangeProperties(this);
- };
-*/
-
- rangeProto.surroundContents = function(node) {
- this.nativeRange.surroundContents(node);
- updateRangeProperties(this);
- };
-
- rangeProto.collapse = function(isStart) {
- this.nativeRange.collapse(isStart);
- updateRangeProperties(this);
- };
-
- rangeProto.cloneRange = function() {
- return new WrappedRange(this.nativeRange.cloneRange());
- };
-
- rangeProto.refresh = function() {
- updateRangeProperties(this);
- };
-
- rangeProto.toString = function() {
- return this.nativeRange.toString();
- };
-
- // Create test range and node for feature detection
-
- var testTextNode = document.createTextNode("test");
- dom.getBody(document).appendChild(testTextNode);
- var range = document.createRange();
-
- /*--------------------------------------------------------------------------------------------------------*/
-
- // Test for Firefox 2 bug that prevents moving the start of a Range to a point after its current end and
- // correct for it
-
- range.setStart(testTextNode, 0);
- range.setEnd(testTextNode, 0);
-
- try {
- range.setStart(testTextNode, 1);
- canSetRangeStartAfterEnd = true;
-
- rangeProto.setStart = function(node, offset) {
- this.nativeRange.setStart(node, offset);
- updateRangeProperties(this);
- };
-
- rangeProto.setEnd = function(node, offset) {
- this.nativeRange.setEnd(node, offset);
- updateRangeProperties(this);
- };
-
- createBeforeAfterNodeSetter = function(name) {
- return function(node) {
- this.nativeRange[name](node);
- updateRangeProperties(this);
- };
- };
-
- } catch(ex) {
-
-
- canSetRangeStartAfterEnd = false;
-
- rangeProto.setStart = function(node, offset) {
- try {
- this.nativeRange.setStart(node, offset);
- } catch (ex) {
- this.nativeRange.setEnd(node, offset);
- this.nativeRange.setStart(node, offset);
- }
- updateRangeProperties(this);
- };
-
- rangeProto.setEnd = function(node, offset) {
- try {
- this.nativeRange.setEnd(node, offset);
- } catch (ex) {
- this.nativeRange.setStart(node, offset);
- this.nativeRange.setEnd(node, offset);
- }
- updateRangeProperties(this);
- };
-
- createBeforeAfterNodeSetter = function(name, oppositeName) {
- return function(node) {
- try {
- this.nativeRange[name](node);
- } catch (ex) {
- this.nativeRange[oppositeName](node);
- this.nativeRange[name](node);
- }
- updateRangeProperties(this);
- };
- };
- }
-
- rangeProto.setStartBefore = createBeforeAfterNodeSetter("setStartBefore", "setEndBefore");
- rangeProto.setStartAfter = createBeforeAfterNodeSetter("setStartAfter", "setEndAfter");
- rangeProto.setEndBefore = createBeforeAfterNodeSetter("setEndBefore", "setStartBefore");
- rangeProto.setEndAfter = createBeforeAfterNodeSetter("setEndAfter", "setStartAfter");
-
- /*--------------------------------------------------------------------------------------------------------*/
-
- // Test for and correct Firefox 2 behaviour with selectNodeContents on text nodes: it collapses the range to
- // the 0th character of the text node
- range.selectNodeContents(testTextNode);
- if (range.startContainer == testTextNode && range.endContainer == testTextNode &&
- range.startOffset == 0 && range.endOffset == testTextNode.length) {
- rangeProto.selectNodeContents = function(node) {
- this.nativeRange.selectNodeContents(node);
- updateRangeProperties(this);
- };
- } else {
- rangeProto.selectNodeContents = function(node) {
- this.setStart(node, 0);
- this.setEnd(node, DomRange.getEndOffset(node));
- };
- }
-
- /*--------------------------------------------------------------------------------------------------------*/
-
- // Test for WebKit bug that has the beahviour of compareBoundaryPoints round the wrong way for constants
- // START_TO_END and END_TO_START: https://bugs.webkit.org/show_bug.cgi?id=20738
-
- range.selectNodeContents(testTextNode);
- range.setEnd(testTextNode, 3);
-
- var range2 = document.createRange();
- range2.selectNodeContents(testTextNode);
- range2.setEnd(testTextNode, 4);
- range2.setStart(testTextNode, 2);
-
- if (range.compareBoundaryPoints(range.START_TO_END, range2) == -1 &
- range.compareBoundaryPoints(range.END_TO_START, range2) == 1) {
- // This is the wrong way round, so correct for it
-
-
- rangeProto.compareBoundaryPoints = function(type, range) {
- range = range.nativeRange || range;
- if (type == range.START_TO_END) {
- type = range.END_TO_START;
- } else if (type == range.END_TO_START) {
- type = range.START_TO_END;
- }
- return this.nativeRange.compareBoundaryPoints(type, range);
- };
- } else {
- rangeProto.compareBoundaryPoints = function(type, range) {
- return this.nativeRange.compareBoundaryPoints(type, range.nativeRange || range);
- };
- }
-
- /*--------------------------------------------------------------------------------------------------------*/
-
- // Test for existence of createContextualFragment and delegate to it if it exists
- if (api.util.isHostMethod(range, "createContextualFragment")) {
- rangeProto.createContextualFragment = function(fragmentStr) {
- return this.nativeRange.createContextualFragment(fragmentStr);
- };
- }
-
- /*--------------------------------------------------------------------------------------------------------*/
-
- // Clean up
- dom.getBody(document).removeChild(testTextNode);
- range.detach();
- range2.detach();
- })();
-
- api.createNativeRange = function(doc) {
- doc = doc || document;
- return doc.createRange();
- };
- } else if (api.features.implementsTextRange) {
- // This is a wrapper around a TextRange, providing full DOM Range functionality using rangy's DomRange as a
- // prototype
-
- WrappedRange = function(textRange) {
- this.textRange = textRange;
- this.refresh();
- };
-
- WrappedRange.prototype = new DomRange(document);
-
- WrappedRange.prototype.refresh = function() {
- var start, end;
-
- // TextRange's parentElement() method cannot be trusted. getTextRangeContainerElement() works around that.
- var rangeContainerElement = getTextRangeContainerElement(this.textRange);
-
- if (textRangeIsCollapsed(this.textRange)) {
- end = start = getTextRangeBoundaryPosition(this.textRange, rangeContainerElement, true, true);
- } else {
-
- start = getTextRangeBoundaryPosition(this.textRange, rangeContainerElement, true, false);
- end = getTextRangeBoundaryPosition(this.textRange, rangeContainerElement, false, false);
- }
-
- this.setStart(start.node, start.offset);
- this.setEnd(end.node, end.offset);
- };
-
- DomRange.copyComparisonConstants(WrappedRange);
-
- // Add WrappedRange as the Range property of the global object to allow expression like Range.END_TO_END to work
- var globalObj = (function() { return this; })();
- if (typeof globalObj.Range == "undefined") {
- globalObj.Range = WrappedRange;
- }
-
- api.createNativeRange = function(doc) {
- doc = doc || document;
- return doc.body.createTextRange();
- };
- }
-
- if (api.features.implementsTextRange) {
- WrappedRange.rangeToTextRange = function(range) {
- if (range.collapsed) {
- var tr = createBoundaryTextRange(new DomPosition(range.startContainer, range.startOffset), true);
-
-
-
- return tr;
-
- //return createBoundaryTextRange(new DomPosition(range.startContainer, range.startOffset), true);
- } else {
- var startRange = createBoundaryTextRange(new DomPosition(range.startContainer, range.startOffset), true);
- var endRange = createBoundaryTextRange(new DomPosition(range.endContainer, range.endOffset), false);
- var textRange = dom.getDocument(range.startContainer).body.createTextRange();
- textRange.setEndPoint("StartToStart", startRange);
- textRange.setEndPoint("EndToEnd", endRange);
- return textRange;
- }
- };
- }
-
- WrappedRange.prototype.getName = function() {
- return "WrappedRange";
- };
-
- api.WrappedRange = WrappedRange;
-
- api.createRange = function(doc) {
- doc = doc || document;
- return new WrappedRange(api.createNativeRange(doc));
- };
-
- api.createRangyRange = function(doc) {
- doc = doc || document;
- return new DomRange(doc);
- };
-
- api.createIframeRange = function(iframeEl) {
- return api.createRange(dom.getIframeDocument(iframeEl));
- };
-
- api.createIframeRangyRange = function(iframeEl) {
- return api.createRangyRange(dom.getIframeDocument(iframeEl));
- };
-
- api.addCreateMissingNativeApiListener(function(win) {
- var doc = win.document;
- if (typeof doc.createRange == "undefined") {
- doc.createRange = function() {
- return api.createRange(this);
- };
- }
- doc = win = null;
- });
-});rangy.createModule("WrappedSelection", function(api, module) {
- // This will create a selection object wrapper that follows the Selection object found in the WHATWG draft DOM Range
- // spec (http://html5.org/specs/dom-range.html)
-
- api.requireModules( ["DomUtil", "DomRange", "WrappedRange"] );
-
- api.config.checkSelectionRanges = true;
-
- var BOOLEAN = "boolean",
- windowPropertyName = "_rangySelection",
- dom = api.dom,
- util = api.util,
- DomRange = api.DomRange,
- WrappedRange = api.WrappedRange,
- DOMException = api.DOMException,
- DomPosition = dom.DomPosition,
- getSelection,
- selectionIsCollapsed,
- CONTROL = "Control";
-
-
-
- function getWinSelection(winParam) {
- return (winParam || window).getSelection();
- }
-
- function getDocSelection(winParam) {
- return (winParam || window).document.selection;
- }
-
- // Test for the Range/TextRange and Selection features required
- // Test for ability to retrieve selection
- var implementsWinGetSelection = api.util.isHostMethod(window, "getSelection"),
- implementsDocSelection = api.util.isHostObject(document, "selection");
-
- var useDocumentSelection = implementsDocSelection && (!implementsWinGetSelection || api.config.preferTextRange);
-
- if (useDocumentSelection) {
- getSelection = getDocSelection;
- api.isSelectionValid = function(winParam) {
- var doc = (winParam || window).document, nativeSel = doc.selection;
-
- // Check whether the selection TextRange is actually contained within the correct document
- return (nativeSel.type != "None" || dom.getDocument(nativeSel.createRange().parentElement()) == doc);
- };
- } else if (implementsWinGetSelection) {
- getSelection = getWinSelection;
- api.isSelectionValid = function() {
- return true;
- };
- } else {
- module.fail("Neither document.selection or window.getSelection() detected.");
- }
-
- api.getNativeSelection = getSelection;
-
- var testSelection = getSelection();
- var testRange = api.createNativeRange(document);
- var body = dom.getBody(document);
-
- // Obtaining a range from a selection
- var selectionHasAnchorAndFocus = util.areHostObjects(testSelection, ["anchorNode", "focusNode"] &&
- util.areHostProperties(testSelection, ["anchorOffset", "focusOffset"]));
- api.features.selectionHasAnchorAndFocus = selectionHasAnchorAndFocus;
-
- // Test for existence of native selection extend() method
- var selectionHasExtend = util.isHostMethod(testSelection, "extend");
- api.features.selectionHasExtend = selectionHasExtend;
-
- // Test if rangeCount exists
- var selectionHasRangeCount = (typeof testSelection.rangeCount == "number");
- api.features.selectionHasRangeCount = selectionHasRangeCount;
-
- var selectionSupportsMultipleRanges = false;
- var collapsedNonEditableSelectionsSupported = true;
-
- if (util.areHostMethods(testSelection, ["addRange", "getRangeAt", "removeAllRanges"]) &&
- typeof testSelection.rangeCount == "number" && api.features.implementsDomRange) {
-
- (function() {
- var iframe = document.createElement("iframe");
- body.appendChild(iframe);
-
- var iframeDoc = dom.getIframeDocument(iframe);
- iframeDoc.open();
- iframeDoc.write("12");
- iframeDoc.close();
-
- var sel = dom.getIframeWindow(iframe).getSelection();
- var docEl = iframeDoc.documentElement;
- var iframeBody = docEl.lastChild, textNode = iframeBody.firstChild;
-
- // Test whether the native selection will allow a collapsed selection within a non-editable element
- var r1 = iframeDoc.createRange();
- r1.setStart(textNode, 1);
- r1.collapse(true);
- sel.addRange(r1);
- collapsedNonEditableSelectionsSupported = (sel.rangeCount == 1);
- sel.removeAllRanges();
-
- // Test whether the native selection is capable of supporting multiple ranges
- var r2 = r1.cloneRange();
- r1.setStart(textNode, 0);
- r2.setEnd(textNode, 2);
- sel.addRange(r1);
- sel.addRange(r2);
-
- selectionSupportsMultipleRanges = (sel.rangeCount == 2);
-
- // Clean up
- r1.detach();
- r2.detach();
-
- body.removeChild(iframe);
- })();
- }
-
- api.features.selectionSupportsMultipleRanges = selectionSupportsMultipleRanges;
- api.features.collapsedNonEditableSelectionsSupported = collapsedNonEditableSelectionsSupported;
-
- // ControlRanges
- var implementsControlRange = false, testControlRange;
-
- if (body && util.isHostMethod(body, "createControlRange")) {
- testControlRange = body.createControlRange();
- if (util.areHostProperties(testControlRange, ["item", "add"])) {
- implementsControlRange = true;
- }
- }
- api.features.implementsControlRange = implementsControlRange;
-
- // Selection collapsedness
- if (selectionHasAnchorAndFocus) {
- selectionIsCollapsed = function(sel) {
- return sel.anchorNode === sel.focusNode && sel.anchorOffset === sel.focusOffset;
- };
- } else {
- selectionIsCollapsed = function(sel) {
- return sel.rangeCount ? sel.getRangeAt(sel.rangeCount - 1).collapsed : false;
- };
- }
-
- function updateAnchorAndFocusFromRange(sel, range, backwards) {
- var anchorPrefix = backwards ? "end" : "start", focusPrefix = backwards ? "start" : "end";
- sel.anchorNode = range[anchorPrefix + "Container"];
- sel.anchorOffset = range[anchorPrefix + "Offset"];
- sel.focusNode = range[focusPrefix + "Container"];
- sel.focusOffset = range[focusPrefix + "Offset"];
- }
-
- function updateAnchorAndFocusFromNativeSelection(sel) {
- var nativeSel = sel.nativeSelection;
- sel.anchorNode = nativeSel.anchorNode;
- sel.anchorOffset = nativeSel.anchorOffset;
- sel.focusNode = nativeSel.focusNode;
- sel.focusOffset = nativeSel.focusOffset;
- }
-
- function updateEmptySelection(sel) {
- sel.anchorNode = sel.focusNode = null;
- sel.anchorOffset = sel.focusOffset = 0;
- sel.rangeCount = 0;
- sel.isCollapsed = true;
- sel._ranges.length = 0;
- }
-
- function getNativeRange(range) {
- var nativeRange;
- if (range instanceof DomRange) {
- nativeRange = range._selectionNativeRange;
- if (!nativeRange) {
- nativeRange = api.createNativeRange(dom.getDocument(range.startContainer));
- nativeRange.setEnd(range.endContainer, range.endOffset);
- nativeRange.setStart(range.startContainer, range.startOffset);
- range._selectionNativeRange = nativeRange;
- range.attachListener("detach", function() {
-
- this._selectionNativeRange = null;
- });
- }
- } else if (range instanceof WrappedRange) {
- nativeRange = range.nativeRange;
- } else if (api.features.implementsDomRange && (range instanceof dom.getWindow(range.startContainer).Range)) {
- nativeRange = range;
- }
- return nativeRange;
- }
-
- function rangeContainsSingleElement(rangeNodes) {
- if (!rangeNodes.length || rangeNodes[0].nodeType != 1) {
- return false;
- }
- for (var i = 1, len = rangeNodes.length; i < len; ++i) {
- if (!dom.isAncestorOf(rangeNodes[0], rangeNodes[i])) {
- return false;
- }
- }
- return true;
- }
-
- function getSingleElementFromRange(range) {
- var nodes = range.getNodes();
- if (!rangeContainsSingleElement(nodes)) {
- throw new Error("getSingleElementFromRange: range " + range.inspect() + " did not consist of a single element");
- }
- return nodes[0];
- }
-
- function isTextRange(range) {
- return !!range && typeof range.text != "undefined";
- }
-
- function updateFromTextRange(sel, range) {
- // Create a Range from the selected TextRange
- var wrappedRange = new WrappedRange(range);
- sel._ranges = [wrappedRange];
-
- updateAnchorAndFocusFromRange(sel, wrappedRange, false);
- sel.rangeCount = 1;
- sel.isCollapsed = wrappedRange.collapsed;
- }
-
- function updateControlSelection(sel) {
- // Update the wrapped selection based on what's now in the native selection
- sel._ranges.length = 0;
- if (sel.docSelection.type == "None") {
- updateEmptySelection(sel);
- } else {
- var controlRange = sel.docSelection.createRange();
- if (isTextRange(controlRange)) {
- // This case (where the selection type is "Control" and calling createRange() on the selection returns
- // a TextRange) can happen in IE 9. It happens, for example, when all elements in the selected
- // ControlRange have been removed from the ControlRange and removed from the document.
- updateFromTextRange(sel, controlRange);
- } else {
- sel.rangeCount = controlRange.length;
- var range, doc = dom.getDocument(controlRange.item(0));
- for (var i = 0; i < sel.rangeCount; ++i) {
- range = api.createRange(doc);
- range.selectNode(controlRange.item(i));
- sel._ranges.push(range);
- }
- sel.isCollapsed = sel.rangeCount == 1 && sel._ranges[0].collapsed;
- updateAnchorAndFocusFromRange(sel, sel._ranges[sel.rangeCount - 1], false);
- }
- }
- }
-
- function addRangeToControlSelection(sel, range) {
- var controlRange = sel.docSelection.createRange();
- var rangeElement = getSingleElementFromRange(range);
-
- // Create a new ControlRange containing all the elements in the selected ControlRange plus the element
- // contained by the supplied range
- var doc = dom.getDocument(controlRange.item(0));
- var newControlRange = dom.getBody(doc).createControlRange();
- for (var i = 0, len = controlRange.length; i < len; ++i) {
- newControlRange.add(controlRange.item(i));
- }
- try {
- newControlRange.add(rangeElement);
- } catch (ex) {
- throw new Error("addRange(): Element within the specified Range could not be added to control selection (does it have layout?)");
- }
- newControlRange.select();
-
- // Update the wrapped selection based on what's now in the native selection
- updateControlSelection(sel);
- }
-
- var getSelectionRangeAt;
-
- if (util.isHostMethod(testSelection, "getRangeAt")) {
- getSelectionRangeAt = function(sel, index) {
- try {
- return sel.getRangeAt(index);
- } catch(ex) {
- return null;
- }
- };
- } else if (selectionHasAnchorAndFocus) {
- getSelectionRangeAt = function(sel) {
- var doc = dom.getDocument(sel.anchorNode);
- var range = api.createRange(doc);
- range.setStart(sel.anchorNode, sel.anchorOffset);
- range.setEnd(sel.focusNode, sel.focusOffset);
-
- // Handle the case when the selection was selected backwards (from the end to the start in the
- // document)
- if (range.collapsed !== this.isCollapsed) {
- range.setStart(sel.focusNode, sel.focusOffset);
- range.setEnd(sel.anchorNode, sel.anchorOffset);
- }
-
- return range;
- };
- }
-
- /**
- * @constructor
- */
- function WrappedSelection(selection, docSelection, win) {
- this.nativeSelection = selection;
- this.docSelection = docSelection;
- this._ranges = [];
- this.win = win;
- this.refresh();
- }
-
- api.getSelection = function(win) {
- win = win || window;
- var sel = win[windowPropertyName];
- var nativeSel = getSelection(win), docSel = implementsDocSelection ? getDocSelection(win) : null;
- if (sel) {
- sel.nativeSelection = nativeSel;
- sel.docSelection = docSel;
- sel.refresh(win);
- } else {
- sel = new WrappedSelection(nativeSel, docSel, win);
- win[windowPropertyName] = sel;
- }
- return sel;
- };
-
- api.getIframeSelection = function(iframeEl) {
- return api.getSelection(dom.getIframeWindow(iframeEl));
- };
-
- var selProto = WrappedSelection.prototype;
-
- function createControlSelection(sel, ranges) {
- // Ensure that the selection becomes of type "Control"
- var doc = dom.getDocument(ranges[0].startContainer);
- var controlRange = dom.getBody(doc).createControlRange();
- for (var i = 0, el; i < rangeCount; ++i) {
- el = getSingleElementFromRange(ranges[i]);
- try {
- controlRange.add(el);
- } catch (ex) {
- throw new Error("setRanges(): Element within the one of the specified Ranges could not be added to control selection (does it have layout?)");
- }
- }
- controlRange.select();
-
- // Update the wrapped selection based on what's now in the native selection
- updateControlSelection(sel);
- }
-
- // Selecting a range
- if (!useDocumentSelection && selectionHasAnchorAndFocus && util.areHostMethods(testSelection, ["removeAllRanges", "addRange"])) {
- selProto.removeAllRanges = function() {
- this.nativeSelection.removeAllRanges();
- updateEmptySelection(this);
- };
-
- var addRangeBackwards = function(sel, range) {
- var doc = DomRange.getRangeDocument(range);
- var endRange = api.createRange(doc);
- endRange.collapseToPoint(range.endContainer, range.endOffset);
- sel.nativeSelection.addRange(getNativeRange(endRange));
- sel.nativeSelection.extend(range.startContainer, range.startOffset);
- sel.refresh();
- };
-
- if (selectionHasRangeCount) {
- selProto.addRange = function(range, backwards) {
- if (implementsControlRange && implementsDocSelection && this.docSelection.type == CONTROL) {
- addRangeToControlSelection(this, range);
- } else {
- if (backwards && selectionHasExtend) {
- addRangeBackwards(this, range);
- } else {
- var previousRangeCount;
- if (selectionSupportsMultipleRanges) {
- previousRangeCount = this.rangeCount;
- } else {
- this.removeAllRanges();
- previousRangeCount = 0;
- }
- this.nativeSelection.addRange(getNativeRange(range));
-
- // Check whether adding the range was successful
- this.rangeCount = this.nativeSelection.rangeCount;
-
- if (this.rangeCount == previousRangeCount + 1) {
- // The range was added successfully
-
- // Check whether the range that we added to the selection is reflected in the last range extracted from
- // the selection
- if (api.config.checkSelectionRanges) {
- var nativeRange = getSelectionRangeAt(this.nativeSelection, this.rangeCount - 1);
- if (nativeRange && !DomRange.rangesEqual(nativeRange, range)) {
- // Happens in WebKit with, for example, a selection placed at the start of a text node
- range = new WrappedRange(nativeRange);
- }
- }
- this._ranges[this.rangeCount - 1] = range;
- updateAnchorAndFocusFromRange(this, range, selectionIsBackwards(this.nativeSelection));
- this.isCollapsed = selectionIsCollapsed(this);
- } else {
- // The range was not added successfully. The simplest thing is to refresh
- this.refresh();
- }
- }
- }
- };
- } else {
- selProto.addRange = function(range, backwards) {
- if (backwards && selectionHasExtend) {
- addRangeBackwards(this, range);
- } else {
- this.nativeSelection.addRange(getNativeRange(range));
- this.refresh();
- }
- };
- }
-
- selProto.setRanges = function(ranges) {
- if (implementsControlRange && ranges.length > 1) {
- createControlSelection(this, ranges);
- } else {
- this.removeAllRanges();
- for (var i = 0, len = ranges.length; i < len; ++i) {
- this.addRange(ranges[i]);
- }
- }
- };
- } else if (util.isHostMethod(testSelection, "empty") && util.isHostMethod(testRange, "select") &&
- implementsControlRange && useDocumentSelection) {
-
- selProto.removeAllRanges = function() {
- // Added try/catch as fix for issue #21
- try {
- this.docSelection.empty();
-
- // Check for empty() not working (issue #24)
- if (this.docSelection.type != "None") {
- // Work around failure to empty a control selection by instead selecting a TextRange and then
- // calling empty()
- var doc;
- if (this.anchorNode) {
- doc = dom.getDocument(this.anchorNode);
- } else if (this.docSelection.type == CONTROL) {
- var controlRange = this.docSelection.createRange();
- if (controlRange.length) {
- doc = dom.getDocument(controlRange.item(0)).body.createTextRange();
- }
- }
- if (doc) {
- var textRange = doc.body.createTextRange();
- textRange.select();
- this.docSelection.empty();
- }
- }
- } catch(ex) {}
- updateEmptySelection(this);
- };
-
- selProto.addRange = function(range) {
- if (this.docSelection.type == CONTROL) {
- addRangeToControlSelection(this, range);
- } else {
- WrappedRange.rangeToTextRange(range).select();
- this._ranges[0] = range;
- this.rangeCount = 1;
- this.isCollapsed = this._ranges[0].collapsed;
- updateAnchorAndFocusFromRange(this, range, false);
- }
- };
-
- selProto.setRanges = function(ranges) {
- this.removeAllRanges();
- var rangeCount = ranges.length;
- if (rangeCount > 1) {
- createControlSelection(this, ranges);
- } else if (rangeCount) {
- this.addRange(ranges[0]);
- }
- };
- } else {
- module.fail("No means of selecting a Range or TextRange was found");
- return false;
- }
-
- selProto.getRangeAt = function(index) {
- if (index < 0 || index >= this.rangeCount) {
- throw new DOMException("INDEX_SIZE_ERR");
- } else {
- return this._ranges[index];
- }
- };
-
- var refreshSelection;
-
- if (useDocumentSelection) {
- refreshSelection = function(sel) {
- var range;
- if (api.isSelectionValid(sel.win)) {
- range = sel.docSelection.createRange();
- } else {
- range = dom.getBody(sel.win.document).createTextRange();
- range.collapse(true);
- }
-
-
- if (sel.docSelection.type == CONTROL) {
- updateControlSelection(sel);
- } else if (isTextRange(range)) {
- updateFromTextRange(sel, range);
- } else {
- updateEmptySelection(sel);
- }
- };
- } else if (util.isHostMethod(testSelection, "getRangeAt") && typeof testSelection.rangeCount == "number") {
- refreshSelection = function(sel) {
- if (implementsControlRange && implementsDocSelection && sel.docSelection.type == CONTROL) {
- updateControlSelection(sel);
- } else {
- sel._ranges.length = sel.rangeCount = sel.nativeSelection.rangeCount;
- if (sel.rangeCount) {
- for (var i = 0, len = sel.rangeCount; i < len; ++i) {
- sel._ranges[i] = new api.WrappedRange(sel.nativeSelection.getRangeAt(i));
- }
- updateAnchorAndFocusFromRange(sel, sel._ranges[sel.rangeCount - 1], selectionIsBackwards(sel.nativeSelection));
- sel.isCollapsed = selectionIsCollapsed(sel);
- } else {
- updateEmptySelection(sel);
- }
- }
- };
- } else if (selectionHasAnchorAndFocus && typeof testSelection.isCollapsed == BOOLEAN && typeof testRange.collapsed == BOOLEAN && api.features.implementsDomRange) {
- refreshSelection = function(sel) {
- var range, nativeSel = sel.nativeSelection;
- if (nativeSel.anchorNode) {
- range = getSelectionRangeAt(nativeSel, 0);
- sel._ranges = [range];
- sel.rangeCount = 1;
- updateAnchorAndFocusFromNativeSelection(sel);
- sel.isCollapsed = selectionIsCollapsed(sel);
- } else {
- updateEmptySelection(sel);
- }
- };
- } else {
- module.fail("No means of obtaining a Range or TextRange from the user's selection was found");
- return false;
- }
-
- selProto.refresh = function(checkForChanges) {
- var oldRanges = checkForChanges ? this._ranges.slice(0) : null;
- refreshSelection(this);
- if (checkForChanges) {
- var i = oldRanges.length;
- if (i != this._ranges.length) {
- return false;
- }
- while (i--) {
- if (!DomRange.rangesEqual(oldRanges[i], this._ranges[i])) {
- return false;
- }
- }
- return true;
- }
- };
-
- // Removal of a single range
- var removeRangeManually = function(sel, range) {
- var ranges = sel.getAllRanges(), removed = false;
- sel.removeAllRanges();
- for (var i = 0, len = ranges.length; i < len; ++i) {
- if (removed || range !== ranges[i]) {
- sel.addRange(ranges[i]);
- } else {
- // According to the draft WHATWG Range spec, the same range may be added to the selection multiple
- // times. removeRange should only remove the first instance, so the following ensures only the first
- // instance is removed
- removed = true;
- }
- }
- if (!sel.rangeCount) {
- updateEmptySelection(sel);
- }
- };
-
- if (implementsControlRange) {
- selProto.removeRange = function(range) {
- if (this.docSelection.type == CONTROL) {
- var controlRange = this.docSelection.createRange();
- var rangeElement = getSingleElementFromRange(range);
-
- // Create a new ControlRange containing all the elements in the selected ControlRange minus the
- // element contained by the supplied range
- var doc = dom.getDocument(controlRange.item(0));
- var newControlRange = dom.getBody(doc).createControlRange();
- var el, removed = false;
- for (var i = 0, len = controlRange.length; i < len; ++i) {
- el = controlRange.item(i);
- if (el !== rangeElement || removed) {
- newControlRange.add(controlRange.item(i));
- } else {
- removed = true;
- }
- }
- newControlRange.select();
-
- // Update the wrapped selection based on what's now in the native selection
- updateControlSelection(this);
- } else {
- removeRangeManually(this, range);
- }
- };
- } else {
- selProto.removeRange = function(range) {
- removeRangeManually(this, range);
- };
- }
-
- // Detecting if a selection is backwards
- var selectionIsBackwards;
- if (!useDocumentSelection && selectionHasAnchorAndFocus && api.features.implementsDomRange) {
- selectionIsBackwards = function(sel) {
- var backwards = false;
- if (sel.anchorNode) {
- backwards = (dom.comparePoints(sel.anchorNode, sel.anchorOffset, sel.focusNode, sel.focusOffset) == 1);
- }
- return backwards;
- };
-
- selProto.isBackwards = function() {
- return selectionIsBackwards(this);
- };
- } else {
- selectionIsBackwards = selProto.isBackwards = function() {
- return false;
- };
- }
-
- // Selection text
- // This is conformant to the new WHATWG DOM Range draft spec but differs from WebKit and Mozilla's implementation
- selProto.toString = function() {
-
- var rangeTexts = [];
- for (var i = 0, len = this.rangeCount; i < len; ++i) {
- rangeTexts[i] = "" + this._ranges[i];
- }
- return rangeTexts.join("");
- };
-
- function assertNodeInSameDocument(sel, node) {
- if (sel.anchorNode && (dom.getDocument(sel.anchorNode) !== dom.getDocument(node))) {
- throw new DOMException("WRONG_DOCUMENT_ERR");
- }
- }
-
- // No current browsers conform fully to the HTML 5 draft spec for this method, so Rangy's own method is always used
- selProto.collapse = function(node, offset) {
- assertNodeInSameDocument(this, node);
- var range = api.createRange(dom.getDocument(node));
- range.collapseToPoint(node, offset);
- this.removeAllRanges();
- this.addRange(range);
- this.isCollapsed = true;
- };
-
- selProto.collapseToStart = function() {
- if (this.rangeCount) {
- var range = this._ranges[0];
- this.collapse(range.startContainer, range.startOffset);
- } else {
- throw new DOMException("INVALID_STATE_ERR");
- }
- };
-
- selProto.collapseToEnd = function() {
- if (this.rangeCount) {
- var range = this._ranges[this.rangeCount - 1];
- this.collapse(range.endContainer, range.endOffset);
- } else {
- throw new DOMException("INVALID_STATE_ERR");
- }
- };
-
- // The HTML 5 spec is very specific on how selectAllChildren should be implemented so the native implementation is
- // never used by Rangy.
- selProto.selectAllChildren = function(node) {
- assertNodeInSameDocument(this, node);
- var range = api.createRange(dom.getDocument(node));
- range.selectNodeContents(node);
- this.removeAllRanges();
- this.addRange(range);
- };
-
- selProto.deleteFromDocument = function() {
- // Sepcial behaviour required for Control selections
- if (implementsControlRange && implementsDocSelection && this.docSelection.type == CONTROL) {
- var controlRange = this.docSelection.createRange();
- var element;
- while (controlRange.length) {
- element = controlRange.item(0);
- controlRange.remove(element);
- element.parentNode.removeChild(element);
- }
- this.refresh();
- } else if (this.rangeCount) {
- var ranges = this.getAllRanges();
- this.removeAllRanges();
- for (var i = 0, len = ranges.length; i < len; ++i) {
- ranges[i].deleteContents();
- }
- // The HTML5 spec says nothing about what the selection should contain after calling deleteContents on each
- // range. Firefox moves the selection to where the final selected range was, so we emulate that
- this.addRange(ranges[len - 1]);
- }
- };
-
- // The following are non-standard extensions
- selProto.getAllRanges = function() {
- return this._ranges.slice(0);
- };
-
- selProto.setSingleRange = function(range) {
- this.setRanges( [range] );
- };
-
- selProto.containsNode = function(node, allowPartial) {
- for (var i = 0, len = this._ranges.length; i < len; ++i) {
- if (this._ranges[i].containsNode(node, allowPartial)) {
- return true;
- }
- }
- return false;
- };
-
- selProto.toHtml = function() {
- var html = "";
- if (this.rangeCount) {
- var container = DomRange.getRangeDocument(this._ranges[0]).createElement("div");
- for (var i = 0, len = this._ranges.length; i < len; ++i) {
- container.appendChild(this._ranges[i].cloneContents());
- }
- html = container.innerHTML;
- }
- return html;
- };
-
- function inspect(sel) {
- var rangeInspects = [];
- var anchor = new DomPosition(sel.anchorNode, sel.anchorOffset);
- var focus = new DomPosition(sel.focusNode, sel.focusOffset);
- var name = (typeof sel.getName == "function") ? sel.getName() : "Selection";
-
- if (typeof sel.rangeCount != "undefined") {
- for (var i = 0, len = sel.rangeCount; i < len; ++i) {
- rangeInspects[i] = DomRange.inspect(sel.getRangeAt(i));
- }
- }
- return "[" + name + "(Ranges: " + rangeInspects.join(", ") +
- ")(anchor: " + anchor.inspect() + ", focus: " + focus.inspect() + "]";
-
- }
-
- selProto.getName = function() {
- return "WrappedSelection";
- };
-
- selProto.inspect = function() {
- return inspect(this);
- };
-
- selProto.detach = function() {
- this.win[windowPropertyName] = null;
- this.win = this.anchorNode = this.focusNode = null;
- };
-
- WrappedSelection.inspect = inspect;
-
- api.Selection = WrappedSelection;
-
- api.selectionPrototype = selProto;
-
- api.addCreateMissingNativeApiListener(function(win) {
- if (typeof win.getSelection == "undefined") {
- win.getSelection = function() {
- return api.getSelection(this);
- };
- }
- win = null;
- });
-});
-/*
- Base.js, version 1.1a
- Copyright 2006-2010, Dean Edwards
- License: http://www.opensource.org/licenses/mit-license.php
-*/
-
-var Base = function() {
- // dummy
-};
-
-Base.extend = function(_instance, _static) { // subclass
- var extend = Base.prototype.extend;
-
- // build the prototype
- Base._prototyping = true;
- var proto = new this;
- extend.call(proto, _instance);
- proto.base = function() {
- // call this method from any other method to invoke that method's ancestor
- };
- delete Base._prototyping;
-
- // create the wrapper for the constructor function
- //var constructor = proto.constructor.valueOf(); //-dean
- var constructor = proto.constructor;
- var klass = proto.constructor = function() {
- if (!Base._prototyping) {
- if (this._constructing || this.constructor == klass) { // instantiation
- this._constructing = true;
- constructor.apply(this, arguments);
- delete this._constructing;
- } else if (arguments[0] != null) { // casting
- return (arguments[0].extend || extend).call(arguments[0], proto);
- }
- }
- };
-
- // build the class interface
- klass.ancestor = this;
- klass.extend = this.extend;
- klass.forEach = this.forEach;
- klass.implement = this.implement;
- klass.prototype = proto;
- klass.toString = this.toString;
- klass.valueOf = function(type) {
- //return (type == "object") ? klass : constructor; //-dean
- return (type == "object") ? klass : constructor.valueOf();
- };
- extend.call(klass, _static);
- // class initialisation
- if (typeof klass.init == "function") klass.init();
- return klass;
-};
-
-Base.prototype = {
- extend: function(source, value) {
- if (arguments.length > 1) { // extending with a name/value pair
- var ancestor = this[source];
- if (ancestor && (typeof value == "function") && // overriding a method?
- // the valueOf() comparison is to avoid circular references
- (!ancestor.valueOf || ancestor.valueOf() != value.valueOf()) &&
- /\bbase\b/.test(value)) {
- // get the underlying method
- var method = value.valueOf();
- // override
- value = function() {
- var previous = this.base || Base.prototype.base;
- this.base = ancestor;
- var returnValue = method.apply(this, arguments);
- this.base = previous;
- return returnValue;
- };
- // point to the underlying method
- value.valueOf = function(type) {
- return (type == "object") ? value : method;
- };
- value.toString = Base.toString;
- }
- this[source] = value;
- } else if (source) { // extending with an object literal
- var extend = Base.prototype.extend;
- // if this object has a customised extend method then use it
- if (!Base._prototyping && typeof this != "function") {
- extend = this.extend || extend;
- }
- var proto = {toSource: null};
- // do the "toString" and other methods manually
- var hidden = ["constructor", "toString", "valueOf"];
- // if we are prototyping then include the constructor
- var i = Base._prototyping ? 0 : 1;
- while (key = hidden[i++]) {
- if (source[key] != proto[key]) {
- extend.call(this, key, source[key]);
-
- }
- }
- // copy each of the source object's properties to this object
- for (var key in source) {
- if (!proto[key]) extend.call(this, key, source[key]);
- }
- }
- return this;
- }
-};
-
-// initialise
-Base = Base.extend({
- constructor: function() {
- this.extend(arguments[0]);
- }
-}, {
- ancestor: Object,
- version: "1.1",
-
- forEach: function(object, block, context) {
- for (var key in object) {
- if (this.prototype[key] === undefined) {
- block.call(context, object[key], key, object);
- }
- }
- },
-
- implement: function() {
- for (var i = 0; i < arguments.length; i++) {
- if (typeof arguments[i] == "function") {
- // if it's a function, call it
- arguments[i](this.prototype);
- } else {
- // add the interface using the extend method
- this.prototype.extend(arguments[i]);
- }
- }
- return this;
- },
-
- toString: function() {
- return String(this.valueOf());
- }
-});/**
- * Detect browser support for specific features
- */
-wysihtml5.browser = (function() {
- var userAgent = navigator.userAgent,
- testElement = document.createElement("div"),
- // Browser sniffing is unfortunately needed since some behaviors are impossible to feature detect
- isIE = userAgent.indexOf("MSIE") !== -1 && userAgent.indexOf("Opera") === -1,
- isGecko = userAgent.indexOf("Gecko") !== -1 && userAgent.indexOf("KHTML") === -1,
- isWebKit = userAgent.indexOf("AppleWebKit/") !== -1,
- isChrome = userAgent.indexOf("Chrome/") !== -1,
- isOpera = userAgent.indexOf("Opera/") !== -1;
-
- function iosVersion(userAgent) {
- return ((/ipad|iphone|ipod/.test(userAgent) && userAgent.match(/ os (\d+).+? like mac os x/)) || [, 0])[1];
- }
-
- return {
- // Static variable needed, publicly accessible, to be able override it in unit tests
- USER_AGENT: userAgent,
-
- /**
- * Exclude browsers that are not capable of displaying and handling
- * contentEditable as desired:
- * - iPhone, iPad (tested iOS 4.2.2) and Android (tested 2.2) refuse to make contentEditables focusable
- * - IE < 8 create invalid markup and crash randomly from time to time
- *
- * @return {Boolean}
- */
- supported: function() {
- var userAgent = this.USER_AGENT.toLowerCase(),
- // Essential for making html elements editable
- hasContentEditableSupport = "contentEditable" in testElement,
- // Following methods are needed in order to interact with the contentEditable area
- hasEditingApiSupport = document.execCommand && document.queryCommandSupported && document.queryCommandState,
- // document selector apis are only supported by IE 8+, Safari 4+, Chrome and Firefox 3.5+
- hasQuerySelectorSupport = document.querySelector && document.querySelectorAll,
- // contentEditable is unusable in mobile browsers (tested iOS 4.2.2, Android 2.2, Opera Mobile, WebOS 3.05)
- isIncompatibleMobileBrowser = (this.isIos() && iosVersion(userAgent) < 5) || userAgent.indexOf("opera mobi") !== -1 || userAgent.indexOf("hpwos/") !== -1;
-
- return hasContentEditableSupport
- && hasEditingApiSupport
- && hasQuerySelectorSupport
- && !isIncompatibleMobileBrowser;
- },
-
- isTouchDevice: function() {
- return this.supportsEvent("touchmove");
- },
-
- isIos: function() {
- var userAgent = this.USER_AGENT.toLowerCase();
- return userAgent.indexOf("webkit") !== -1 && userAgent.indexOf("mobile") !== -1;
- },
-
- /**
- * Whether the browser supports sandboxed iframes
- * Currently only IE 6+ offers such feature