# HG changeset patch
# User František Kučera <franta-hg@frantovo.cz>
# Date 1318342671 -7200
# Node ID 2177f9b14688aa76de2a52bbccaa6796ea24bf4f
# Parent  b51612c18a541c6e0ad111155650bcc7764fda7c
Drupal: hlavičky, poměrně funkční čtení příspěvků (vlánka).

diff -r b51612c18a54 -r 2177f9b14688 src/org/sonews/storage/impl/DrupalDatabase.java
--- a/src/org/sonews/storage/impl/DrupalDatabase.java	Tue Oct 11 01:17:30 2011 +0200
+++ b/src/org/sonews/storage/impl/DrupalDatabase.java	Tue Oct 11 16:17:51 2011 +0200
@@ -26,10 +26,13 @@
 import java.sql.Statement;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.Date;
 import java.util.List;
 import java.util.logging.Level;
 import java.util.logging.Logger;
+import javax.mail.internet.MailDateFormat;
 import javax.mail.internet.MimeUtility;
+import org.apache.commons.codec.net.BCodec;
 import org.apache.commons.codec.net.QuotedPrintableCodec;
 import org.sonews.config.Config;
 import org.sonews.feed.Subscription;
@@ -47,12 +50,15 @@
 public class DrupalDatabase implements Storage {
 
 	private static final Logger log = Logger.getLogger(DrupalDatabase.class.getName());
+	public static final String CHARSET = "UTF-8";
 	public static final String CRLF = "\r\n";
 	public static final int MAX_RESTARTS = 2;
 	/** How many times the database connection was reinitialized */
 	protected int restarts = 0;
 	protected Connection conn = null;
-	private QuotedPrintableCodec qpc = new QuotedPrintableCodec("UTF-8");
+	private QuotedPrintableCodec qpc = new QuotedPrintableCodec(CHARSET);
+	// TODO: správná doména
+	private String myDomain = "kinderporno.cz";
 
 	public DrupalDatabase() throws StorageBackendException {
 		connectDatabase();
@@ -102,12 +108,12 @@
 
 	/**
 	 * 
-	 * @param messageID {0}-{1}-{2}@domain.tld where {0} is nntp_id and {1} is group_id and {2} is group_name
+	 * @param messageID &lt;{0}-{1}-{2}@domain.tld&gt; where {0} is nntp_id and {1} is group_id and {2} is group_name
 	 * @return array where [0] = nntp_id and [1] = group_id and [2] = group_name or returns null if messageID is invalid
 	 */
 	private static String[] parseMessageID(String messageID) {
-		if (messageID.matches("[0-9]+\\-[0-9]+\\-[a-z0-9\\.]+@.+")) {
-			return messageID.split("@")[0].split("\\-");
+		if (messageID.matches("<[0-9]+\\-[0-9]+\\-[a-z0-9\\.]+@.+>")) {
+			return messageID.substring(1).split("@")[0].split("\\-");
 		} else {
 			return null;
 		}
@@ -140,33 +146,57 @@
 		}
 	}
 
-	private static String constructHeaders(ResultSet rs) throws SQLException, UnsupportedEncodingException {
+	private static String constructMessageId(int articleID, int groupID, String groupName, String domainName) {
+		StringBuilder sb = new StringBuilder();
+		sb.append("<");
+		sb.append(articleID);
+		sb.append("-");
+		sb.append(groupID);
+		sb.append("-");
+		sb.append(groupName);
+		sb.append("@");
+		sb.append(domainName);
+		sb.append(">");
+		return sb.toString();
+	}
+
+	/**
+	 * 
+	 * @param sb header list to be appended with new header. List must be terminated by line end.
+	 * @param key header name (without : and space)
+	 * @param value header value
+	 * @param encode true if value should be encoded/escaped before appending
+	 * @throws UnsupportedEncodingException 
+	 */
+	private static void addHeader(StringBuilder sb, String key, String value, boolean encode) throws UnsupportedEncodingException {
+		sb.append(key);
+		sb.append(": ");
+		if (encode) {
+			sb.append(MimeUtility.encodeWord(value));
+		} else {
+			sb.append(value);
+		}
+		sb.append(CRLF);
+	}
+
+	private String constructHeaders(ResultSet rs) throws SQLException, UnsupportedEncodingException {
 		StringBuilder sb = new StringBuilder();
 
-		sb.append("Message-id: <");
-		sb.append(rs.getInt("id"));
-		sb.append("-");
-		sb.append(rs.getInt("group_id"));
-		sb.append("-");
-		sb.append(rs.getString("group_name"));
-		sb.append("@");
-		sb.append("nntp.kinderporno.cz>");
-		sb.append(CRLF);
+		addHeader(sb, "Message-id", constructMessageId(rs.getInt("id"), rs.getInt("group_id"), rs.getString("group_name"), myDomain), false);
+		addHeader(sb, "From", MimeUtility.encodeWord(rs.getString("sender_name")) + " <>", false);
+		addHeader(sb, "Subject", rs.getString("subject"), true);
+		/** TODO: správný formát data: */
+		addHeader(sb, "Date", MailDateFormat.getInstance().format(new Date(rs.getLong("created") * 1000)), false);
+		addHeader(sb, "Content-Type", "text/html; charset=" + CHARSET, false);
+		addHeader(sb, "Content-Transfer-Encoding", "quoted-printable", false);
+		//addHeader(sb, "Content-Transfer-Encoding", "base64", false);
 
-		sb.append("From: ");
-		sb.append(MimeUtility.encodeWord(rs.getString("sender_name")));
-		sb.append(" <>");
-		sb.append(CRLF);
-
-		sb.append("Subject: ");
-		sb.append(MimeUtility.encodeWord(rs.getString("subject")));
-		sb.append(CRLF);
-
-
-		sb.append("Content-Type: text/html; charset=UTF-8");
-		sb.append(CRLF);
-		sb.append("Content-Transfer-Encoding: quoted-printable");
-		sb.append(CRLF);
+		Integer parentID = rs.getInt("parent_id");
+		if (parentID != null && parentID > 0) {
+			String parentMessageID = constructMessageId(parentID, rs.getInt("group_id"), rs.getString("group_name"), myDomain);
+			addHeader(sb, "In-Reply-To", parentMessageID, false);
+			addHeader(sb, "References", parentMessageID, false);
+		}
 
 		return sb.toString();
 	}
@@ -243,7 +273,10 @@
 
 			if (rs.next()) {
 				String headers = constructHeaders(rs);
+				// TODO: fold?
+				BCodec bc = new BCodec(CHARSET);
 				byte[] body = qpc.encode(rs.getString("text")).getBytes();
+				//byte[] body = bc.encode(rs.getString("text")).getBytes();
 
 				return new Article(headers, body);
 			} else {
@@ -261,7 +294,8 @@
 		PreparedStatement ps = null;
 		ResultSet rs = null;
 		try {
-			ps = conn.prepareStatement("SELECT * FROM nntp_article WHERE group_id = ? AND id >= ? AND id <= ?");
+			// TODO: je nutné řazení?
+			ps = conn.prepareStatement("SELECT * FROM nntp_article WHERE group_id = ? AND id >= ? AND id <= ? ORDER BY id");
 			ps.setLong(1, group.getInternalID());
 			ps.setLong(2, first);
 			ps.setLong(3, last);