# HG changeset patch # User František Kučera # 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 <{0}-{1}-{2}@domain.tld> 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);