diff -r d54786065fa3 -r d843b4fee5dc src/org/sonews/storage/impl/DrupalDatabase.java --- a/src/org/sonews/storage/impl/DrupalDatabase.java Wed Oct 19 21:40:51 2011 +0200 +++ b/src/org/sonews/storage/impl/DrupalDatabase.java Thu Oct 20 09:59:04 2011 +0200 @@ -28,12 +28,13 @@ import java.util.logging.Level; import java.util.logging.Logger; import org.sonews.config.Config; -import org.sonews.daemon.Connections; import org.sonews.feed.Subscription; import org.sonews.storage.Article; import org.sonews.storage.ArticleHead; import org.sonews.storage.DrupalArticle; import org.sonews.storage.DrupalMessage; +import static org.sonews.storage.DrupalMessage.parseArticleID; +import static org.sonews.storage.DrupalMessage.parseGroupID; import org.sonews.storage.Group; import org.sonews.storage.Storage; import org.sonews.storage.StorageBackendException; @@ -68,6 +69,18 @@ String password = Config.inst().get(Config.LEVEL_FILE, Config.STORAGE_PASSWORD, ""); conn = DriverManager.getConnection(url, username, password); + /** + * Kódování češtiny: + * SET NAMES utf8 → dobrá čeština + * Client characterset: utf8 + * Conn. characterset: utf8 + * SET CHARACTER SET utf8; → dobrá čeština jen pro SLECT, ale při volání funkce se zmrší + * Client characterset: utf8 + * Conn. characterset: latin1 + * + * Správné řešení: + * V JDBC URL musí být: ?useUnicode=true&characterEncoding=UTF-8 + */ conn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE); if (conn.getTransactionIsolation() != Connection.TRANSACTION_SERIALIZABLE) { log.warning("Database is NOT fully serializable!"); @@ -98,40 +111,6 @@ } } - /** - * - * @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.substring(1).split("@")[0].split("\\-"); - } else { - return null; - } - } - - private static Long parseArticleID(String messageID) { - String[] localPart = parseMessageID(messageID); - if (localPart == null) { - return null; - } else { - return Long.parseLong(localPart[0]); - } - } - - private static Long parseGroupID(String messageID) { - String[] localPart = parseMessageID(messageID); - if (localPart == null) { - return null; - } else { - return Long.parseLong(localPart[1]); - // If needed: - // parseGroupName() will be same as this method, just with: - // return localPart[2]; - } - } - @Override public List getGroups() throws StorageBackendException { PreparedStatement ps = null; @@ -397,7 +376,8 @@ * (but should not be thrown if only bad thing is wrong username or password) */ @Override - public boolean authenticateUser(String username, char[] password) throws StorageBackendException { + public boolean authenticateUser(String username, + char[] password) throws StorageBackendException { PreparedStatement ps = null; ResultSet rs = null; try { @@ -414,14 +394,81 @@ } } + /** + * Validates article and if OK, calls {@link #insertArticle(java.lang.String, java.lang.String, java.lang.String, java.lang.Long, java.lang.Long) } + * @param article + * @throws StorageBackendException + */ @Override - public void addArticle(Article art) throws StorageBackendException { - if (art.getAuthenticatedUser() == null) { + public void addArticle(Article article) throws StorageBackendException { + if (article.getAuthenticatedUser() == null) { log.log(Level.SEVERE, "User was not authenticated, so his article was rejected."); throw new StorageBackendException("User must be authenticated to post articles"); } else { + try { + DrupalMessage m = new DrupalMessage(article); - log.log(Level.INFO, "User ''{0}'' has posted an article", art.getAuthenticatedUser()); + Long parentID = m.getParentID(); + Long groupID = m.getGroupID(); + + if (parentID == null || groupID == null) { + throw new StorageBackendException("No valid In-Reply-To header was found → rejecting posted message."); + } else { + if (m.isMimeType("text/plain")) { + Object content = m.getContent(); + if (content instanceof String) { + String subject = m.getSubject(); + String text = (String) content; + + /** + * TODO: validovat a transformovat text + * (v současné době se o to stará až Drupal při výstupu) + */ + if (subject == null || subject.length() < 1) { + subject = text.substring(0, Math.min(10, text.length())); + } + + insertArticle(article.getAuthenticatedUser(), subject, text, parentID, groupID); + log.log(Level.INFO, "User ''{0}'' has posted an article", article.getAuthenticatedUser()); + } + } else { + throw new StorageBackendException("Only text/plain messages are supported for now – post it as plain text please."); + } + } + } catch (Exception e) { + throw new StorageBackendException(e); + } + } + } + + /** + * Physically stores article in database. + * @param subject + * @param text + * @param parentID + * @param groupID + */ + private void insertArticle(String sender, String subject, String text, Long parentID, Long groupID) throws StorageBackendException { + PreparedStatement ps = null; + ResultSet rs = null; + try { + ps = conn.prepareStatement("SELECT nntp_post_article(?, ?, ?, ?, ?)"); + + ps.setString(1, sender); + ps.setString(2, subject); + ps.setString(3, text); + ps.setLong(4, parentID); + ps.setLong(5, groupID); + + rs = ps.executeQuery(); + rs.next(); + + Long articleID = rs.getLong(1); + log.log(Level.INFO, "Article was succesfully stored as {0}", articleID); + } catch (Exception e) { + throw new StorageBackendException(e); + } finally { + close(null, ps, rs); } }