Add libcommons-codec-java to Debian dependencies.
3 * see AUTHORS for the list of contributors
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 package org.sonews.storage;
20 import java.io.ByteArrayInputStream;
21 import java.io.ByteArrayOutputStream;
22 import java.io.IOException;
23 import java.security.MessageDigest;
24 import java.security.NoSuchAlgorithmException;
25 import java.util.UUID;
26 import java.util.ArrayList;
27 import java.util.Enumeration;
28 import java.util.List;
29 import java.util.logging.Level;
30 import javax.mail.Header;
31 import javax.mail.Message;
32 import javax.mail.MessagingException;
33 import javax.mail.internet.InternetHeaders;
34 import org.sonews.config.Config;
35 import org.sonews.util.Log;
38 * Represents a newsgroup article.
39 * @author Christian Lins
40 * @author Denis Schwerdel
43 public class Article extends ArticleHead {
46 * Loads the Article identified by the given ID from the JDBCDatabase.
48 * @return null if Article is not found or if an error occurred.
50 public static Article getByMessageID(final String messageID) {
52 return StorageManager.current().getArticle(messageID);
53 } catch (StorageBackendException ex) {
54 Log.get().log(Level.WARNING, ex.getLocalizedMessage(), ex);
58 private byte[] body = new byte[0];
61 * Default constructor.
67 * Creates a new Article object using the date from the given
70 public Article(String headers, byte[] body) {
75 this.headers = new InternetHeaders(
76 new ByteArrayInputStream(headers.getBytes()));
78 this.headerSrc = headers;
79 } catch (MessagingException ex) {
80 Log.get().log(Level.WARNING, ex.getLocalizedMessage(), ex);
85 * Creates an Article instance using the data from the javax.mail.Message
86 * object. This constructor is called by the Mailinglist gateway.
87 * @see javax.mail.Message
90 * @throws MessagingException
92 public Article(final Message msg)
93 throws IOException, MessagingException {
94 this.headers = new InternetHeaders();
96 for (Enumeration e = msg.getAllHeaders(); e.hasMoreElements();) {
97 final Header header = (Header) e.nextElement();
98 this.headers.addHeader(header.getName(), header.getValue());
101 // Reads the raw byte body using Message.writeTo(OutputStream out)
102 this.body = readContent(msg);
109 * Reads from the given Message into a byte array.
112 * @throws IOException
114 private byte[] readContent(Message in)
115 throws IOException, MessagingException {
116 ByteArrayOutputStream out = new ByteArrayOutputStream();
118 return out.toByteArray();
122 * Removes the header identified by the given key.
125 public void removeHeader(final String headerKey) {
126 this.headers.removeHeader(headerKey);
127 this.headerSrc = null;
131 * Generates a message id for this article and sets it into
132 * the header object. You have to update the JDBCDatabase manually to make this
134 * Note: a Message-ID should never be changed and only generated once.
136 private String generateMessageID() {
140 md5 = MessageDigest.getInstance("MD5");
142 md5.update(getBody());
143 md5.update(getHeader(Headers.SUBJECT)[0].getBytes());
144 md5.update(getHeader(Headers.FROM)[0].getBytes());
145 byte[] result = md5.digest();
146 StringBuilder hexString = new StringBuilder();
147 for (int i = 0; i < result.length; i++) {
148 hexString.append(Integer.toHexString(0xFF & result[i]));
150 randomString = hexString.toString();
151 } catch (NoSuchAlgorithmException ex) {
152 Log.get().log(Level.WARNING, ex.getLocalizedMessage(), ex);
153 randomString = UUID.randomUUID().toString();
155 String msgID = "<" + randomString + "@"
156 + Config.inst().get(Config.HOSTNAME, "localhost") + ">";
158 this.headers.setHeader(Headers.MESSAGE_ID, msgID);
164 * Returns the body string.
166 public byte[] getBody() {
171 * @return Numerical IDs of the newsgroups this Article belongs to.
173 public List<Group> getGroups() {
174 String[] groupnames = getHeader(Headers.NEWSGROUPS)[0].split(",");
175 ArrayList<Group> groups = new ArrayList<Group>();
178 for (String newsgroup : groupnames) {
179 newsgroup = newsgroup.trim();
180 Group group = StorageManager.current().getGroup(newsgroup);
181 if (group != null && // If the server does not provide the group, ignore it
182 !groups.contains(group)) // Yes, there may be duplicates
187 } catch (StorageBackendException ex) {
188 Log.get().log(Level.WARNING, ex.getLocalizedMessage(), ex);
194 public void setBody(byte[] body) {
200 * @param groupname Name(s) of newsgroups
202 public void setGroup(String groupname) {
203 this.headers.setHeader(Headers.NEWSGROUPS, groupname);
207 * Returns the Message-ID of this Article. If the appropriate header
208 * is empty, a new Message-ID is created.
209 * @return Message-ID of this Article.
211 public String getMessageID() {
212 String[] msgID = getHeader(Headers.MESSAGE_ID);
213 return msgID[0].equals("") ? generateMessageID() : msgID[0];
217 * @return String containing the Message-ID.
220 public String toString() {
221 return getMessageID();