diff --git a/apps/files/ajax/scan.php b/apps/files/ajax/scan.php
index 0706d4e78296b0afdd677e8072cd61266bdcdfce..5b32b6db9b72ad27b8c383ec3acc243c1b7fe891 100644
--- a/apps/files/ajax/scan.php
+++ b/apps/files/ajax/scan.php
@@ -16,72 +16,56 @@ if (isset($_GET['users'])) {
 }
 
 $eventSource = new OC_EventSource();
-ScanListener::$eventSource = $eventSource;
-ScanListener::$view = \OC\Files\Filesystem::getView();
-
-OC_Hook::connect('\OC\Files\Cache\Scanner', 'scan_folder', 'ScanListener', 'folder');
-OC_Hook::connect('\OC\Files\Cache\Scanner', 'scan_file', 'ScanListener', 'file');
+$listener = new ScanListener($eventSource);
 
 foreach ($users as $user) {
 	$eventSource->send('user', $user);
-	OC_Util::tearDownFS();
-	OC_Util::setupFS($user);
-
-	$absolutePath = \OC\Files\Filesystem::getView()->getAbsolutePath($dir);
-
-	$mountPoints = \OC\Files\Filesystem::getMountPoints($absolutePath);
-	$mountPoints[] = \OC\Files\Filesystem::getMountPoint($absolutePath);
-	$mountPoints = array_reverse($mountPoints); //start with the mount point of $dir
-
-	foreach ($mountPoints as $mountPoint) {
-		$storage = \OC\Files\Filesystem::getStorage($mountPoint);
-		if ($storage) {
-			ScanListener::$mountPoints[$storage->getId()] = $mountPoint;
-			$scanner = $storage->getScanner();
-			if ($force) {
-				$scanner->scan('', \OC\Files\Cache\Scanner::SCAN_RECURSIVE, \OC\Files\Cache\Scanner::REUSE_ETAG);
-			} else {
-				$scanner->backgroundScan();
-			}
-		}
+	$scanner = new \OC\Files\Utils\Scanner($user);
+	$scanner->listen('\OC\Files\Utils\Scanner', 'scanFile', array($listener, 'file'));
+	$scanner->listen('\OC\Files\Utils\Scanner', 'scanFolder', array($listener, 'folder'));
+	if ($force) {
+		$scanner->scan($dir);
+	} else {
+		$scanner->backgroundScan($dir);
 	}
 }
 
-$eventSource->send('done', ScanListener::$fileCount);
+$eventSource->send('done', $listener->getCount());
 $eventSource->close();
 
 class ScanListener {
 
-	static public $fileCount = 0;
-	static public $lastCount = 0;
+	private $fileCount = 0;
+	private $lastCount = 0;
 
 	/**
-	 * @var \OC\Files\View $view
+	 * @var \OC_EventSource event source to pass events to
 	 */
-	static public $view;
+	private $eventSource;
 
 	/**
-	 * @var array $mountPoints map storage ids to mountpoints
+	 * @param \OC_EventSource $eventSource
 	 */
-	static public $mountPoints = array();
+	public function __construct($eventSource) {
+		$this->eventSource = $eventSource;
+	}
 
 	/**
-	 * @var \OC_EventSource event source to pass events to
+	 * @param string $path
 	 */
-	static public $eventSource;
-
-	static function folder($params) {
-		$internalPath = $params['path'];
-		$mountPoint = self::$mountPoints[$params['storage']];
-		$path = self::$view->getRelativePath($mountPoint . $internalPath);
-		self::$eventSource->send('folder', $path);
+	public function folder($path) {
+		$this->eventSource->send('folder', $path);
 	}
 
-	static function file() {
-		self::$fileCount++;
-		if (self::$fileCount > self::$lastCount + 20) { //send a count update every 20 files
-			self::$lastCount = self::$fileCount;
-			self::$eventSource->send('count', self::$fileCount);
+	public function file() {
+		$this->fileCount++;
+		if ($this->fileCount > $this->lastCount + 20) { //send a count update every 20 files
+			$this->lastCount = $this->fileCount;
+			$this->eventSource->send('count', $this->fileCount);
 		}
 	}
+
+	public function getCount() {
+		return $this->fileCount;
+	}
 }
diff --git a/lib/eventsource.php b/lib/eventsource.php
index 31d6edc1874cbd44f94a152a76f917c19eb01783..a83084d92514af6276d6ac4c7cfd8c64d1d8612c 100644
--- a/lib/eventsource.php
+++ b/lib/eventsource.php
@@ -53,7 +53,7 @@ class OC_EventSource{
 	/**
 	 * send a message to the client
 	 * @param string $type
-	 * @param object $data
+	 * @param mixed $data
 	 *
 	 * if only one parameter is given, a typeless message will be send with that parameter as data
 	 */
diff --git a/lib/files/cache/scanner.php b/lib/files/cache/scanner.php
index 9b94a24f48123e3e6e20eb1c531cb2ab23f6cfd1..bcd6032fcac7649e108afc5c72607451936deb48 100644
--- a/lib/files/cache/scanner.php
+++ b/lib/files/cache/scanner.php
@@ -9,8 +9,18 @@
 namespace OC\Files\Cache;
 
 use OC\Files\Filesystem;
+use OC\Hooks\BasicEmitter;
 
-class Scanner {
+/**
+ * Class Scanner
+ *
+ * Hooks available in scope \OC\Files\Cache\Scanner:
+ *  - scanFile(string $path, string $storageId)
+ *  - scanFolder(string $path, string $storageId)
+ *
+ * @package OC\Files\Cache
+ */
+class Scanner extends BasicEmitter {
 	/**
 	 * @var \OC\Files\Storage\Storage $storage
 	 */
@@ -71,6 +81,7 @@ class Scanner {
 		if (!self::isPartialFile($file)
 			and !Filesystem::isFileBlacklisted($file)
 		) {
+			$this->emit('\OC\Files\Cache\Scanner', 'scanFile', array($file, $this->storageId));
 			\OC_Hook::emit('\OC\Files\Cache\Scanner', 'scan_file', array('path' => $file, 'storage' => $this->storageId));
 			$data = $this->getData($file);
 			if ($data) {
@@ -134,7 +145,7 @@ class Scanner {
 		if ($reuse === -1) {
 			$reuse = ($recursive === self::SCAN_SHALLOW) ? self::REUSE_ETAG | self::REUSE_SIZE : 0;
 		}
-		\OC_Hook::emit('\OC\Files\Cache\Scanner', 'scan_folder', array('path' => $path, 'storage' => $this->storageId));
+		$this->emit('\OC\Files\Cache\Scanner', 'scanFolder', array($path, $this->storageId));
 		$size = 0;
 		$childQueue = array();
 		$existingChildren = array();
diff --git a/lib/files/filesystem.php b/lib/files/filesystem.php
index 1bf7270c7f17422a787deb6f67cf7c504f83b7d7..d6ebe7d629a6d90e00332e7179f242de678c1f79 100644
--- a/lib/files/filesystem.php
+++ b/lib/files/filesystem.php
@@ -148,13 +148,20 @@ class Filesystem {
 	 */
 	private static $loader;
 
-	public static function getLoader(){
+	public static function getLoader() {
 		if (!self::$loader) {
 			self::$loader = new Loader();
 		}
 		return self::$loader;
 	}
 
+	public static function getMountManager() {
+		if (!self::$mounts) {
+			\OC_Util::setupFS();
+		}
+		return self::$mounts;
+	}
+
 	/**
 	 * get the mountpoint of the storage object for a path
 	 * ( note: because a storage is not always mounted inside the fakeroot, the
diff --git a/lib/files/utils/scanner.php b/lib/files/utils/scanner.php
new file mode 100644
index 0000000000000000000000000000000000000000..800bb64993429ba5f5dba1bd7149ac419f1984ab
--- /dev/null
+++ b/lib/files/utils/scanner.php
@@ -0,0 +1,89 @@
+<?php
+/**
+ * Copyright (c) 2013 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+namespace OC\Files\Utils;
+
+use OC\Hooks\BasicEmitter;
+use OC\Files\Filesystem;
+
+/**
+ * Class Scanner
+ *
+ * Hooks available in scope \OC\Utils\Scanner
+ *  - scanFile(string $absolutePath)
+ *  - scanFolder(string $absolutePath)
+ *
+ * @package OC\Files\Utils
+ */
+class Scanner extends BasicEmitter {
+	/**
+	 * @var string $user
+	 */
+	private $user;
+
+	/**
+	 * @param string $user
+	 */
+	public function __construct($user) {
+		$this->user = $user;
+	}
+
+	/**
+	 * get all storages for $dir
+	 *
+	 * @param string $dir
+	 * @return \OC\Files\Mount\Mount[]
+	 */
+	protected function getMounts($dir) {
+		//TODO: move to the node based fileapi once that's done
+		\OC_Util::tearDownFS();
+		\OC_Util::setupFS($this->user);
+		$absolutePath = Filesystem::getView()->getAbsolutePath($dir);
+
+		$mountManager = Filesystem::getMountManager();
+		$mounts = $mountManager->findIn($absolutePath);
+		$mounts[] = $mountManager->find($absolutePath);
+		$mounts = array_reverse($mounts); //start with the mount of $dir
+
+		return $mounts;
+	}
+
+	/**
+	 * attach listeners to the scanner
+	 *
+	 * @param \OC\Files\Mount\Mount $mount
+	 */
+	protected function attachListener($mount) {
+		$scanner = $mount->getStorage()->getScanner();
+		$scanner->listen('\OC\Files\Cache\Scanner', 'scanFile', function ($path) use ($mount) {
+			$this->emit('\OC\Files\Utils\Scanner', 'scanFile', array($mount->getMountPoint() . $path));
+		});
+		$scanner->listen('\OC\Files\Cache\Scanner', 'scanFolder', function ($path) use ($mount) {
+			$this->emit('\OC\Files\Utils\Scanner', 'scanFolder', array($mount->getMountPoint() . $path));
+		});
+	}
+
+	public function backgroundScan($dir) {
+		$mounts = $this->getMounts($dir);
+		foreach ($mounts as $mount) {
+			$scanner = $mount->getStorage()->getScanner();
+			$this->attachListener($mount);
+			$scanner->backgroundScan();
+		}
+	}
+
+	public function scan($dir) {
+		$mounts = $this->getMounts($dir);
+		foreach ($mounts as $mount) {
+			$scanner = $mount->getStorage()->getScanner();
+			$this->attachListener($mount);
+			$scanner->scan('', \OC\Files\Cache\Scanner::SCAN_RECURSIVE, \OC\Files\Cache\Scanner::REUSE_ETAG);
+		}
+	}
+}
+