diff --git a/apps/bookmarks/ajax/updateList.php b/apps/bookmarks/ajax/updateList.php
index d2a5397452f97cd5b5ebda1a0928d11f6c86a0c0..487e0d290e3d664097d018fd86c90644e6e84285 100644
--- a/apps/bookmarks/ajax/updateList.php
+++ b/apps/bookmarks/ajax/updateList.php
@@ -5,6 +5,7 @@
 *
 * @author Arthur Schiwon
 * @copyright 2011 Arthur Schiwon blizzz@arthur-schiwon.de
+* @copyright 2012 David Iwanowitsch <david at unclouded dot de>
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
@@ -30,71 +31,20 @@ require_once('../../../lib/base.php');
 OC_JSON::checkLoggedIn();
 OC_JSON::checkAppEnabled('bookmarks');
 
-$params=array(OC_User::getUser());
-$CONFIG_DBTYPE = OC_Config::getValue( 'dbtype', 'sqlite' );
 
 //Filter for tag?
-$filterTag = isset($_GET['tag']) ? '%' . htmlspecialchars_decode($_GET['tag']) . '%' : false;
-if($filterTag){
-	$sqlFilterTag = 'HAVING tags LIKE ?';
-	$params[] = $filterTag;
-	if($CONFIG_DBTYPE == 'pgsql' ) {
-		$sqlFilterTag = 'HAVING array_to_string(array_agg(tag), \' \')  LIKE ?';
-	}
-} else {
-	$sqlFilterTag = '';
-}
+$filterTag = isset($_GET['tag']) ? htmlspecialchars_decode($_GET['tag']) : false;
 
 $offset = isset($_GET['page']) ? intval($_GET['page']) * 10 : 0;
 
 $sort = isset($_GET['sort']) ? ($_GET['sort']) : 'bookmarks_sorting_recent';
 if($sort == 'bookmarks_sorting_clicks') {
-	$sqlSort = 'clickcount DESC';
+	$sqlSortColumn = 'clickcount';
 } else {
-	$sqlSort = 'id DESC';
+	$sqlSortColumn = 'id';
 }
 
-if( $CONFIG_DBTYPE == 'sqlite' or $CONFIG_DBTYPE == 'sqlite3' ){
-	$_gc_separator = ', \' \'';
-} else {
-	$_gc_separator = 'SEPARATOR \' \'';
-}
-
-if($CONFIG_DBTYPE == 'pgsql' ){
-	$params[] = $offset;
-	$query = OC_DB::prepare('
-		SELECT id, url, title, array_to_string(array_agg(tag), \' \') as tags
-		FROM *PREFIX*bookmarks
-		LEFT JOIN *PREFIX*bookmarks_tags ON *PREFIX*bookmarks.id = *PREFIX*bookmarks_tags.bookmark_id 
-		WHERE 
-			*PREFIX*bookmarks.user_id = ?
-		GROUP BY id, url, title
-		'.$sqlFilterTag.'
-		ORDER BY *PREFIX*bookmarks.'.$sqlSort.' 
-		LIMIT 10
-		OFFSET ?');
-} else {
-	$query = OC_DB::prepare('
-		SELECT id, url, title, 
-		CASE WHEN *PREFIX*bookmarks.id = *PREFIX*bookmarks_tags.bookmark_id
-				THEN GROUP_CONCAT( tag ' .$_gc_separator. ' )
-				ELSE \' \'
-			END
-			AS tags
-		FROM *PREFIX*bookmarks
-		LEFT JOIN *PREFIX*bookmarks_tags ON 1=1
-		WHERE (*PREFIX*bookmarks.id = *PREFIX*bookmarks_tags.bookmark_id 
-				OR *PREFIX*bookmarks.id NOT IN (
-					SELECT *PREFIX*bookmarks_tags.bookmark_id FROM *PREFIX*bookmarks_tags
-				)
-			)
-			AND *PREFIX*bookmarks.user_id = ?
-		GROUP BY url
-		'.$sqlFilterTag.'
-		ORDER BY *PREFIX*bookmarks.'.$sqlSort.' 
-		LIMIT '.$offset.',  10');
-}
 
-$bookmarks = $query->execute($params)->fetchAll();
+$bookmarks = OC_Bookmarks_Bookmarks::findBookmarks($offset, $sqlSortColumn, $filterTag, true);
 
 OC_JSON::success(array('data' => $bookmarks));
diff --git a/apps/bookmarks/appinfo/app.php b/apps/bookmarks/appinfo/app.php
index 44a1e47dff9fb0cc0fca21b0c885dd51c62ceb9b..479d8ed476751a830ef4486c6dbdd68c6ca6dab8 100644
--- a/apps/bookmarks/appinfo/app.php
+++ b/apps/bookmarks/appinfo/app.php
@@ -7,8 +7,13 @@
 * See the COPYING-README file.
 */
 
+OC::$CLASSPATH['OC_Bookmarks_Bookmarks'] = 'apps/bookmarks/lib/bookmarks.php';
+
 OC_App::register( array( 'order' => 70, 'id' => 'bookmark', 'name' => 'Bookmarks' ));
 
-OC_App::addNavigationEntry( array( 'id' => 'bookmarks_index', 'order' => 70, 'href' => OC_Helper::linkTo( 'bookmarks', 'index.php' ), 'icon' => OC_Helper::imagePath( 'bookmarks', 'bookmarks.png' ), 'name' => 'Bookmarks' ));
+$l = new OC_l10n('bookmarks');
+OC_App::addNavigationEntry( array( 'id' => 'bookmarks_index', 'order' => 70, 'href' => OC_Helper::linkTo( 'bookmarks', 'index.php' ), 'icon' => OC_Helper::imagePath( 'bookmarks', 'bookmarks.png' ), 'name' => $l->t('Bookmarks')));
 
 OC_App::registerPersonal('bookmarks', 'settings');
+require_once('apps/bookmarks/lib/search.php');
+OC_Util::addScript('bookmarks','bookmarksearch');
diff --git a/apps/bookmarks/js/bookmarksearch.js b/apps/bookmarks/js/bookmarksearch.js
new file mode 100644
index 0000000000000000000000000000000000000000..39874aa0b294c6acfcf5a7849dc23ec5d53d0f34
--- /dev/null
+++ b/apps/bookmarks/js/bookmarksearch.js
@@ -0,0 +1,22 @@
+/**
+ * Copyright (c) 2012 David Iwanowitsch <david at unclouded dot de>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+$(document).ready(function(){
+	OC.search.customResults.Bookm.=function(row,item){
+		var a=row.find('a');
+		a.attr('target','_blank');
+		a.click(recordClick);
+	}
+});
+
+function recordClick(event) {
+	var jsFileLocation = $('script[src*=bookmarksearch]').attr('src');
+	jsFileLocation = jsFileLocation.replace('js/bookmarksearch.js', '');
+	$.ajax({
+		url: jsFileLocation + 'ajax/recordClick.php',
+		data: 'url=' + encodeURI($(this).attr('href')),
+	});	
+}
diff --git a/apps/bookmarks/l10n/xgettextfiles b/apps/bookmarks/l10n/xgettextfiles
new file mode 100644
index 0000000000000000000000000000000000000000..cd5554323902ab3fd08f3ff56a2e53d6ef3f1136
--- /dev/null
+++ b/apps/bookmarks/l10n/xgettextfiles
@@ -0,0 +1,5 @@
+../appinfo/app.php
+../lib/search.php
+../templates/settings.php
+../templates/addBm.php
+../templates/list.php
diff --git a/apps/bookmarks/lib/bookmarks.php b/apps/bookmarks/lib/bookmarks.php
new file mode 100644
index 0000000000000000000000000000000000000000..81c1b03981aed56a3ad4a80a4ce6251fd36d1b52
--- /dev/null
+++ b/apps/bookmarks/lib/bookmarks.php
@@ -0,0 +1,117 @@
+<?php
+/**
+ * ownCloud - bookmarks plugin
+ *
+ * @author Arthur Schiwon
+ * @copyright 2011 Arthur Schiwon blizzz@arthur-schiwon.de
+ *
+ * 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/>.
+ *
+ */
+
+/**
+ * This class manages bookmarks
+ */
+class OC_Bookmarks_Bookmarks{
+
+	/**
+	 * @brief Finds all bookmarks, matching the filter
+	 * @param offset result offset
+	 * @param sqlSortColumn sort result with this column
+	 * @param filter can be: empty -> no filter, a string -> filter this, a string array -> filter for all strings
+	 * @param filterTagOnly if true, filter affacts only tags, else filter affects url, title and tags
+	 * @return void
+	 */
+	public static function findBookmarks($offset, $sqlSortColumn, $filter, $filterTagOnly){
+		//OC_Log::write('bookmarks', 'findBookmarks ' .$offset. ' '.$sqlSortColumn.' '. $filter.' '. $filterTagOnly ,OC_Log::DEBUG);
+		$CONFIG_DBTYPE = OC_Config::getValue( 'dbtype', 'sqlite' );
+	
+		$params=array(OC_User::getUser());
+	
+		if( $CONFIG_DBTYPE == 'sqlite' or $CONFIG_DBTYPE == 'sqlite3' ){
+			$_gc_separator = ', \' \'';
+		} else {
+			$_gc_separator = 'SEPARATOR \' \'';
+		}
+
+		if($filter){
+			if($CONFIG_DBTYPE == 'pgsql' )
+				$tagString = 'array_to_string(array_agg(tag), \' \')';
+			else
+				$tagString = 'tags';
+
+			$sqlFilterTag = 'HAVING ';
+			if(is_array($filter)){
+				$first = true;
+				$filterstring = '';
+				foreach ($filter as $singleFilter){
+					$filterstring = $filterstring . ($first?'':' AND ') . $tagString.' LIKE ? ';
+					$params[] = '%'.$singleFilter.'%';
+					$first=false;
+				}
+				$sqlFilterTag = $sqlFilterTag . $filterstring;
+			} else{
+				$sqlFilterTag = $sqlFilterTag .$tagString.' LIKE ? ';
+				$params[] = '%'.$filter.'%';
+			}
+		} else {
+			$sqlFilterTag = '';
+		}
+
+		if($CONFIG_DBTYPE == 'pgsql' ){
+			$query = OC_DB::prepare('
+				SELECT id, url, title, '.($filterTagOnly?'':'url || title ||').' array_to_string(array_agg(tag), \' \') as tags
+				FROM *PREFIX*bookmarks
+				LEFT JOIN *PREFIX*bookmarks_tags ON *PREFIX*bookmarks.id = *PREFIX*bookmarks_tags.bookmark_id 
+				WHERE 
+					*PREFIX*bookmarks.user_id = ?
+				GROUP BY id, url, title
+				'.$sqlFilterTag.'
+				ORDER BY *PREFIX*bookmarks.'.$sqlSortColumn.' DESC 
+				LIMIT 10
+				OFFSET '. $offset);
+		} else {
+			if( $CONFIG_DBTYPE == 'sqlite' or $CONFIG_DBTYPE == 'sqlite3' )
+				$concatFunction = '(url || title || ';
+			else
+				$concatFunction = 'Concat(Concat( url, title), ';
+		
+			$query = OC_DB::prepare('
+				SELECT id, url, title, '
+				.($filterTagOnly?'':$concatFunction).
+				'CASE WHEN *PREFIX*bookmarks.id = *PREFIX*bookmarks_tags.bookmark_id
+						THEN GROUP_CONCAT( tag ' .$_gc_separator. ' )
+						ELSE \' \'
+					END '
+				.($filterTagOnly?'':')').'
+					AS tags
+				FROM *PREFIX*bookmarks
+				LEFT JOIN *PREFIX*bookmarks_tags ON 1=1
+				WHERE (*PREFIX*bookmarks.id = *PREFIX*bookmarks_tags.bookmark_id 
+						OR *PREFIX*bookmarks.id NOT IN (
+							SELECT *PREFIX*bookmarks_tags.bookmark_id FROM *PREFIX*bookmarks_tags
+						)
+					)
+					AND *PREFIX*bookmarks.user_id = ?
+				GROUP BY url
+				'.$sqlFilterTag.'
+				ORDER BY *PREFIX*bookmarks.'.$sqlSortColumn.' DESC
+				LIMIT '.$offset.',  10');
+		}
+
+		$bookmarks = $query->execute($params)->fetchAll();
+		return $bookmarks;
+	}
+}
+?>
diff --git a/apps/bookmarks/lib/search.php b/apps/bookmarks/lib/search.php
new file mode 100644
index 0000000000000000000000000000000000000000..59495db82eac16151d1a95afa35d9b708f61246e
--- /dev/null
+++ b/apps/bookmarks/lib/search.php
@@ -0,0 +1,50 @@
+<?php
+/**
+ * ownCloud - bookmarks plugin
+ *
+ * @author David Iwanowitsch
+ * @copyright 2012 David Iwanowitsch <david at unclouded dot de>
+ *
+ * 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/>.
+ *
+ */
+
+class OC_Search_Provider_Bookmarks extends OC_Search_Provider{
+	function search($query){
+		$results=array();
+		
+		$offset = 0;
+		$sqlSortColumn = 'id';
+		
+		$searchquery=array();
+		if(substr_count($query, ' ') > 0){
+			$searchquery = explode(' ', $query);
+		}else{
+			$searchquery = $query;
+		}
+		
+//		OC_Log::write('bookmarks', 'search ' .$query ,OC_Log::DEBUG);
+		$bookmarks = OC_Bookmarks_Bookmarks::findBookmarks($offset, $sqlSortColumn, $searchquery, false);
+//		OC_Log::write('bookmarks', 'found ' .count($bookmarks) ,OC_Log::DEBUG);
+		//$l = new OC_l10n('bookmarks'); //resulttype can't be localized, javascript relies on that type
+		foreach($bookmarks as $bookmark){
+			$results[]=new OC_Search_Result($bookmark['title'],'', $bookmark['url'],'Bookm.');
+		}
+		
+		return $results;
+	}
+}
+new OC_Search_Provider_Bookmarks();
+
+?>