diff --git a/etc/web.xml b/etc/web.xml index 0270d9f..e9937ad 100644 --- a/etc/web.xml +++ b/etc/web.xml @@ -312,6 +312,12 @@ /dump/* + + + default.jsp + index.html + + 60 diff --git a/setup/database.sql b/setup/database.sql index dec6198..4c432b9 100644 --- a/setup/database.sql +++ b/setup/database.sql @@ -377,9 +377,12 @@ CREATE TABLE postdata ( CREATE TABLE postattach ( postid BIGINT NOT NULL PRIMARY KEY, datalen INT, + hits INT DEFAULT 0, + last_hit DATETIME, + stgmethod SMALLINT DEFAULT 0, + priority SMALLINT DEFAULT 0, filename VARCHAR(255), mimetype VARCHAR(128), - stgmethod SMALLINT DEFAULT 0, data MEDIUMBLOB ); diff --git a/src/com/silverwrist/venice/core/impl/TopicMessageUserContextImpl.java b/src/com/silverwrist/venice/core/impl/TopicMessageUserContextImpl.java index 5e13555..717aad1 100644 --- a/src/com/silverwrist/venice/core/impl/TopicMessageUserContextImpl.java +++ b/src/com/silverwrist/venice/core/impl/TopicMessageUserContextImpl.java @@ -20,6 +20,7 @@ package com.silverwrist.venice.core.impl; import java.io.*; import java.sql.*; import java.util.*; +import java.util.zip.*; import org.apache.log4j.*; import com.silverwrist.util.StringUtil; import com.silverwrist.util.collections.*; @@ -60,6 +61,7 @@ class TopicMessageUserContextImpl implements TopicMessageContext private int datalen; private String filename; private String mimetype; + private int stgmethod; private boolean nuked = false; private String creator_cache = null; private String text_cache = null; @@ -73,7 +75,7 @@ class TopicMessageUserContextImpl implements TopicMessageContext long postid, long parent, int num, int linecount, int creator_uid, java.util.Date posted, boolean hidden, int scribble_uid, java.util.Date scribble_date, String pseud, int datalen, - String filename, String mimetype) + String filename, String mimetype, int stgmethod) { this.engine = engine; this.conf = conf; @@ -91,6 +93,7 @@ class TopicMessageUserContextImpl implements TopicMessageContext this.datalen = datalen; this.filename = filename; this.mimetype = mimetype; + this.stgmethod = stgmethod; } // end constructor @@ -114,6 +117,7 @@ class TopicMessageUserContextImpl implements TopicMessageContext this.datalen = 0; this.filename = null; this.mimetype = null; + this.stgmethod = -1; } // end constructor @@ -138,8 +142,9 @@ class TopicMessageUserContextImpl implements TopicMessageContext Statement stmt = conn.createStatement(); StringBuffer sql = new StringBuffer("SELECT posts.hidden, posts.scribble_uid, posts.scribble_date, " + "posts.pseud, postattach.datalen, postattach.filename, " - + "postattach.mimetype FROM posts LEFT JOIN postattach ON " - + "posts.postid = postattach.postid WHERE posts.postid = "); + + "postattach.mimetype, postattach.stgmethod FROM posts " + + "LEFT JOIN postattach ON posts.postid = postattach.postid " + + "WHERE posts.postid = "); sql.append(postid).append(';'); ResultSet rs = stmt.executeQuery(sql.toString()); if (rs.next()) @@ -151,6 +156,9 @@ class TopicMessageUserContextImpl implements TopicMessageContext datalen = rs.getInt(5); filename = rs.getString(6); mimetype = rs.getString(7); + stgmethod = rs.getInt(8); + if (rs.wasNull()) + stgmethod = -1; } // end if else @@ -165,6 +173,7 @@ class TopicMessageUserContextImpl implements TopicMessageContext datalen = 0; filename = null; mimetype = null; + stgmethod = -1; nuked = true; creator_cache = null; text_cache = null; @@ -384,10 +393,16 @@ class TopicMessageUserContextImpl implements TopicMessageContext } // end if - // Create the statement and the SQL we need to retrieve the attachment. + // This will cause a "hit" on the attachment data. Update that record. Statement stmt = conn.createStatement(); - StringBuffer sql = new StringBuffer("SELECT data FROM postattach WHERE postid = "); - sql.append(postid).append(';'); + StringBuffer sql = new StringBuffer("UPDATE postattach SET hits = hits + 1, last_hit = '"); + sql.append(SQLUtil.encodeDate(new java.util.Date())).append("' WHERE postid = ").append(postid); + sql.append(';'); + stmt.executeUpdate(sql.toString()); + + // Create the SQL we need to retrieve the attachment. + sql.setLength(0); + sql.append("SELECT data FROM postattach WHERE postid = ").append(postid).append(';'); // Execute the query! ResultSet rs = stmt.executeQuery(sql.toString()); @@ -402,19 +417,35 @@ class TopicMessageUserContextImpl implements TopicMessageContext // need to make a temporary copy of it, to a ByteArrayOutputStream. (Attachments can only be // 1 Mb in size, so this shouldn't be a big problem.) InputStream sqldata = rs.getBinaryStream(1); + InputStream real_input; + switch (stgmethod) + { // where's our input really coming from + case 0: // copy verbatim + real_input = sqldata; + break; + + case 1: // gunzip it first + real_input = new GZIPInputStream(sqldata); + break; + + default: + throw new DataException("Unknown storage method value: " + stgmethod); + + } // end switch + ByteArrayOutputStream copy = new ByteArrayOutputStream(datalen); byte[] buffer = new byte[4096]; - int rd = sqldata.read(buffer); + int rd = real_input.read(buffer); while (rd>=0) { // write, then read again if (rd>0) copy.write(buffer,0,rd); - rd = sqldata.read(buffer); + rd = real_input.read(buffer); } // end while // Close both our streams, making sure we create the stream we need for the return value. - sqldata.close(); + real_input.close(); rc = new ByteArrayInputStream(copy.toByteArray()); copy.close(); @@ -816,6 +847,40 @@ class TopicMessageUserContextImpl implements TopicMessageContext } // end else if + // Compress the attachment data in memory. + InputStream real_data = null; + int real_length = 0; + try + { // create a compressor into a memory buffer + ByteArrayOutputStream bytestm = new ByteArrayOutputStream(length); + GZIPOutputStream gzipstm = new GZIPOutputStream(bytestm); + + // do the usual read/write loop to get the data compressed + byte[] buffer = new byte[4096]; + int rd = data.read(buffer); + while (rd>=0) + { // write, then read + if (rd>0) + gzipstm.write(buffer,0,rd); + rd = data.read(buffer); + + } // end while + + // finish compression, then get the data and the real length + gzipstm.finish(); + buffer = bytestm.toByteArray(); + real_length = buffer.length; + real_data = new ByteArrayInputStream(buffer); + gzipstm.close(); + + } // end try + catch (IOException ioe) + { // the big error + logger.error("IOException in compressor loop: " + ioe.getMessage(),ioe); + throw new DataException("Failure in compressing read data: " + ioe.getMessage()); + + } // end catch + Connection conn = null; AuditRecord ar = null; @@ -834,20 +899,23 @@ class TopicMessageUserContextImpl implements TopicMessageContext // Build the SQL statement that inserts the attachment. Note the use of the "?" to specify the // BLOB parameter (the attachment data itself); this comes later. - StringBuffer sql = - new StringBuffer("INSERT INTO postattach (postid, datalen, filename, mimetype, data) VALUES ("); - sql.append(postid).append(", ").append(length).append(", '").append(SQLUtil.encodeString(file)); - sql.append("', '").append(SQLUtil.encodeString(m_type)).append("', ?);"); + StringBuffer sql = new StringBuffer("INSERT INTO postattach (postid, datalen, last_hit, stgmethod, " + + "filename, mimetype, data) VALUES ("); + sql.append(postid).append(", ").append(length).append(", '"); + sql.append(SQLUtil.encodeDate(new java.util.Date())).append("', 1, '"); + sql.append(SQLUtil.encodeString(file)).append("', '").append(SQLUtil.encodeString(m_type)); + sql.append("', ?);"); // Prepare the statement, set the BLOB parameter, and execute it. PreparedStatement stmt = conn.prepareStatement(sql.toString()); - stmt.setBinaryStream(1,data,length); + stmt.setBinaryStream(1,real_data,real_length); stmt.executeUpdate(); // Save off the local attachment values. datalen = length; filename = file; mimetype = m_type; + stgmethod = 1; // Generate an audit record indicating what we did. ar = new AuditRecord(AuditRecord.UPLOAD_ATTACHMENT,conf.realUID(),conf.userRemoteAddress(), @@ -1036,8 +1104,8 @@ class TopicMessageUserContextImpl implements TopicMessageContext StringBuffer sql = new StringBuffer("SELECT p.postid, p.parent, p.num, p.linecount, p.creator_uid, p.posted, " + "p.hidden, p.scribble_uid, p.scribble_date, p.pseud, a.datalen, a.filename, " - + "a.mimetype FROM posts p LEFT JOIN postattach a ON p.postid = a.postid " - + "WHERE p.topicid = "); + + "a.mimetype, a.stgmethod FROM posts p LEFT JOIN postattach a ON " + + "p.postid = a.postid WHERE p.topicid = "); sql.append(topicid).append(" AND p.num >= ").append(post_low).append(" AND p.num <= "); sql.append(post_high).append(" ORDER BY p.num ASC;"); if (logger.isDebugEnabled()) @@ -1050,7 +1118,8 @@ class TopicMessageUserContextImpl implements TopicMessageContext new TopicMessageUserContextImpl(engine,conf,datapool,rs.getLong(1),rs.getLong(2),rs.getInt(3), rs.getInt(4),rs.getInt(5),SQLUtil.getFullDateTime(rs,6), rs.getBoolean(7),rs.getInt(8),SQLUtil.getFullDateTime(rs,9), - rs.getString(10),rs.getInt(11),rs.getString(12),rs.getString(13)); + rs.getString(10),rs.getInt(11),rs.getString(12),rs.getString(13), + rs.getInt(14)); rc.add(val); } // end while @@ -1091,8 +1160,8 @@ class TopicMessageUserContextImpl implements TopicMessageContext StringBuffer sql = new StringBuffer("SELECT p.postid, p.parent, p.num, p.linecount, p.creator_uid, p.posted, " + "p.hidden, p.scribble_uid, p.scribble_date, p.pseud, a.datalen, a.filename, " - + "a.mimetype FROM posts p LEFT JOIN postattach a ON p.postid = a.postid " - + "WHERE p.topicid = "); + + "a.mimetype, a.stgmethod FROM posts p LEFT JOIN postattach a ON " + + "p.postid = a.postid WHERE p.topicid = "); sql.append(topicid).append(" AND p.num = ").append(message_num).append(';'); if (logger.isDebugEnabled()) logger.debug("SQL: " + sql.toString()); @@ -1103,7 +1172,7 @@ class TopicMessageUserContextImpl implements TopicMessageContext rs.getInt(4),rs.getInt(5),SQLUtil.getFullDateTime(rs,6), rs.getBoolean(7),rs.getInt(8),SQLUtil.getFullDateTime(rs,9), rs.getString(10),rs.getInt(11),rs.getString(12), - rs.getString(13)); + rs.getString(13),rs.getInt(14)); // indicates an error... throw new DataException("Message not found."); @@ -1140,8 +1209,8 @@ class TopicMessageUserContextImpl implements TopicMessageContext StringBuffer sql = new StringBuffer("SELECT p.postid, p.parent, p.num, p.linecount, p.creator_uid, p.posted, " + "p.hidden, p.scribble_uid, p.scribble_date, p.pseud, a.datalen, a.filename, " - + "a.mimetype FROM topics t, posts p LEFT JOIN postattach a ON p.postid = a.postid " - + "WHERE t.topicid = p.topicid AND t.confid = "); + + "a.mimetype, a.stgmethod FROM topics t, posts p LEFT JOIN postattach a " + + "ON p.postid = a.postid WHERE t.topicid = p.topicid AND t.confid = "); sql.append(conf.realConfID()).append(" AND p.postid = ").append(postid).append(';'); if (logger.isDebugEnabled()) logger.debug("SQL: " + sql.toString()); @@ -1152,7 +1221,7 @@ class TopicMessageUserContextImpl implements TopicMessageContext rs.getInt(4),rs.getInt(5),SQLUtil.getFullDateTime(rs,6), rs.getBoolean(7),rs.getInt(8),SQLUtil.getFullDateTime(rs,9), rs.getString(10),rs.getInt(11),rs.getString(12), - rs.getString(13)); + rs.getString(13),rs.getInt(14)); // indicates an error... throw new DataException("Message not found."); diff --git a/src/com/silverwrist/venice/db/SQLUtil.java b/src/com/silverwrist/venice/db/SQLUtil.java index 5e1d810..acc940f 100644 --- a/src/com/silverwrist/venice/db/SQLUtil.java +++ b/src/com/silverwrist/venice/db/SQLUtil.java @@ -7,7 +7,7 @@ * WARRANTY OF ANY KIND, either express or implied. See the License for the specific * language governing rights and limitations under the License. * - * The Original Code is the Venice Web Community System. + * The Original Code is the Venice Web Communities System. * * The Initial Developer of the Original Code is Eric J. Bowersox , * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are @@ -23,6 +23,13 @@ import com.silverwrist.util.StringUtil; public class SQLUtil { + /*-------------------------------------------------------------------------------- + * Static data members + *-------------------------------------------------------------------------------- + */ + + private static SimpleTimeZone utc = new SimpleTimeZone(0,"UTC"); + /*-------------------------------------------------------------------------------- * Internal functions *-------------------------------------------------------------------------------- @@ -35,7 +42,7 @@ public class SQLUtil try { // do almost the reverse process of formatting it into a string - GregorianCalendar cal = new GregorianCalendar(new SimpleTimeZone(0,"UTC")); + GregorianCalendar cal = new GregorianCalendar(utc); cal.set(Calendar.YEAR,Integer.parseInt(dstr.substring(0,4))); cal.set(Calendar.MONTH,Integer.parseInt(dstr.substring(5,7)) - 1 + Calendar.JANUARY); cal.set(Calendar.DAY_OF_MONTH,Integer.parseInt(dstr.substring(8,10))); @@ -112,7 +119,7 @@ public class SQLUtil public static String encodeDate(java.util.Date d) { // Break down the date as a UTC value. - GregorianCalendar cal = new GregorianCalendar(new SimpleTimeZone(0,"UTC")); + GregorianCalendar cal = new GregorianCalendar(utc); cal.setTime(d); // Create the two string buffers converting the date. diff --git a/src/com/silverwrist/venice/servlets/Attachment.java b/src/com/silverwrist/venice/servlets/Attachment.java index b9aa73a..8bfadc3 100644 --- a/src/com/silverwrist/venice/servlets/Attachment.java +++ b/src/com/silverwrist/venice/servlets/Attachment.java @@ -111,14 +111,14 @@ public class Attachment extends VeniceServlet return new ErrorBox(null,"Internal Error: 'thefile' should be a file param",target); // get the SIG - SIGContext sig = getSIGParameter(request,user,true,"top"); + SIGContext sig = getSIGParameter(mphandler,user,true,"top"); changeMenuSIG(request,sig); // get the conference - ConferenceContext conf = getConferenceParameter(request,sig,true,"top"); + ConferenceContext conf = getConferenceParameter(mphandler,sig,true,"top"); // get the message we want to use - TopicMessageContext msg = getMessageParameter(request,conf,true,"top"); + TopicMessageContext msg = getMessageParameter(mphandler,conf,true,"top"); try { // attach the data to the message! diff --git a/web/default.jsp b/web/default.jsp new file mode 100644 index 0000000..aced927 --- /dev/null +++ b/web/default.jsp @@ -0,0 +1,22 @@ +<%-- + The contents of this file are subject to the Mozilla Public License Version 1.1 + (the "License"); you may not use this file except in compliance with the License. + You may obtain a copy of the License at . + + Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + WARRANTY OF ANY KIND, either express or implied. See the License for the specific + language governing rights and limitations under the License. + + The Original Code is the Venice Web Communities System. + + The Initial Developer of the Original Code is Eric J. Bowersox , + for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + Copyright (C) 2001 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + + Contributor(s): +--%> +<% +ServletContext ctxt = getServletConfig().getServletContext(); +RequestDispatcher disp = ctxt.getNamedDispatcher("top"); +disp.forward(request,response); +%> \ No newline at end of file