- added new unified bookmark api to /xml/bookmarks/

the get_bookmarks api currently supports:
  .xml: posts, xbel, rss, flexigrid
  .json: posts, flexigrid
  .html: work in progress
- YaCy-UI: support for new bookmark api 

git-svn-id: https://svn.berlios.de/svnroot/repos/yacy/trunk@5467 6c8d7289-2bf4-0310-a012-ef5d649a1542
pull/1/head
apfelmaennchen 16 years ago
parent c1330f5743
commit cc207a979e

@ -0,0 +1,275 @@
// /xml/bookmarks/get_bookmarks.java
// -------------------------------
// (C) 2009 Stefan Förster (apfelmaennchen)
// part of yacy
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
package xml.bookmarks;
import java.util.Date;
import java.util.Iterator;
import de.anomic.data.bookmarksDB;
import de.anomic.data.userDB;
import de.anomic.htmlFilter.htmlFilterCharacterCoding;
import de.anomic.http.httpRequestHeader;
import de.anomic.plasma.plasmaSwitchboard;
import de.anomic.server.serverDate;
import de.anomic.server.serverObjects;
import de.anomic.server.serverSwitch;
public class get_bookmarks {
private static final serverObjects prop = new serverObjects();
private static plasmaSwitchboard sb = null;
private static userDB.Entry user = null;
private static boolean isAdmin = false;
private static int R = 1; // TODO: solve the recursion problem an remove global variable
final static int SORT_ALPHA = 1;
final static int SORT_SIZE = 2;
final static int SHOW_ALL = -1;
final static int MAXRESULTS = 10000;
// file types and display types
final static int XML = 0; // .xml
final static int XHTML = 0; // .html (.xml)
final static int JSON = 0; // .json
final static int FLEXIGRID = 1; // .json .xml
final static int XBEL = 2; // .xml
final static int RSS = 3; // .xml (.rss)
final static int RDF = 4; // .xml
public static serverObjects respond(final httpRequestHeader header, final serverObjects post, final serverSwitch<?> env) {
prop.clear();
sb = (plasmaSwitchboard) env;
user = sb.userDB.getUser(header);
isAdmin = (sb.verifyAuthentication(header, true) || user != null && user.hasRight(userDB.Entry.BOOKMARK_RIGHT));
// set user name
final String username;
if(user != null) username=user.getUserName();
else if(isAdmin) username="admin";
else username = "unknown";
prop.putHTML("display_user", username);
// set peer address
prop.put("display_address", sb.webIndex.seedDB.mySeed().getPublicAddress());
prop.put("display_peer", sb.webIndex.seedDB.mySeed().getName());
int rp = MAXRESULTS; // items per page
int page = 1; // page
int display = 0; // default for JSON, XML or XHTML
// String sortorder = "asc";
// String sortname = "date";
String qtype = "";
String query = "";
// check for GET parameters
if (post != null){
if (post.containsKey("rp")) rp = Integer.parseInt(post.get("rp"));
if (post.containsKey("page")) page = Integer.parseInt(post.get("page"));
if (post.containsKey("query")) query = post.get("query");
if (post.containsKey("qtype")) qtype = post.get("qtype");
// if (post.containsKey("sortorder")) sortorder = post.get("sortorder");
if (post.containsKey("display")) {
if (post.get("display").equals("flexigrid") || post.get("display").equals("1")) {
display = FLEXIGRID;
}
else if (post.get("display").equals("xbel") || post.get("display").equals("2")) {
display = XBEL;
}
else if (post.get("display").equals("rss") || post.get("display").equals("3")) {
display = RSS;
}
}
prop.put("display", display);
}
int count = 0;
int total = 0;
int start = 0;
final Iterator<String> it;
bookmarksDB.Bookmark bookmark;
switch (display) {
case XBEL:
String root = "/";
if (qtype.equals("tags") && !query.equals("")) {
prop.putHTML("display_folder", "1");
prop.putHTML("display_folder_foldername", query);
prop.putHTML("display_folder_folderhash", bookmarksDB.tagHash(query));
it = sb.bookmarksDB.getBookmarksIterator(query, isAdmin);
count = print_XBEL(it, count);
prop.put("display_xbel", count);
break;
} else if (qtype.equals("folders") && !query.equals("")) {
if (query.startsWith("/")) { root = query; }
else { root = "/" + query; }
}
prop.putHTML("display_folder", "0");
R = root.replaceAll("[^/]","").length() - 1;
count = recurseFolders(sb.bookmarksDB.getFolderList(root, isAdmin),root,0,true,"");
prop.put("display_xbel", count);
break;
default:
// default covers all non XBEL formats
// set bookmark iterator according to query
if (qtype.equals("tags") && !query.equals("")) {
it = sb.bookmarksDB.getBookmarksIterator(query, isAdmin);
} else {
it = sb.bookmarksDB.getBookmarksIterator(isAdmin);
}
if (rp < MAXRESULTS) {
//skip the first entries (display next page)
if (page > 1) {
start = ((page-1)*rp)+1;
}
count = 0;
while(count < start && it.hasNext()){
it.next();
count++;
}
total += count;
}
count = 0;
while(count < rp && it.hasNext()){
bookmark = sb.bookmarksDB.getBookmark(it.next());
if(bookmark!=null) {
prop.put("display_bookmarks_"+count+"_id",count);
prop.put("display_bookmarks_"+count+"_link",bookmark.getUrl());
prop.put("display_bookmarks_"+count+"_date", serverDate.formatISO8601(new Date(bookmark.getTimeStamp())));
prop.put("display_bookmarks_"+count+"_rfc822date", serverDate.formatRFC1123(new Date(bookmark.getTimeStamp())));
prop.put("display_bookmarks_"+count+"_public", (bookmark.getPublic() ? "0" : "1"));
prop.put("display_bookmarks_"+count+"_hash", bookmark.getUrlHash());
prop.put("display_bookmarks_"+count+"_comma", ",");
// offer both HTML encoded
prop.putHTML("display_bookmarks_"+count+"_title-enc", bookmark.getTitle());
prop.putHTML("display_bookmarks_"+count+"_desc-enc", bookmark.getDescription());
prop.putHTML("display_bookmarks_"+count+"_tags-enc", bookmark.getTagsString().replaceAll(",", ", "));
prop.putHTML("display_bookmarks_"+count+"_folders-enc", (bookmark.getFoldersString()));
// and plain text (potentially unsecure)
prop.put("display_bookmarks_"+count+"_title", bookmark.getTitle());
prop.put("display_bookmarks_"+count+"_desc", bookmark.getDescription());
prop.put("display_bookmarks_"+count+"_tags", bookmark.getTagsString());
prop.put("display_bookmarks_"+count+"_folders", (bookmark.getFoldersString()));
count++;
}
}
// eliminate the trailing comma for Json output
rp--;
prop.put("display_bookmarks_"+rp+"_comma", "");
prop.put("display_bookmarks", count);
while(it.hasNext()){
it.next();
count++;
}
total += count;
prop.put("display_page", page);
prop.put("display_total", total);
break;
} // end switch
// return rewrite properties
return prop;
}
private static int recurseFolders(final Iterator<String> it, String root, int count, final boolean next, final String prev){
String fn="";
if(next) fn = it.next();
else fn = prev;
if(fn.equals("\uffff")) {
int i = prev.replaceAll("[^/]","").length() - R;
while(i>0){
prop.put("display_xbel_"+count+"_elements", "</folder>");
count++;
i--;
}
return count;
}
if(fn.startsWith(root)){
prop.put("display_xbel_"+count+"_elements", "<folder id=\""+bookmarksDB.tagHash(fn)+"\">");
count++;
final String title = fn; // just to make sure fn stays untouched
prop.put("display_xbel_"+count+"_elements", "<title>" + htmlFilterCharacterCoding.unicode2xml(title.replaceAll("(/.[^/]*)*/", ""), true) + "</title>");
count++;
final Iterator<String> bit=sb.bookmarksDB.getBookmarksIterator(fn, isAdmin);
count = print_XBEL(bit, count);
if(it.hasNext()){
count = recurseFolders(it, fn, count, true, fn);
}
} else {
prop.put("display_xbel_"+count+"_elements", "</folder>");
count++;
root = root.replaceAll("(/.[^/]*$)", "");
if(root.equals("")) root = "/";
count = recurseFolders(it, root, count, false, fn);
}
return count;
}
private static int print_XBEL(final Iterator<String> bit, int count) {
bookmarksDB.Bookmark bookmark;
Date date;
while(bit.hasNext()){
bookmark=sb.bookmarksDB.getBookmark(bit.next());
date=new Date(bookmark.getTimeStamp());
prop.put("display_xbel_"+count+"_elements", "<bookmark id=\"" + bookmark.getUrlHash()
+ "\" href=\"" + htmlFilterCharacterCoding.unicode2xml(bookmark.getUrl(), true)
+ "\" added=\"" + htmlFilterCharacterCoding.unicode2xml(serverDate.formatISO8601(date), true)+"\">");
count++;
prop.put("display_xbel_"+count+"_elements", "<title>");
count++;
prop.putXML("display_xbel_"+count+"_elements", bookmark.getTitle());
count++;
prop.put("display_xbel_"+count+"_elements", "</title>");
count++;
prop.put("display_xbel_"+count+"_elements", "<info>");
count++;
prop.put("display_xbel_"+count+"_elements", "<metadata owner=\"Mozilla\" ShortcutURL=\""
+ htmlFilterCharacterCoding.unicode2xml(bookmark.getTagsString().replaceAll("/.*,", "").toLowerCase(), true)
+ "\"/>");
count++;
prop.put("display_xbel_"+count+"_elements", "<metadata owner=\"YaCy\" public=\""+Boolean.toString(bookmark.getPublic())+"\"/>");
count++;
prop.put("display_xbel_"+count+"_elements", "</info>");
count++;
prop.put("display_xbel_"+count+"_elements", "<desc>");
count++;
prop.putXML("display_xbel_"+count+"_elements", bookmark.getDescription());
count++;
prop.put("display_xbel_"+count+"_elements", "</desc>");
count++;
prop.put("display_xbel_"+count+"_elements", "</bookmark>");
count++;
}
return count;
}
}

@ -0,0 +1,27 @@
#(display)#
{
page: #[page]#,
total: #[total]#,
posts: [
#{bookmarks}#
{bookmark:["#[hash]#",#(public)#"public"::"private"#(/public)#,"#[title]#","#[link]#","#[tags]#","#[folders]#","#[date]#"]}#[comma]#
#{/bookmarks}#
]
}
::
{
page: #[page]#,
total: #[total]#,
rows: [
#{bookmarks}#
{id:"#[id]#",cell:[
"#[hash]#",
#(public)#"<img src='img-2/world2.png' alt='public' title='public bookmark'/>"::"<img src='img-2/lock.png' alt='private' title='private bookmark'/>"#(/public)#,
"<h3 class='linktitle'>#[title-enc]#</h3><p class='desc'>#[desc-enc]#</p><p class='url'><a href='#[link]#'>#[link]#</a>",
"<p class='tags'>#[tags-enc]#</p>",
"<p class='folders'>#[folders-enc]#</p>",
"<p class='date'>#[rfc822date]#</p>"]}#[comma]#
#{/bookmarks}#
]
}
#(/display)#

@ -0,0 +1,52 @@
<?xml version="1.0" encoding="UTF-8"?>
#(display)#
<!-- DOCTYPE YaCy Bookmarks http://www.yacy.net -->
<posts>
#{bookmarks}#
<post href="#[link]#" description="#[title]#" extended="#[desc]#" hash="#[hash]#" tag="#[tags]#" time="#[date]#" #(public)#private="false"::private="true"#(/public)#/>
#{/bookmarks}#
</posts>
::
<!-- DOCTYPE flexigrid http://www.flexigrid.info/ -->
<rows>
<page>#[page]#</page>
<total>#[total]#</total>
#{bookmarks}#<row id='#[id]#'>
<cell><![CDATA[#[hash]#]]></cell>
#(public)#<cell><![CDATA[<img src='img-2/world2.png' alt='public' title='public bookmark'/>]]></cell>::
<cell><![CDATA[<img src='img-2/lock.png' alt='private' title='private bookmark'/>]]></cell>#(/public)#
<cell><![CDATA[<h3 class='linktitle'>#[title-enc]#</h3><p class='desc'>#[desc-enc]#</p><p class='url'><a href='#[link]#'>#[link]#</a>]]></cell>
<cell><![CDATA[<p class='tags'>#[tags-enc]#</p>]]></cell>
<cell><![CDATA[<p class='folders'>#[folders-enc]#</p>]]></cell>
<cell><![CDATA[<p class='date'>#[rfc822date]#</p>]]></cell>
</row>#{/bookmarks}#
</rows>
::
<!DOCTYPE xbel PUBLIC "+//IDN python.org//DTD XML Bookmark Exchange Language 1.0//EN//XML" "http://pyxml.sourceforge.net/topics/dtds/xbel-1.0.dtd">
<xbel>
#(folder)#::
<folder id="#[folderhash]#">
<title>#[foldername]#</title>
#(/folder)#
#{xbel}#
#[elements]#
#{/xbel}#
#(folder)#::</folder>#(/folder)#
</xbel>
::
<rss version="2.0">
<channel>
<title><![CDATA[YaCy '#[peer]#': Bookmarks]]></title>
<link>http://#[address]#/xml/bookmarks/get_bookmarks.xml</link>
<description><![CDATA[#[user]#'s Bookmark-Feed]]></description>
</channel>
#{bookmarks}#<item>
<title><![CDATA[#[title]#]]></title>
<link>#[link]#</link>
<pubDate>#[rfc822date]#</pubDate>
<guid>#[hash]#</guid>
<description><![CDATA[<p>#[desc]#</p>]]></description>
<category><![CDATA[#[tags]#]]></category>
</item>#{/bookmarks}#
</rss>
#(/display)#

@ -3,68 +3,51 @@
$(document).ready(function() {
$("#side1").accordion("activate", 0);
// $("#side2").accordion("activate", 1);
// $('#yoptions').resetForm();
$.ajax({
type: "POST",
async: true,
url: "/xml/bookmarks/xbel/xbel.xml?tag="+qtag,
dataType: "xml",
success: function(xml) {
$(xml).find('bookmark').each(function(){
var link = $(this).attr('href');
var hash = $(this).attr('id');
var title = $(this).find('title').text();
var date = $(this).attr('added');
var desc = $(this).find('desc').text();
var pub = $(this).find('metadata[owner=YaCy][public]').attr('public');
var tags = $(this).find('metadata[owner=Mozilla][ShortcutURL]').attr('ShortcutURL');
if (tags != undefined) {
tags = tags.replace(",",", ","g");
} else {
tags ="";
}
if (pub == "true") {
icon = '<img src="img-2/world2.png" alt="public" title="public bookmark"/>'
} else {
var icon = '<img src="img-2/lock.png" alt="private" title="private bookmark"/>'
}
$('<tr></tr')
.html('<td>' +hash+ '</td><td>' +icon+ '</td><td><h3 class="linktitle">' +HTMLenc(title)+ '</h3><p class="desc">' +HTMLenc(desc)+ '</p><p class="url"><a href="' +link+ '">' +link+ '</a></p><td class="tags">' +HTMLenc(tags)+ ' </td><td class="date">' +date+ '</td>')
.appendTo('#ymarks tbody');
}); //close each(
var height=document.documentElement.clientHeight - 205;
$('#ymarks').flexigrid({
colModel: [
{display: 'Hash', name : 'hash', width : 50, sortable : false, align: 'center', hide: true},
{display: '', name : 'public', width : 25, sortable : true, align: 'center'},
{display: 'Title', name : 'title', width : 450, sortable : true, align: 'left'},
{display: 'Tags', name : 'tags', width : 240, sortable : false, align: 'left'},
{display: 'Date', name : 'date', width : 130, sortable : true, align: 'left'}
],
buttons: [
{name: 'Crawl', bclass: 'crawl', onpress: bm_action},
{separator: true},
{name: 'Bookmark', bclass: 'bookmark', onpress: bm_action},
{separator: true},
{name: 'Edit', bclass: 'edit', onpress: bm_action},
{name: 'Delete', bclass: 'delete', onpress: bm_action},
{separator: true},
{name: 'RSS', bclass: 'rss', onpress: bm_action},
{name: 'XBEL', bclass: 'xml', onpress: bm_action},
{name: 'XML', bclass: 'xml', onpress: bm_action},
{separator: true},
{name: 'Import', bclass: 'import', onpress: bm_action},
{separator: true},
{name: 'Help', bclass: 'help', onpress: bm_action},
],
striped: true,
nowrap: false,
height: height,
title: 'YaCy Bookmarks: ' + HTMLenc(qtag)
});
}
}); //close $.ajax(
// $('#yoptions').resetForm();
var height=document.documentElement.clientHeight - 240;
$('#ymarks').flexigrid({
url: '/xml/bookmarks/get_bookmarks.json?display=1',
dataType: 'json',
method: 'GET',
colModel: [
{display: 'Hash', name : 'hash', width : 50, sortable : false, align: 'center', hide: true},
{display: 'Public', name : 'public', width : 25, sortable : true, align: 'center'},
{display: 'Title', name : 'title', width : 450, sortable : true, align: 'left'},
{display: 'Tags', name : 'tags', width : 240, sortable : false, align: 'left'},
{display: 'Folders', name : 'folders', width : 240, sortable : false, align: 'left', hide: true},
{display: 'Date', name : 'date', width : 100, sortable : true, align: 'left'}
],
buttons: [
{name: 'Crawl', bclass: 'crawl', onpress: bm_action},
{separator: true},
{name: 'Bookmark', bclass: 'bookmark', onpress: bm_action},
{separator: true},
{name: 'Edit', bclass: 'edit', onpress: bm_action},
{name: 'Delete', bclass: 'delete', onpress: bm_action},
{separator: true},
{name: 'RSS', bclass: 'rss', onpress: bm_action},
{name: 'XBEL', bclass: 'xml', onpress: bm_action},
{name: 'XML', bclass: 'xml', onpress: bm_action},
{separator: true},
{name: 'Import', bclass: 'import', onpress: bm_action},
{separator: true},
{name: 'Help', bclass: 'help', onpress: bm_action},
],
searchitems : [
{display: 'Tags', name : 'tags'}
],
useRp: true,
rp: 15,
sortname: "date",
sortorder: "asc",
usepager: true,
striped: true,
nowrap: false,
height: height,
title: 'YaCy Bookmarks: ' + HTMLenc(qtag)
});
});
function bm_action(com,grid) {
if (com=='XBEL') {
@ -121,8 +104,8 @@
$("input[@name='bm_url']").setValue($('.trSelected',grid).find('.url').text());
$("textarea[@name='bm_title']").setValue($('.trSelected',grid).find('h3.linktitle').text().replace(/^\s+/g,""));
$("textarea[@name='bm_desc']").setValue($('.trSelected',grid).find('p.desc').text().replace(/^\s+/g,""));
$("input[@name='bm_tags']").setValue($('.trSelected',grid).find('td.tags').text());
// $("input[@name='bm_path']").setValue($('.trSelected',grid).find('.path').text());
$("input[@name='bm_tags']").setValue($('.trSelected',grid).find('p.tags').text().replace(/\s+/g,""));
$("input[@name='bm_path']").setValue($('.trSelected',grid).find('p.folders').text());
$("select[@name='bm_public']").setValue($('.trSelected',grid).find('img').attr('alt'));
$("#bmadd").dialog('open');
}

@ -7,6 +7,7 @@
apfelmaennchen
<h3>Change Log</h3>
<ul>
<li>11-01-2009: support for new unified bookmark api ==> much improved handling due to json and flexigrid</li>
<li>27-09-2008: Enabled edit bookmark and added some more icons to toolbar</li>
<li>27-09-2008: Added scrollbar to folder widget</li>
<li>27-09-2008: Slightly improved Ajax handling for folder and tag widget</li>

Loading…
Cancel
Save