diff --git a/htroot/Blog.html b/htroot/Blog.html new file mode 100644 index 000000000..ca879e716 --- /dev/null +++ b/htroot/Blog.html @@ -0,0 +1,61 @@ + + + +YaCy '#[clientname]#': Blog +#%env/templates/metas.template%# + + +#%env/templates/header.template%# +#(mode)# + +
+#{entries}# + + + + +
#[date]#by #[author]#

#[subject]#


#[page]#
link#(admin)#:: - edit#(/admin)#
+
+#{/entries}# +#(moreentries)#::show more entries...#(/moreentries)# +
+#(admin)#::new entry - #(/admin)#Blog-Home
+:: + +
+

Author:

+

Subject:

+

Text:

+ + + + + +
+:: + +

Preview

+

No changes have been submitted so far!

+ + + + +
#[date]#by #[author]#

#[subject]#


#[page]#
+
+

Author:

+

Subject:

+

Text:

+ + + + + +
+:: + +

Access denied

+To edit or create blog-entries you need to be logged in as Admin or User that has Blog rights. +#(/mode)# +#%env/templates/footer.template%# + + diff --git a/htroot/Blog.java b/htroot/Blog.java new file mode 100644 index 000000000..942429273 --- /dev/null +++ b/htroot/Blog.java @@ -0,0 +1,164 @@ +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Iterator; + +import de.anomic.data.userDB; +import de.anomic.data.blogBoard; +import de.anomic.data.wikiCode; +import de.anomic.http.httpHeader; +import de.anomic.plasma.plasmaSwitchboard; +import de.anomic.server.serverObjects; +import de.anomic.server.serverSwitch; + +public class Blog { + + private static SimpleDateFormat SimpleFormatter = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); +// TODO: make userdefined date/time-strings (localisation) + + public static String dateString(Date date) { + return SimpleFormatter.format(date); + } + + public static serverObjects respond(httpHeader header, serverObjects post, serverSwitch env) { + plasmaSwitchboard switchboard = (plasmaSwitchboard) env; + serverObjects prop = new serverObjects(); + + boolean hasRights = switchboard.verifyAuthentication(header, true); + if(!hasRights){ + userDB.Entry userentry = switchboard.userDB.proxyAuth((String)header.get("Authorization", "xxxxxx")); + if(userentry != null && userentry.hasBlogRight()){ + hasRights=true; + } + } + + if(hasRights) prop.put("mode_admin",1); + else prop.put("mode_admin",0); + + if (post == null) { + post = new serverObjects(); + post.put("page", "blog_default"); + } + + String pagename = post.get("page", "blog_default"); + String ip = post.get("CLIENTIP", "127.0.0.1"); + String author = post.get("author", "anonymous"); + if (author.equals("anonymous")) { + author = switchboard.blogDB.guessAuthor(ip); + if (author == null) { + if (de.anomic.yacy.yacyCore.seedDB.mySeed == null) + author = "anonymous"; + else + author = de.anomic.yacy.yacyCore.seedDB.mySeed.get("Name", "anonymous"); + } + } + + if (post.containsKey("submit") && (hasRights)) { + // store a new/edited blog-entry + byte[] content; + try { + content = post.get("content", "").getBytes("UTF-8"); + } catch (UnsupportedEncodingException e) { + content = post.get("content", "").getBytes(); + } + + //set name for new entry + if(pagename.equals("blog_default")) + pagename = String.valueOf(System.currentTimeMillis()); + + try { + switchboard.blogDB.write(switchboard.blogDB.newEntry(pagename, post.get("subject",""), author, ip, content)); + } catch (IOException e) {} + } + + blogBoard.entry page = switchboard.blogDB.read(pagename); + + if (post.containsKey("edit")) { + //edit an entry + if(hasRights) { + try { + prop.put("mode", 1); //edit + prop.put("mode_author", author); + prop.put("mode_pageid", page.key()); + prop.put("mode_subject", page.subject()); + prop.put("mode_page-code", new String(page.page(), "UTF-8").replaceAll("<","<").replaceAll(">",">")); + } catch (UnsupportedEncodingException e) {} + } + else { + prop.put("mode",3); //access denied (no rights) + } + } + else if(post.containsKey("preview")) { + //preview the page + if(hasRights) { + wikiCode wikiTransformer=new wikiCode(switchboard); + prop.put("mode", 2);//preview + prop.put("mode_pageid", pagename); + prop.put("mode_author", author); + prop.put("mode_subject", post.get("subject","")); + prop.put("mode_date", dateString(new Date())); + prop.put("mode_page", wikiTransformer.transform(post.get("content", ""))); + prop.put("mode_page-code", post.get("content", "").replaceAll("<","<").replaceAll(">",">")); + } + else prop.put("mode",3); //access denied (no rights) + } + else { + wikiCode wikiTransformer=new wikiCode(switchboard); + // show blog-entry/entries + prop.put("mode", 0); //viewing + if(pagename.equals("blog_default")) { + //index all entries + try { + Iterator i = switchboard.blogDB.keys(false); + String pageid; + blogBoard.entry entry; + int count = 0; //counts how many entries are shown to the user + int start = post.getInt("start",0); //indicates from where entries should be shown + int num = post.getInt("num",20); //indicates how many entries should be shown + int nextstart = start+num; //indicates the starting offset for next results + while(i.hasNext()) { + if(count >= num && num > 0) + break; + pageid = (String) i.next(); + if(0 < start--) + continue; + entry = switchboard.blogDB.read(pageid); + prop.put("mode_entries_"+count+"_pageid",entry.key()); + prop.put("mode_entries_"+count+"_subject", entry.subject()); + prop.put("mode_entries_"+count+"_author", entry.author()); + prop.put("mode_entries_"+count+"_date", dateString(entry.date())); + prop.put("mode_entries_"+count+"_page", wikiTransformer.transform(entry.page())); + if(hasRights) { + prop.put("mode_entries_"+count+"_admin", 1); + prop.put("mode_entries_"+count+"_admin_pageid",entry.key()); + } + else prop.put("mode_entries_"+count+"_admin", 0); + ++count; + } + prop.put("mode_entries",count); + if(i.hasNext()) { + prop.put("mode_moreentries",1); //more entries are availible + prop.put("mode_moreentries_start",nextstart); + prop.put("mode_moreentries_num",num); + } + else prop.put("moreentries",0); + } catch (IOException e) { + + } + } + else { + //only show 1 entry + prop.put("mode_entries",1); + prop.put("mode_entries_0_pageid", page.key()); + prop.put("mode_entries_0_subject", page.subject()); + prop.put("mode_entries_0_author", page.author()); + prop.put("mode_entries_0_date", dateString(page.date())); + prop.put("mode_entries_0_page", wikiTransformer.transform(page.page())); + } + } + + // return rewrite properties + return prop; + } +} diff --git a/htroot/PerformanceMemory_p.html b/htroot/PerformanceMemory_p.html index 5437fdead..85d80f993 100644 --- a/htroot/PerformanceMemory_p.html +++ b/htroot/PerformanceMemory_p.html @@ -238,6 +238,23 @@ This cache is divided in two parts, one for the wiki database and one for its ba Increasing this cache may speed up access to the wiki pages. + +Blog +#[chunkBlog]# +#[slreqBlog]# +#[slempBlog]# +#[slhigBlog]# +#[slmedBlog]# +#[sllowBlog]# +#[usedBlog]# + +#[dfltBlog]# +#[goodBlog]# +#[bestBlog]# +The YaCy-Blog uses a database to store its entries. +Increasing this cache may speed up access to the Blog. + + News #[chunkNews]# diff --git a/htroot/PerformanceMemory_p.java b/htroot/PerformanceMemory_p.java index b03a73534..a832108df 100644 --- a/htroot/PerformanceMemory_p.java +++ b/htroot/PerformanceMemory_p.java @@ -87,6 +87,7 @@ public class PerformanceMemory_p { env.setConfig("ramCacheDHT", Long.parseLong(post.get("ramCacheDHT", "0")) * KB); env.setConfig("ramCacheMessage", Long.parseLong(post.get("ramCacheMessage", "0")) * KB); env.setConfig("ramCacheWiki", Long.parseLong(post.get("ramCacheWiki", "0")) * KB); + env.setConfig("ramCacheBlog", Long.parseLong(post.get("ramCacheBlog", "0")) * KB); env.setConfig("ramCacheNews", Long.parseLong(post.get("ramCacheNews", "0")) * KB); env.setConfig("ramCacheRobots", Long.parseLong(post.get("ramCacheRobots", "0")) * KB); env.setConfig("ramCacheProfiles", Long.parseLong(post.get("ramCacheProfiles", "0")) * KB); @@ -100,6 +101,7 @@ public class PerformanceMemory_p { env.setConfig("ramCacheDHT", Long.parseLong((String) defaultSettings.get("ramCacheDHT"))); env.setConfig("ramCacheMessage", Long.parseLong((String) defaultSettings.get("ramCacheMessage"))); env.setConfig("ramCacheWiki", Long.parseLong((String) defaultSettings.get("ramCacheWiki"))); + env.setConfig("ramCacheWiki", Long.parseLong((String) defaultSettings.get("ramCacheBlog"))); env.setConfig("ramCacheNews", Long.parseLong((String) defaultSettings.get("ramCacheNews"))); env.setConfig("ramCacheRobots", Long.parseLong((String) defaultSettings.get("ramCacheRobots"))); env.setConfig("ramCacheProfiles", Long.parseLong((String) defaultSettings.get("ramCacheProfiles"))); @@ -192,6 +194,11 @@ public class PerformanceMemory_p { slt = sb.wikiDB.dbCacheFillStatus(); putprop(prop, env, "Wiki", set); + req = sb.blogDB.size(); + chk = sb.blogDB.dbCacheChunkSize(); + slt = sb.blogDB.dbCacheFillStatus(); + putprop(prop, env, "Blog", set); + req = yacyCore.newsPool.dbSize(); chk = yacyCore.newsPool.dbCacheChunkSize(); slt = yacyCore.newsPool.dbCacheFillStatus(); diff --git a/htroot/Wiki.java b/htroot/Wiki.java index 20d7b8651..c3d69db78 100644 --- a/htroot/Wiki.java +++ b/htroot/Wiki.java @@ -85,7 +85,7 @@ public class Wiki { String ip = post.get("CLIENTIP", "127.0.0.1"); String author = post.get("author", "anonymous"); if (author.equals("anonymous")) { - author = switchboard.wikiDB.guessAuthor(ip); + author = wikiBoard.guessAuthor(ip); if (author == null) { if (de.anomic.yacy.yacyCore.seedDB.mySeed == null) author = "anonymous"; else author = de.anomic.yacy.yacyCore.seedDB.mySeed.get("Name", "anonymous"); diff --git a/source/de/anomic/data/blogBoard.java b/source/de/anomic/data/blogBoard.java new file mode 100644 index 000000000..584af8287 --- /dev/null +++ b/source/de/anomic/data/blogBoard.java @@ -0,0 +1,229 @@ +// wikiBoard.java +// ------------------------------------- +// (C) by Michael Peter Christen; mc@anomic.de +// first published on http://www.anomic.de +// Frankfurt, Germany, 2004 +// last major change: 20.07.2004 +// +// 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Using this software in any meaning (reading, learning, copying, compiling, +// running) means that you agree that the Author(s) is (are) not responsible +// for cost, loss of data or any harm that may be caused directly or indirectly +// by usage of this softare or this documentation. The usage of this software +// is on your own risk. The installation and usage (starting/running) of this +// software may allow other people or application to access your computer and +// any attached devices and is highly dependent on the configuration of the +// software which must be done by the user of the software; the author(s) is +// (are) also not responsible for proper configuration and usage of the +// software, even if provoked by documentation provided together with +// the software. +// +// Any changes to this file according to the GPL as documented in the file +// gpl.txt aside this file in the shipment you received can be done to the +// lines that follows this copyright notice here, but changes must not be +// done inside the copyright notive above. A re-distribution must contain +// the intact and unchanged copyright notice. +// Contributions and changes to the program code must be marked as such. + +// Contains contributions from Jan Sandbrink [JS] + +package de.anomic.data; + +import java.io.File; +import java.io.IOException; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.TimeZone; + +import de.anomic.kelondro.kelondroBase64Order; +import de.anomic.kelondro.kelondroDyn; +import de.anomic.kelondro.kelondroMap; + +public class blogBoard { + + public static final int keyLength = 64; + private static final String dateFormat = "yyyyMMddHHmmss"; + private static final int recordSize = 512; + + private static TimeZone GMTTimeZone = TimeZone.getTimeZone("PST"); + private static SimpleDateFormat SimpleFormatter = new SimpleDateFormat(dateFormat); + + private kelondroMap datbase = null; + + public blogBoard(File actpath, int bufferkb) { + new File(actpath.getParent()).mkdir(); + if (datbase == null) { + if (actpath.exists()) try { + datbase = new kelondroMap(new kelondroDyn(actpath, bufferkb / 2 * 0x40, '_')); + } catch (IOException e) { + datbase = new kelondroMap(new kelondroDyn(actpath, bufferkb / 2 * 0x400, keyLength, recordSize, '_', true)); + } else { + datbase = new kelondroMap(new kelondroDyn(actpath, bufferkb / 2 * 0x400, keyLength, recordSize, '_', true)); + } + } + } + + public int size() { + return datbase.size(); + } + + public int[] dbCacheChunkSize() { + return datbase.cacheChunkSize(); + } + + public int[] dbCacheFillStatus() { + return datbase.cacheFillStatus(); + } + + public void close() { + try {datbase.close();} catch (IOException e) {} + } + + private static String dateString() { + return dateString(new GregorianCalendar(GMTTimeZone).getTime()); + } + + private static String dateString(Date date) { + return SimpleFormatter.format(date); + } + + private static String normalize(String key) { + if (key == null) return "null"; + return key.trim().toLowerCase(); + } + + public static String webalize(String key) { + if (key == null) return "null"; + key = key.trim().toLowerCase(); + int p; + while ((p = key.indexOf(" ")) >= 0) + key = key.substring(0, p) + "%20" + key.substring(p +1); + return key; + } + + public String guessAuthor(String ip) { + return wikiBoard.guessAuthor(ip); + } + + public entry newEntry(String key, String subject, String author, String ip, byte[] page) throws IOException { + return new entry(normalize(key), subject, author, ip, page); + } + + public class entry { + + String key; + Map record; + + public entry(String nkey, String subject, String author, String ip, byte[] page) throws IOException { + record = new HashMap(); + key = nkey; + if (key.length() > keyLength) key = key.substring(0, keyLength); + record.put("date", dateString()); + if ((subject == null) || (subject.length() == 0)) subject = ""; + record.put("subject", kelondroBase64Order.enhancedCoder.encode(subject.getBytes("UTF-8"))); + if ((author == null) || (author.length() == 0)) author = "anonymous"; + record.put("author", kelondroBase64Order.enhancedCoder.encode(author.getBytes("UTF-8"))); + if ((ip == null) || (ip.length() == 0)) ip = ""; + record.put("ip", ip); + if (page == null) + record.put("page", ""); + else + record.put("page", kelondroBase64Order.enhancedCoder.encode(page)); + + wikiBoard.setAuthor(ip, author); + //System.out.println("DEBUG: setting author " + author + " for ip = " + ip + ", authors = " + authors.toString()); + } + + private entry(String key, Map record) { + this.key = key; + this.record = record; + } + + public String key() { + return key; + } + + public String subject() { + String a = (String) record.get("subject"); + if (a == null) return ""; + byte[] b = kelondroBase64Order.enhancedCoder.decode(a); + if (b == null) return ""; + return new String(b); + } + + public Date date() { + try { + String c = (String) record.get("date"); + return SimpleFormatter.parse(c); + } catch (ParseException e) { + return new Date(); + } + } + + public String author() { + String a = (String) record.get("author"); + if (a == null) return "anonymous"; + byte[] b = kelondroBase64Order.enhancedCoder.decode(a); + if (b == null) return "anonymous"; + return new String(b); + } + + public byte[] page() { + String m = (String) record.get("page"); + if (m == null) return new byte[0]; + byte[] b = kelondroBase64Order.enhancedCoder.decode(m); + if (b == null) return "".getBytes(); + return b; + } + + } + + public String write(entry page) { + // writes a new page and returns key + try { + datbase.set(page.key, page.record); + return page.key; + } catch (IOException e) { + return null; + } + } + + public entry read(String key) { + return read(key, datbase); + } + + private entry read(String key, kelondroMap base) { + try { + key = normalize(key); + if (key.length() > keyLength) key = key.substring(0, keyLength); + Map record = base.get(key); + if (record == null) return newEntry(key, "", "anonymous", "127.0.0.1", "".getBytes()); + return new entry(key, record); + } catch (IOException e) { + return null; + } + } + + public Iterator keys(boolean up) throws IOException { + return datbase.keys(up, false); + } + +} diff --git a/source/de/anomic/data/wikiBoard.java b/source/de/anomic/data/wikiBoard.java index 188b63b8b..44943dcc2 100644 --- a/source/de/anomic/data/wikiBoard.java +++ b/source/de/anomic/data/wikiBoard.java @@ -67,7 +67,7 @@ public class wikiBoard { private kelondroMap datbase = null; private kelondroMap bkpbase = null; - private HashMap authors = new HashMap(); + private static HashMap authors = new HashMap(); public wikiBoard(File actpath, File bkppath, int bufferkb) { new File(actpath.getParent()).mkdir(); @@ -143,11 +143,15 @@ public class wikiBoard { return key; } - public String guessAuthor(String ip) { + public static String guessAuthor(String ip) { String author = (String) authors.get(ip); //yacyCore.log.logDebug("DEBUG: guessing author for ip = " + ip + " is '" + author + "', authors = " + authors.toString()); return author; } + + public static void setAuthor(String ip, String author) { + authors.put(ip,author); + } public entry newEntry(String subject, String author, String ip, String reason, byte[] page) throws IOException { return new entry(normalize(subject), author, ip, reason, page); diff --git a/source/de/anomic/plasma/plasmaSwitchboard.java b/source/de/anomic/plasma/plasmaSwitchboard.java index 4068b12dd..2b3847589 100644 --- a/source/de/anomic/plasma/plasmaSwitchboard.java +++ b/source/de/anomic/plasma/plasmaSwitchboard.java @@ -120,6 +120,7 @@ import java.util.Set; import java.util.TreeSet; import java.util.logging.Level; +import de.anomic.data.blogBoard; import de.anomic.data.bookmarksDB; import de.anomic.data.messageBoard; import de.anomic.data.wikiBoard; @@ -186,6 +187,7 @@ public final class plasmaSwitchboard extends serverAbstractSwitch implements ser public plasmaCrawlStacker sbStackCrawlThread; public messageBoard messageDB; public wikiBoard wikiDB; + public blogBoard blogDB; public static plasmaCrawlRobotsTxt robots; public plasmaCrawlProfile profiles; public plasmaCrawlProfile.entry defaultProxyProfile; @@ -332,6 +334,7 @@ public final class plasmaSwitchboard extends serverAbstractSwitch implements ser int ramProfiles= (int) getConfigLong("ramCacheProfiles",1024) / 1024; int ramPreNURL = (int) getConfigLong("ramCachePreNURL", 1024) / 1024; int ramWiki = (int) getConfigLong("ramCacheWiki", 1024) / 1024; + int ramBlog = (int) getConfigLong("ramCacheBlog", 1024) / 1024; this.log.logConfig("LURL Cache memory = " + ppRamString(ramLURL)); this.log.logConfig("NURL Cache memory = " + ppRamString(ramNURL)); this.log.logConfig("EURL Cache memory = " + ppRamString(ramEURL)); @@ -339,6 +342,7 @@ public final class plasmaSwitchboard extends serverAbstractSwitch implements ser this.log.logConfig("HTTP Cache memory = " + ppRamString(ramHTTP)); this.log.logConfig("Message Cache memory = " + ppRamString(ramMessage)); this.log.logConfig("Wiki Cache memory = " + ppRamString(ramWiki)); + this.log.logConfig("Blog Cache memory = " + ppRamString(ramBlog)); this.log.logConfig("Robots Cache memory = " + ppRamString(ramRobots)); this.log.logConfig("Profiles Cache memory = " + ppRamString(ramProfiles)); this.log.logConfig("PreNURL Cache memory = " + ppRamString(ramPreNURL)); @@ -457,6 +461,9 @@ public final class plasmaSwitchboard extends serverAbstractSwitch implements ser // starting wiki initWiki(ramWiki); + //starting blog + initBlog(ramBlog); + // Init User DB this.log.logConfig("Loading User DB"); File userDbFile = new File(getRootPath(), "DATA/SETTINGS/user.db"); @@ -623,6 +630,14 @@ public final class plasmaSwitchboard extends serverAbstractSwitch implements ser ", " + this.wikiDB.size() + " entries" + ", " + ppRamString(wikiDbFile.length()/1024)); } + public void initBlog(int ramBlog) { + this.log.logConfig("Starting Blog"); + File blogDbFile = new File(workPath, "blog.db"); + this.blogDB = new blogBoard(blogDbFile, ramBlog); + this.log.logConfig("Loaded Blog DB from file " + blogDbFile.getName() + + ", " + this.blogDB.size() + " entries" + + ", " + ppRamString(blogDbFile.length()/1024)); + } public void initBookmarks(){ this.log.logConfig("Loading Bookmarks DB"); File bookmarksFile = new File(workPath, "bookmarks.db"); @@ -816,6 +831,7 @@ public final class plasmaSwitchboard extends serverAbstractSwitch implements ser this.dbImportManager.close(); cacheLoader.close(); wikiDB.close(); + blogDB.close(); userDB.close(); bookmarksDB.close(); messageDB.close(); diff --git a/yacy.init b/yacy.init index 28bc2e054..8cc74ccdb 100644 --- a/yacy.init +++ b/yacy.init @@ -487,6 +487,9 @@ ramCacheMessage = 8192 # ram cache for wiki.db ramCacheWiki = 8192 +# ram cache for blog.db +ramCacheBlog = 2048 + # ram cache for news1.db ramCacheNews = 8192