diff --git a/apps/admin_export/appinfo/info.xml b/apps/admin_export/appinfo/info.xml
index c4a2a9b398c4084b118d2ed127b75adcb2865c64..df8a07c2f5be7ec0985b7f7439909741a3cf4acf 100644
--- a/apps/admin_export/appinfo/info.xml
+++ b/apps/admin_export/appinfo/info.xml
@@ -7,4 +7,5 @@
 	<licence>AGPL</licence>
 	<author>Thomas Schmidt</author>
 	<require>2</require>
+	<default_enable/>
 </info>
diff --git a/apps/gallery/ajax/cover.php b/apps/gallery/ajax/cover.php
index d83f4daaa52ef0f0fac5f6b58b4aef2e9f33ec0e..181a919375db977f3eb1d20604343648887e44c6 100644
--- a/apps/gallery/ajax/cover.php
+++ b/apps/gallery/ajax/cover.php
@@ -1,4 +1,26 @@
 <?php
+
+/**
+* ownCloud - gallery application
+*
+* @author Bartek Przybylski
+* @copyright 2012 Bartek Przybylski bart.p.pl@gmail.com
+* 
+* 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 Lesser General Public 
+* License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+* 
+*/
+
 require_once('../../../lib/base.php');
 OC_JSON::checkLoggedIn();
 OC_JSON::checkAppEnabled('gallery');
diff --git a/apps/gallery/ajax/createAlbum.php b/apps/gallery/ajax/createAlbum.php
index 9413b54718abf46a9393ce957e6740182bb0b067..152f5834bcb4130d7f0f1db203c13f0aa521bbf0 100644
--- a/apps/gallery/ajax/createAlbum.php
+++ b/apps/gallery/ajax/createAlbum.php
@@ -1,4 +1,26 @@
 <?php
+
+/**
+* ownCloud - gallery application
+*
+* @author Bartek Przybylski
+* @copyright 2012 Bartek Przybylski bart.p.pl@gmail.com
+* 
+* 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 Lesser General Public 
+* License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+* 
+*/
+
 require_once('../../../lib/base.php');
 OC_JSON::checkLoggedIn();
 OC_JSON::checkAppEnabled('gallery');
diff --git a/apps/gallery/ajax/galleryOp.php b/apps/gallery/ajax/galleryOp.php
index cd7cab202b118eda196ccc00532116943d8fe73c..3d1ed1f33cbc26e063be9ddc976e2d9efc144741 100644
--- a/apps/gallery/ajax/galleryOp.php
+++ b/apps/gallery/ajax/galleryOp.php
@@ -1,6 +1,28 @@
 <?
+
+/**
+* ownCloud - gallery application
+*
+* @author Bartek Przybylski
+* @copyright 2012 Bartek Przybylski bart.p.pl@gmail.com
+* 
+* 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 Lesser General Public 
+* License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+* 
+*/
+
 require_once('../../../lib/base.php');
-require_once('../lib/album.php');
+require_once(OC::$CLASSPATH['OC_Gallery_Album']);
 OC_JSON::checkLoggedIn();
 OC_JSON::checkAppEnabled('gallery');
 
@@ -26,4 +48,4 @@ if ($_GET['operation']) {
      OC_JSON::error(array('cause' => "Unknown operation"));
   }
 }
-?>
\ No newline at end of file
+?>
diff --git a/apps/gallery/ajax/getAlbums.php b/apps/gallery/ajax/getAlbums.php
index e4736076fed346f5d30c4ea1d661b958f53f7551..9e9c6ef496c7b6a889db143a0ec1443da6d3341b 100644
--- a/apps/gallery/ajax/getAlbums.php
+++ b/apps/gallery/ajax/getAlbums.php
@@ -1,4 +1,26 @@
 <?php
+
+/**
+* ownCloud - gallery application
+*
+* @author Bartek Przybylski
+* @copyright 2012 Bartek Przybylski bart.p.pl@gmail.com
+* 
+* 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 Lesser General Public 
+* License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+* 
+*/
+
 require_once('../../../lib/base.php');
 OC_JSON::checkLoggedIn();
 OC_JSON::checkAppEnabled('gallery');
diff --git a/apps/gallery/ajax/getCovers.php b/apps/gallery/ajax/getCovers.php
index db7c8e9fcdec977aff344fe630741e46a0dc7f8d..4db73d0fbf3594dd510da0566f308f912f719ba3 100644
--- a/apps/gallery/ajax/getCovers.php
+++ b/apps/gallery/ajax/getCovers.php
@@ -1,4 +1,26 @@
 <?php
+
+/**
+* ownCloud - gallery application
+*
+* @author Bartek Przybylski
+* @copyright 2012 Bartek Przybylski bart.p.pl@gmail.com
+* 
+* 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 Lesser General Public 
+* License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+* 
+*/
+
 require_once('../../../lib/base.php');
 OC_JSON::checkLoggedIn();
 OC_JSON::checkAppEnabled('gallery');
diff --git a/apps/gallery/ajax/scanForAlbums.php b/apps/gallery/ajax/scanForAlbums.php
index f603cbb497173b95f02123f188db511552590494..b8ed639d9dc20ee5da64b26b73050f428bf25b24 100644
--- a/apps/gallery/ajax/scanForAlbums.php
+++ b/apps/gallery/ajax/scanForAlbums.php
@@ -1,10 +1,31 @@
 <?php
 
+/**
+* ownCloud - gallery application
+*
+* @author Bartek Przybylski
+* @copyright 2012 Bartek Przybylski bart.p.pl@gmail.com
+* 
+* 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 Lesser General Public 
+* License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+* 
+*/
+
 require_once('../../../lib/base.php');
 OC_JSON::checkLoggedIn();
 OC_JSON::checkAppEnabled('gallery');
 
 OC_Gallery_Scanner::cleanUp();
-OC_JSON::success(array('albums' => OC_Gallery_Scanner::scan('')));
+OC_JSON::success(array('albums' => OC_Gallery_Scanner::scan('/')));
 
 ?>
diff --git a/apps/gallery/ajax/thumbnail.php b/apps/gallery/ajax/thumbnail.php
index d937691fa036607b94b8b4a80d2213a5964d872b..6d25c7a2536ad146f352e26b73cd67ea4d39b1ae 100644
--- a/apps/gallery/ajax/thumbnail.php
+++ b/apps/gallery/ajax/thumbnail.php
@@ -1,4 +1,26 @@
 <?php
+
+/**
+* ownCloud - gallery application
+*
+* @author Bartek Przybylski
+* @copyright 2012 Bartek Przybylski bart.p.pl@gmail.com
+* 
+* 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 Lesser General Public 
+* License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+* 
+*/
+
 require_once('../../../lib/base.php');
 OC_JSON::checkLoggedIn();
 OC_JSON::checkAppEnabled('gallery');
diff --git a/apps/gallery/appinfo/app.php b/apps/gallery/appinfo/app.php
index 2b1ab857afcdacbe24dc0ef5f8d75582c0966160..9c665fd3500f34b6ffb3554a01d4a2ece3654cdf 100644
--- a/apps/gallery/appinfo/app.php
+++ b/apps/gallery/appinfo/app.php
@@ -1,7 +1,30 @@
 <?php
+
+/**
+* ownCloud - gallery application
+*
+* @author Bartek Przybylski
+* @copyright 2012 Bartek Przybylski bart.p.pl@gmail.com
+* 
+* 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 Lesser General Public 
+* License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+* 
+*/
+
 OC::$CLASSPATH['OC_Gallery_Album'] = 'apps/gallery/lib/album.php';
 OC::$CLASSPATH['OC_Gallery_Photo'] = 'apps/gallery/lib/photo.php';
 OC::$CLASSPATH['OC_Gallery_Scanner'] = 'apps/gallery/lib/scanner.php';
+OC::$CLASSPATH['OC_Gallery_Hooks_Handlers'] = 'apps/gallery/lib/hooks_handlers.php';
 
 OC_App::register(array(
   'order' => 20,
@@ -28,4 +51,6 @@ OC_App::addNavigationEntry( array(
 }
 
 new OC_GallerySearchProvider();
+
+require_once('apps/gallery/lib/hooks_handlers.php');
 ?>
diff --git a/apps/gallery/appinfo/database.xml b/apps/gallery/appinfo/database.xml
index fd55b3a6fb4cd320e8b3d8b34d11415185671d85..db88e4c1b5a875d0130894a16643806db423b1a4 100644
--- a/apps/gallery/appinfo/database.xml
+++ b/apps/gallery/appinfo/database.xml
@@ -27,6 +27,12 @@
 				<notnull>true</notnull>
 				<length>100</length>
 			</field>
+      <field>
+        <name>album_path</name>
+        <type>text</type>
+        <notnull>true</notnull>
+        <length>100</length>
+      </field>
 		</declaration>
 	</table>
 	<table>
diff --git a/apps/gallery/appinfo/info.xml b/apps/gallery/appinfo/info.xml
index 054ddb6f1398b544ce01bf1d1d0b296252aacd36..c275f39bb253c39a5772a2d05057d697427d01bf 100644
--- a/apps/gallery/appinfo/info.xml
+++ b/apps/gallery/appinfo/info.xml
@@ -2,9 +2,10 @@
 <info>
 	<id>gallery</id>
 	<name>Gallery</name>
-	<version>0.1</version>
+	<version>0.2</version>
 	<licence>AGPL</licence>
-	<author>Bartosz Przybylski</author>
+	<author>Bartek Przybylski</author>
 	<require>2</require>
-	<description></description>
-</info>
\ No newline at end of file
+	<description>Gallery application for ownCloud</description>
+	<default_enable/>
+</info>
diff --git a/apps/gallery/css/styles.css b/apps/gallery/css/styles.css
index 53c3c0901d96c6cf4f4ed82c78aa2596052bf6fb..cc343ba0d08515ffe3eff87cde109d03cc2433a4 100644
--- a/apps/gallery/css/styles.css
+++ b/apps/gallery/css/styles.css
@@ -1,60 +1,11 @@
-div#gallery_list {
-  margin: 90pt 20pt;
-}
-div#gallery_list.leftcontent {
-  padding-top: 15px;
-  margin: 0;
-  text-align: center;
-}
+div#gallery_list { margin: 90pt 20pt; }
+div#gallery_list.leftcontent { padding-top: 15px; margin: 0; text-align: center; }
+div#gallery_album_box { width: 200px; text-align: center; border: 0; display: inline-block; margin: 5pt; vertical-align: top; padding: 10px; border: solid 1px black; position: relative; overflow: hidden; color: #999; }
+div#gallery_album_box:hover { color: black; }
+.leftcontent div#gallery_album_box { margin: 5px; }
+div#gallery_album_box h1 { font-size: 12pt; font-family: Verdana; }
+div#gallery_album_cover { width: 199px; height: 199px; border: solid 1pt #999; padding: 0; }
+div#gallery_control_overlay { border: 0; position:absolute; right: 10pt; background-color: #333; opacity: 0.5; visibility:hidden; padding: 0 5pt; }
+div#gallery_control_overlay a { color:white; }
+#gallery_images { padding:10px 5px; }
 
-div#gallery_album_box {
-  width: 200px;
-  text-align: center;
-  border: 0;
-  display: inline-block;
-  margin: 5pt;
-  vertical-align: top;
-  padding: 10px;
-  border: solid 1px black;
-  position: relative;
-  overflow: hidden;
-  color: #999;
-}
-
-div#gallery_album_box:hover {
-  color: black; 
-}
-
-.leftcontent div#gallery_album_box {
-  margin: 5px;
-}
-
-div#gallery_album_box h1 {
-  font-size: 12pt;
-  font-family: Verdana;
-}
-
-div#gallery_album_cover {
-  width: 199px;
-  height: 199px;
-  border: solid 1pt #999;
-  padding: 0;
-}
-
-div#gallery_control_overlay {
-  border: 0;
-  position:absolute;
-  right: 10pt;
-  background-color: #333;
-  opacity: 0.5;
-  visibility:hidden;
-  padding: 0 5pt;
-}
-
-div#gallery_control_overlay a {
-  color:white;
-}
-
-#gallery_images {
-padding:10px 5px;
-}
diff --git a/apps/gallery/index.php b/apps/gallery/index.php
index 0cd795bac0137d470dae0bca4d9e4d05e0927801..822a5b8e143ec8d595837dc8b97177287064e612 100644
--- a/apps/gallery/index.php
+++ b/apps/gallery/index.php
@@ -1,4 +1,26 @@
 <?php
+
+/**
+* ownCloud - gallery application
+*
+* @author Bartek Przybylski
+* @copyright 2012 Bartek Przybylski bart.p.pl@gmail.com
+* 
+* 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 Lesser General Public 
+* License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+* 
+*/
+
 require_once('../../lib/base.php');
 
 OC_Util::checkLoggedIn();
diff --git a/apps/gallery/js/album_cover.js b/apps/gallery/js/album_cover.js
index 619aa391c564cbea90e8a75b0cdca337e7c7e5da..f6cb2da3103fb739049240f1e8804a46f9eb5b91 100644
--- a/apps/gallery/js/album_cover.js
+++ b/apps/gallery/js/album_cover.js
@@ -31,7 +31,11 @@ function createNewAlbum() {
 }
 
 function scanForAlbums() {
+  $("#notification").fadeIn();
+  $("#notification").slideDown();
   $.getJSON('ajax/scanForAlbums.php', function(r) {
+    $("#notification").fadeOut();
+    $("#notification").slideUp();
     if (r.status == 'success') {
       window.location.reload(true);
     } else {
diff --git a/apps/gallery/lib/album.php b/apps/gallery/lib/album.php
index 0999429c5d5ca40f3487952cac9a496c2cb1112f..a94eff3acd7864abf4907883cd6a2b94672e7616 100644
--- a/apps/gallery/lib/album.php
+++ b/apps/gallery/lib/album.php
@@ -1,9 +1,30 @@
 <?php
 
+/**
+* ownCloud - gallery application
+*
+* @author Bartek Przybylski
+* @copyright 2012 Bartek Przybylski bart.p.pl@gmail.com
+* 
+* 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 Lesser General Public 
+* License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+* 
+*/
+
 class OC_Gallery_Album {
-	public static function create($owner, $name){
-		$stmt = OC_DB::prepare('INSERT INTO *PREFIX*gallery_albums (uid_owner, album_name) VALUES (?, ?)');
-		$stmt->execute(array($owner, $name));
+	public static function create($owner, $name, $path){
+		$stmt = OC_DB::prepare('INSERT INTO *PREFIX*gallery_albums (uid_owner, album_name, album_path) VALUES (?, ?, ?)');
+		$stmt->execute(array($owner, $name, $path));
 	}
 	
 	public static function rename($oldname, $newname, $owner) {
@@ -22,14 +43,21 @@ class OC_Gallery_Album {
 		return $stmt->execute($args);
 	}
 	
-	public static function find($owner, $name=null){
+  public static function find($owner, $name=null, $path=null){
 		$sql = 'SELECT * FROM *PREFIX*gallery_albums WHERE uid_owner = ?';
 		$args = array($owner);
 		if (!is_null($name)){
 			$sql .= ' AND album_name = ?';
 			$args[] = $name;
-		}
+    }
+    if (!is_null($path)){
+      $sql .= ' AND album_path = ?';
+      $args[] = $path;
+    }
 		$stmt = OC_DB::prepare($sql);
 		return $stmt->execute($args);
 	}
+
 }
+
+?>
diff --git a/apps/gallery/lib/hooks_handlers.php b/apps/gallery/lib/hooks_handlers.php
new file mode 100644
index 0000000000000000000000000000000000000000..65f3faaeeaf3f57559289a9797c2d1e46b0b0e1c
--- /dev/null
+++ b/apps/gallery/lib/hooks_handlers.php
@@ -0,0 +1,118 @@
+<?php
+
+/**
+* ownCloud - gallery application
+*
+* @author Bartek Przybylski
+* @copyright 2012 Bartek Przybylski bart.p.pl@gmail.com
+* 
+* 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 Lesser General Public 
+* License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+* 
+*/
+
+OC_Hook::connect("OC_Filesystem", "post_write", "OC_Gallery_Hooks_Handlers", "addPhotoFromPath");
+OC_Hook::connect("OC_Filesystem", "delete", "OC_Gallery_Hooks_Handlers", "removePhoto");
+OC_Hook::connect("OC_Filesystem", "post_rename", "OC_Gallery_Hooks_Handlers", "renamePhoto");
+
+require_once(OC::$CLASSPATH['OC_Gallery_Album']);
+require_once(OC::$CLASSPATH['OC_Gallery_Photo']);
+
+class OC_Gallery_Hooks_Handlers {
+  private static $APP_TAG = "Gallery";
+
+  private static function isPhoto($filename) {
+    OC_Log::write(self::$APP_TAG, "Checking file ".$filename." with mimetype ".OC_Filesystem::getMimeType($filename), OC_Log::DEBUG);
+    if (substr(OC_Filesystem::getMimeType($filename), 0, 6) == "image/")
+      return 1;
+    return 0;
+  }
+
+  private static function createAlbum($path) {
+    $new_album_name = trim(str_replace('/', '.', $path), '.');
+    if ($new_album_name == '')
+      $new_album_name = 'main';
+
+    OC_Log::write(self::$APP_TAG, 'Creating new album '.$new_album_name, OC_Log::DEBUG);
+    OC_Gallery_Album::create(OC_User::getUser(), $new_album_name, $path);
+
+    return OC_Gallery_Album::find(OC_User::getUser(), null, $path);
+  }
+
+  public static function addPhotoFromPath($params) {
+    if (!self::isPhoto($params['path'])) return;
+    $fullpath = $params['path'];
+    OC_Log::write(self::$APP_TAG, 'Adding file with path '. $fullpath, OC_Log::DEBUG);
+    $path = substr($fullpath, 0, strrpos($fullpath, '/'));
+    if ($path == '') $path = '/';
+    $album = OC_Gallery_Album::find(OC_User::getUser(), null, $path);
+
+    if ($album->numRows() == 0) {
+      $album = self::createAlbum($path);
+    }
+    $album = $album->fetchRow();
+    $albumId = $album['album_id'];
+    $photo = OC_Gallery_Photo::find($albumId, $fullpath);
+    if ($photo->numRows() == 0) { // don't duplicate photo entries
+      OC_Log::write(self::$APP_TAG, 'Adding new photo to album', OC_Log::DEBUG);
+      OC_Gallery_Photo::create($albumId, $fullpath);
+    }
+
+  }
+
+  public static function removePhoto($params) {
+    $path = $params['path'];
+    if (!self::isPhoto($path)) return;
+    OC_Gallery_Photo::removeByPath($path);
+  }
+
+  public static function renamePhoto($params) {
+    $olddir = substr($params['oldpath'], 0, strrpos($params['oldpath'], '/'));
+    $newdir = substr($params['newpath'], 0, strrpos($params['newpath'], '/'));
+    if ($olddir == '') $olddir = '/';
+    if ($newdir == '') $newdir = '/';
+    if (!self::isPhoto($params['newpath'])) return;
+    OC_Log::write(self::$APP_TAG, 'Moving photo from '.$params['oldpath'].' to '.$params['newpath'], OC_Log::DEBUG);
+    $album;
+    $newAlbumId;
+    $oldAlbumId;
+    if ($olddir == $newdir) {
+      // album changing is not needed
+      $album = OC_Gallery_Album::find(OC_User::getUser(), null, $olddir);
+      if ($album->numRows() == 0) {
+        $album = self::createAlbum($newdir);
+      }
+      $album = $album->fetchRow();
+      $newAlbumId = $oldAlbumId = $album['album_id'];
+    } else {
+      $newalbum = OC_Gallery_Album::find(OC_User::getUser(), null, $newdir);
+      $oldalbum = OC_Gallery_Album::find(OC_User::getUser(), null, $olddir);
+
+      if ($newalbum->numRows() == 0) {
+        $newalbum = self::createAlbum($newdir);
+      }
+      $newalbum = $newalbum->fetchRow();
+      if ($oldalbum->numRows() == 0) {
+        OC_Gallery_Photo::create($newalbum['album_id'], $params['newpath']);
+        return;
+      }
+      $oldalbum = $oldalbum->fetchRow();
+      $newAlbumId = $newalbum['album_id'];
+      $oldAlbumId = $oldalbum['album_id'];
+
+    }
+    OC_Gallery_Photo::changePath($oldAlbumId, $newAlbumId, $params['oldpath'], $params['newpath']);
+  }
+}
+
+?>
diff --git a/apps/gallery/lib/images_utils.php b/apps/gallery/lib/images_utils.php
index cb46bf3f16093bbf66487502079561cacf5e5f56..0cfa52eb56431f8510d637882c0c93cda8c77e74 100644
--- a/apps/gallery/lib/images_utils.php
+++ b/apps/gallery/lib/images_utils.php
@@ -1,4 +1,26 @@
 <?php
+
+/**
+* ownCloud - gallery application
+*
+* @author Bartek Przybylski
+* @copyright 2012 Bartek Przybylski bart.p.pl@gmail.com
+* 
+* 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 Lesser General Public 
+* License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+* 
+*/
+
 require_once('../../../lib/base.php');
 OC_JSON::checkLoggedIn();
 OC_JSON::checkAppEnabled('gallery');
diff --git a/apps/gallery/lib/photo.php b/apps/gallery/lib/photo.php
index 97d159935f543028aac257efb1cefed0e5dcf91e..23887098e0fe87c5d2b27dc43cf933634550c0d8 100644
--- a/apps/gallery/lib/photo.php
+++ b/apps/gallery/lib/photo.php
@@ -1,5 +1,26 @@
 <?php
 
+/**
+* ownCloud - gallery application
+*
+* @author Bartek Przybylski
+* @copyright 2012 Bartek Przybylski bart.p.pl@gmail.com
+* 
+* 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 Lesser General Public 
+* License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+* 
+*/
+
 class OC_Gallery_Photo{
 	public static function create($albumId, $img){
 		$stmt = OC_DB::prepare('INSERT INTO *PREFIX*gallery_photos (album_id, file_path) VALUES (?, ?)');
@@ -8,7 +29,6 @@ class OC_Gallery_Photo{
 	public static function find($albumId, $img=null){
 		$sql = 'SELECT * FROM *PREFIX*gallery_photos WHERE album_id = ?';
 		$args = array($albumId);
-		$args = array($albumId);
 		if (!is_null($img)){
 			$sql .= ' AND file_path = ?';
 			$args[] = $img;
@@ -25,4 +45,20 @@ class OC_Gallery_Photo{
 				.' AND photos.album_id = albums.album_id');
 		return $stmt->execute(array($owner, $album_name));
 	}
+
+  public static function removeByPath($path) {
+    $stmt = OC_DB::prepare('DELETE FROM *PREFIX*gallery_photos WHERE file_path = ?');
+    $stmt->execute(array($path));
+  }
+
+  public static function removeById($id) {
+    $stmt = OC_DB::prepare('DELETE FROM *PREFIX*gallery_photos WHERE photo_id = ?');
+    $stmt->execute(array($id));
+  }
+
+  public static function changePath($oldAlbumId, $newAlbumId, $oldpath, $newpath) {
+    $stmt = OC_DB::prepare("UPDATE *PREFIX*gallery_photos SET file_path = ?, album_id = ? WHERE album_id = ? and file_path = ?");
+    $stmt->execute(array($newpath, $newAlbumId, $oldAlbumId, $oldpath));
+  }
 }
+
diff --git a/apps/gallery/lib/scanner.php b/apps/gallery/lib/scanner.php
index 59c34b8e69a075953c34e3c605890d7a2ae19db7..3eba9260ac7ff30f294fc6d1ee285a4159163901 100644
--- a/apps/gallery/lib/scanner.php
+++ b/apps/gallery/lib/scanner.php
@@ -1,5 +1,26 @@
 <?php
 
+/**
+* ownCloud - gallery application
+*
+* @author Bartek Przybylski
+* @copyright 2012 Bartek Przybylski bart.p.pl@gmail.com
+* 
+* 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 Lesser General Public 
+* License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+* 
+*/
+
 require_once('base.php'); // base lib
 require_once('images_utils.php');
 
@@ -21,13 +42,13 @@ class OC_Gallery_Scanner {
   public static function scanDir($path, &$albums) {
     $current_album = array('name'=> $path, 'imagesCount' => 0, 'images' => array());
     $current_album['name'] = str_replace('/', '.', str_replace(OC::$CONFIG_DATADIRECTORY, '', $current_album['name']));
-    $current_album['name'] = ($current_album['name']==='') ?
+    $current_album['name'] = ($current_album['name']==='.') ?
                              'main' :
                              trim($current_album['name'],'.');
 
     if ($dh = OC_Filesystem::opendir($path)) {
       while (($filename = readdir($dh)) !== false) {
-        $filepath = $path.'/'.$filename;
+        $filepath = ($path[strlen($path)-1]=='/'?$path:$path.'/').$filename;
         if (substr($filename, 0, 1) == '.') continue;
         if (OC_Filesystem::is_dir($filepath)) {
           self::scanDir($filepath, $albums);
@@ -41,7 +62,7 @@ class OC_Gallery_Scanner {
 
     $result = OC_Gallery_Album::find(OC_User::getUser(), $current_album['name']);
     if ($result->numRows() == 0 && count($current_album['images'])) {
-	    OC_Gallery_Album::create(OC_User::getUser(), $current_album['name']);
+	    OC_Gallery_Album::create(OC_User::getUser(), $current_album['name'], $path);
 	    $result = OC_Gallery_Album::find(OC_User::getUser(), $current_album['name']);
     }
     $albumId = $result->fetchRow();
diff --git a/apps/gallery/templates/index.php b/apps/gallery/templates/index.php
index 0e89e448768bfab117352aa774b6b41bf95db968..7c6e91a468eab23b3ea3212b55fc43b74f007cc0 100644
--- a/apps/gallery/templates/index.php
+++ b/apps/gallery/templates/index.php
@@ -4,9 +4,10 @@ OC_Util::addScript('gallery', 'albums');
 OC_Util::addScript('gallery', 'album_cover');
 ?>
 
+<div id="notification"><div id="gallery_notification_text">Creating thumbnails</div></div>
 <div id="controls">
-  <!--  <input type="button" value="New album" onclick="javascript:createNewAlbum();" />-->
-  <input type="button" value="Rescan" onclick="javascript:scanForAlbums();" /><br/>
+  <input type="button" value="Rescan" onclick="javascript:scanForAlbums();" />
+  <br/>
 </div>
 <div id="gallery_list">
 </div>
diff --git a/apps/media/css/music.css b/apps/media/css/music.css
index a6738058be3fe4f868b3ee1adbd5d678931fa86a..41ade44a66f15ae3488c948632e9755a5792eb3c 100644
--- a/apps/media/css/music.css
+++ b/apps/media/css/music.css
@@ -22,11 +22,11 @@ div.jp-volume-bar-value { background:#ccc; width:0; height:0.4em; }
 #collection li.album,#collection li.song { margin-left:3em; }
 #leftcontent img.remove { display:none; float:right; cursor:pointer; }
 #leftcontent li:hover img.remove { display:inline; }
-#leftcontent li {white-space: normal; }
+#leftcontent li div.label { float: left; width: 200px; overflow: hidden; text-overflow: ellipsis; }
 #collection li button { float:right; }
 #collection li,#playlist li { list-style-type:none; }
 .template { display:none; }
-.collection_playing { background:#eee; }
+.collection_playing { background:#eee; font-weight: bold; }
 
 #collection li { padding-right:10px; }
 #searchresults input.play, #searchresults input.add { float:left; height:1em; width:1em; }
diff --git a/apps/media/js/playlist.js b/apps/media/js/playlist.js
index 57180b3be7b6323742105a896ad0e043f58e35fe..089065989aef2c3ba9f163ede2190a31d0357f7b 100644
--- a/apps/media/js/playlist.js
+++ b/apps/media/js/playlist.js
@@ -1,11 +1,23 @@
 PlayList.render=function(){
 	$('#playlist').show();
+
+	/*
+	 * We should not empty() PlayList.parent() but thorougly manage its
+	 * elements instead because some code might be attached to those.
+	 * JQuery tipsies are one of them. The following line make sure they
+	 * are all removed before we delete the associated <li/>.
+	 */
+	$(".tipsy").remove();
+
 	PlayList.parent.empty();
 	for(var i=0;i<PlayList.items.length;i++){
 		var item=PlayList.items[i];
 		var li=$('<li/>');
-		li.append(item.name);
-                li.attr('class', 'jp-playlist-' + i);
+		li.attr('class', 'jp-playlist-' + i);
+		li.attr('title', item.artist + ' - ' + item.name + '<br/>(' + item.album + ')');
+		var div = $('<div class="label">' + item.name + '</div>');
+		li.append(div);
+		$('.jp-playlist-' + i).tipsy({gravity:'w', fade:true, live:true, html:true});
 		var img=$('<img class="remove svg action" src="'+OC.imagePath('core','actions/delete')+'"/>');
 		img.click(function(event){
 			event.stopPropagation();
diff --git a/apps/media/lib_collection.php b/apps/media/lib_collection.php
index caa3ac3f47985b2da5e6c78a741f9434506fdc70..1240f1de2f00f4cdd99668cdea5159ba8f7a8a99 100644
--- a/apps/media/lib_collection.php
+++ b/apps/media/lib_collection.php
@@ -127,7 +127,7 @@ class OC_MEDIA_COLLECTION{
 			$search='%';
 		}
 		$query=OC_DB::prepare("SELECT DISTINCT *PREFIX*media_artists.artist_name AS artist_name , *PREFIX*media_artists.artist_id AS artist_id FROM *PREFIX*media_artists
-			INNER JOIN *PREFIX*media_songs ON *PREFIX*media_artists.artist_id=*PREFIX*media_songs.song_artist WHERE artist_name LIKE ? AND *PREFIX*media_songs.song_user=?");
+			INNER JOIN *PREFIX*media_songs ON *PREFIX*media_artists.artist_id=*PREFIX*media_songs.song_artist WHERE artist_name LIKE ? AND *PREFIX*media_songs.song_user=? ORDER BY artist_name");
 		return $query->execute(array($search,self::$uid))->fetchAll();
 	}
 	
@@ -160,7 +160,7 @@ class OC_MEDIA_COLLECTION{
 	*/
 	static public function getAlbums($artist=0,$search='%',$exact=false){
 		$cmd="SELECT DISTINCT *PREFIX*media_albums.album_name AS album_name , *PREFIX*media_albums.album_artist AS album_artist , *PREFIX*media_albums.album_id AS album_id
-			FROM *PREFIX*media_albums INNER JOIN *PREFIX*media_songs ON *PREFIX*media_albums.album_id=*PREFIX*media_songs.song_album WHERE *PREFIX*media_songs.song_user=? ";
+			FROM *PREFIX*media_albums INNER JOIN *PREFIX*media_songs ON *PREFIX*media_albums.album_id=*PREFIX*media_songs.song_album WHERE *PREFIX*media_songs.song_user=? ORDER BY album_name";
 		$params=array(self::$uid);
 		if($artist!=0){
 			$cmd.="AND *PREFIX*media_albums.album_artist = ? ";
@@ -233,7 +233,7 @@ class OC_MEDIA_COLLECTION{
 		}else{
 			$searchString='';
 		}
-		$query=OC_DB::prepare("SELECT * FROM *PREFIX*media_songs WHERE song_user=? $artistString $albumString $searchString");
+		$query=OC_DB::prepare("SELECT * FROM *PREFIX*media_songs WHERE song_user=? $artistString $albumString $searchString ORDER BY song_track, song_name");
 		return $query->execute($params)->fetchAll();
 	}
 	
@@ -378,4 +378,4 @@ class OC_MEDIA_COLLECTION{
 	}
 }
 
-?>
\ No newline at end of file
+?>
diff --git a/apps/media/lib_scanner.php b/apps/media/lib_scanner.php
index c2bea2d836d95f5e0b85fe205be4611473ccf23d..320b1f79199aefc06a814d1d7d915ee77c5d5443 100644
--- a/apps/media/lib_scanner.php
+++ b/apps/media/lib_scanner.php
@@ -120,7 +120,20 @@ class OC_MEDIA_SCANNER{
 				$title=stripslashes($data['comments']['title'][0]);
 			}
 			$size=$data['filesize'];
-			$track=(isset($data['comments']['track']))?$data['comments']['track'][0]:0;
+			if (isset($data['comments']['track']))
+			{
+				$track = $data['comments']['track'][0];
+			}
+			else if (isset($data['comments']['track_number']))
+			{
+				$track = $data['comments']['track_number'][0];
+				$track = explode('/',$track);
+				$track = $track[0];
+			}
+			else
+			{
+				$track = 0;
+			}
 			$length=isset($data['playtime_seconds'])?round($data['playtime_seconds']):0;
 		}
 		if(!isset(self::$artists[$artist])){
diff --git a/lib/MDB2/Driver/Manager/sqlite3.php b/lib/MDB2/Driver/Manager/sqlite3.php
index c5c19a90fb52de158bf9bab7c318716809b39822..8f4e1312eb8f09faf456d22be3998a5ff490bd28 100644
--- a/lib/MDB2/Driver/Manager/sqlite3.php
+++ b/lib/MDB2/Driver/Manager/sqlite3.php
@@ -168,9 +168,6 @@ class MDB2_Driver_Manager_sqlite3 extends MDB2_Driver_Manager_Common
         if (PEAR::isError($query_fields)) {
             return $query_fields;
         }
-        if (!empty($options['primary'])) {
-            $query_fields.= ', PRIMARY KEY ('.implode(', ', array_keys($options['primary'])).')';
-        }
         if (!empty($options['foreign_keys'])) {
             foreach ($options['foreign_keys'] as $fkname => $fkdef) {
                 if (empty($fkdef)) {
@@ -534,9 +531,26 @@ class MDB2_Driver_Manager_sqlite3 extends MDB2_Driver_Manager_Common
             return MDB2_OK;
         }
 
+        if (empty($changes['remove']) and empty($changes['rename']) and empty($changes['change']) ){//if only rename or add changes are required, we can use ALTER TABLE
+			$query = '';
+			if (!empty($changes['name'])) {
+				$change_name = $db->quoteIdentifier($changes['name'], true);
+				$query = 'RENAME TO ' . $change_name;
+				$db->exec("ALTER TABLE $name $query");
+			}
+
+			if (!empty($changes['add']) && is_array($changes['add'])) {
+				foreach ($changes['add'] as $field_name => $field) {
+					$query= 'ADD ' . $db->getDeclaration($field['type'], $field_name, $field);
+					$db->exec("ALTER TABLE $name $query");
+				}
+			}
+			return MDB2_OK;
+        }
+
         $db->loadModule('Reverse', null, true);
 
-        // actually sqlite 2.x supports no ALTER TABLE at all .. so we emulate it
+        // for other operations we need to emulate them with sqlite3
         $fields = $db->manager->listTableFields($name);
         if (PEAR::isError($fields)) {
             return $fields;
@@ -636,44 +650,54 @@ class MDB2_Driver_Manager_sqlite3 extends MDB2_Driver_Manager_Common
             }
         }
 
+		//rename the old table so we can create the new one
+        $db->exec("ALTER TABLE $name RENAME TO __$name");
         $data = null;
-        if (!empty($select_fields)) {
-            $query = 'SELECT '.implode(', ', $select_fields).' FROM '.$db->quoteIdentifier($name, true);
-            $data = $db->queryAll($query, null, MDB2_FETCHMODE_ORDERED);
-        }
 
-        $result = $this->dropTable($name);
-        if (PEAR::isError($result)) {
-            return $result;
-        }
 
         $result = $this->createTable($name_new, $fields, $options);
         if (PEAR::isError($result)) {
             return $result;
         }
 
-        foreach ($indexes as $index => $definition) {
-            $this->createIndex($name_new, $index, $definition);
-        }
+        //these seem to only give errors
 
-        foreach ($constraints as $constraint => $definition) {
-            $this->createConstraint($name_new, $constraint, $definition);
-        }
+//         foreach ($indexes as $index => $definition) {
+//             $this->createIndex($name_new, $index, $definition);
+//         }
 
-        if (!empty($select_fields) && !empty($data)) {
-            $query = 'INSERT INTO '.$db->quoteIdentifier($name_new, true);
-            $query.= '('.implode(', ', array_slice(array_keys($fields), 0, count($select_fields))).')';
-            $query.=' VALUES (?'.str_repeat(', ?', (count($select_fields) - 1)).')';
-            $stmt =$db->prepare($query, null, MDB2_PREPARE_MANIP);
-            if (PEAR::isError($stmt)) {
-                return $stmt;
-            }
-            foreach ($data as $row) {
-                $result = $stmt->execute($row);
-                if (PEAR::isError($result)) {
-                    return $result;
-                }
-            }
+//         foreach ($constraints as $constraint => $definition) {
+//             $this->createConstraint($name_new, $constraint, $definition);
+//         }
+
+        //fill the new table with data from the old one
+        if (!empty($select_fields)) {
+			$query = 'INSERT INTO '.$db->quoteIdentifier($name_new, true);
+			$query.= '('.implode(', ', array_slice(array_keys($fields), 0, count($select_fields))).')';
+            $query .= ' SELECT '.implode(', ', $select_fields).' FROM '.$db->quoteIdentifier('__'.$name, true);
+            $db->exec($query);
+        }
+
+//         if (!empty($select_fields) && !empty($data)) {
+//             $query = 'INSERT INTO '.$db->quoteIdentifier($name_new, true);
+//             $query.= '('.implode(', ', array_slice(array_keys($fields), 0, count($select_fields))).')';
+//             $query.=' VALUES (?'.str_repeat(', ?', (count($select_fields) - 1)).')';
+//             $stmt =$db->prepare($query, null, MDB2_PREPARE_MANIP);
+//             if (PEAR::isError($stmt)) {
+//                 return $stmt;
+//             }
+//             foreach ($data as $row) {
+//                 $result = $stmt->execute($row);
+//                 if (PEAR::isError($result)) {
+//                     return $result;
+//                 }
+//             }
+//         }
+
+        //remove the old table
+        $result = $this->dropTable('__'.$name);
+        if (PEAR::isError($result)) {
+            return $result;
         }
         return MDB2_OK;
     }
@@ -798,7 +822,7 @@ class MDB2_Driver_Manager_sqlite3 extends MDB2_Driver_Manager_Common
             return $db;
         }
 
-        $query = "SELECT name FROM sqlite_master WHERE type='table' AND sql NOT NULL ORDER BY name";
+        $query = "SELECT name FROM sqlite_master WHERE type='table' AND sql NOT NULL AND name!='sqlite_sequence' ORDER BY name";
         $table_names = $db->queryCol($query);
         if (PEAR::isError($table_names)) {
             return $table_names;
diff --git a/lib/MDB2/Driver/Reverse/sqlite3.php b/lib/MDB2/Driver/Reverse/sqlite3.php
index d5595da84c54a53dac0987247e7f99a636b07359..33e5b59026895181e1c029e4264d2e6b3984fc6f 100644
--- a/lib/MDB2/Driver/Reverse/sqlite3.php
+++ b/lib/MDB2/Driver/Reverse/sqlite3.php
@@ -69,7 +69,7 @@ class MDB2_Driver_Reverse_sqlite3 extends MDB2_Driver_Reverse_Common
             return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
                 'unexpected empty table column definition list', __FUNCTION__);
         }
-        $regexp = '/^\s*([^\s]+) +(CHAR|VARCHAR|VARCHAR2|TEXT|BOOLEAN|SMALLINT|INT|INTEGER|DECIMAL|BIGINT|DOUBLE|FLOAT|DATETIME|DATE|TIME|LONGTEXT|LONGBLOB)( ?\(([1-9][0-9]*)(:([1-9][0-9]*))?\))?( NULL| NOT NULL)?( UNSIGNED)?( NULL| NOT NULL)?( PRIMARY KEY)?( DEFAULT (\'[^\']*\'|[^ ]+))?( NULL| NOT NULL)?( PRIMARY KEY)?(\s*\-\-.*)?$/i';
+        $regexp = '/^\s*([^\s]+) +(CHAR|VARCHAR|VARCHAR2|TEXT|BOOLEAN|SMALLINT|INT|INTEGER|DECIMAL|BIGINT|DOUBLE|FLOAT|DATETIME|DATE|TIME|LONGTEXT|LONGBLOB)( ?\(([1-9][0-9]*)(:([1-9][0-9]*))?\))?( NULL| NOT NULL)?( UNSIGNED)?( NULL| NOT NULL)?( PRIMARY KEY)?( AUTOINCREMENT)?( DEFAULT (\'[^\']*\'|[^ ]+))?( NULL| NOT NULL)?( PRIMARY KEY)?(\s*\-\-.*)?$/i';
         $regexp2 = '/^\s*([^ ]+) +(PRIMARY|UNIQUE|CHECK)$/i';
         for ($i=0, $j=0; $i<$count; ++$i) {
             if (!preg_match($regexp, trim($column_sql[$i]), $matches)) {
@@ -90,11 +90,16 @@ class MDB2_Driver_Reverse_sqlite3 extends MDB2_Driver_Reverse_Common
             if (isset($matches[8]) && strlen($matches[8])) {
                 $columns[$j]['unsigned'] = true;
             }
-            if (isset($matches[9]) && strlen($matches[9])) {
+            if (isset($matches[10]) && strlen($matches[10])) {
                 $columns[$j]['autoincrement'] = true;
+                $columns[$j]['notnull']=true;
             }
-            if (isset($matches[12]) && strlen($matches[12])) {
-                $default = $matches[12];
+            if (isset($matches[10]) && strlen($matches[10])) {
+                $columns[$j]['autoincrement'] = true;
+                $columns[$j]['notnull']=true;
+            }
+            if (isset($matches[13]) && strlen($matches[13])) {
+                $default = $matches[13];
                 if (strlen($default) && $default[0]=="'") {
                     $default = str_replace("''", "'", substr($default, 1, strlen($default)-2));
                 }
@@ -107,8 +112,8 @@ class MDB2_Driver_Reverse_sqlite3 extends MDB2_Driver_Reverse_Common
                 $columns[$j]['notnull'] = ($matches[7] === ' NOT NULL');
             } else if (isset($matches[9]) && strlen($matches[9])) {
                 $columns[$j]['notnull'] = ($matches[9] === ' NOT NULL');
-            } else if (isset($matches[13]) && strlen($matches[13])) {
-                $columns[$j]['notnull'] = ($matches[13] === ' NOT NULL');
+            } else if (isset($matches[14]) && strlen($matches[14])) {
+                $columns[$j]['notnull'] = ($matches[14] === ' NOT NULL');
             }
             ++$j;
         }
diff --git a/lib/app.php b/lib/app.php
index 1873e1136cd5ac6166eac2dab4ac7ee4e5f9d420..13c4cef32b41c5db59db6f890c799b2bb14302d6 100644
--- a/lib/app.php
+++ b/lib/app.php
@@ -371,4 +371,35 @@ class OC_App{
 		}
 		return $apps;
 	}
+	
+	/**
+	 * check if any apps need updating and update those
+	 */
+	public static function updateApps(){
+		// The rest comes here
+		$apps = OC_Appconfig::getApps();
+		foreach( $apps as $app ){
+			$installedVersion=OC_Appconfig::getValue($app,'installed_version');
+			$appInfo=OC_App::getAppInfo($app);
+			if (isset($appInfo['version'])) {
+				$currentVersion=$appInfo['version'];
+				if (version_compare($currentVersion, $installedVersion, '>')) {
+					OC_App::updateApp($app);
+				}
+			}
+		}
+	}
+	
+	/**
+	 * update the database for the app and call the update script
+	 * @param string appid
+	 */
+	public static function updateApp($appid){
+		if(file_exists(OC::$SERVERROOT.'/apps/'.$appid.'/appinfo/database.xml')){
+			OC_DB::updateDbFromStructure(OC::$SERVERROOT.'/apps/'.$appid.'/appinfo/database.xml');
+		}
+		if(file_exists(OC::$SERVERROOT.'/apps/'.$appid.'/appinfo/update.php')){
+			include OC::$SERVERROOT.'/apps/'.$appid.'/appinfo/update.php';
+		}
+	}
 }
diff --git a/lib/base.php b/lib/base.php
index 0954e3615bdb03b3e8cfb1de3b6570bc5660a225..854b91b0c1d9876c116f0a20930cb7b806101235 100644
--- a/lib/base.php
+++ b/lib/base.php
@@ -152,6 +152,17 @@ class OC{
 			}
 		}
 
+		if(OC_Config::getValue('installed', false)){
+			$installedVersion=OC_Config::getValue('version','0.0.0');
+			$currentVersion=implode('.',OC_Util::getVersion());
+			if (version_compare($currentVersion, $installedVersion, '>')) {
+				OC_DB::updateDbFromStructure('../db_structure.xml');
+				OC_Config::setValue('version',implode('.',OC_Util::getVersion()));
+			}
+
+			OC_App::updateApps();
+		}
+
 		ini_set('session.cookie_httponly','1;');
 		session_start();
 
@@ -230,8 +241,6 @@ if( !isset( $RUNTIME_NOAPPS )){
 	$RUNTIME_NOAPPS = false;
 }
 
-OC::init();
-
 if(!function_exists('get_temp_dir')) {
 	function get_temp_dir() {
 		if( $temp=ini_get('upload_tmp_dir') )        return $temp;
@@ -247,6 +256,8 @@ if(!function_exists('get_temp_dir')) {
 	}
 }
 
+OC::init();
+
 require_once('fakedirstream.php');
 
 
diff --git a/lib/db.php b/lib/db.php
index c7085a975ef663ab666ef5259221ee275b07400b..b901cc8b513bedd4980cf02a02a5c2a9c6cd82b3 100644
--- a/lib/db.php
+++ b/lib/db.php
@@ -71,7 +71,14 @@ class OC_DB {
 	/**
 	 * connect to the database using pdo
 	 */
-	private static function connectPDO(){
+	public static function connectPDO(){
+		if(self::$connection){
+			if(self::$backend==self::BACKEND_MDB2){
+				self::disconnect();
+			}else{
+				return;
+			}
+		}
 		// The global data we need
 		$name = OC_Config::getValue( "dbname", "owncloud" );
 		$host = OC_Config::getValue( "dbhost", "" );
@@ -113,7 +120,14 @@ class OC_DB {
 	/**
 	 * connect to the database using mdb2
 	 */
-	static private function connectMDB2(){
+	public static function connectMDB2(){
+		if(self::$connection){
+			if(self::$backend==self::BACKEND_PDO){
+				self::disconnect();
+			}else{
+				return;
+			}
+		}
 		// The global data we need
 		$name = OC_Config::getValue( "dbname", "owncloud" );
 		$host = OC_Config::getValue( "dbhost", "" );
@@ -255,8 +269,8 @@ class OC_DB {
 				self::$connection->disconnect();
 			}
 			self::$connection=false;
-			self::$mdb2=false;
-			self::$pdo=false;
+			self::$MDB2=false;
+			self::$PDO=false;
 		}
 
 		return true;
@@ -338,7 +352,6 @@ class OC_DB {
 	 * @param $file file to read structure from
 	 */
 	public static function updateDbFromStructure($file){
-		$CONFIG_DBNAME  = OC_Config::getValue( "dbname", "owncloud" );
 		$CONFIG_DBTABLEPREFIX = OC_Config::getValue( "dbtableprefix", "oc_" );
 		$CONFIG_DBTYPE = OC_Config::getValue( "dbtype", "sqlite" );
 
@@ -347,17 +360,17 @@ class OC_DB {
 		// read file
 		$content = file_get_contents( $file );
 		
+		$previousSchema = self::$schema->getDefinitionFromDatabase();
+
 		// Make changes and save them to a temporary file
 		$file2 = tempnam( get_temp_dir(), 'oc_db_scheme_' );
-		$content = str_replace( '*dbname*', $CONFIG_DBNAME, $content );
+		$content = str_replace( '*dbname*', $previousSchema['name'], $content );
 		$content = str_replace( '*dbprefix*', $CONFIG_DBTABLEPREFIX, $content );
 		if( $CONFIG_DBTYPE == 'pgsql' ){ //mysql support it too but sqlite doesn't
 			$content = str_replace( '<default>0000-00-00 00:00:00</default>', '<default>CURRENT_TIMESTAMP</default>', $content );
 		}
 		file_put_contents( $file2, $content );
-		$previousSchema = self::$schema->getDefinitionFromDatabase();
-		$op = $schema->updateDatabase($file2, $previousSchema, array(), false);
-
+		$op = self::$schema->updateDatabase($file2, $previousSchema, array(), false);
 		if (PEAR::isError($op)) {
 		    $error = $op->getMessage();
 		    OC_Log::write('core','Failed to update database structure ('.$error.')',OC_Log::FATAL);
@@ -375,6 +388,8 @@ class OC_DB {
 	private static function connectScheme(){
 		// We need a mdb2 database connection
 		self::connectMDB2();
+		self::$MDB2->loadModule('Manager');
+		self::$MDB2->loadModule('Reverse');
 
 		// Connect if this did not happen before
 		if(!self::$schema){
diff --git a/lib/setup.php b/lib/setup.php
index b53c626c9a723fd6fa80470b5328990c307038cb..ebe7a45a1f6f4e7c5488386957180a95e5b2080e 100644
--- a/lib/setup.php
+++ b/lib/setup.php
@@ -98,35 +98,45 @@ class OC_Setup {
 					);
 				}
 				else {
+					$oldUser=OC_Config::getValue('dbuser', false);
+					$oldPassword=OC_Config::getValue('dbpassword', false);
+					
 					$query="SELECT user FROM mysql.user WHERE user='$dbuser'"; //this should be enough to check for admin rights in mysql
 					if(mysql_query($query, $connection)) {
 						//use the admin login data for the new database user
 
 						//add prefix to the mysql user name to prevent collissions
-						$dbusername=substr('oc_mysql_'.$username,0,16);
-						//hash the password so we don't need to store the admin config in the config file
-						$dbpassword=md5(time().$password);
-						
-						self::createDBUser($dbusername, $dbpassword, $connection);
-						
-						OC_Config::setValue('dbuser', $dbusername);
-						OC_Config::setValue('dbpassword', $dbpassword);
+						$dbusername=substr('oc_'.$username,0,16);
+						if($dbusername!=$oldUser){
+							//hash the password so we don't need to store the admin config in the config file
+							$dbpassword=md5(time().$password);
+
+							self::createDBUser($dbusername, $dbpassword, $connection);
+
+							OC_Config::setValue('dbuser', $dbusername);
+							OC_Config::setValue('dbpassword', $dbpassword);
+						}
 
 						//create the database
 						self::createDatabase($dbname, $dbusername, $connection);
 					}
 					else {
-						OC_Config::setValue('dbuser', $dbuser);
-						OC_Config::setValue('dbpassword', $dbpass);
+						if($dbuser!=$oldUser){
+							OC_Config::setValue('dbuser', $dbuser);
+							OC_Config::setValue('dbpassword', $dbpass);
+						}
 
 						//create the database
 						self::createDatabase($dbname, $dbuser, $connection);
 					}
 
 					//fill the database if needed
-					$query="SELECT * FROM $dbname.{$dbtableprefix}users";
+					$query="select count(*) from information_schema.tables where table_schema='$dbname' AND table_name = '{$dbtableprefix}users';";
 					$result = mysql_query($query,$connection);
-					if(!$result) {
+					if($result){
+						$row=mysql_fetch_row($result);
+					}
+					if(!$result or $row[0]==0) {
 						OC_DB::createDbFromStructure('db_structure.xml');
 					}
 					mysql_close($connection);
@@ -160,8 +170,8 @@ class OC_Setup {
 
 						//add prefix to the postgresql user name to prevent collissions
 						$dbusername='oc_'.$username;
-						//hash the password so we don't need to store the admin config in the config file
-						$dbpassword=md5(time().$password);
+						//create a new password so we don't need to store the admin config in the config file
+						$dbpassword=md5(time());
 						
 						self::pg_createDBUser($dbusername, $dbpassword, $connection);
 						
@@ -221,7 +231,7 @@ class OC_Setup {
 	}
 
 	public static function createDatabase($name,$user,$connection) {
-		//we cant user OC_BD functions here because we need to connect as the administrative user.
+		//we cant use OC_BD functions here because we need to connect as the administrative user.
 		$query = "CREATE DATABASE IF NOT EXISTS  `$name`";
 		$result = mysql_query($query, $connection);
 		if(!$result) {
@@ -243,7 +253,7 @@ class OC_Setup {
 	}
 
 	public static function pg_createDatabase($name,$user,$connection) {
-		//we cant user OC_BD functions here because we need to connect as the administrative user.
+		//we cant use OC_BD functions here because we need to connect as the administrative user.
 		$query = "CREATE DATABASE $name OWNER $user";
 		$result = pg_query($connection, $query);
 		if(!$result) {