diff --git a/apps/bookmarks/appinfo/migrate.php b/apps/bookmarks/appinfo/migrate.php
index e7e572f52dc881c89782b4883bf1e4cfc766370a..f1353f1887eb180db6d402761a378c8bc5317b7b 100644
--- a/apps/bookmarks/appinfo/migrate.php
+++ b/apps/bookmarks/appinfo/migrate.php
@@ -40,8 +40,8 @@ class OC_Migration_Provider_Bookmarks extends OC_Migration_Provider{
 				$idmap = array();
 				while( $row = $results->fetchRow() ){
 					// Import each bookmark, saving its id into the map	
-					$query = OCP\DB::prepare( "INSERT INTO *PREFIX*bookmarks(url, title, user_id, public, added, lastmodified) VALUES (?, ?, ?, ?, ?, ?)" );
-					$query->execute( array( $row['url'], $row['title'], $this->uid, $row['public'], $row['added'], $row['lastmodified'] ) );
+					$bookmarkquery = OCP\DB::prepare( "INSERT INTO *PREFIX*bookmarks(url, title, user_id, public, added, lastmodified) VALUES (?, ?, ?, ?, ?, ?)" );
+					$bookmarkquery->execute( array( $row['url'], $row['title'], $this->uid, $row['public'], $row['added'], $row['lastmodified'] ) );
 					// Map the id
 					$idmap[$row['id']] = OCP\DB::insertid();
 				}
@@ -51,8 +51,8 @@ class OC_Migration_Provider_Bookmarks extends OC_Migration_Provider{
 					$results = $query->execute( array( $oldid ) );
 					while( $row = $results->fetchRow() ){
 						// Import the tags for this bookmark, using the new bookmark id
-						$query = OCP\DB::prepare( "INSERT INTO *PREFIX*bookmarks_tags(bookmark_id, tag) VALUES (?, ?)" );
-						$query->execute( array( $newid, $row['tag'] ) );	
+						$tagquery = OCP\DB::prepare( "INSERT INTO *PREFIX*bookmarks_tags(bookmark_id, tag) VALUES (?, ?)" );
+						$tagquery->execute( array( $newid, $row['tag'] ) );	
 					}		
 				}
 				// All done!
diff --git a/apps/contacts/ajax/contacts.php b/apps/contacts/ajax/contacts.php
index 07b442159c91670482c4189e481d1c0193477c90..67ebcaf7362fc79cfcd0aac6081c3df077b72543 100644
--- a/apps/contacts/ajax/contacts.php
+++ b/apps/contacts/ajax/contacts.php
@@ -17,24 +17,44 @@ function cmp($a, $b)
 OCP\JSON::checkLoggedIn();
 OCP\JSON::checkAppEnabled('contacts');
 
-$active_addressbooks = OC_Contacts_Addressbook::active(OCP\USER::getUser());
+$start = isset($_GET['startat'])?$_GET['startat']:0;
+$aid = isset($_GET['aid'])?$_GET['aid']:null;
 
+if(is_null($aid)) {
+	// Called initially to get the active addressbooks.
+	$active_addressbooks = OC_Contacts_Addressbook::active(OCP\USER::getUser());
+} else {
+	// called each time more contacts has to be shown.
+	$active_addressbooks = array(OC_Contacts_Addressbook::find($aid));
+}
+
+
+session_write_close();
+
+// create the addressbook associate array
 $contacts_addressbook = array();
 $ids = array();
 foreach($active_addressbooks as $addressbook) {
 	$ids[] = $addressbook['id'];
 	if(!isset($contacts_addressbook[$addressbook['id']])) {
-		$contacts_addressbook[$addressbook['id']] = array('contacts' => array());
+		$contacts_addressbook[$addressbook['id']] = array('contacts' => array('type' => 'book',));
 		$contacts_addressbook[$addressbook['id']]['displayname'] = $addressbook['displayname'];
 	}
 }	
-$contacts_alphabet = OC_Contacts_VCard::all($ids);
 
+$contacts_alphabet = array(); 
+
+// get next 50 for each addressbook.
+foreach($ids as $id) {
+	if($id) {
+		$contacts_alphabet = array_merge($contacts_alphabet, OC_Contacts_VCard::all($id, $start, 50));
+	}
+}
 // Our new array for the contacts sorted by addressbook
 if($contacts_alphabet) {
 	foreach($contacts_alphabet as $contact) {
 		if(!isset($contacts_addressbook[$contact['addressbookid']])) { // It should never execute.
-			$contacts_addressbook[$contact['addressbookid']] = array('contacts' => array());
+			$contacts_addressbook[$contact['addressbookid']] = array('contacts' => array('type' => 'book',));
 		}
 		$display = trim($contact['fullname']);
 		if(!$display) {
@@ -44,15 +64,11 @@ if($contacts_alphabet) {
 				$display = isset($struct['EMAIL'][0])?$struct['EMAIL'][0]['value']:'[UNKNOWN]';
 			}
 		}
-		$contacts_addressbook[$contact['addressbookid']]['contacts'][] = array('id' => $contact['id'], 'addressbookid' => $contact['addressbookid'], 'displayname' => htmlspecialchars($display));
+		$contacts_addressbook[$contact['addressbookid']]['contacts'][] = array('type' => 'contact', 'id' => $contact['id'], 'addressbookid' => $contact['addressbookid'], 'displayname' => htmlspecialchars($display));
 	}
 }
 unset($contacts_alphabet);
 uasort($contacts_addressbook, 'cmp');
 
-$tmpl = new OCP\Template("contacts", "part.contacts");
-$tmpl->assign('books', $contacts_addressbook, false);
-$page = $tmpl->fetchPage();
-
-OCP\JSON::success(array('data' => array( 'page' => $page )));
+OCP\JSON::success(array('data' => array('entries' => $contacts_addressbook)));
 
diff --git a/apps/contacts/ajax/loadphoto.php b/apps/contacts/ajax/loadphoto.php
index 61b5356edce31c3bb28b3cd6d43c990d85ef037a..a35631055eba7f82b657c49b13c761888f2d0eb1 100644
--- a/apps/contacts/ajax/loadphoto.php
+++ b/apps/contacts/ajax/loadphoto.php
@@ -42,11 +42,5 @@ foreach($vcard->children as $property){
 	}
 }
 
-$tmpl = new OCP\Template("contacts", "part.contactphoto");
-$tmpl->assign('id', $id);
-if($refresh) {
-	$tmpl->assign('refresh', 1);
-}
-$page = $tmpl->fetchPage();
-OCP\JSON::success(array('data' => array('page'=>$page, 'checksum'=>$checksum)));
-?>
+OCP\JSON::success(array('data' => array('checksum'=>$checksum)));
+
diff --git a/apps/contacts/appinfo/migrate.php b/apps/contacts/appinfo/migrate.php
index 1400cdf79d4707d4b76da70674b430ee1c8993aa..cceb4406172933db1510350b999927590d4bfeda 100644
--- a/apps/contacts/appinfo/migrate.php
+++ b/apps/contacts/appinfo/migrate.php
@@ -40,19 +40,20 @@ class OC_Migration_Provider_Contacts extends OC_Migration_Provider{
 				$idmap = array();
 				while( $row = $results->fetchRow() ){
 					// Import each bookmark, saving its id into the map	
-					$query = OCP\DB::prepare( "INSERT INTO *PREFIX*contacts_addressbooks (`userid`, `displayname`, `uri`, `description`, `ctag`) VALUES (?, ?, ?, ?, ?)" );
-					$query->execute( array( $this->uid, $row['displayname'], $row['uri'], $row['description'], $row['ctag'] ) );
+					$addressbookquery = OCP\DB::prepare( "INSERT INTO *PREFIX*contacts_addressbooks (`userid`, `displayname`, `uri`, `description`, `ctag`) VALUES (?, ?, ?, ?, ?)" );
+					$addressbookquery->execute( array( $this->uid, $row['displayname'], $row['uri'], $row['description'], $row['ctag'] ) );
 					// Map the id
 					$idmap[$row['id']] = OCP\DB::insertid();
 				}
 				// Now tags
 				foreach($idmap as $oldid => $newid){
+					
 					$query = $this->content->prepare( "SELECT * FROM contacts_cards WHERE addressbookid LIKE ?" );
 					$results = $query->execute( array( $oldid ) );
 					while( $row = $results->fetchRow() ){
 						// Import the tags for this bookmark, using the new bookmark id
-						$query = OCP\DB::prepare( "INSERT INTO *PREFIX*contacts_cards (`addressbookid`, `fullname`, `carddata`, `uri`, `lastmodified`) VALUES (?, ?, ?, ?, ?)" );
-						$query->execute( array( $newid, $row['fullname'], $row['carddata'], $row['uri'], $row['lastmodified'] ) );	
+						$contactquery = OCP\DB::prepare( "INSERT INTO *PREFIX*contacts_cards (`addressbookid`, `fullname`, `carddata`, `uri`, `lastmodified`) VALUES (?, ?, ?, ?, ?)" );
+						$contactquery->execute( array( $newid, $row['fullname'], $row['carddata'], $row['uri'], $row['lastmodified'] ) );	
 					}		
 				}
 				// All done!
diff --git a/apps/contacts/css/contacts.css b/apps/contacts/css/contacts.css
index 1766c28761ec03e270afc03ec32e479a85b786bd..ce4daa1d3a1fc37a70b26d4fb63c2e4c66365d12 100644
--- a/apps/contacts/css/contacts.css
+++ b/apps/contacts/css/contacts.css
@@ -73,10 +73,10 @@ label:hover, dt:hover { color: #333; }
 .contactsection { position: relative; float: left; /*max-width: 40em;*/ padding: 0.5em; height: auto: border: thin solid lightgray;/* -webkit-border-radius: 0.5em; -moz-border-radius: 0.5em; border-radius: 0.5em; background-color: #f8f8f8;*/ }
 
 #cropbox { margin: auto; }
-#contacts_details_photo_wrapper { min-width: 120px; }
+#contacts_details_photo_wrapper { width: 200px; }
 #contacts_details_photo_wrapper.wait { opacity: 0.6; filter:alpha(opacity=0.6); z-index:1000; background: url('%webroot%/core/img/loading.gif') no-repeat center center; cursor: wait; }
-#contacts_details_photo { border-radius: 0.5em; border: thin solid #bbb; margin: 0.3em; background: url('%webroot%/core/img/loading.gif') no-repeat center center; -moz-box-shadow: 0 1px 3px #777; -webkit-box-shadow: 0 1px 3px #777; box-shadow: 0 1px 3px #777; }
-#contacts_details_photo:hover { background: #fff; cursor: default; }
+.contacts_details_photo { border-radius: 0.5em; border: thin solid #bbb; margin: 0.3em; background: url('%webroot%/core/img/loading.gif') no-repeat center center; -moz-box-shadow: 0 1px 3px #777; -webkit-box-shadow: 0 1px 3px #777; box-shadow: 0 1px 3px #777; opacity: 1; }
+.contacts_details_photo:hover { background: #fff; cursor: default; }
 #phototools { position:absolute; margin: 5px 0 0 10px; width:auto; height:22px; padding:0px; background-color:#fff; list-style-type:none; border-radius: 0.5em; -moz-box-shadow: 0 1px 3px #777; -webkit-box-shadow: 0 1px 3px #777; box-shadow: 0 1px 3px #777; }
 #phototools li { display: inline; }
 #phototools li a { float:left; cursor:pointer; width:22px; height:22px; opacity: 0.6; }
diff --git a/apps/contacts/js/contacts.js b/apps/contacts/js/contacts.js
index e5326ad880509fc15b9b8a3b2a32c71d4b134a9b..9d41b70a314e8a155e186427f5e30ca6808795bf 100644
--- a/apps/contacts/js/contacts.js
+++ b/apps/contacts/js/contacts.js
@@ -144,6 +144,31 @@ Contacts={
 			$('#edit_name').click(function(){Contacts.UI.Card.editName()});
 			$('#edit_name').keydown(function(){Contacts.UI.Card.editName()});
 			
+			$('#phototools li a').click(function() {
+				$(this).tipsy('hide');
+			});
+			$('#contacts_details_photo_wrapper').hover(
+				function () {
+					$('#phototools').slideDown(200);
+				},
+				function () {
+					$('#phototools').slideUp(200);
+				}
+			);
+			$('#phototools').hover(
+				function () {
+					$(this).removeClass('transparent');
+				},
+				function () {
+					$(this).addClass('transparent');
+				}
+			);
+			$('#phototools .upload').click(function() {
+				$('#file_upload_start').trigger('click');
+			});
+			$('#phototools .cloud').click(function() {
+				OC.dialogs.filepicker(t('contacts', 'Select photo'), Contacts.UI.Card.cloudPhotoSelected, false, 'image', true);
+			});
 			/* Initialize the photo edit dialog */
 			$('#edit_photo_dialog').dialog({ 
 				autoOpen: false, modal: true, height: 'auto', width: 'auto'
@@ -273,7 +298,7 @@ Contacts={
 			update:function(id, bookid) {
 				var newid, firstitem;
 				if(!id) {
-					firstitem = $('#contacts:first-child li:first-child');
+					firstitem = $('#contacts ul').first().find('li:first-child');
 					if(firstitem.length > 0) {
 						newid = firstitem.data('id');
 						bookid = firstitem.data('bookid');
@@ -285,6 +310,7 @@ Contacts={
 				if(!bookid) {
 					bookid = $('#contacts h3').first().data('id');
 				}
+				console.log('bookid: ' +bookid);
 				var localLoadContact = function(newid, bookid) {
 					if($('.contacts li').length > 0) {
 						$('#contacts li[data-id="'+newid+'"]').addClass('active');
@@ -340,6 +366,9 @@ Contacts={
 				Contacts.UI.Card.add(';;;;;', '', '', true);
 				return false;
 			},
+			createEntry:function(data) {
+				return $('<li data-id="'+data.id+'" data-bookid="'+data.addressbookid+'" role="button"><a href="'+OC.linkTo('contacts', 'index.php')+'&id='+data.id+'"  style="background: url('+OC.filePath('contacts', '', 'thumbnail.php')+'?id='+data.id+') no-repeat scroll 0% 0% transparent;">'+data.displayname+'</a></li>');
+			},
 			add:function(n, fn, aid, isnew){ // add a new contact
 				aid = aid?aid:$('#contacts h3.active').first().data('id');
 				var localAddcontact = function(n, fn, aid, isnew) {
@@ -1105,25 +1134,6 @@ Contacts={
 			loadPhotoHandlers:function(){
 				$('#phototools li a').tipsy('hide');
 				$('#phototools li a').tipsy();
-				$('#phototools li a').click(function() {
-					$(this).tipsy('hide');
-				});
-				$('#contacts_details_photo_wrapper').hover(
-					function () {
-						$('#phototools').slideDown(200);
-					},
-					function () {
-						$('#phototools').slideUp(200);
-					}
-				);
-				$('#phototools').hover(
-					function () {
-						$(this).removeClass('transparent');
-					},
-					function () {
-						$(this).addClass('transparent');
-					}
-				);
 				if(this.data.PHOTO) {
 					$('#phototools .delete').click(function() {
 						$(this).tipsy('hide');
@@ -1134,16 +1144,12 @@ Contacts={
 						$(this).tipsy('hide');
 						Contacts.UI.Card.editCurrentPhoto();
 					});
+					$('#phototools .delete').show();
+					$('#phototools .edit').show();
 				} else {
 					$('#phototools .delete').hide();
 					$('#phototools .edit').hide();
 				}
-				$('#phototools .upload').click(function() {
-					$('#file_upload_start').trigger('click');
-				});
-				$('#phototools .cloud').click(function() {
-					OC.dialogs.filepicker(t('contacts', 'Select photo'), Contacts.UI.Card.cloudPhotoSelected, false, 'image', true);
-				});
 			},
 			cloudPhotoSelected:function(path){
 				$.getJSON(OC.filePath('contacts', 'ajax', 'oc_photo.php'),{'path':path,'id':Contacts.UI.Card.id},function(jsondata){
@@ -1158,22 +1164,33 @@ Contacts={
 				});
 			},
 			loadPhoto:function(refresh){
+				var self = this;
+				var refreshstr = (refresh?'&refresh=1'+Math.random():'')
 				$('#phototools li a').tipsy('hide');
 				var wrapper = $('#contacts_details_photo_wrapper');
-				wrapper.addClass('wait');
+				wrapper.addClass('loading').addClass('wait');
+				
+				var img = new Image();
+				$(img).load(function () {
+					$('img.contacts_details_photo').remove()
+					$(this).addClass('contacts_details_photo').hide();
+					wrapper.removeClass('loading').removeClass('wait');
+					$(this).insertAfter($('#phototools')).fadeIn();
+				}).error(function () {
+					// notify the user that the image could not be loaded
+					$(t('contacts','something went wrong.')).insertAfter($('#phototools'));
+				}).attr('src', OC.linkTo('contacts', 'photo.php')+'?id='+self.id+refreshstr);
+		
 				$.getJSON(OC.filePath('contacts', 'ajax', 'loadphoto.php'),{'id':this.id, 'refresh': refresh},function(jsondata){
 					if(jsondata.status == 'success'){
 						$('#contacts_details_photo_wrapper').data('checksum', jsondata.data.checksum);
-						wrapper.html(jsondata.data.page).ready(function(){ wrapper.removeClass('wait').tipsy() });
 						Contacts.UI.Card.loadPhotoHandlers();
 					}
 					else{
-						wrapper.removeClass('wait');
 						OC.dialogs.alert(jsondata.data.message, t('contacts', 'Error'));
 					}
 				});
 				$('#file_upload_form').show();
-				$('#contacts_propertymenu_dropdown a[data-type="PHOTO"]').parent().hide();
 			},
 			editCurrentPhoto:function(){
 				$.getJSON(OC.filePath('contacts', 'ajax', 'currentphoto.php'),{'id':this.id},function(jsondata){
@@ -1209,15 +1226,15 @@ Contacts={
 				var target = $('#crop_target');
 				var form = $('#cropform');
 				var wrapper = $('#contacts_details_photo_wrapper');
+				var self = this;
 				wrapper.addClass('wait');
 				form.submit();
 				target.load(function(){
 					var response=jQuery.parseJSON(target.contents().text());
 					if(response != undefined && response.status == 'success'){
 						// load cropped photo.
-						wrapper.html(response.data.page).ready(function(){ wrapper.removeClass('wait') });
+						self.loadPhoto(true);
 						Contacts.UI.Card.data.PHOTO = true;
-						Contacts.UI.Card.loadPhotoHandlers();
 					}else{
 						OC.dialogs.alert(response.data.message, t('contacts', 'Error'));
 						wrapper.removeClass('wait');
@@ -1532,6 +1549,7 @@ Contacts={
 			}
 		},
 		Contacts:{
+			batchnum:50,
 			drop:function(event, ui) {
 				var dragitem = ui.draggable, droptarget = $(this);
 				//console.log('Drop ' + dragitem.data('id') +' on: ' + droptarget.data('id'));
@@ -1563,64 +1581,79 @@ Contacts={
 				});
 			},
 			// Reload the contacts list.
-			update:function(id){
-				$.getJSON(OC.filePath('contacts', 'ajax', 'contacts.php'),{},function(jsondata){
+			update:function(id, aid, start){
+				self = this;
+				console.log('update: ' + aid + ' ' + start);
+				var firstrun = false;
+				var opts = {};
+				opts['startat'] = (start?start:0);
+				if(aid) {
+					opts['aid'] = aid;
+				}
+				$.getJSON(OC.filePath('contacts', 'ajax', 'contacts.php'),opts,function(jsondata){
 					if(jsondata.status == 'success'){
-						$('#contacts').html(jsondata.data.page).ready(function() {
-							/*setTimeout(function() {
-								$('.contacts li').unbind('inview');
-								$('.contacts li:visible').bind('inview', function(event, isInView, visiblePartX, visiblePartY) {
-									if (isInView) {
-										if (!$(this).find('a').attr('style')) {
-											$(this).find('a').css('background','url('+OC.filePath('contacts', '', 'thumbnail.php')+'?id='+$(this).data('id')+') no-repeat');
-										}
+						var books = jsondata.data.entries;
+						$.each(jsondata.data.entries, function(b, book) { 
+							if($('#contacts h3[data-id="'+b+'"]').length == 0) {
+								firstrun = true;
+								
+								if($('#contacts h3').length == 0) {
+									$('#contacts').html('<h3 class="addressbook" data-id="'+b+'">'+book.displayname+'</h3><ul class="contacts" data-id="'+b+'"></ul>');
+								} else {
+									if(!$('#contacts h3[data-id="'+b+'"]').length) {
+										$('<h3 class="addressbook" data-id="'+b+'">'+book.displayname+'</h3><ul class="contacts" data-id="'+b+'"></ul>')
+										.appendTo('#contacts');
 									}
-								})}, 100);
-							setTimeout(Contacts.UI.Contacts.lazyupdate, 500);*/
-							if($('#contacts h3').length > 1) {
-								$('#contacts h3,#contacts ul').each(function(index) {
-									var id = $(this).data('id');
-									var accept = 'li:not([data-bookid="'+id+'"])';
-									$(this).droppable({
-										drop: Contacts.UI.Contacts.drop,
-										activeClass: 'ui-state-hover',
-										accept: accept
-									});
+								}
+								$('#contacts h3[data-id="'+b+'"]').on('click', function(event) {
+									$('#contacts h3').removeClass('active');
+									$(this).addClass('active');
+									$('#contacts ul[data-id="'+b+'"]').slideToggle(300);
+									return false;
 								});
-								$('#contacts li').draggable({
-									revert: 'invalid',
-									axis: 'y', containment: '#contacts',
-									scroll: true, scrollSensitivity: 100,
-									opacity: 0.7, helper: 'clone'
+								var accept = 'li:not([data-bookid="'+b+'"])';
+								$('#contacts h3[data-id="'+b+'"]').droppable({
+									drop: Contacts.UI.Contacts.drop,
+									activeClass: 'ui-state-hover',
+									accept: accept
 								});
-							} else {
-								$('#contacts h3').first().addClass('active');
+							}
+							var contactlist = $('#contacts ul[data-id="'+b+'"]');
+							for(var c in book.contacts) {
+								if(book.contacts[c].id == undefined) { continue; }
+								var contact = Contacts.UI.Card.createEntry(book.contacts[c]);
+								if(c == self.batchnum-5) {
+									contact.bind('inview', function(event, isInView, visiblePartX, visiblePartY) {
+										$(this).unbind(event);
+										var bookid = $(this).data('bookid');
+										var numsiblings = $('.contacts li[data-bookid="'+bookid+'"]').length;
+										if (isInView && numsiblings >= self.batchnum) {
+											console.log('This would be a good time to load more contacts.');
+											Contacts.UI.Contacts.update(id, bookid, $('#contacts li[data-bookid="'+bookid+'"]').length);
+										}
+									});
+								}
+								contactlist.append(contact);
 							}
 						});
-						Contacts.UI.Card.update(id);
+						if($('#contacts h3').length > 1) {
+							$('#contacts li').draggable({
+								revert: 'invalid',
+								axis: 'y', containment: '#contacts',
+								scroll: true, scrollSensitivity: 100,
+								opacity: 0.7, helper: 'clone'
+							});
+						} else {
+							$('#contacts h3').first().addClass('active');
+						}
+						if(opts['startat'] == 0) { // only update card on first load.
+							Contacts.UI.Card.update();
+						}
 					}
 					else{
 						OC.dialogs.alert(jsondata.data.message, t('contacts', 'Error'));
 					}
 				});
-				/*setTimeout(function() {
-					$('.contacts li').unbind('inview');
-					$('.contacts li:visible').bind('inview', function(event, isInView, visiblePartX, visiblePartY) {
-						if (isInView) {
-							if (!$(this).find('a').attr('style')) {
-								$(this).find('a').css('background','url('+OC.filePath('contacts', '', 'thumbnail.php')+'?id='+$(this).data('id')+') no-repeat');
-							}
-						}
-					})}, 500);
-				setTimeout(Contacts.UI.Contacts.lazyupdate, 500);*/
-			},
-			// Add thumbnails to the contact list as they become visible in the viewport.
-			lazyupdate:function(){
-				$('.contacts li').live('inview', function(){
-					if (!$(this).find('a').attr('style')) {
-						$(this).find('a').css('background','url('+OC.filePath('contacts', '', 'thumbnail.php')+'?id='+$(this).data('id')+') no-repeat');
-					}
-				});
 			},
 			refreshThumbnail:function(id){
 				var item = $('.contacts li[data-id="'+id+'"]').find('a');
@@ -1681,13 +1714,6 @@ $(document).ready(function(){
 		return false;
 	});
 
-	$(document).on('click', '.addressbook', function(event){
-		$('#contacts h3').removeClass('active');
-		$(this).addClass('active');
-		$(this).next().slideToggle(300);
-		return false;
-	});
-	
 	/*$('.contacts li').bind('inview', function(event, isInView, visiblePartX, visiblePartY) {
 		if (isInView) { //NOTE: I've kept all conditions for future reference ;-)
 			// element is now visible in the viewport
diff --git a/apps/contacts/lib/vcard.php b/apps/contacts/lib/vcard.php
index bf22be0de74ff7a9c31904acb4bff1776c4be3d8..e3b656056243a527a26d104dc810df175a118b23 100644
--- a/apps/contacts/lib/vcard.php
+++ b/apps/contacts/lib/vcard.php
@@ -47,11 +47,18 @@ class OC_Contacts_VCard{
 	 * The cards are associative arrays. You'll find the original vCard in
 	 * ['carddata']
 	 */
-	public static function all($id){
+	public static function all($id, $start=null, $num=null){
+		$limitsql = '';
+		if(!is_null($num)) {
+			$limitsql = ' LIMIT '.$num;
+		}
+		if(!is_null($start) && !is_null($num)) {
+			$limitsql .= ' OFFSET '.$start.' ';
+		}
 		$result = null;
 		if(is_array($id) && count($id)) {
 			$id_sql = join(',', array_fill(0, count($id), '?'));
-			$prep = 'SELECT * FROM *PREFIX*contacts_cards WHERE addressbookid IN ('.$id_sql.') ORDER BY fullname';
+			$prep = 'SELECT * FROM *PREFIX*contacts_cards WHERE addressbookid IN ('.$id_sql.') ORDER BY fullname '.$limitsql;
 			try {
 				$stmt = OCP\DB::prepare( $prep );
 				$result = $stmt->execute($id);
@@ -63,7 +70,8 @@ class OC_Contacts_VCard{
 			}
 		} elseif(is_int($id) || is_string($id)) {
 			try {
-				$stmt = OCP\DB::prepare( 'SELECT * FROM *PREFIX*contacts_cards WHERE addressbookid = ? ORDER BY fullname' );
+				$sql = 'SELECT * FROM *PREFIX*contacts_cards WHERE addressbookid = ? ORDER BY fullname'.$limitsql;
+				$stmt = OCP\DB::prepare( $sql );
 				$result = $stmt->execute(array($id));
 			} catch(Exception $e) {
 				OCP\Util::writeLog('contacts',__CLASS__.'::'.__METHOD__.', exception: '.$e->getMessage(),OCP\Util::ERROR);
diff --git a/apps/contacts/templates/part.contact.php b/apps/contacts/templates/part.contact.php
index 5757563fe5b852ba3b3b0f153c87a70d67bcbccb..bb574372e52a749d08e3562d6e2063533dcda332 100644
--- a/apps/contacts/templates/part.contact.php
+++ b/apps/contacts/templates/part.contact.php
@@ -18,7 +18,14 @@ $id = isset($_['id']) ? $_['id'] : '';
 
 	<iframe name="file_upload_target" id='file_upload_target' src=""></iframe>
 	<div class="tip propertycontainer" id="contacts_details_photo_wrapper" title="<?php echo $l->t('Drop photo to upload'); ?> (max <?php echo $_['uploadMaxHumanFilesize']; ?>)" data-element="PHOTO">
+	<ul id="phototools" class="transparent hidden">
+		<li><a class="svg delete" title="<?php echo $l->t('Delete current photo'); ?>"></a></li>
+		<li><a class="svg edit" title="<?php echo $l->t('Edit current photo'); ?>"></a></li>
+		<li><a class="svg upload" title="<?php echo $l->t('Upload new photo'); ?>"></a></li>
+		<li><a class="svg cloud" title="<?php echo $l->t('Select photo from ownCloud'); ?>"></a></li>
+	</ul>
 	</div>
+	<img />
 	</div> <!-- contact_photo -->
 
 	<div id="contact_identity" class="contactsection">
@@ -104,7 +111,6 @@ $id = isset($_['id']) ? $_['id'] : '';
 	<div id="contacts_propertymenu">
 	<button class="button" id="contacts_propertymenu_button"><?php echo $l->t('Add field'); ?></button>
 	<ul id="contacts_propertymenu_dropdown" role="menu" class="hidden">
-		<li><a role="menuitem" data-type="PHOTO"><?php echo $l->t('Profile picture'); ?></a></li>
 		<li><a role="menuitem" data-type="ORG"><?php echo $l->t('Organization'); ?></a></li>
 		<li><a role="menuitem" data-type="NICKNAME"><?php echo $l->t('Nickname'); ?></a></li>
 		<li><a role="menuitem" data-type="BDAY"><?php echo $l->t('Birthday'); ?></a></li>
diff --git a/apps/contacts/templates/part.contactphoto.php b/apps/contacts/templates/part.contactphoto.php
deleted file mode 100644
index bddf4cc8a8190fb7b22e654cec68df6690381469..0000000000000000000000000000000000000000
--- a/apps/contacts/templates/part.contactphoto.php
+++ /dev/null
@@ -1,16 +0,0 @@
-<?php 
-$id = $_['id'];
-$wattr = isset($_['width'])?'width="'.$_['width'].'"':'';
-$hattr = isset($_['height'])?'height="'.$_['height'].'"':'';
-$rand = isset($_['refresh'])?'&refresh='.rand():'';
-?>
-<ul id="phototools" class="transparent hidden">
-	<li><a class="svg delete" title="<?php echo $l->t('Delete current photo'); ?>"></a></li>
-	<li><a class="svg edit" title="<?php echo $l->t('Edit current photo'); ?>"></a></li>
-	<li><a class="svg upload" title="<?php echo $l->t('Upload new photo'); ?>"></a></li>
-	<li><a class="svg cloud" title="<?php echo $l->t('Select photo from ownCloud'); ?>"></a></li>
-</ul>
-<img class="loading" id="contacts_details_photo" <?php echo $wattr; ?> <?php echo $hattr; ?> src="<?php echo OCP\Util::linkToAbsolute('contacts', 'photo.php'); ?>?id=<?php echo $id.$rand; ?>" />
-<progress id="contacts_details_photo_progress" style="display:none;" value="0" max="100">0 %</progress>
-
-
diff --git a/apps/contacts/templates/part.contacts.php b/apps/contacts/templates/part.contacts.php
deleted file mode 100644
index c33c5832e8275149b34f3ef4a1a325e49222ea72..0000000000000000000000000000000000000000
--- a/apps/contacts/templates/part.contacts.php
+++ /dev/null
@@ -1,10 +0,0 @@
-<?php
-foreach($_['books'] as $id => $addressbook) {
-	echo '<h3 class="addressbook" data-id="'.$id.'">'.$addressbook['displayname'].'</h3>';
-	echo '<ul class="contacts hidden" data-id="'.$id.'">';
-	foreach($addressbook['contacts'] as $contact) {
-		echo '<li role="button" data-bookid="'.$contact['addressbookid'].'" data-id="'.$contact['id'].'"><a href="'.link_to('contacts','index.php').'&id='.$contact['id'].'" style="background: url('.link_to('contacts','thumbnail.php').'?id='.$contact['id'].') no-repeat scroll 0 0 transparent;">'.$contact['displayname'].'</a></li>';
-	}
-	echo '</ul>';
-}
-?>
diff --git a/apps/files_external/lib/amazons3.php b/apps/files_external/lib/amazons3.php
index b8e5b9b079be31fd893d20993b67f02c306e7cce..9feb490dac0c91c5e2b94b9863b9e7583484f1c9 100644
--- a/apps/files_external/lib/amazons3.php
+++ b/apps/files_external/lib/amazons3.php
@@ -96,8 +96,8 @@ class OC_Filestorage_AmazonS3 extends OC_Filestorage_Common {
 			foreach ($response->body->CommonPrefixes as $object) {
 				$files[] = basename($object->Prefix);
 			}
-			OC_FakeDirStream::$dirs['amazons3'] = $files;
-			return opendir('fakedir://amazons3');
+			OC_FakeDirStream::$dirs['amazons3'.$path] = $files;
+			return opendir('fakedir://amazons3'.$path);
 		}
 		return false;
 	}
diff --git a/lib/migrate.php b/lib/migrate.php
index f26b4b256739d02f57cabbfdbdb6cc49e1b604b3..731b6a6839c90a52c811e81b4eb5c4ff66cb2de8 100644
--- a/lib/migrate.php
+++ b/lib/migrate.php
@@ -64,7 +64,7 @@ class OC_Migrate{
 		$apps = OC_App::getAllApps();
 
 		foreach($apps as $app){
-			$path = self::getAppPath($app) . '/appinfo/migrate.php';
+			$path = OC_App::getAppPath($app) . '/appinfo/migrate.php';
 			if( file_exists( $path ) ){
 				include( $path );
 			}
@@ -398,7 +398,7 @@ class OC_Migrate{
 			if( OC_App::isEnabled( $provider->getID() ) ){
 				$success = true;
 				// Does this app use the database?
-				if( file_exists( self::getAppPath($provider->getID()).'/appinfo/database.xml' ) ){
+				if( file_exists( OC_App::getAppPath($provider->getID()).'/appinfo/database.xml' ) ){
 					// Create some app tables
 					$tables = self::createAppTables( $provider->getID() );
 					if( is_array( $tables ) ){
@@ -539,7 +539,7 @@ class OC_Migrate{
 		}
 
 		// There is a database.xml file
-		$content = file_get_contents(self::getAppPath($appid) . '/appinfo/database.xml' );
+		$content = file_get_contents(OC_App::getAppPath($appid) . '/appinfo/database.xml' );
 
 		$file2 = 'static://db_scheme';
 		// TODO get the relative path to migration.db from the data dir
diff --git a/lib/setup.php b/lib/setup.php
index e1c1a110b38333bbb0f0eb30abc70c0917bb3acb..59c3aefbf13aec36f6dfea364f67569e6c1e4355 100644
--- a/lib/setup.php
+++ b/lib/setup.php
@@ -163,6 +163,7 @@ class OC_Setup {
 						'error' => 'PostgreSQL username and/or password not valid',
 						'hint' => 'You need to enter either an existing account or the administrator.'
 					);
+					return $error;
 				}
 				else {
 					//check for roles creation rights in postgresql