diff --git a/lib/private/files.php b/lib/private/files.php
index b9fd1093319ac95f4ed40d95fd5b44fcfe548365..6268bf8a129fac5ab8887b8d64e490941e169c1e 100644
--- a/lib/private/files.php
+++ b/lib/private/files.php
@@ -269,37 +269,34 @@ class OC_Files {
 	 * set the maximum upload size limit for apache hosts using .htaccess
 	 *
 	 * @param int $size file size in bytes
+	 * @param array $files override '.htaccess' and '.user.ini' locations
 	 * @return bool false on failure, size on success
 	 */
-	static function setUploadLimit($size) {
+	public static function setUploadLimit($size, $files = []) {
 		//don't allow user to break his config
-		if ($size > PHP_INT_MAX) {
-			//max size is always 1 byte lower than computerFileSize returns
-			if ($size > PHP_INT_MAX + 1)
-				return false;
-			$size -= 1;
-		}
+		$size = intval($size);
 		if ($size < self::UPLOAD_MIN_LIMIT_BYTES) {
 			return false;
 		}
 		$size = OC_Helper::phpFileSize($size);
 
-		//don't allow user to break his config -- broken or malicious size input
-		if (intval($size) === 0) {
-			return false;
-		}
-
 		$phpValueKeys = array(
 			'upload_max_filesize',
 			'post_max_size'
 		);
 
+		// default locations if not overridden by $files
+		$files = array_merge([
+			'.htaccess' => OC::$SERVERROOT . '/.htaccess',
+			'.user.ini' => OC::$SERVERROOT . '/.user.ini'
+		], $files);
+
 		$updateFiles = [
-			OC::$SERVERROOT . '/.htaccess' => [
+			$files['.htaccess'] => [
 				'pattern' => '/php_value %1$s (\S)*/',
 				'setting' => 'php_value %1$s %2$s'
 			],
-			OC::$SERVERROOT . '/.user.ini' => [
+			$files['.user.ini'] => [
 				'pattern' => '/%1$s=(\S)*/',
 				'setting' => '%1$s=%2$s'
 			]
diff --git a/tests/data/setUploadLimit/htaccess b/tests/data/setUploadLimit/htaccess
new file mode 100644
index 0000000000000000000000000000000000000000..65957a2983834b858bc7b56db2868c1bc54a3aae
--- /dev/null
+++ b/tests/data/setUploadLimit/htaccess
@@ -0,0 +1,60 @@
+# Version: 8.2.0
+<IfModule mod_headers.c>
+  <IfModule mod_fcgid.c>
+    <IfModule mod_setenvif.c>
+       SetEnvIfNoCase ^Authorization$ "(.+)" XAUTHORIZATION=$1
+       RequestHeader set XAuthorization %{XAUTHORIZATION}e env=XAUTHORIZATION
+    </IfModule>
+  </IfModule>
+
+  <IfModule mod_env.c>
+    # Add security and privacy related headers
+    Header set X-Content-Type-Options "nosniff"
+    Header set X-XSS-Protection "1; mode=block"
+    Header set X-Robots-Tag "none"
+    Header set X-Frame-Options "SAMEORIGIN"
+    SetEnv modHeadersAvailable true
+  </IfModule>
+
+  # Add cache control for CSS and JS files
+  <FilesMatch "\.(css|js)$">
+    Header set Cache-Control "max-age=7200, public"
+  </FilesMatch>
+</IfModule>
+<IfModule mod_php5.c>
+php_value upload_max_filesize 513M
+php_value post_max_size 513M
+php_value memory_limit 512M
+php_value mbstring.func_overload 0
+php_value always_populate_raw_post_data -1
+php_value default_charset 'UTF-8'
+php_value output_buffering off
+<IfModule mod_env.c>
+  SetEnv htaccessWorking true
+</IfModule>
+</IfModule>
+<IfModule mod_rewrite.c>
+RewriteEngine on
+RewriteRule .* - [env=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
+RewriteRule ^\.well-known/host-meta /public.php?service=host-meta [QSA,L]
+RewriteRule ^\.well-known/host-meta\.json /public.php?service=host-meta-json [QSA,L]
+RewriteRule ^\.well-known/carddav /remote.php/carddav/ [R=301,L]
+RewriteRule ^\.well-known/caldav /remote.php/caldav/ [R=301,L]
+RewriteRule ^apps/calendar/caldav\.php remote.php/caldav/ [QSA,L]
+RewriteRule ^apps/contacts/carddav\.php remote.php/carddav/ [QSA,L]
+RewriteRule ^remote/(.*) remote.php [QSA,L]
+RewriteRule ^(build|tests|config|lib|3rdparty|templates)/.* - [R=404,L]
+RewriteRule ^(\.|autotest|occ|issue|indie|db_|console).* - [R=404,L]
+</IfModule>
+<IfModule mod_mime.c>
+AddType image/svg+xml svg svgz
+AddEncoding gzip svgz
+</IfModule>
+<IfModule mod_dir.c>
+DirectoryIndex index.php index.html
+</IfModule>
+AddDefaultCharset utf-8
+Options -Indexes
+<IfModule pagespeed_module>
+  ModPagespeed Off
+</IfModule>
diff --git a/tests/data/setUploadLimit/user.ini b/tests/data/setUploadLimit/user.ini
new file mode 100644
index 0000000000000000000000000000000000000000..c5996e8d47e852173cb054e2414d612fd6be7269
--- /dev/null
+++ b/tests/data/setUploadLimit/user.ini
@@ -0,0 +1,7 @@
+upload_max_filesize=513M
+post_max_size=513M
+memory_limit=512M
+mbstring.func_overload=0
+always_populate_raw_post_data=-1
+default_charset='UTF-8'
+output_buffering=off
diff --git a/tests/lib/files.php b/tests/lib/files.php
new file mode 100644
index 0000000000000000000000000000000000000000..6808b3e9f645a609e0bb5ae46d681f5afbdd8355
--- /dev/null
+++ b/tests/lib/files.php
@@ -0,0 +1,135 @@
+<?php
+/**
+ * @author Robin McCorkell <rmccorkell@karoshi.org.uk>
+ *
+ * @copyright Copyright (c) 2015, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library 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 AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Test;
+
+class Files extends \Test\TestCase {
+
+	const UPLOAD_LIMIT_DEFAULT_STR = '513M';
+	const UPLOAD_LIMIT_SETTING_STR = '2M';
+	const UPLOAD_LIMIT_SETTING_BYTES = 2097152;
+
+	/** @var array $tmpDirs */
+	private $tmpDirs = [];
+
+	/**
+	 * @return array
+	 */
+	private function getUploadLimitTestFiles() {
+		$dir = \OC::$server->getTempManager()->getTemporaryFolder();
+		$this->tmpDirs[] = $dir;
+		$result = [
+			'.htaccess' => $dir . '/htaccess',
+			'.user.ini' => $dir . '/user.ini'
+		];
+		copy(\OC::$SERVERROOT . '/tests/data/setUploadLimit/htaccess', $result['.htaccess']);
+		copy(\OC::$SERVERROOT . '/tests/data/setUploadLimit/user.ini', $result['.user.ini']);
+		return $result;
+	}
+
+	protected function tearDown() {
+		foreach ($this->tmpDirs as $dir) {
+			\OC_Helper::rmdirr($dir);
+		}
+		parent::tearDown();
+	}
+
+	public function testSetUploadLimitSizeSanity() {
+		$this->assertFalse(\OC_Files::setUploadLimit(PHP_INT_MAX + 10));
+		$this->assertFalse(\OC_Files::setUploadLimit(\OC_Files::UPLOAD_MIN_LIMIT_BYTES - 10));
+		$this->assertFalse(\OC_Files::setUploadLimit('foobar'));
+	}
+
+	public function setUploadLimitWriteProvider() {
+		return [
+			[
+				// both files writable
+				true, true,
+				self::UPLOAD_LIMIT_SETTING_BYTES, self::UPLOAD_LIMIT_SETTING_BYTES,
+				self::UPLOAD_LIMIT_SETTING_STR, self::UPLOAD_LIMIT_SETTING_STR
+			],
+			[
+				// neither file writable
+				false, false,
+				self::UPLOAD_LIMIT_SETTING_BYTES, false,
+				self::UPLOAD_LIMIT_DEFAULT_STR, self::UPLOAD_LIMIT_DEFAULT_STR
+			],
+			[
+				// only .htaccess writable
+				true, false,
+				self::UPLOAD_LIMIT_SETTING_BYTES, false,
+				self::UPLOAD_LIMIT_SETTING_STR, self::UPLOAD_LIMIT_DEFAULT_STR
+			],
+			[
+				// only .user.ini writable
+				false, true,
+				self::UPLOAD_LIMIT_SETTING_BYTES, false,
+				self::UPLOAD_LIMIT_DEFAULT_STR, self::UPLOAD_LIMIT_SETTING_STR
+			],
+			[
+				// test rounding of values
+				true, true,
+				self::UPLOAD_LIMIT_SETTING_BYTES + 20, self::UPLOAD_LIMIT_SETTING_BYTES,
+				self::UPLOAD_LIMIT_SETTING_STR, self::UPLOAD_LIMIT_SETTING_STR
+			]
+		];
+	}
+
+	/**
+	 * @dataProvider setUploadLimitWriteProvider
+	 */
+	public function testSetUploadLimitWrite(
+		$htaccessWritable, $userIniWritable,
+		$setSize, $expectedSize,
+		$htaccessStr, $userIniStr
+	) {
+		$files = $this->getUploadLimitTestFiles();
+		chmod($files['.htaccess'], ($htaccessWritable ? 0644 : 0444));
+		chmod($files['.user.ini'], ($userIniWritable ? 0644 : 0444));
+
+		$htaccessSize = filesize($files['.htaccess']);
+		$userIniSize = filesize($files['.user.ini']);
+		$htaccessSizeMod = 2*(strlen($htaccessStr) - strlen(self::UPLOAD_LIMIT_DEFAULT_STR));
+		$userIniSizeMod = 2*(strlen($userIniStr) - strlen(self::UPLOAD_LIMIT_DEFAULT_STR));
+
+		$this->assertEquals($expectedSize, \OC_Files::setUploadLimit($setSize, $files));
+
+		// check file contents
+		$htaccess = file_get_contents($files['.htaccess']);
+		$this->assertEquals(1,
+			preg_match('/php_value upload_max_filesize '.$htaccessStr.'/', $htaccess)
+		);
+		$this->assertEquals(1,
+			preg_match('/php_value post_max_size '.$htaccessStr.'/', $htaccess)
+		);
+		$this->assertEquals($htaccessSize + $htaccessSizeMod, filesize($files['.htaccess']));
+
+		$userIni = file_get_contents($files['.user.ini']);
+		$this->assertEquals(1,
+			preg_match('/upload_max_filesize='.$userIniStr.'/', $userIni)
+		);
+		$this->assertEquals(1,
+			preg_match('/post_max_size='.$userIniStr.'/', $userIni)
+		);
+		$this->assertEquals($userIniSize + $userIniSizeMod, filesize($files['.user.ini']));
+	}
+}