001: // wikiBoard.java
002: // -------------------------------------
003: // (C) by Michael Peter Christen; mc@anomic.de
004: // first published on http://www.anomic.de
005: // Frankfurt, Germany, 2004
006: // last major change: 20.07.2004
007: //
008: // This program is free software; you can redistribute it and/or modify
009: // it under the terms of the GNU General Public License as published by
010: // the Free Software Foundation; either version 2 of the License, or
011: // (at your option) any later version.
012: //
013: // This program is distributed in the hope that it will be useful,
014: // but WITHOUT ANY WARRANTY; without even the implied warranty of
015: // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
016: // GNU General Public License for more details.
017: //
018: // You should have received a copy of the GNU General Public License
019: // along with this program; if not, write to the Free Software
020: // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
021: //
022: // Using this software in any meaning (reading, learning, copying, compiling,
023: // running) means that you agree that the Author(s) is (are) not responsible
024: // for cost, loss of data or any harm that may be caused directly or indirectly
025: // by usage of this softare or this documentation. The usage of this software
026: // is on your own risk. The installation and usage (starting/running) of this
027: // software may allow other people or application to access your computer and
028: // any attached devices and is highly dependent on the configuration of the
029: // software which must be done by the user of the software; the author(s) is
030: // (are) also not responsible for proper configuration and usage of the
031: // software, even if provoked by documentation provided together with
032: // the software.
033: //
034: // Any changes to this file according to the GPL as documented in the file
035: // gpl.txt aside this file in the shipment you received can be done to the
036: // lines that follows this copyright notice here, but changes must not be
037: // done inside the copyright notive above. A re-distribution must contain
038: // the intact and unchanged copyright notice.
039: // Contributions and changes to the program code must be marked as such.
040:
041: // This file is contributed by Jan Sandbrink
042: // based on the Code of wikiBoard.java
043:
044: package de.anomic.data;
045:
046: import java.io.ByteArrayInputStream;
047: import java.io.File;
048: import java.io.IOException;
049: import java.io.UnsupportedEncodingException;
050: import java.text.ParseException;
051: import java.util.ArrayList;
052: import java.util.Date;
053: import java.util.HashMap;
054: import java.util.Iterator;
055:
056: import javax.xml.parsers.DocumentBuilder;
057: import javax.xml.parsers.DocumentBuilderFactory;
058: import javax.xml.parsers.ParserConfigurationException;
059:
060: import org.w3c.dom.Document;
061: import org.w3c.dom.Node;
062: import org.w3c.dom.NodeList;
063: import org.xml.sax.SAXException;
064:
065: import de.anomic.kelondro.kelondroBase64Order;
066: import de.anomic.kelondro.kelondroDyn;
067: import de.anomic.kelondro.kelondroMapObjects;
068: import de.anomic.kelondro.kelondroNaturalOrder;
069: import de.anomic.server.serverDate;
070:
071: public class blogBoard {
072:
073: public static final int keyLength = 64;
074: private static final int recordSize = 512;
075:
076: private kelondroMapObjects datbase = null;
077:
078: public blogBoard(File actpath, long preloadTime) {
079: new File(actpath.getParent()).mkdir();
080: if (datbase == null) {
081: datbase = new kelondroMapObjects(new kelondroDyn(actpath,
082: true, true, preloadTime, keyLength, recordSize,
083: '_', kelondroNaturalOrder.naturalOrder, true,
084: false, false), 500);
085: }
086: }
087:
088: public int size() {
089: return datbase.size();
090: }
091:
092: public void close() {
093: datbase.close();
094: }
095:
096: private static String normalize(String key) {
097: if (key == null)
098: return "null";
099: return key.trim().toLowerCase();
100: }
101:
102: public static String webalize(String key) {
103: if (key == null)
104: return "null";
105: key = key.trim().toLowerCase();
106: int p;
107: while ((p = key.indexOf(" ")) >= 0)
108: key = key.substring(0, p) + "%20" + key.substring(p + 1);
109: return key;
110: }
111:
112: public String guessAuthor(String ip) {
113: return wikiBoard.guessAuthor(ip);
114: }
115:
116: public entry newEntry(String key, byte[] subject, byte[] author,
117: String ip, Date date, byte[] page,
118: ArrayList<String> comments, String commentMode) {
119: return new entry(normalize(key), subject, author, ip, date,
120: page, comments, commentMode);
121: }
122:
123: public class entry {
124:
125: String key;
126: HashMap<String, String> record;
127:
128: public entry(String nkey, byte[] subject, byte[] author,
129: String ip, Date date, byte[] page,
130: ArrayList<String> comments, String commentMode) {
131: record = new HashMap<String, String>();
132: key = nkey;
133: if (key.length() > keyLength)
134: key = key.substring(0, keyLength);
135: if (date == null)
136: date = new Date();
137: record.put("date", serverDate.formatShortSecond(date));
138: if (subject == null)
139: record.put("subject", "");
140: else
141: record.put("subject", kelondroBase64Order.enhancedCoder
142: .encode(subject));
143: if (author == null)
144: record.put("author", "");
145: else
146: record.put("author", kelondroBase64Order.enhancedCoder
147: .encode(author));
148: if ((ip == null) || (ip.length() == 0))
149: ip = "";
150: record.put("ip", ip);
151: if (page == null)
152: record.put("page", "");
153: else
154: record.put("page", kelondroBase64Order.enhancedCoder
155: .encode(page));
156: if (comments == null)
157: record.put("comments", listManager
158: .collection2string(new ArrayList<String>()));
159: else
160: record.put("comments", listManager
161: .collection2string(comments));
162: if (commentMode == null)
163: record.put("commentMode", "1");
164: else
165: record.put("commentMode", commentMode);
166:
167: wikiBoard.setAuthor(ip, new String(author));
168: //System.out.println("DEBUG: setting author " + author + " for ip = " + ip + ", authors = " + authors.toString());
169: }
170:
171: private entry(String key, HashMap<String, String> record) {
172: this .key = key;
173: this .record = record;
174: if (this .record.get("comments") == null)
175: this .record.put("comments", listManager
176: .collection2string(new ArrayList<String>()));
177: if (this .record.get("commentMode") == null
178: || this .record.get("commentMode").equals(""))
179: this .record.put("commentMode", "1");
180: }
181:
182: public String key() {
183: return key;
184: }
185:
186: public byte[] subject() {
187: String m = record.get("subject");
188: if (m == null)
189: return new byte[0];
190: byte[] b = kelondroBase64Order.enhancedCoder.decode(m,
191: "de.anomic.data.blogBoard.subject()");
192: if (b == null)
193: return "".getBytes();
194: return b;
195: }
196:
197: public Date date() {
198: try {
199: String c = record.get("date");
200: if (c == null) {
201: System.out
202: .println("DEBUG - ERROR: date field missing in blogBoard");
203: return new Date();
204: }
205: return serverDate.parseShortSecond(c);
206: } catch (ParseException e) {
207: return new Date();
208: }
209: }
210:
211: public String timestamp() {
212: String c = record.get("date");
213: if (c == null) {
214: System.out
215: .println("DEBUG - ERROR: date field missing in blogBoard");
216: return serverDate.formatShortSecond();
217: }
218: return c;
219: }
220:
221: public byte[] author() {
222: String m = record.get("author");
223: if (m == null)
224: return new byte[0];
225: byte[] b = kelondroBase64Order.enhancedCoder.decode(m,
226: "de.anomic.data.blogBoard.author()");
227: if (b == null)
228: return "".getBytes();
229: return b;
230: }
231:
232: public int commentsSize() {
233: ArrayList<String> m = listManager.string2arraylist(record
234: .get("comments"));
235: return m.size();
236: }
237:
238: public ArrayList<String> comments() {
239: ArrayList<String> m = listManager.string2arraylist(record
240: .get("comments"));
241: return m;
242: }
243:
244: public String ip() {
245: String a = record.get("ip");
246: if (a == null)
247: return "127.0.0.1";
248: return a;
249: }
250:
251: public byte[] page() {
252: String m = record.get("page");
253: if (m == null)
254: return new byte[0];
255: byte[] b = kelondroBase64Order.enhancedCoder.decode(m,
256: "de.anomic.data.blogBoard.page()");
257: if (b == null)
258: return "".getBytes();
259: return b;
260: }
261:
262: public void addComment(String commentID) {
263: ArrayList<String> comments = listManager
264: .string2arraylist(record.get("comments"));
265: comments.add(commentID);
266: record.put("comments", listManager
267: .collection2string(comments));
268: }
269:
270: public boolean removeComment(String commentID) {
271: ArrayList<String> comments = listManager
272: .string2arraylist(record.get("comments"));
273: boolean success = comments.remove(commentID);
274: record.put("comments", listManager
275: .collection2string(comments));
276: return success;
277: }
278:
279: public int getCommentMode() {
280: return Integer.parseInt(record.get("commentMode"));
281: }
282: }
283:
284: public String write(entry page) {
285: // writes a new page and returns key
286: try {
287: datbase.set(page.key, page.record);
288: return page.key;
289: } catch (IOException e) {
290: return null;
291: }
292: }
293:
294: public entry read(String key) {
295: return read(key, datbase);
296: }
297:
298: private entry read(String key, kelondroMapObjects base) {
299: key = normalize(key);
300: if (key.length() > keyLength)
301: key = key.substring(0, keyLength);
302: HashMap<String, String> record = base.getMap(key);
303: if (record == null)
304: return newEntry(key, "".getBytes(), "anonymous".getBytes(),
305: "127.0.0.1", new Date(), "".getBytes(), null, null);
306: return new entry(key, record);
307: }
308:
309: public boolean importXML(String input) {
310: DocumentBuilderFactory factory = DocumentBuilderFactory
311: .newInstance();
312: try {
313: DocumentBuilder builder = factory.newDocumentBuilder();
314: Document doc = builder.parse(new ByteArrayInputStream(input
315: .getBytes()));
316: return parseXMLimport(doc);
317: } catch (ParserConfigurationException e) {
318: } catch (SAXException e) {
319: } catch (IOException e) {
320: }
321:
322: return false;
323: }
324:
325: private boolean parseXMLimport(Document doc) {
326: if (!doc.getDocumentElement().getTagName().equals("blog"))
327: return false;
328:
329: NodeList items = doc.getDocumentElement().getElementsByTagName(
330: "item");
331: if (items.getLength() == 0)
332: return false;
333:
334: for (int i = 0; i < items.getLength(); ++i) {
335: String key = null, ip = null, StrSubject = null, StrAuthor = null, StrPage = null, StrDate = null;
336: Date date = null;
337:
338: if (!items.item(i).getNodeName().equals("item"))
339: continue;
340:
341: NodeList currentNodeChildren = items.item(i)
342: .getChildNodes();
343:
344: for (int j = 0; j < currentNodeChildren.getLength(); ++j) {
345: Node currentNode = currentNodeChildren.item(j);
346: if (currentNode.getNodeName().equals("id"))
347: key = currentNode.getFirstChild().getNodeValue();
348: else if (currentNode.getNodeName().equals("ip"))
349: ip = currentNode.getFirstChild().getNodeValue();
350: else if (currentNode.getNodeName().equals("timestamp"))
351: StrDate = currentNode.getFirstChild()
352: .getNodeValue();
353: else if (currentNode.getNodeName().equals("subject"))
354: StrSubject = currentNode.getFirstChild()
355: .getNodeValue();
356: else if (currentNode.getNodeName().equals("author"))
357: StrAuthor = currentNode.getFirstChild()
358: .getNodeValue();
359: else if (currentNode.getNodeName().equals("content"))
360: StrPage = currentNode.getFirstChild()
361: .getNodeValue();
362: }
363:
364: try {
365: date = serverDate.parseShortSecond(StrDate);
366: } catch (ParseException e1) {
367: date = new Date();
368: }
369:
370: if (key == null || ip == null || StrSubject == null
371: || StrAuthor == null || StrPage == null
372: || date == null)
373: return false;
374:
375: byte[] subject, author, page;
376: try {
377: subject = StrSubject.getBytes("UTF-8");
378: } catch (UnsupportedEncodingException e1) {
379: subject = StrSubject.getBytes();
380: }
381: try {
382: author = StrAuthor.getBytes("UTF-8");
383: } catch (UnsupportedEncodingException e1) {
384: author = StrAuthor.getBytes();
385: }
386: try {
387: page = StrPage.getBytes("UTF-8");
388: } catch (UnsupportedEncodingException e1) {
389: page = StrPage.getBytes();
390: }
391:
392: write(newEntry(key, subject, author, ip, date, page, null,
393: null));
394: }
395: return true;
396: }
397:
398: public void delete(String key) {
399: key = normalize(key);
400: try {
401: datbase.remove(key);
402: } catch (IOException e) {
403: }
404: }
405:
406: public Iterator<String> keys(boolean up) throws IOException {
407: return datbase.keys(up, false);
408: }
409:
410: }
|