diff --git a/pom.xml b/pom.xml
index 092acea79ff08511f3fc0a03ed2514558cdba0b2..16e3abea2e3e420746b702cf83eb67f8d67d7d8d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -333,7 +333,7 @@
 		<dependency>
 			<groupId>de.thm.arsnova.connector</groupId>
 			<artifactId>connector-client</artifactId>
-			<version>0.14.0-SNAPSHOT</version>
+			<version>0.40.1-SNAPSHOT</version>
 		</dependency>
 		
 		<dependency>
diff --git a/src/main/java/de/thm/arsnova/ImageUtils.java b/src/main/java/de/thm/arsnova/ImageUtils.java
new file mode 100644
index 0000000000000000000000000000000000000000..0af116547c229c335ee88ca292528365c927cf7c
--- /dev/null
+++ b/src/main/java/de/thm/arsnova/ImageUtils.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2014 THM webMedia
+ *
+ * This file is part of ARSnova.
+ *
+ * ARSnova 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * ARSnova 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, see <http://www.gnu.org/licenses/>.
+ */
+
+package de.thm.arsnova;
+
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import javax.imageio.ImageIO;
+
+import org.apache.commons.codec.binary.Base64;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Util class for image operations.
+ * 
+ * @author Daniel Vogel (daniel.vogel@mni.thm.de)
+ *
+ */
+public class ImageUtils {
+	public static final Logger LOGGER = LoggerFactory.getLogger(ImageUtils.class);
+
+	/**
+	 * Converts an image to an Base64 String.
+	 * 
+	 * @param  imageUrl The image url as a {@link String}
+	 * @return The Base64 {@link String} of the image on success, otherwise <code>null</code>.
+	 */
+	public static String encodeImageToString(String imageUrl) {
+		
+		String[]      urlParts = imageUrl.split("\\.");
+		StringBuilder result   = new StringBuilder();
+		
+		// get format
+	    //
+	    // The format is read dynamically. We have to take control
+	    // in the frontend that no unsupported formats are transmitted!
+	    if ( urlParts.length > 0 ) {
+
+			String extension = urlParts[urlParts.length-1];
+
+	    	result.append("data:image/" + extension + ";base64,");
+	    	result.append(Base64.encodeBase64String(convertFileToByteArray(imageUrl)));
+	    	
+			return result.toString();
+	    }
+	    
+		return null;
+	}
+	
+	/**
+	 * Gets the bytestream of an image url.
+	 * s
+	 * @param  imageUrl The image url as a {@link String}
+	 * @return The <code>byte[]</code> of the image on success, otherwise <code>null</code>.
+	 */
+	public static byte[] convertImageToByteArray(String imageUrl, String extension) {
+
+		try {
+			URL 				  url   = new URL(imageUrl);
+			BufferedImage 		  image = ImageIO.read(url);
+		    ByteArrayOutputStream baos  = new ByteArrayOutputStream();
+
+		    ImageIO.write(image, extension, baos);
+		    
+		    baos.flush();
+		    baos.close();
+		    return baos.toByteArray();
+		    
+		} catch (MalformedURLException e) {
+			LOGGER.error(e.getLocalizedMessage());
+		} catch (IOException e) {
+			LOGGER.error(e.getLocalizedMessage());
+		}
+
+	    return null;
+	}
+	
+	/**
+	 * Gets the bytestream of an image url.
+	 * s
+	 * @param  imageUrl The image url as a {@link String}
+	 * @return The <code>byte[]</code> of the image on success, otherwise <code>null</code>.
+	 */
+	public static byte[] convertFileToByteArray(String imageUrl) {
+
+		try {
+			URL 				  url   = new URL(imageUrl);
+		    ByteArrayOutputStream baos  = new ByteArrayOutputStream();
+		    
+		    InputStream is = url.openStream();
+		    byte[] byteChunk = new byte[4096]; // Or whatever size you want to read in at a time.
+		    int n;
+
+		    while ( (n = is.read(byteChunk)) > 0 ) {
+		    	baos.write(byteChunk, 0, n);
+		    }
+
+		    baos.flush();
+		    baos.close();
+		    
+		    return baos.toByteArray();
+		    
+		} catch (MalformedURLException e) {
+			LOGGER.error(e.getLocalizedMessage());
+		} catch (IOException e) {
+			LOGGER.error(e.getLocalizedMessage());
+		}
+
+	    return null;
+	}
+}
+
diff --git a/src/main/java/de/thm/arsnova/controller/SessionController.java b/src/main/java/de/thm/arsnova/controller/SessionController.java
index 525bd65ddea5469aed9cca1da4301d66c3749d3a..b8443784bf35398a46b3845e246b7f97b5ae019e 100644
--- a/src/main/java/de/thm/arsnova/controller/SessionController.java
+++ b/src/main/java/de/thm/arsnova/controller/SessionController.java
@@ -191,6 +191,24 @@ public class SessionController extends AbstractController {
 		return null;
 	}
 
+	@RequestMapping(value = "/{sessionkey}/learningprogress", method = RequestMethod.GET)
+	@ResponseBody
+	public final int learningProgress(
+			@PathVariable final String sessionkey,
+			final HttpServletResponse response
+	) {
+		return sessionService.getLearningProgress(sessionkey);
+	}
+
+	@RequestMapping(value = "/{sessionkey}/mylearningprogress", method = RequestMethod.GET)
+	@ResponseBody
+	public final int myLearningProgress(
+			@PathVariable final String sessionkey,
+			final HttpServletResponse response
+	) {
+		return sessionService.getMyLearningProgress(sessionkey);
+	}
+
 	/* internal redirections */
 
 	@RequestMapping(value = "/{sessionKey}/lecturerquestion")
diff --git a/src/main/java/de/thm/arsnova/dao/CouchDBDao.java b/src/main/java/de/thm/arsnova/dao/CouchDBDao.java
index ae721ae3660ba4c0587d506c1c4a1639080867ac..28ff837d321414e12a645f32e0f3bcfa83b3b640 100644
--- a/src/main/java/de/thm/arsnova/dao/CouchDBDao.java
+++ b/src/main/java/de/thm/arsnova/dao/CouchDBDao.java
@@ -289,6 +289,12 @@ public class CouchDBDao implements IDatabaseDao {
 		q.put("showStatistic", question.isShowStatistic());
 		q.put("showAnswer", question.isShowAnswer());
 		q.put("abstention", question.isAbstention());
+		q.put("image", question.getImage());
+		q.put("gridSize", question.getGridSize());
+		q.put("offsetX", question.getOffsetX());
+		q.put("offsetY", question.getOffsetY());
+		q.put("zoomLvl", question.getZoomLvl());
+
 		return q;
 	}
 
@@ -306,6 +312,11 @@ public class CouchDBDao implements IDatabaseDao {
 			q.put("showStatistic", question.isShowStatistic());
 			q.put("showAnswer", question.isShowAnswer());
 			q.put("abstention", question.isAbstention());
+			q.put("image", question.getImage());
+			q.put("gridSize", question.getGridSize());
+			q.put("offsetX", question.getOffsetX());
+			q.put("offsetY", question.getOffsetY());
+			q.put("zoomLvl", question.getZoomLvl());
 			this.database.saveDocument(q);
 			question.set_rev(q.getRev());
 
@@ -354,7 +365,8 @@ public class CouchDBDao implements IDatabaseDao {
 					results.getJSONArray("rows").optJSONObject(0).optJSONObject("value"),
 					Question.class
 			);
-			JSONArray possibleAnswers = results.getJSONArray("rows").optJSONObject(0).optJSONObject("value")
+			JSONArray possibleAnswers = new JSONArray();
+			possibleAnswers = results.getJSONArray("rows").optJSONObject(0).optJSONObject("value")
 					.getJSONArray("possibleAnswers");
 			Collection<PossibleAnswer> answers = JSONArray.toCollection(
 					possibleAnswers,
@@ -924,6 +936,7 @@ public class CouchDBDao implements IDatabaseDao {
 			a.put("questionId", answer.getQuestionId());
 			a.put("answerSubject", answer.getAnswerSubject());
 			a.put("questionVariant", answer.getQuestionVariant());
+			a.put("questionValue", answer.getQuestionValue());
 			a.put("answerText", answer.getAnswerText());
 			a.put("timestamp", answer.getTimestamp());
 			a.put("user", user.getUsername());
@@ -947,6 +960,7 @@ public class CouchDBDao implements IDatabaseDao {
 			a.put("answerText", answer.getAnswerText());
 			a.put("timestamp", answer.getTimestamp());
 			a.put("abstention", answer.isAbstention());
+			a.put("questionValue", answer.getQuestionValue());
 			this.database.saveDocument(a);
 			answer.set_rev(a.getRev());
 			return answer;
@@ -1408,4 +1422,38 @@ public class CouchDBDao implements IDatabaseDao {
 
 		return false;
 	}
+
+	public int getLearningProgress(Session session) {
+		NovaView courseView = new NovaView("learning_progress/course_value");
+		NovaView maximumView = new NovaView("learning_progress/maximum_value");
+		courseView.setKey(session.get_id());
+		maximumView.setKey(session.get_id());
+
+		return getProgressPercentage(courseView, maximumView);
+	}
+
+	@Override
+	public int getMyLearningProgress(Session session, User user) {
+		NovaView userView = new NovaView("learning_progress/user_value");
+		NovaView maximumView = new NovaView("learning_progress/maximum_value");
+		userView.setKey(session.get_id(), user.getUsername());
+		maximumView.setKey(session.get_id());
+
+		return getProgressPercentage(userView, maximumView);
+	}
+
+	private int getProgressPercentage(NovaView progressView, NovaView maximumView) {
+		List<Document> progressValue = this.getDatabase().view(progressView).getResults();
+		List<Document> maximumValue = this.getDatabase().view(maximumView).getResults();
+		if (maximumValue.isEmpty()) {
+			return 0;
+		}
+		int maximum = maximumValue.get(0).getInt("value");
+		int progress = 0;
+		if (!progressValue.isEmpty()) {
+			progress = progressValue.get(0).getInt("value");
+		}
+		int percentage = (int)((progress * 100.0f) / maximum);
+		return percentage < 0 ? 0 : percentage;
+	}
 }
diff --git a/src/main/java/de/thm/arsnova/dao/IDatabaseDao.java b/src/main/java/de/thm/arsnova/dao/IDatabaseDao.java
index 4bb273c40e83b567071c783f282f99b5baa01dc6..e4697f4018717134195c7787bec8c4c41d34f8f4 100644
--- a/src/main/java/de/thm/arsnova/dao/IDatabaseDao.java
+++ b/src/main/java/de/thm/arsnova/dao/IDatabaseDao.java
@@ -168,4 +168,8 @@ public interface IDatabaseDao {
 	DbUser getUser(String username);
 
 	boolean deleteUser(DbUser dbUser);
+
+	int getLearningProgress(Session session);
+
+	int getMyLearningProgress(Session session, User user);
 }
diff --git a/src/main/java/de/thm/arsnova/entities/Answer.java b/src/main/java/de/thm/arsnova/entities/Answer.java
index aed482cfba76aac0f3f915fcba3d21b117af4579..d2361ed901256dfb1906f059d87ef92d6ffea750 100644
--- a/src/main/java/de/thm/arsnova/entities/Answer.java
+++ b/src/main/java/de/thm/arsnova/entities/Answer.java
@@ -10,6 +10,7 @@ public class Answer {
 	private String answerText;
 	private String answerSubject;
 	private String questionVariant;
+	private int questionValue;
 	private int piRound;
 	private String user;
 	private long timestamp;
@@ -133,6 +134,14 @@ public class Answer {
 		this.questionVariant = questionVariant;
 	}
 
+	public int getQuestionValue() {
+		return questionValue;
+	}
+
+	public void setQuestionValue(int questionValue) {
+		this.questionValue = questionValue;
+	}
+
 	@Override
 	public final String toString() {
 		return "Answer type:'" + type + "'"
diff --git a/src/main/java/de/thm/arsnova/entities/PossibleAnswer.java b/src/main/java/de/thm/arsnova/entities/PossibleAnswer.java
index acfea0d3de09a13c2d1e469de0963c85714d110d..ebc36f98e9c2f88d9ac05668ae808a01170289fb 100644
--- a/src/main/java/de/thm/arsnova/entities/PossibleAnswer.java
+++ b/src/main/java/de/thm/arsnova/entities/PossibleAnswer.java
@@ -23,6 +23,7 @@ public class PossibleAnswer {
 	private String id;
 	private String text;
 	private boolean correct;
+	private int value;
 
 	public String getId() {
 		return this.id;
@@ -48,6 +49,14 @@ public class PossibleAnswer {
 		this.correct = correct;
 	}
 
+	public int getValue() {
+		return value;
+	}
+
+	public void setValue(int value) {
+		this.value = value;
+	}
+
 	@Override
 	public String toString() {
 		return "PossibleAnswer [id=" + id + ", text=" + text + ", correct=" + correct + "]";
diff --git a/src/main/java/de/thm/arsnova/entities/Question.java b/src/main/java/de/thm/arsnova/entities/Question.java
index 33c2e59a14ac3385e6f4e44cf695a80a3c0b8d47..8b2d36e30c75c655eec2f7fdc76b95bffe0060fe 100644
--- a/src/main/java/de/thm/arsnova/entities/Question.java
+++ b/src/main/java/de/thm/arsnova/entities/Question.java
@@ -44,6 +44,12 @@ public class Question {
 	private String _id;
 	private String _rev;
 
+	private String image;
+	private int gridSize;
+	private int offsetX;
+	private int offsetY;
+	private int zoomLvl;
+
 	public final String getType() {
 		return type;
 	}
@@ -212,6 +218,46 @@ public class Question {
 		this._rev = _rev;
 	}
 
+	public String getImage() {
+		return image;
+	}
+
+	public void setImage(String image) {
+		this.image = image;
+	}
+
+	public int getGridSize() {
+		return gridSize;
+	}
+
+	public void setGridSize(int gridSize) {
+		this.gridSize = gridSize;
+	}
+
+	public int getOffsetX() {
+		return offsetX;
+	}
+
+	public void setOffsetX(int offsetX) {
+		this.offsetX = offsetX;
+	}
+
+	public int getOffsetY() {
+		return offsetY;
+	}
+
+	public void setOffsetY(int offsetY) {
+		this.offsetY = offsetY;
+	}
+
+	public int getZoomLvl() {
+		return zoomLvl;
+	}
+
+	public void setZoomLvl(int zoomLvl) {
+		this.zoomLvl = zoomLvl;
+	}
+
 	@Override
 	public final String toString() {
 		return "Question type '" + this.type + "': " + this.subject + ";\n" + this.text + this.possibleAnswers;
diff --git a/src/main/java/de/thm/arsnova/services/ISessionService.java b/src/main/java/de/thm/arsnova/services/ISessionService.java
index d868e4bc1b75c68de8986bcdb7f5bb9fb2f85f7a..611f3ce91aece07210e2472c8f709316a05f80ad 100644
--- a/src/main/java/de/thm/arsnova/services/ISessionService.java
+++ b/src/main/java/de/thm/arsnova/services/ISessionService.java
@@ -51,4 +51,8 @@ public interface ISessionService {
 	Session updateSession(String sessionkey, Session session);
 
 	void deleteSession(String sessionkey, User user);
+
+	int getLearningProgress(String sessionkey);
+
+	int getMyLearningProgress(String sessionkey);
 }
diff --git a/src/main/java/de/thm/arsnova/services/QuestionService.java b/src/main/java/de/thm/arsnova/services/QuestionService.java
index 0467de78e4aa89783df70616385df70ea61b6aab..f91da75e999fb8f84ae0589072373c8325b2a9a1 100644
--- a/src/main/java/de/thm/arsnova/services/QuestionService.java
+++ b/src/main/java/de/thm/arsnova/services/QuestionService.java
@@ -24,9 +24,13 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 
+import de.thm.arsnova.ImageUtils;
 import de.thm.arsnova.annotation.Authenticated;
 import de.thm.arsnova.dao.IDatabaseDao;
 import de.thm.arsnova.entities.Answer;
@@ -35,6 +39,7 @@ import de.thm.arsnova.entities.InterposedReadingCount;
 import de.thm.arsnova.entities.Question;
 import de.thm.arsnova.entities.Session;
 import de.thm.arsnova.entities.User;
+import de.thm.arsnova.exceptions.BadRequestException;
 import de.thm.arsnova.exceptions.ForbiddenException;
 import de.thm.arsnova.exceptions.NotFoundException;
 import de.thm.arsnova.exceptions.UnauthorizedException;
@@ -51,6 +56,11 @@ public class QuestionService implements IQuestionService {
 
 	@Autowired
 	private ARSnovaSocketIOServer socketIoServer;
+	
+	@Value("${upload.filesize_b}")
+	private int uploadFileSizeByte;
+	
+	public static final Logger LOGGER = LoggerFactory.getLogger(QuestionService.class);
 
 	public void setDatabaseDao(IDatabaseDao databaseDao) {
 		this.databaseDao = databaseDao;
@@ -86,6 +96,25 @@ public class QuestionService implements IQuestionService {
 		} else if (question.getPiRound() < 1 || question.getPiRound() > 2) {
 			question.setPiRound(1);
 		}
+		
+		// convert imageurl to base64 if neccessary
+		if ("grid".equals(question.getQuestionType())) {
+			org.slf4j.Logger logger = LoggerFactory.getLogger(QuestionService.class);
+			if (question.getImage().startsWith("http")) {
+				String base64ImageString = ImageUtils.encodeImageToString(question.getImage());
+				if (base64ImageString == null) {
+					throw new BadRequestException();
+				}
+				question.setImage(base64ImageString);
+			}
+			
+			// base64 adds offset to filesize, formular taken from: http://en.wikipedia.org/wiki/Base64#MIME
+			int fileSize =  (int)((question.getImage().length()-814)/1.37);
+			if ( fileSize > this.uploadFileSizeByte ) {
+				LOGGER.error("Could not save file. File is too large with "+ fileSize + " Byte.");
+				throw new BadRequestException();
+			}
+		}
 
 		Question result = this.databaseDao.saveQuestion(session, question);
 		socketIoServer.reportLecturerQuestionAvailable(result.getSessionKeyword(), result.get_id());
diff --git a/src/main/java/de/thm/arsnova/services/SessionService.java b/src/main/java/de/thm/arsnova/services/SessionService.java
index e9e6af9b97eb11a115f681484eebdfca9a5ecc57..205ee49b743cfafe17347bbed23d3c8deca2323e 100644
--- a/src/main/java/de/thm/arsnova/services/SessionService.java
+++ b/src/main/java/de/thm/arsnova/services/SessionService.java
@@ -256,4 +256,19 @@ public class SessionService implements ISessionService {
 		}
 		databaseDao.deleteSession(session);
 	}
+
+	@Override
+	@Authenticated
+	public int getLearningProgress(String sessionkey) {
+		Session session = databaseDao.getSession(sessionkey);
+		return databaseDao.getLearningProgress(session);
+	}
+
+	@Override
+	@Authenticated
+	public int getMyLearningProgress(String sessionkey) {
+		Session session = databaseDao.getSession(sessionkey);
+		User user = userService.getCurrentUser();
+		return databaseDao.getMyLearningProgress(session, user);
+	}
 }
diff --git a/src/main/java/de/thm/arsnova/web/CorsFilter.java b/src/main/java/de/thm/arsnova/web/CorsFilter.java
new file mode 100644
index 0000000000000000000000000000000000000000..fc2e55f393103ae8fbbb6d17df6a05f4fa61af12
--- /dev/null
+++ b/src/main/java/de/thm/arsnova/web/CorsFilter.java
@@ -0,0 +1,29 @@
+package de.thm.arsnova.web;
+
+import java.io.IOException;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.stereotype.Component;
+import org.springframework.web.filter.OncePerRequestFilter;
+
+@Component
+public class CorsFilter extends OncePerRequestFilter {
+
+	@Override
+	protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
+			throws ServletException, IOException {
+		response.addHeader("Access-Control-Allow-Credentials", "true");
+		response.addHeader("Access-Control-Allow-Methods", "GET");
+		response.addHeader("Access-Control-Allow-Headers", "Content-Type, Authorization, X-Requested-With");
+
+		if (request.getHeader("origin") != null) {
+			response.addHeader("Access-Control-Allow-Origin", request.getHeader("origin"));
+		}
+
+		filterChain.doFilter(request, response);
+	}
+}
diff --git a/src/main/webapp/WEB-INF/spring/arsnova-servlet.xml b/src/main/webapp/WEB-INF/spring/arsnova-servlet.xml
index 9c20a5817520dbc5707fd3750cc786f7a739d5ef..1c3c4a18ef671d045bd04421cf4ba5e9590be830 100644
--- a/src/main/webapp/WEB-INF/spring/arsnova-servlet.xml
+++ b/src/main/webapp/WEB-INF/spring/arsnova-servlet.xml
@@ -11,56 +11,65 @@
 		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd">
 
 	<!-- ARSnova Servlet Context -->
-	
-	<context:component-scan base-package="de.thm.arsnova.controller" />
+
+	<context:component-scan base-package="de.thm.arsnova.controller,de.thm.arsnova.web" />
 	<context:property-placeholder location="file:///etc/arsnova/arsnova.properties" file-encoding="UTF-8" />
-	<mvc:annotation-driven content-negotiation-manager="contentNegotiationManager" />
-	
-	<bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
-	    <property name="favorPathExtension" value="false" />
-	    <property name="favorParameter" value="true" />
-	    <property name="mediaTypes" >
-	        <value>
-	        	html=text/html
-	          	json=application/json
-	        </value>
-	    </property>
+	<mvc:annotation-driven
+		content-negotiation-manager="contentNegotiationManager" />
+
+	<bean id="contentNegotiationManager"
+		class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
+		<property name="favorPathExtension" value="false" />
+		<property name="favorParameter" value="true" />
+		<property name="mediaTypes">
+			<value>
+				html=text/html
+				json=application/json
+			</value>
+		</property>
 	</bean>
 
 	<mvc:annotation-driven />
 	<mvc:resources mapping="/**" location="/" />
-	
+
 	<!-- -->
-	<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" />
-	<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
+	<bean
+		class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" />
+	<bean
+		class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
 		<property name="messageConverters">
 			<list>
-	            <bean class = "org.springframework.http.converter.StringHttpMessageConverter">
-	                <property name="supportedMediaTypes" value = "text/plain;charset=UTF-8" />
-	            </bean>
-				<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter" />
+				<bean
+					class="org.springframework.http.converter.StringHttpMessageConverter">
+					<property name="supportedMediaTypes" value="text/plain;charset=UTF-8" />
+				</bean>
+				<bean
+					class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter" />
 			</list>
 		</property>
 	</bean>
 	<!-- -->
 
-	<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
-		<property name="viewResolvers">  
-			<list>  
-				<bean class="org.springframework.web.servlet.view.UrlBasedViewResolver">  
-					<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>  
-					<property name="prefix" value="/WEB-INF/jsp/"/>  
-					<property name="suffix" value=".jsp"/>  
-				</bean>  
-		    </list>  
-		</property>  
-		<property name="defaultViews">  
-			<list>  
-				<bean class="org.springframework.web.servlet.view.json.MappingJackson2JsonView">  
-					<property name="prefixJson" value="false"/>  
-				</bean>  
-			</list>  
-		</property>  
+	<bean
+		class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
+		<property name="viewResolvers">
+			<list>
+				<bean class="org.springframework.web.servlet.view.UrlBasedViewResolver">
+					<property name="viewClass"
+						value="org.springframework.web.servlet.view.JstlView" />
+					<property name="prefix" value="/WEB-INF/jsp/" />
+					<property name="suffix" value=".jsp" />
+				</bean>
+			</list>
+		</property>
+		<property name="defaultViews">
+			<list>
+				<bean
+					class="org.springframework.web.servlet.view.json.MappingJackson2JsonView">
+					<property name="prefixJson" value="false" />
+				</bean>
+			</list>
+		</property>
 	</bean>
-	
+
 </beans>
diff --git a/src/main/webapp/WEB-INF/spring/spring-main.xml b/src/main/webapp/WEB-INF/spring/spring-main.xml
index 384e0a721d19bd74bc2d7e12a5cb73fdc4f14c26..72d0f00e72f8cc69868a1949b1070d03a38b029e 100644
--- a/src/main/webapp/WEB-INF/spring/spring-main.xml
+++ b/src/main/webapp/WEB-INF/spring/spring-main.xml
@@ -25,14 +25,14 @@
 		</property>
 		<property name="fileEncoding" value="UTF-8" />
 	</bean>
-	
+
 	<import resource="spring-security.xml" />
 
 	<context:component-scan base-package="de.thm.arsnova.dao,de.thm.arsnova.events,de.thm.arsnova.security,de.thm.arsnova.services" />
 	<context:annotation-config />
 
 	<task:annotation-driven />
-	
+
 	<aop:aspectj-autoproxy>
 		<aop:include name="authorizationAdviser" />
 		<aop:include name="userSessionAspect" />
@@ -42,11 +42,11 @@
 		init-method="startServer" destroy-method="stopServer" scope="singleton"
 		p:portNumber="${socketio.port}" p:hostIp="${socketio.ip}" p:useSSL="${security.ssl}" p:keystore="${security.keystore}"
 		p:storepass="${security.storepass}" />
-		
+
 	<bean id="authorizationAdviser" class="de.thm.arsnova.aop.AuthorizationAdviser">
 		<property name="userService" ref="userService" />
 	</bean>
-	
+
 	<bean id="userSessionAspect" class="de.thm.arsnova.aop.UserSessionAspect" />
 
 	<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml
index 8ebba29fa000ab97ff476a88dd6dc00bcb439785..75b4f85dfa2d9be9d897517d4ce23c473a78bce5 100644
--- a/src/main/webapp/WEB-INF/web.xml
+++ b/src/main/webapp/WEB-INF/web.xml
@@ -58,6 +58,15 @@
 		<listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</listener-class>
 	</listener>
 
+	<filter>
+		<filter-name>corsFilter</filter-name>
+		<filter-class>de.thm.arsnova.web.CorsFilter</filter-class>
+	</filter>
+	<filter-mapping>
+		<filter-name>corsFilter</filter-name>
+		<url-pattern>/*</url-pattern>
+	</filter-mapping>
+
 	<mime-mapping>
 		<extension>manifest</extension>
 		<mime-type>text/cache-manifest</mime-type>
diff --git a/src/main/webapp/arsnova.properties.example b/src/main/webapp/arsnova.properties.example
index 76a0efbc0476e43aae1c6b97b698ab0c8ea79ce0..9fa91c0b6001648560e0fdf8ca60d7599a149e55 100644
--- a/src/main/webapp/arsnova.properties.example
+++ b/src/main/webapp/arsnova.properties.example
@@ -60,6 +60,9 @@ mail.host=
 # minutes, after which the feedback is deleted
 feedback.cleanup=10
 
+# maximal filesize in bytes
+upload.filesize_b=1048576
+
 couchdb.host=localhost
 couchdb.port=5984
 couchdb.name=arsnova
diff --git a/src/test/java/de/thm/arsnova/dao/StubDatabaseDao.java b/src/test/java/de/thm/arsnova/dao/StubDatabaseDao.java
index a93f1bcc38a4720e6558a76d6a55c374798829f8..dbc071b24c46faa3d3bbf49608f48c8a62dd23cf 100644
--- a/src/test/java/de/thm/arsnova/dao/StubDatabaseDao.java
+++ b/src/test/java/de/thm/arsnova/dao/StubDatabaseDao.java
@@ -510,4 +510,16 @@ public class StubDatabaseDao implements IDatabaseDao {
 		// TODO Auto-generated method stub
 		return null;
 	}
+
+	@Override
+	public int getLearningProgress(Session session) {
+		// TODO Auto-generated method stub
+		return 0;
+	}
+
+	@Override
+	public int getMyLearningProgress(Session session, User user) {
+		// TODO Auto-generated method stub
+		return 0;
+	}
 }
diff --git a/src/test/resources/arsnova.properties.example b/src/test/resources/arsnova.properties.example
index 76a0efbc0476e43aae1c6b97b698ab0c8ea79ce0..9fa91c0b6001648560e0fdf8ca60d7599a149e55 100644
--- a/src/test/resources/arsnova.properties.example
+++ b/src/test/resources/arsnova.properties.example
@@ -60,6 +60,9 @@ mail.host=
 # minutes, after which the feedback is deleted
 feedback.cleanup=10
 
+# maximal filesize in bytes
+upload.filesize_b=1048576
+
 couchdb.host=localhost
 couchdb.port=5984
 couchdb.name=arsnova