Drupal: hlavičky, poměrně funkční čtení příspěvků (vlánka).
authorFrantišek Kučera <franta-hg@frantovo.cz>
Tue Oct 11 16:17:51 2011 +0200 (2011-10-11)
changeset 702177f9b14688
parent 69 b51612c18a54
child 71 beb11d70f0eb
Drupal: hlavičky, poměrně funkční čtení příspěvků (vlánka).
src/org/sonews/storage/impl/DrupalDatabase.java
     1.1 --- a/src/org/sonews/storage/impl/DrupalDatabase.java	Tue Oct 11 01:17:30 2011 +0200
     1.2 +++ b/src/org/sonews/storage/impl/DrupalDatabase.java	Tue Oct 11 16:17:51 2011 +0200
     1.3 @@ -26,10 +26,13 @@
     1.4  import java.sql.Statement;
     1.5  import java.util.ArrayList;
     1.6  import java.util.Collections;
     1.7 +import java.util.Date;
     1.8  import java.util.List;
     1.9  import java.util.logging.Level;
    1.10  import java.util.logging.Logger;
    1.11 +import javax.mail.internet.MailDateFormat;
    1.12  import javax.mail.internet.MimeUtility;
    1.13 +import org.apache.commons.codec.net.BCodec;
    1.14  import org.apache.commons.codec.net.QuotedPrintableCodec;
    1.15  import org.sonews.config.Config;
    1.16  import org.sonews.feed.Subscription;
    1.17 @@ -47,12 +50,15 @@
    1.18  public class DrupalDatabase implements Storage {
    1.19  
    1.20  	private static final Logger log = Logger.getLogger(DrupalDatabase.class.getName());
    1.21 +	public static final String CHARSET = "UTF-8";
    1.22  	public static final String CRLF = "\r\n";
    1.23  	public static final int MAX_RESTARTS = 2;
    1.24  	/** How many times the database connection was reinitialized */
    1.25  	protected int restarts = 0;
    1.26  	protected Connection conn = null;
    1.27 -	private QuotedPrintableCodec qpc = new QuotedPrintableCodec("UTF-8");
    1.28 +	private QuotedPrintableCodec qpc = new QuotedPrintableCodec(CHARSET);
    1.29 +	// TODO: správná doména
    1.30 +	private String myDomain = "kinderporno.cz";
    1.31  
    1.32  	public DrupalDatabase() throws StorageBackendException {
    1.33  		connectDatabase();
    1.34 @@ -102,12 +108,12 @@
    1.35  
    1.36  	/**
    1.37  	 * 
    1.38 -	 * @param messageID {0}-{1}-{2}@domain.tld where {0} is nntp_id and {1} is group_id and {2} is group_name
    1.39 +	 * @param messageID &lt;{0}-{1}-{2}@domain.tld&gt; where {0} is nntp_id and {1} is group_id and {2} is group_name
    1.40  	 * @return array where [0] = nntp_id and [1] = group_id and [2] = group_name or returns null if messageID is invalid
    1.41  	 */
    1.42  	private static String[] parseMessageID(String messageID) {
    1.43 -		if (messageID.matches("[0-9]+\\-[0-9]+\\-[a-z0-9\\.]+@.+")) {
    1.44 -			return messageID.split("@")[0].split("\\-");
    1.45 +		if (messageID.matches("<[0-9]+\\-[0-9]+\\-[a-z0-9\\.]+@.+>")) {
    1.46 +			return messageID.substring(1).split("@")[0].split("\\-");
    1.47  		} else {
    1.48  			return null;
    1.49  		}
    1.50 @@ -140,33 +146,57 @@
    1.51  		}
    1.52  	}
    1.53  
    1.54 -	private static String constructHeaders(ResultSet rs) throws SQLException, UnsupportedEncodingException {
    1.55 +	private static String constructMessageId(int articleID, int groupID, String groupName, String domainName) {
    1.56 +		StringBuilder sb = new StringBuilder();
    1.57 +		sb.append("<");
    1.58 +		sb.append(articleID);
    1.59 +		sb.append("-");
    1.60 +		sb.append(groupID);
    1.61 +		sb.append("-");
    1.62 +		sb.append(groupName);
    1.63 +		sb.append("@");
    1.64 +		sb.append(domainName);
    1.65 +		sb.append(">");
    1.66 +		return sb.toString();
    1.67 +	}
    1.68 +
    1.69 +	/**
    1.70 +	 * 
    1.71 +	 * @param sb header list to be appended with new header. List must be terminated by line end.
    1.72 +	 * @param key header name (without : and space)
    1.73 +	 * @param value header value
    1.74 +	 * @param encode true if value should be encoded/escaped before appending
    1.75 +	 * @throws UnsupportedEncodingException 
    1.76 +	 */
    1.77 +	private static void addHeader(StringBuilder sb, String key, String value, boolean encode) throws UnsupportedEncodingException {
    1.78 +		sb.append(key);
    1.79 +		sb.append(": ");
    1.80 +		if (encode) {
    1.81 +			sb.append(MimeUtility.encodeWord(value));
    1.82 +		} else {
    1.83 +			sb.append(value);
    1.84 +		}
    1.85 +		sb.append(CRLF);
    1.86 +	}
    1.87 +
    1.88 +	private String constructHeaders(ResultSet rs) throws SQLException, UnsupportedEncodingException {
    1.89  		StringBuilder sb = new StringBuilder();
    1.90  
    1.91 -		sb.append("Message-id: <");
    1.92 -		sb.append(rs.getInt("id"));
    1.93 -		sb.append("-");
    1.94 -		sb.append(rs.getInt("group_id"));
    1.95 -		sb.append("-");
    1.96 -		sb.append(rs.getString("group_name"));
    1.97 -		sb.append("@");
    1.98 -		sb.append("nntp.kinderporno.cz>");
    1.99 -		sb.append(CRLF);
   1.100 +		addHeader(sb, "Message-id", constructMessageId(rs.getInt("id"), rs.getInt("group_id"), rs.getString("group_name"), myDomain), false);
   1.101 +		addHeader(sb, "From", MimeUtility.encodeWord(rs.getString("sender_name")) + " <>", false);
   1.102 +		addHeader(sb, "Subject", rs.getString("subject"), true);
   1.103 +		/** TODO: správný formát data: */
   1.104 +		addHeader(sb, "Date", MailDateFormat.getInstance().format(new Date(rs.getLong("created") * 1000)), false);
   1.105 +		addHeader(sb, "Content-Type", "text/html; charset=" + CHARSET, false);
   1.106 +		addHeader(sb, "Content-Transfer-Encoding", "quoted-printable", false);
   1.107 +		//addHeader(sb, "Content-Transfer-Encoding", "base64", false);
   1.108  
   1.109 -		sb.append("From: ");
   1.110 -		sb.append(MimeUtility.encodeWord(rs.getString("sender_name")));
   1.111 -		sb.append(" <>");
   1.112 -		sb.append(CRLF);
   1.113 -
   1.114 -		sb.append("Subject: ");
   1.115 -		sb.append(MimeUtility.encodeWord(rs.getString("subject")));
   1.116 -		sb.append(CRLF);
   1.117 -
   1.118 -
   1.119 -		sb.append("Content-Type: text/html; charset=UTF-8");
   1.120 -		sb.append(CRLF);
   1.121 -		sb.append("Content-Transfer-Encoding: quoted-printable");
   1.122 -		sb.append(CRLF);
   1.123 +		Integer parentID = rs.getInt("parent_id");
   1.124 +		if (parentID != null && parentID > 0) {
   1.125 +			String parentMessageID = constructMessageId(parentID, rs.getInt("group_id"), rs.getString("group_name"), myDomain);
   1.126 +			addHeader(sb, "In-Reply-To", parentMessageID, false);
   1.127 +			addHeader(sb, "References", parentMessageID, false);
   1.128 +		}
   1.129  
   1.130  		return sb.toString();
   1.131  	}
   1.132 @@ -243,7 +273,10 @@
   1.133  
   1.134  			if (rs.next()) {
   1.135  				String headers = constructHeaders(rs);
   1.136 +				// TODO: fold?
   1.137 +				BCodec bc = new BCodec(CHARSET);
   1.138  				byte[] body = qpc.encode(rs.getString("text")).getBytes();
   1.139 +				//byte[] body = bc.encode(rs.getString("text")).getBytes();
   1.140  
   1.141  				return new Article(headers, body);
   1.142  			} else {
   1.143 @@ -261,7 +294,8 @@
   1.144  		PreparedStatement ps = null;
   1.145  		ResultSet rs = null;
   1.146  		try {
   1.147 -			ps = conn.prepareStatement("SELECT * FROM nntp_article WHERE group_id = ? AND id >= ? AND id <= ?");
   1.148 +			// TODO: je nutné řazení?
   1.149 +			ps = conn.prepareStatement("SELECT * FROM nntp_article WHERE group_id = ? AND id >= ? AND id <= ? ORDER BY id");
   1.150  			ps.setLong(1, group.getInternalID());
   1.151  			ps.setLong(2, first);
   1.152  			ps.setLong(3, last);