diff --git a/build.properties.sample b/build.properties.sample index b7cf3c6..6fb7ae3 100644 --- a/build.properties.sample +++ b/build.properties.sample @@ -35,6 +35,11 @@ collections.base=/usr/local/java/commons-collections-2.1 # collections.lib=${collections.base} # collections.jarfile=commons-collections.jar +# [Location of Commons Codec Library 1.2] +codec.base=/usr/local/java/commons-codec-1.2 +# codec.lib=${codec.base} +# codec.jarfile=commons-codec-1.2.jar + # [Location of Jakarta Regexp Library 1.3] regexp.base=/usr/local/java/jakarta-regexp-1.3 # regexp.lib=${regexp.base} diff --git a/build.xml b/build.xml index e6165fd..83039de 100644 --- a/build.xml +++ b/build.xml @@ -48,6 +48,11 @@ + + + + + @@ -81,6 +86,7 @@ + @@ -165,6 +171,7 @@ + diff --git a/etc/ui-config.xml b/etc/ui-config.xml index caadee5..7647df5 100644 --- a/etc/ui-config.xml +++ b/etc/ui-config.xml @@ -175,12 +175,14 @@ + + @@ -233,12 +235,14 @@ + + @@ -437,6 +441,8 @@ Text of this agreement is TBD. Conference Activity Reports Conference E-Mail + Export Messages + Import Messages Delete Conference diff --git a/scripts/conf/export.js b/scripts/conf/export.js new file mode 100644 index 0000000..54ec8ef --- /dev/null +++ b/scripts/conf/export.js @@ -0,0 +1,103 @@ +// 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) 2004 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. +// +// Contributor(s): + +importPackage(java.lang); +importPackage(java.util); +importPackage(Packages.com.silverwrist.venice.core); +importPackage(Packages.com.silverwrist.venice.except); +importPackage(Packages.com.silverwrist.venice.ui); +importPackage(Packages.com.silverwrist.venice.ui.conf); +importPackage(Packages.com.silverwrist.venice.ui.helpers); +importPackage(Packages.com.silverwrist.venice.ui.view); + +// get the request object and the community +rinput = bsf.lookupBean("request"); +comm = rinput.getCommunity(true,"top.js.vs"); + +// get the current conference +currc = new CurrentConference(rinput); +conf = currc.getConference(true,"conf/conferences.js.vs?cc=" + comm.communityID); +on_error = "conf/manage_conf.js.vs?cc=" + comm.communityID + "&conf=" + conf.confID; + +if (!(conf.canChangeConference())) +{ // you can't fiddle with this conference + vlib.output(new ErrorBox("Access Error","You do not have permission to export posts from this conference.", + on_error)); + vlib.done(); + +} // end if + +rc = null; // return from this script +try +{ // figure out what to do here + if ("GET"==rinput.verb) + { // load and display the JSP page for the form + l = conf.getTopicList(ConferenceContext.GET_ALL,ConferenceContext.SORT_NUMBER); + rinput.setRequestAttribute("topic.list",l); + + rc = new JSPView("Export Messages: " + conf.name,"conf/export.jsp"); + rc.menuSelector = Content.MENU_SELECTOR_COMMUNITY; + + } // end if + else // POST + { // get the parameters and generate the export file + if (rinput.isImageButtonClicked("cancel")) + rc = new Redirect(on_error,LinkTypes.SERVLET); // cancel - go back to menu + else if (rinput.isImageButtonClicked("export")) + { // get the list of topics to be exported + tarray = rinput.getParameterValues("tselect"); + if (tarray==null) + rc = new ErrorBox("Input Error","No topics selected.",on_error); + else if (tarray.length==0) + rc = new ErrorBox("Input Error","No topics selected.",on_error); + else + { // convert the array of string equivalent topic numbers to a set of topic indexes + tset = new HashSet(); + for (i=0; i. +// +// 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) 2004 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. +// +// Contributor(s): + +importPackage(java.lang); +importPackage(java.util); +importPackage(Packages.com.silverwrist.venice.core); +importPackage(Packages.com.silverwrist.venice.except); +importPackage(Packages.com.silverwrist.venice.ui); +importPackage(Packages.com.silverwrist.venice.ui.conf); +importPackage(Packages.com.silverwrist.venice.ui.helpers); +importPackage(Packages.com.silverwrist.venice.ui.view); + +// get the request object and the community +rinput = bsf.lookupBean("request"); +comm = rinput.getCommunity(true,"top.js.vs"); + +// get the current conference +currc = new CurrentConference(rinput); +conf = currc.getConference(true,"conf/conferences.js.vs?cc=" + comm.communityID); +on_error = "conf/manage_conf.js.vs?cc=" + comm.communityID + "&conf=" + conf.confID; + +if (!(conf.canChangeConference())) +{ // you can't fiddle with this conference + vlib.output(new ErrorBox("Access Error","You do not have permission to import posts to this conference.", + on_error)); + vlib.done(); + +} // end if + +rc = null; // return from this script +try +{ // figure out what to do + if ("GET"==rinput.verb) + { // load and display the JSP page for the form + rc = new JSPView("Import Messages: " + conf.name,"conf/import.jsp"); + rc.menuSelector = Content.MENU_SELECTOR_COMMUNITY; + + } // end get + else // POST + { // which button was pressed to get the POST going? + if (rinput.isImageButtonClicked("cancel")) + rc = new Redirect(on_error,LinkTypes.SERVLET); // cancel - go back to menu + else if (rinput.isImageButtonClicked("import")) + { // begin the import! + match_meth = rinput.getParameterInt("match",0); + create_new = rinput.hasParameter("create"); + if (rinput.hasParameter("the_file")) + { // perform the import and set up the results + msgs = conf.importMessages(rinput.getParameterDataStream("the_file"),match_meth,create_new); + rinput.setRequestAttribute("output.list",msgs); + rc = new JSPView("Import Message Results: " + conf.name,"conf/import_results.jsp"); + rc.menuSelector = Content.MENU_SELECTOR_COMMUNITY; + + } // end if + else // no input file specified + rc = new ErrorBox("Input Error","No input file specified.", + "conf/import.js.vs?cc=" + comm.communityID + "&conf=" + conf.confID); + + } // end else if + else + { // invalid command button pressed + logger.error("no known button click on POST to conf/import.js"); + rc = new ErrorBox("Internal Error","Unknown command button pressed",on_error); + + } // end else + + } // end else + +} // end try +catch (e) +{ // figure out the exception type + etype = vlib.exceptionType(e) + ""; + if (etype.match("AccessError")) + rc = new ErrorBox("Access Error",e.message,on_error); + else if (etype.match("DataException")) + rc = new ErrorBox("Database Error",e.message,on_error); + else if (etype.match("IOException")) + rc = new ErrorBox("I/O Error",e.message,on_error); + else + rc = e; + +} // end catch + +vlib.output(rc); diff --git a/src/com/silverwrist/util/Base64EncodeInputStream.java b/src/com/silverwrist/util/Base64EncodeInputStream.java new file mode 100644 index 0000000..09823e6 --- /dev/null +++ b/src/com/silverwrist/util/Base64EncodeInputStream.java @@ -0,0 +1,194 @@ +/* + * 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) 2004 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.util; + +import java.io.*; +import org.apache.commons.codec.binary.Base64; +import org.apache.log4j.*; + +public class Base64EncodeInputStream extends FilterInputStream +{ + /*-------------------------------------------------------------------------------- + * Static data members + *-------------------------------------------------------------------------------- + */ + + private static Logger logger = Logger.getLogger(Base64EncodeInputStream.class); + + private static final int NREAD = 768; // must be divisible by three + + /*-------------------------------------------------------------------------------- + * Attributes + *-------------------------------------------------------------------------------- + */ + + private byte[] m_coded_data = null; + private int m_ptr = 0; + + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + public Base64EncodeInputStream(InputStream inner) + { + super(inner); + + } // end constructor + + /*-------------------------------------------------------------------------------- + * Internal operations + *-------------------------------------------------------------------------------- + */ + + private boolean backfill() throws IOException + { + if ((m_coded_data!=null) && (m_coded_data.length<=m_ptr)) + { // the buffer is empty - clear it + logger.debug("buffer drained"); + m_coded_data = null; + + } // end if + + if (m_coded_data==null) + { // read in a chunk from the underlying stream + byte[] data = new byte[NREAD]; + int nr = in.read(data); + if (nr<=0) + { // done with underlying stream + logger.debug("B64EIS - underlying stream at EOF"); + return true; + + } // end if + + if (logger.isDebugEnabled()) + logger.debug("read " + nr + " bytes from underlying stream"); + + if (nrb.length) + throw new IndexOutOfBoundsException("off right end of array"); + if (len==0) + return 0; + int rc = 0; + while (len>0) + { // force a backfill before copying + if (backfill()) + break; // end of the underlying file + int ncpy = Math.min(len,m_coded_data.length - m_ptr); + System.arraycopy(m_coded_data,m_ptr,b,off,ncpy); + m_ptr += ncpy; + off += ncpy; + rc += ncpy; + len -= ncpy; + + } // end while + + if (rc==0) + rc = -1; // EOF + return rc; + + } // end read + + public synchronized long skip(long n) throws IOException + { + long rc = 0; + + while (n>0) + { // force a backfill before skipping + if (backfill()) + break; // end of the underlying file + long nskp = Math.min(n,m_coded_data.length - m_ptr); + m_ptr += (int)nskp; + rc += nskp; + n -= nskp; + + } // end while + + return rc; + + } // end skip + + public void close() throws IOException + { + in.close(); + m_coded_data = null; + + } // end close + + public synchronized int available() throws IOException + { + if (backfill()) + return 0; // at end of file + return (m_coded_data.length - m_ptr) + (in.available() * 4 / 3); + + } // end available + + public void mark(int readLimit) + { // do nothing + } // end mark + + public void reset() + { // do nothing + } // end reset + + public boolean markSupported() + { + return false; + + } // end markSupported + +} // end class Base64EncodeInputStream diff --git a/src/com/silverwrist/util/IOUtil.java b/src/com/silverwrist/util/IOUtil.java index d622e09..72126ea 100644 --- a/src/com/silverwrist/util/IOUtil.java +++ b/src/com/silverwrist/util/IOUtil.java @@ -9,9 +9,9 @@ * * The Original Code is the Venice Web Communities System. * - * The Initial Developer of the Original Code is Eric J. Bowersox , + * 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. + * Copyright (C) 2001-2004 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. * * Contributor(s): */ @@ -125,20 +125,25 @@ public class IOUtil * @param input The stream to copy binary data from. * @param output The stream to copy binary data to. * @param bufsize The size of the buffer to allocate for copying. + * @return The total number of bytes copied. * @exception java.io.IOException If an exception occurred while reading or writing data. */ - public static void copy(InputStream input, OutputStream output, int bufsize) throws IOException + public static int copy(InputStream input, OutputStream output, int bufsize) throws IOException { byte[] buffer = new byte[bufsize]; + int rc = 0; int rd = input.read(buffer); while (rd>=0) { // simple read-write loop to shove data out the door if (rd>0) output.write(buffer,0,rd); + rc += rd; rd = input.read(buffer); } // end while + return rc; + } // end copy /** @@ -147,13 +152,14 @@ public class IOUtil * * @param input The stream to copy binary data from. * @param output The stream to copy binary data to. + * @return The total number of bytes copied. * @exception java.io.IOException If an exception occurred while reading or writing data. * @see #DEFAULT_BUFSIZE * @see #copy(java.io.InputStream,java.io.OutputStream,int) */ - public static void copy(InputStream input, OutputStream output) throws IOException + public static int copy(InputStream input, OutputStream output) throws IOException { - copy(input,output,DEFAULT_BUFSIZE); + return copy(input,output,DEFAULT_BUFSIZE); } // end copy @@ -246,20 +252,25 @@ public class IOUtil * @param input The reader to copy character data from. * @param output The writer to copy character data to. * @param bufsize The size of the buffer to allocate for copying. + * @return The number of characters copied. * @exception java.io.IOException If an exception occurred while reading or writing data. */ - public static void copy(Reader input, Writer output, int bufsize) throws IOException + public static int copy(Reader input, Writer output, int bufsize) throws IOException { char[] buffer = new char[bufsize]; + int rc = 0; int rd = input.read(buffer); while (rd>=0) { // simple read-write loop to shove data out the door if (rd>0) output.write(buffer,0,rd); + rc += rd; rd = input.read(buffer); } // end while + return rc; + } // end copy /** @@ -268,13 +279,14 @@ public class IOUtil * * @param input The reader to copy character data from. * @param output The writer to copy character data to. + * @return The number of characters copied. * @exception java.io.IOException If an exception occurred while reading or writing data. * @see #DEFAULT_BUFSIZE * @see #copy(java.io.Reader,java.io.Writer,int) */ - public static void copy(Reader input, Writer output) throws IOException + public static int copy(Reader input, Writer output) throws IOException { - copy(input,output,DEFAULT_BUFSIZE); + return copy(input,output,DEFAULT_BUFSIZE); } // end copy diff --git a/src/com/silverwrist/venice/core/ConferenceContext.java b/src/com/silverwrist/venice/core/ConferenceContext.java index 4c826c6..5e912f5 100644 --- a/src/com/silverwrist/venice/core/ConferenceContext.java +++ b/src/com/silverwrist/venice/core/ConferenceContext.java @@ -9,16 +9,19 @@ * * The Original Code is the Venice Web Communities System. * - * The Initial Developer of the Original Code is Eric J. Bowersox , + * 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. + * Copyright (C) 2001-2004 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. * * Contributor(s): */ package com.silverwrist.venice.core; +import java.io.InputStream; +import java.io.IOException; import java.util.Date; import java.util.List; +import java.util.Set; import com.silverwrist.venice.except.AccessError; import com.silverwrist.venice.except.DataException; import com.silverwrist.venice.except.EmailException; @@ -43,6 +46,9 @@ public interface ConferenceContext public static final int CUST_BLOCK_TOP = 0; public static final int CUST_BLOCK_BOTTOM = 1; + public static final int IMPORT_MATCH_NUM = 0; + public static final int IMPORT_MATCH_NAME = 1; + public abstract int getConfID(); public abstract String getName(); @@ -192,4 +198,9 @@ public interface ConferenceContext public abstract String getPostLink() throws DataException; + public abstract String exportTopics(Set select_topics) throws AccessError, DataException, IOException; + + public abstract List importMessages(InputStream xmlstream, int match_method, boolean create_new) + throws AccessError, DataException; + } // end interface ConferenceContext diff --git a/src/com/silverwrist/venice/core/TopicMessageContext.java b/src/com/silverwrist/venice/core/TopicMessageContext.java index 3391d52..2b8e122 100644 --- a/src/com/silverwrist/venice/core/TopicMessageContext.java +++ b/src/com/silverwrist/venice/core/TopicMessageContext.java @@ -18,6 +18,8 @@ package com.silverwrist.venice.core; import java.io.InputStream; +import java.io.IOException; +import java.io.OutputStream; import java.util.Date; import com.silverwrist.venice.except.AccessError; import com.silverwrist.venice.except.DataException; @@ -60,6 +62,8 @@ public interface TopicMessageContext public abstract InputStream getAttachmentData() throws AccessError, DataException; + public abstract int getAttachmentData(OutputStream here) throws AccessError, DataException, IOException; + public abstract boolean canHide(); public abstract boolean canScribble(); diff --git a/src/com/silverwrist/venice/core/impl/ConferenceUserContextImpl.java b/src/com/silverwrist/venice/core/impl/ConferenceUserContextImpl.java index ed7f9d5..6a9395f 100644 --- a/src/com/silverwrist/venice/core/impl/ConferenceUserContextImpl.java +++ b/src/com/silverwrist/venice/core/impl/ConferenceUserContextImpl.java @@ -9,14 +9,15 @@ * * The Original Code is the Venice Web Communities System. * - * The Initial Developer of the Original Code is Eric J. Bowersox , + * 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-02 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * Copyright (C) 2001-2004 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. * * Contributor(s): */ package com.silverwrist.venice.core.impl; +import java.io.*; import java.sql.*; import java.util.*; import org.apache.log4j.*; @@ -1778,6 +1779,95 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend } // end getPostLink + public String exportTopics(Set select_topics) throws AccessError, DataException, IOException + { + if (logger.isDebugEnabled()) + logger.debug("exportTopics(" + select_topics.toString() + ") entry"); + if (!(getConferenceData().canChangeConference(level))) + throw new AccessError("You are not permitted to export posts from this conference."); + if (deleted) + throw new DataException("Cannot export posts from a deleted conference."); + + // "Normalize" the topic selection set. + HashSet norm_select_topics = null; + if (select_topics!=null) + { // build the normalized set + norm_select_topics = new HashSet(); + for (Iterator it=select_topics.iterator(); it.hasNext(); ) + { // get each object out in turn + Object o = it.next(); + if (o==null) + continue; + if (o instanceof Integer) + { // it's already an integer + norm_select_topics.add(o); + continue; + + } // end if + + if (o instanceof Number) + { // convert to Integer and add it + norm_select_topics.add(new Integer(((Number)o).intValue())); + continue; + + } // end if + + try + { // append integer equivalent to set + norm_select_topics.add(new Integer(o.toString())); + + } // end try + catch (NumberFormatException e) + { // do nothing + } // end catch + + } // end for + + } // end if + + ConferencingExporter xprt = new ConferencingExporter(); + xprt.setTopics(norm_select_topics); + return xprt.exportConference(this); + + } // end exportTopics + + public List importMessages(InputStream xmlstream, int match_method, boolean create_new) + throws AccessError, DataException + { + if (xmlstream==null) + throw new NullPointerException("bad input stream"); + if ((match_method!=IMPORT_MATCH_NUM) && (match_method!=IMPORT_MATCH_NAME)) + throw new IndexOutOfBoundsException("invalid match method specified"); + + if (!(getConferenceData().canChangeConference(level))) + throw new AccessError("You are not permitted to import posts to this conference."); + if (deleted) + throw new DataException("Cannot import messages to a deleted conference."); + + Connection conn = null; + try + { // get a connection and create the worker + conn = env.getConnection(); + ConferencingImporter worker = new ConferencingImporter(env.getUserID(),confid,match_method,create_new,conn, + env.getEngine()); + + // run it! + return worker.importMessages(xmlstream); + + } // end try + catch (SQLException e) + { // translate SQLException to DataException + throw new DataException("Error getting database connection: " + e.getMessage(),e); + + } // end catch + finally + { // shut down the connection + SQLUtil.shutdown(conn); + + } // end finally + + } // end importMessages + /*-------------------------------------------------------------------------------- * Implementations from interface ConferenceBackend *-------------------------------------------------------------------------------- diff --git a/src/com/silverwrist/venice/core/impl/ConferencingExporter.java b/src/com/silverwrist/venice/core/impl/ConferencingExporter.java new file mode 100644 index 0000000..dfa7608 --- /dev/null +++ b/src/com/silverwrist/venice/core/impl/ConferencingExporter.java @@ -0,0 +1,220 @@ +/* + * 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) 2004 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.venice.core.impl; + +import java.io.*; +import java.text.*; +import java.util.*; +import org.apache.log4j.*; +import com.silverwrist.util.*; +import com.silverwrist.venice.core.*; +import com.silverwrist.venice.except.*; + +class ConferencingExporter +{ + /*-------------------------------------------------------------------------------- + * Static data members + *-------------------------------------------------------------------------------- + */ + + private static Logger logger = Logger.getLogger(ConferencingExporter.class); + + private static final DateFormat s_datefmt; + + /*-------------------------------------------------------------------------------- + * Attributes + *-------------------------------------------------------------------------------- + */ + + private StringWriter m_buffer = null; + private PrintWriter m_wr = null; + private Set m_include = null; + + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + ConferencingExporter() + { // do nothing + } // end constructor + + /*-------------------------------------------------------------------------------- + * Internal operations + *-------------------------------------------------------------------------------- + */ + + private void visit(TopicMessageUserContextImpl msg) throws DataException, AccessError, IOException + { + if (logger.isDebugEnabled()) + logger.debug("exporting post #" + msg.getPostNumber()); + + m_wr.write("\n"); + + } // end visit + + private void visit(TopicUserContextImpl topic) throws DataException, AccessError, IOException + { + if ((m_include!=null) && !(m_include.contains(new Integer(topic.getTopicNumber())))) + return; // skip this topic + + if (logger.isDebugEnabled()) + logger.debug("exporting topic \"" + topic.getName() + "\""); + + // write the main topic information + m_wr.write("\n\n"); + + // get the posts and write them out + List l = topic.getMessages(0,topic.getTopMessage()); + for (Iterator it=l.iterator(); it.hasNext(); ) + visit((TopicMessageUserContextImpl)(it.next())); + + // done with the topic + m_wr.write("\n"); + + } // end visit + + /*-------------------------------------------------------------------------------- + * External operations + *-------------------------------------------------------------------------------- + */ + + void setTopics(Set s) + { + m_include = s; + + } // end setTopics + + String exportConference(ConferenceUserContextImpl conf) throws DataException, AccessError, IOException + { + if (logger.isDebugEnabled()) + logger.debug("exporting conference \"" + conf.getName() + "\""); + m_buffer = new StringWriter(); + m_wr = new PrintWriter(m_buffer); + m_wr.write("\n\n"); + + List l = conf.getTopicList(ConferenceContext.GET_ALL,ConferenceContext.SORT_NUMBER); + for (Iterator it=l.iterator(); it.hasNext(); ) + visit((TopicUserContextImpl)(it.next())); + + m_wr.write("\n"); + m_wr.flush(); + + // Return the finished buffer. + String rc = m_buffer.toString(); + m_wr.close(); + m_wr = null; + m_buffer = null; + return rc; + + } // end exportConference + + /*-------------------------------------------------------------------------------- + * Static initializer + *-------------------------------------------------------------------------------- + */ + + static + { // create an ISO 8601 date formatter + SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd'T'HHmmss"); + df.setTimeZone(new SimpleTimeZone(0,"UTC")); + s_datefmt = df; + + } // end static initializer + +} // end class ConferencingExporter diff --git a/src/com/silverwrist/venice/core/impl/ConferencingImporter.java b/src/com/silverwrist/venice/core/impl/ConferencingImporter.java new file mode 100644 index 0000000..5277467 --- /dev/null +++ b/src/com/silverwrist/venice/core/impl/ConferencingImporter.java @@ -0,0 +1,1293 @@ +/* + * 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) 2004 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.venice.core.impl; + +import java.io.*; +import java.sql.*; +import java.text.*; +import java.util.*; +import java.util.zip.*; +import javax.xml.parsers.*; +import org.apache.commons.codec.binary.Base64; +import org.apache.log4j.*; +import org.xml.sax.*; +import org.xml.sax.helpers.*; +import com.silverwrist.util.*; +import com.silverwrist.venice.core.ConferenceContext; +import com.silverwrist.venice.core.internals.EngineBackend; +import com.silverwrist.venice.db.*; +import com.silverwrist.venice.except.*; + +class ConferencingImporter +{ + /*-------------------------------------------------------------------------------- + * Inner class containing topic data + *-------------------------------------------------------------------------------- + */ + + private class TopicData + { + /*==================================================================== + * Attributes + *==================================================================== + */ + + private int m_index; // topic index + private boolean m_frozen = false; // are we frozen? + private boolean m_archived = false; // are we archived? + private StringBuffer m_name; // topic name buffer + + /*==================================================================== + * Constructor + *==================================================================== + */ + + TopicData(Attributes attrs) throws SAXException + { + boolean index_seen = false; + for (int i=0; i index specified twice"); + m_index = Integer.parseInt(attrs.getValue(i)); + index_seen = true; + + } // end if + catch (NumberFormatException e) + { // this sucks! + throw new SAXException("invalid numeric format for index"); + + } // end catch + + } // end if + else if (name.equals("frozen")) + { // parse the "frozen" attribute + if (StringUtil.isBooleanTrue(attrs.getValue(i))) + m_frozen = true; + else if (StringUtil.isBooleanFalse(attrs.getValue(i))) + m_frozen = false; + else + throw new SAXException("invalid boolean format for frozen"); + + } // end else if + else if (name.equals("archived")) + { // parse the "archived" attribute + if (StringUtil.isBooleanTrue(attrs.getValue(i))) + m_archived = true; + else if (StringUtil.isBooleanFalse(attrs.getValue(i))) + m_archived = false; + else + throw new SAXException("invalid boolean format for archived"); + + } // end else if + // else ignore any unknown attributes + + } // end for + + if (!index_seen) + throw new SAXException(" index not specified"); + + m_name = new StringBuffer(); + + } // end constructor + + /*==================================================================== + * External operations + *==================================================================== + */ + + final void appendNameData(char[] ch, int start, int length) + { + m_name.append(ch,start,length); + + } // end appendNameData + + final void resolveTopic() throws SAXException + { + Statement stmt_x = null; + PreparedStatement stmt = null; + boolean mid_create = false; + + try + { // lock the tables we need + stmt_x = m_conn.createStatement(); + stmt_x.executeUpdate("LOCK TABLES confs WRITE, topics WRITE;"); + + // determine how to try to match the topic + switch (m_match_method) + { + case ConferenceContext.IMPORT_MATCH_NUM: + stmt = m_conn.prepareStatement("SELECT topicid FROM topics WHERE confid = ? AND num = ?;"); + stmt.setInt(2,m_index); + break; + + case ConferenceContext.IMPORT_MATCH_NAME: + stmt = m_conn.prepareStatement("SELECT topicid FROM topics WHERE confid = ? AND name = ?;"); + stmt.setString(2,m_name.toString()); + break; + + default: + throw new SAXException("internal error: invalid match method"); + + } // end switch + + stmt.setInt(1,m_conf_id); + ResultSet rs = stmt.executeQuery(); + if (rs.next()) + { // found a matching topic - save the ID and return + m_cur_topic = rs.getInt(1); + SQLUtil.shutdown(rs); + return; + + } // end if + + SQLUtil.shutdown(rs); + if (!m_create_new) + { // the topic was not matched and cannot be created - ignore it + recordEvent("Topic <" + m_index + ".> (" + m_name.toString() + ") not matched or created - skipped."); + m_cur_topic = -1; + return; + + } // end if + + mid_create = true; + + // get the proper topic index + SQLUtil.shutdown(stmt); + stmt = m_conn.prepareStatement("SELECT top_topic + 1 FROM confs WHERE confid = ?;"); + stmt.setInt(1,m_conf_id); + rs = stmt.executeQuery(); + if (rs.next()) + m_index = rs.getInt(1); + else + m_index = 1; + SQLUtil.shutdown(rs); + + // prepare the new topic entry + SQLUtil.shutdown(stmt); + stmt = m_conn.prepareStatement("INSERT INTO topics (confid, num, creator_uid, top_message, frozen, archived, " + + "createdate, lastupdate, name) VALUES (?, ?, ?, -1, ?, ?, ?, ?, ?);"); + stmt.setInt(1,m_conf_id); + stmt.setInt(2,m_index); + stmt.setInt(3,m_uid); + stmt.setInt(4,m_frozen ? 1 : 0); + stmt.setInt(5,m_archived ? 1 : 0); + java.util.Date now = new java.util.Date(); + SQLUtil.setFullDateTime(stmt,6,now); + SQLUtil.setFullDateTime(stmt,7,now); + stmt.setString(8,m_name.toString()); + stmt.executeUpdate(); + + // get the new topic ID + rs = stmt_x.executeQuery("SELECT LAST_INSERT_ID();"); + if (rs.next()) + m_cur_topic = rs.getInt(1); + else + throw new SAXException("internal error: can\'t get new topic ID"); + + // update the last update and top topic fields + SQLUtil.shutdown(stmt); + stmt = m_conn.prepareStatement("UPDATE confs SET lastupdate = ?, top_topic = ? WHERE confid = ?;"); + SQLUtil.setFullDateTime(stmt,1,now); + stmt.setInt(2,m_index); + stmt.setInt(3,m_conf_id); + stmt.executeUpdate(); + + } // end try + catch (SQLException e) + { // record the event and continue + if (mid_create) + recordEvent("error creating topic \"" + m_name.toString() + "\"",e); + else + recordEvent("error resolving topic <" + m_index + ".> (" + m_name.toString() + ")",e); + m_cur_topic = -1; + + } // end catch + finally + { // shut down things + SQLUtil.unlockTables(m_conn); + SQLUtil.shutdown(stmt); + SQLUtil.shutdown(stmt_x); + + } // end finally + + } // end resolveTopic + + } // end class TopicData + + /*-------------------------------------------------------------------------------- + * Inner class containing post data + *-------------------------------------------------------------------------------- + */ + + private class PostData + { + /*==================================================================== + * Attributes + *==================================================================== + */ + + private long m_id_in; + private long m_parent_in; + private int m_index; + private int m_line_count; + private String m_author; + private java.util.Date m_date; + private boolean m_hidden = false; + private String m_scribble_by = null; + private java.util.Date m_scribble_date = null; + private StringBuffer m_pseud; + private StringBuffer m_text; + private int m_att_length = -1; + private String m_att_type = null; + private String m_att_filename = null; + private File m_att_data = null; + + /*==================================================================== + * Constructor + *==================================================================== + */ + + PostData(Attributes attrs) throws SAXException + { + boolean id_seen = false, parent_seen = false, index_seen = false, linecount_seen = false, author_seen = false; + boolean date_seen = false; + for (int i=0; i ID specified twice"); + m_id_in = Long.parseLong(attrs.getValue(i)); + id_seen = true; + + } // end if + catch (NumberFormatException e) + { // this sucks! + throw new SAXException("invalid numeric format for ID"); + + } // end catch + + } // end if + else if (name.equals("parent")) + { // get the parent ID + try + { // handle parsing the topic index + if (parent_seen) + throw new SAXException(" parent ID specified twice"); + m_parent_in = Long.parseLong(attrs.getValue(i)); + parent_seen = true; + + } // end if + catch (NumberFormatException e) + { // this sucks! + throw new SAXException("invalid numeric format for parent ID"); + + } // end catch + + } // end else if + else if (name.equals("index")) + { // get the index + try + { // handle parsing the topic index + if (index_seen) + throw new SAXException(" index specified twice"); + m_index = Integer.parseInt(attrs.getValue(i)); + index_seen = true; + + } // end if + catch (NumberFormatException e) + { // this sucks! + throw new SAXException("invalid numeric format for index"); + + } // end catch + + } // end else if + else if (name.equals("lines")) + { // get the number of lines + try + { // handle parsing the topic index + if (linecount_seen) + throw new SAXException(" line count specified twice"); + m_line_count = Integer.parseInt(attrs.getValue(i)); + linecount_seen = true; + + } // end if + catch (NumberFormatException e) + { // this sucks! + throw new SAXException("invalid numeric format for line count"); + + } // end catch + + } // end else if + else if (name.equals("author")) + { // get the post author as a string + if (author_seen) + throw new SAXException(" author name specified twice"); + m_author = attrs.getValue(i); + author_seen = true; + + } // end else if + else if (name.equals("date")) + { // get the post date + try + { // parse the ISO 8601 date + if (date_seen) + throw new SAXException(" date specified twice"); + m_date = s_datefmt.parse(attrs.getValue(i)); + date_seen = true; + + } // end try + catch (ParseException e) + { // date parsing failed + throw new SAXException("invalid date format for date",e); + + } // end catch + + } // end else if + else if (name.equals("hidden")) + { // parse the "hidden" attribute + if (StringUtil.isBooleanTrue(attrs.getValue(i))) + m_hidden = true; + else if (StringUtil.isBooleanFalse(attrs.getValue(i))) + m_hidden = false; + else + throw new SAXException("invalid boolean format for hidden"); + + } // end else if + // else ignore any unknown attributes + + } // end for + + if (!id_seen) + throw new SAXException(" ID not specified"); + if (!parent_seen) + throw new SAXException(" parent ID not specified"); + if (!index_seen) + throw new SAXException(" index not specified"); + if (!linecount_seen) + throw new SAXException(" line count not specified"); + if (!author_seen) + throw new SAXException(" author name not specified"); + if (!date_seen) + throw new SAXException(" date not specified"); + + m_pseud = new StringBuffer(); + m_text = new StringBuffer(); + + } // end constructor + + /*==================================================================== + * External operations + *==================================================================== + */ + + final void dispose() + { + if (m_att_data!=null) + { // delete the temp file + m_att_data.delete(); + m_att_data = null; + + } // end if + + } // end dispose + + final void markScribbled(Attributes attrs) throws SAXException + { + boolean by_seen = false, date_seen = false; + for (int i=0; i user name specified twice"); + m_scribble_by = attrs.getValue(i); + by_seen = true; + + } // end if + else if (name.equals("date")) + { // get the scribbled date + try + { // parse the ISO 8601 date + if (date_seen) + throw new SAXException(" date specified twice"); + m_scribble_date = s_datefmt.parse(attrs.getValue(i)); + date_seen = true; + + } // end try + catch (ParseException e) + { // date parsing failed + throw new SAXException("invalid date format for date",e); + + } // end catch + + } // end else if + // else ignore any unknown attributes + + } // end for + + if (!by_seen) + throw new SAXException(" user name not specified"); + if (!date_seen) + throw new SAXException(" date not specified"); + + } // end markScribbled + + final void appendPseud(char[] ch, int start, int length) + { + m_pseud.append(ch,start,length); + + } // end appendPseud + + final void appendText(char[] ch, int start, int length) + { + m_text.append(ch,start,length); + + } // end appendText + + final OutputStream openAttachment(Attributes attrs) throws SAXException + { + boolean length_seen = false, type_seen = false, filename_seen = false; + for (int i=0; i length specified twice"); + m_att_length = Integer.parseInt(attrs.getValue(i)); + length_seen = true; + + } // end if + catch (NumberFormatException e) + { // this sucks! + throw new SAXException("invalid numeric format for length"); + + } // end catch + + } // end if + else if (name.equals("type")) + { // get the MIME type + if (type_seen) + throw new SAXException(" MIME type specified twice"); + m_att_type = attrs.getValue(i); + type_seen = true; + + } // end else if + else if (name.equals("filename")) + { // get the filename + if (filename_seen) + throw new SAXException(" filename specified twice"); + m_att_filename = attrs.getValue(i); + filename_seen = true; + + } // end else if + // else ignore any unknown attributes + + } // end for + + if (!length_seen) + throw new SAXException(" length not specified"); + if (!type_seen) + throw new SAXException(" MIME type not specified"); + if (!filename_seen) + throw new SAXException(" filename not specified"); + + boolean need_delete = false; + try + { // create the attachment data file and open it + m_att_data = File.createTempFile("Attachment",null); + need_delete = true; + return new FileOutputStream(m_att_data); + + } // end try + catch (IOException e) + { // record the event and continue + recordEvent("unable to open temporary file for attachment \"" + m_att_filename + "\"",e); + m_att_length = -1; + m_att_type = null; + m_att_filename = null; + if (need_delete) + m_att_data.delete(); + m_att_data = null; + + } // end catch + + return null; + + } // end openAttachment + + final void postThis() throws SAXException + { + /* + private String m_att_type = null; + private String m_att_filename = null; + */ + + // get the creator UID + int creator_uid = getUIDForUser(m_author); + if (creator_uid==-1) + { // add a note to the beginning of the text and change the creator UID + m_text.insert(0,"(Originally posted by \"" + m_author + "\")\r\n\r\n"); + m_line_count += 2; + creator_uid = m_uid; + + } // end if + + // get the scribble UID + int scribble_uid = -1; + if (m_scribble_by!=null) + { // get the UID of the scribbling user + scribble_uid = getUIDForUser(m_scribble_by); + if (scribble_uid==-1) + scribble_uid = m_uid; + + } // end if + + Statement stmt_x = null; + PreparedStatement stmt = null; + try + { // lock the tables we'll need + stmt_x = m_conn.createStatement(); + stmt_x.executeUpdate("LOCK TABLES confs WRITE, confsettings WRITE, topics WRITE, topicsettings WRITE, " + + "posts WRITE, postdata WRITE, postattach WRITE;"); + + // get the new index for the post + stmt = m_conn.prepareStatement("SELECT top_message + 1 FROM topics WHERE topicid = ?;"); + stmt.setInt(1,m_cur_topic); + ResultSet rs = stmt.executeQuery(); + if (rs.next()) + m_index = rs.getInt(1); + else + m_index = 0; + SQLUtil.shutdown(rs); + + // prepare the initial post entry + SQLUtil.shutdown(stmt); + stmt = m_conn.prepareStatement("INSERT INTO posts (parent, topicid, num, linecount, creator_uid, posted, " + + "hidden, pseud) VALUES (?, ?, ?, ?, ?, ?, ?, ?);"); + stmt.setLong(1,getPostMapping(m_parent_in)); + stmt.setInt(2,m_cur_topic); + stmt.setInt(3,m_index); + stmt.setInt(4,m_line_count); + stmt.setInt(5,creator_uid); + SQLUtil.setFullDateTime(stmt,6,m_date); + stmt.setInt(7,m_hidden ? 1 : 0); + stmt.setString(8,m_pseud.toString()); + stmt.executeUpdate(); + + // get the new post ID + long pid; + rs = stmt.executeQuery("SELECT LAST_INSERT_ID();"); + if (rs.next()) + pid = rs.getLong(1); + else + throw new SAXException("internal error: cannot get new post ID"); + setPostMapping(m_id_in,pid); + + // add the post data + SQLUtil.shutdown(stmt); + stmt = m_conn.prepareStatement("INSERT INTO postdata(postid, data) VALUES (?, ?);"); + stmt.setLong(1,pid); + stmt.setString(2,m_text.toString()); + stmt.executeUpdate(); + + if (m_scribble_date!=null) + { // update the post to reflect scribble dates + SQLUtil.shutdown(stmt); + stmt = m_conn.prepareStatement("UPDATE posts SET scribble_uid = ?, scribble_date = ? WHERE postid = ?;"); + stmt.setInt(1,scribble_uid); + SQLUtil.setFullDateTime(stmt,2,m_scribble_date); + stmt.setLong(3,pid); + stmt.executeUpdate(); + + } // end if + + // update the topic to reflect the last update + SQLUtil.shutdown(stmt); + stmt = m_conn.prepareStatement("UPDATE topics SET top_message = ?, lastupdate = ? WHERE topicid = ?;"); + stmt.setInt(1,m_index); + SQLUtil.setFullDateTime(stmt,2,m_date); + stmt.setInt(3,m_cur_topic); + stmt.executeUpdate(); + + // update the topic settings to reflect the last post date + SQLUtil.shutdown(stmt); + stmt = m_conn.prepareStatement("UPDATE topicsettings SET last_post = ? WHERE topicid = ? AND uid = ?;"); + SQLUtil.setFullDateTime(stmt,1,m_date); + stmt.setInt(2,m_cur_topic); + stmt.setInt(3,creator_uid); + if (stmt.executeUpdate()<1) + { // We didn't have a topic settings record yet; create one. + SQLUtil.shutdown(stmt); + stmt = m_conn.prepareStatement("INSERT INTO topicsettings (topicid, uid, last_post) VALUES (?, ?, ?);"); + stmt.setInt(1,m_cur_topic); + stmt.setInt(2,creator_uid); + SQLUtil.setFullDateTime(stmt,3,m_date); + stmt.executeUpdate(); + + } // end if + + // Update the "last update" date of the conference. + SQLUtil.shutdown(stmt); + stmt = m_conn.prepareStatement("UPDATE confs SET lastupdate = ? WHERE confid = ?;"); + SQLUtil.setFullDateTime(stmt,1,m_date); + stmt.setInt(2,m_conf_id); + + // Update the "last post" timestamp in conference settings. + SQLUtil.shutdown(stmt); + stmt = m_conn.prepareStatement("UPDATE confsettings SET last_read = ?, last_post = ? WHERE confid = ? " + + "AND uid = ?;"); + SQLUtil.setFullDateTime(stmt,1,m_date); + SQLUtil.setFullDateTime(stmt,2,m_date); + stmt.setInt(3,m_conf_id); + stmt.setInt(4,creator_uid); + if (stmt.executeUpdate()<1) + { // no "confsettings" record found - create one + SQLUtil.shutdown(stmt); + stmt = m_conn.prepareStatement("INSERT INTO confsettings (confid, uid, last_read, last_post) " + + "VALUES (?, ?, ?, ?);"); + stmt.setInt(1,m_conf_id); + stmt.setInt(2,creator_uid); + SQLUtil.setFullDateTime(stmt,3,m_date); + SQLUtil.setFullDateTime(stmt,4,m_date); + + } // end if + + if (m_att_type!=null) + { // there's an attachment to be stored! First see if we need to compress the data. + InputStream stm = null; + int stg_method, stmlen; + try + { // handle all the IO manipulations here + if (m_engine.isNoCompressMimeType(m_att_type)) + { // don't compress, just copy the file data directly + stm = new FileInputStream(m_att_data); + stmlen = m_att_length; + stg_method = 0; + + } // end if + else + { // create the buffer to compress into + ByteArrayOutputStream bytestm = new ByteArrayOutputStream(m_att_length); + GZIPOutputStream gzipstm = new GZIPOutputStream(bytestm); + IOUtil.copy(new FileInputStream(m_att_data),gzipstm); + gzipstm.finish(); + byte[] buffer = bytestm.toByteArray(); + stmlen = buffer.length; + stm = new ByteArrayInputStream(buffer); + IOUtil.shutdown(gzipstm); + stg_method = 1; + + } // end else + + // add the attachment record to the database! + stmt = m_conn.prepareStatement("INSERT INTO postattach(postid, datalen, last_hit, stgmethod, " + + "filename, mimetype, data) VALUES (?, ?, ?, ?, ?, ?, ?);"); + stmt.setLong(1,pid); + stmt.setInt(2,m_att_length); + SQLUtil.setFullDateTime(stmt,3,new java.util.Date()); + stmt.setInt(4,stg_method); + stmt.setString(5,m_att_filename); + stmt.setString(6,m_att_type); + stmt.setBinaryStream(7,stm,stmlen); + stmt.executeUpdate(); + + } // end try + catch (IOException e) + { // bail out from attachment if we screw this up + recordEvent("error getting/compressing attachment data",e); + return; + + } // end catch + + } // end if + + } // end try + catch (SQLException e) + { // record a database error here + recordEvent("error posting message",e); + + } // end catch + finally + { // close everything down + SQLUtil.unlockTables(m_conn); + SQLUtil.shutdown(stmt_x); + SQLUtil.shutdown(stmt); + + } // end finally + + } // end postThis + + } // end class PostData + + /*-------------------------------------------------------------------------------- + * Inner class containing XML listener + *-------------------------------------------------------------------------------- + */ + + private class Listener extends DefaultHandler + { + /*==================================================================== + * Attributes + *==================================================================== + */ + + private TopicData m_topicdata = null; + private PostData m_postdata = null; + private OutputStream m_attachment = null; + private byte[] m_leftover = null; + + /*==================================================================== + * Constructor + *==================================================================== + */ + + Listener() + { + super(); + + } // end constructor + + /*==================================================================== + * Internal operations + *==================================================================== + */ + + private final void handleAttachmentChars(char[] ch, int start, int length) throws SAXException + { + if (m_attachment==null) + return; // no attachment - don't bother + + byte[] code_data = null; + try + { // convert from an array of characters to an array of bytes + String tmp = new String(ch,start,length); + code_data = tmp.getBytes("US-ASCII"); + + } // end try + catch (UnsupportedEncodingException e) + { // this should never happen + throw new SAXException("?!?!?!? WTF? US-ASCII is OK!",e); + + } // end catch + + int len_leftover = (m_leftover!=null) ? m_leftover.length : 0; + if (len_leftover==0) + m_leftover = null; + int t = (len_leftover + code_data.length) / 4; + int ilen = t * 4; + int len_new_leftover = (len_leftover + code_data.length) - ilen; + + byte[] input_data = null; + if (ilen>0) + { // create a perfect input group of 4-byte blocks + input_data = new byte[ilen]; + if (len_leftover>0) + System.arraycopy(m_leftover,0,input_data,0,len_leftover); + System.arraycopy(code_data,0,input_data,len_leftover,ilen - len_leftover); + + } // end if + + if (len_new_leftover>0) + { // set the leftovers aside + m_leftover = new byte[len_new_leftover]; + System.arraycopy(code_data,code_data.length - len_new_leftover,m_leftover,0,len_new_leftover); + + } // end if + else // no leftovers + m_leftover = null; + + if (ilen==0) + return; // no data to write + + try + { // decode the base-64 data and write it! + m_attachment.write(Base64.decodeBase64(input_data)); + + } // end try + catch (IOException e) + { // error during the decode or write + throw new SAXException("error decoding and writing attachment data",e); + + } // end catch + + } // end handleAttachmentChars + + private final void finishAttachment() throws SAXException + { + if ((m_leftover!=null) && (m_leftover.length==0)) + m_leftover = null; + if (m_leftover==null) + return; + + try + { // decode the base-64 data and write it! + m_attachment.write(Base64.decodeBase64(m_leftover)); + + } // end try + catch (IOException e) + { // error during the decode or write + throw new SAXException("error decoding and writing attachment data",e); + + } // end catch + finally + { // null out the leftover array + m_leftover = null; + + } // end finally + + } // end finishAttachment + + /*==================================================================== + * Overrides from class DefaultHandler + *==================================================================== + */ + + public void setDocumentLocator(Locator locator) + { + m_locator = locator; + + } // end setDocumentLocator + + public void startDocument() + { + m_state = ST_PRESTART; + m_cur_topic = -1; + + } // end startDocument + + public void endDocument() throws SAXException + { + if (m_state!=ST_END) + throw new SAXException("no content found"); + m_locator = null; + + } // end endDocument + + public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException + { + String name = resolveName(localName,qName); + switch (m_state) + { + case ST_PRESTART: + if (!(name.equals("vcif"))) + throw new SAXException(" expected"); + m_state = ST_INSTART; + break; + + case ST_INSTART: + if (!(name.equals("topic"))) + throw new SAXException(" expected"); + m_topicdata = new TopicData(attributes); + m_state = ST_INTOPIC_1; + break; + + case ST_INTOPIC_1: + if (!(name.equals("topicname"))) + throw new SAXException(" expected"); + m_state = ST_INTOPIC_NAME; + break; + + case ST_INTOPIC: + if (!(name.equals("post"))) + throw new SAXException(" expected"); + if (m_cur_topic>0) + m_postdata = new PostData(attributes); + m_state = ST_INPOST; + break; + + case ST_INPOST: + if (name.equals("scribbled")) + { // mark post as scribbled + if (m_postdata!=null) + m_postdata.markScribbled(attributes); + m_state = ST_SCRIBBLETAG; + + } // end if + else if (name.equals("pseud")) + m_state = ST_PSEUD; + else if (name.equals("text")) + m_state = ST_TEXT; + else if (name.equals("attachment")) + { // open the attachment + if (m_postdata!=null) + m_attachment = m_postdata.openAttachment(attributes); + m_state = ST_ATTACHMENT; + + } // end else if + else + throw new SAXException(", , , or expected"); + break; + + default: + throw new SAXException("startElement state error (state = " + m_state + ", elt = \"" + name + "\")"); + + } // end switch + + } // end startElement + + public void endElement(String uri, String localName, String qName) throws SAXException + { + String name = resolveName(localName,qName); + switch (m_state) + { + case ST_INSTART: + if (!(name.equals("vcif"))) + throw new SAXException(" expected"); + m_state = ST_END; + break; + + case ST_INTOPIC_NAME: + if (!(name.equals("topicname"))) + throw new SAXException(" expected"); + if (m_topicdata==null) + throw new SAXException("internal error: no topic data"); + m_topicdata.resolveTopic(); + m_topicdata = null; + m_state = ST_INTOPIC; + break; + + case ST_INTOPIC: + if (!(name.equals("topic"))) + throw new SAXException(" expected"); + m_cur_topic = -1; + m_state = ST_INSTART; + break; + + case ST_INPOST: + if (!(name.equals("post"))) + throw new SAXException(" expected"); + if (m_postdata!=null) + { // post complete - make it + try + { // post the message! + m_postdata.postThis(); + + } // end try + finally + { // make sure we dispose the postdata + m_postdata.dispose(); + m_postdata = null; + + } // end finally + + } // end if + + m_state = ST_INTOPIC; + break; + + case ST_SCRIBBLETAG: + if (!(name.equals("scribbled"))) + throw new SAXException(" expected"); + m_state = ST_INPOST; + break; + + case ST_PSEUD: + if (!(name.equals("pseud"))) + throw new SAXException(" expected"); + m_state = ST_INPOST; + break; + + case ST_TEXT: + if (!(name.equals("text"))) + throw new SAXException(" expected"); + m_state = ST_INPOST; + break; + + case ST_ATTACHMENT: + if (!(name.equals("attachment"))) + throw new SAXException(" expected"); + try + { // finish the attachment + finishAttachment(); + + } // end try + finally + { // close it all down + IOUtil.shutdown(m_attachment); + m_attachment = null; + m_state = ST_INPOST; + + } // end finally + break; + + default: + throw new SAXException("endElement state error (state = " + m_state + ", elt = \"" + name + "\")"); + + } // end switch + + } // end endElement + + public void characters(char[] ch, int start, int length) throws SAXException + { + switch (m_state) + { + case ST_INTOPIC_NAME: + if (m_topicdata!=null) + m_topicdata.appendNameData(ch,start,length); + break; + + case ST_PSEUD: + if (m_postdata!=null) + m_postdata.appendPseud(ch,start,length); + break; + + case ST_TEXT: + if (m_postdata!=null) + m_postdata.appendText(ch,start,length); + break; + + case ST_ATTACHMENT: + handleAttachmentChars(ch,start,length); + break; + + default: + break; // ignore characters + + } // end switch + + } // end characters + + public void warning(SAXParseException e) throws SAXException + { + recordEvent("parser warning",e); + super.warning(e); + + } // end warning + + public void error(SAXParseException e) throws SAXException + { + recordEvent("parser error",e); + super.error(e); + + } // end error + + public void fatalError(SAXParseException e) throws SAXException + { + recordEvent("parser fatal error",e); + super.fatalError(e); + + } // end fatalError + + } // end class Listener + + /*-------------------------------------------------------------------------------- + * Static data members + *-------------------------------------------------------------------------------- + */ + + private static Logger logger = Logger.getLogger(ConferencingImporter.class); + + private static final DateFormat s_datefmt; + + private static final int ST_PRESTART = 0; + private static final int ST_INSTART = 1; + private static final int ST_END = 2; + private static final int ST_INTOPIC_1 = 3; + private static final int ST_INTOPIC_NAME = 4; + private static final int ST_INTOPIC = 5; + private static final int ST_INPOST = 6; + private static final int ST_SCRIBBLETAG = 7; + private static final int ST_PSEUD = 8; + private static final int ST_TEXT = 9; + private static final int ST_ATTACHMENT = 10; + + /*-------------------------------------------------------------------------------- + * Attributes + *-------------------------------------------------------------------------------- + */ + + private int m_uid; // UID we're creating stuff with + private int m_conf_id; // conference ID we're importing to + private int m_match_method; // conference match method + private boolean m_create_new; // create new topic if it doesn't exist? + private Connection m_conn; // SQL database connection + private EngineBackend m_engine; // the engine + private LinkedList m_events = null; // the events reported by the parser + private Locator m_locator = null; // locator for events + private int m_state; // current state of the parser + private int m_cur_topic; // current topic ID + private HashMap m_post_map; // mapping from old to new post IDs + + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + ConferencingImporter(int uid, int conf_id, int match_method, boolean create_new, Connection conn, + EngineBackend engine) + { + m_uid = uid; + m_conf_id = conf_id; + m_match_method = match_method; + m_create_new = create_new; + m_conn = conn; + m_engine = engine; + m_post_map = new HashMap(); + + } // end constructor + + /*-------------------------------------------------------------------------------- + * Internal operations + *-------------------------------------------------------------------------------- + */ + + private static final String resolveName(String local_name, String q_name) + { + if ((local_name!=null) && (local_name.length()>0)) + return local_name; + else + return q_name; + + } // end resolveName + + private final int getUIDForUser(String username) + { + PreparedStatement stmt = null; + ResultSet rs = null; + try + { // straightforward query + stmt = m_conn.prepareStatement("SELECT uid FROM users WHERE username = ?;"); + stmt.setString(1,username); + rs = stmt.executeQuery(); + if (rs.next()) + return rs.getInt(1); + else + return -1; + + } // end try + catch (SQLException e) + { // whoops: big error! + recordEvent("error getting UID for user name \"" + username + "\"",e); + return -1; + + } // end catch + finally + { // shut everything down + SQLUtil.shutdown(rs); + SQLUtil.shutdown(stmt); + + } // end finally + + } // end getUIDForUser + + private final void recordEvent(String message) + { + StringBuffer buf = new StringBuffer("["); + buf.append(m_locator.getLineNumber()).append(", ").append(m_locator.getColumnNumber()).append("] "); + buf.append(message); + if (m_events==null) + m_events = new LinkedList(); + m_events.addLast(buf.toString()); + + } // end recordEvent + + private final void recordEvent(String message, Throwable t) + { + StringBuffer buf = new StringBuffer("["); + buf.append(m_locator.getLineNumber()).append(", ").append(m_locator.getColumnNumber()).append("] "); + buf.append(message).append(" - ").append(t.getMessage()); + if (m_events==null) + m_events = new LinkedList(); + m_events.addLast(buf.toString()); + + } // end recordEvent + + private final long getPostMapping(long old) + { + if (old==0) + return 0; + Long rc = (Long)(m_post_map.get(new Long(old))); + return (rc==null) ? 0 : rc.longValue(); + + } // end getPostMapping + + private final void setPostMapping(long old, long nu) + { + m_post_map.put(new Long(old),new Long(nu)); + + } // end setPostMapping + + /*-------------------------------------------------------------------------------- + * External operations + *-------------------------------------------------------------------------------- + */ + + final List importMessages(InputStream xmlstm) throws DataException + { + try + { // create a SAX parser and let it loose on the input data with our listener + SAXParserFactory fact = SAXParserFactory.newInstance(); + fact.setNamespaceAware(false); + fact.setValidating(false); + SAXParser parser = fact.newSAXParser(); + parser.parse(xmlstm,new Listener()); + + } // end try + catch (ParserConfigurationException e) + { // configuration error + throw new DataException("Error configuring XML parser for message import: " + e.getMessage(),e); + + } // end catch + catch (SAXException e) + { // give an error message + throw new DataException("Error importing messages: " + e.getMessage(),e); + + } // end catch + catch (IOException e) + { // I/O error in parsing! + throw new DataException("Error importing messages: " + e.getMessage(),e); + + } // end catch + + if (m_events==null) + return Collections.EMPTY_LIST; + ArrayList rc = new ArrayList(m_events); + m_events = null; + return Collections.unmodifiableList(rc); + + } // end importMessages + + /*-------------------------------------------------------------------------------- + * Static initializer + *-------------------------------------------------------------------------------- + */ + + static + { // create an ISO 8601 date formatter + SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd'T'HHmmss"); + df.setTimeZone(new SimpleTimeZone(0,"UTC")); + df.setLenient(false); + s_datefmt = df; + + } // end static initializer + +} // end class ConferencingImporter diff --git a/src/com/silverwrist/venice/core/impl/PublishedMessageImpl.java b/src/com/silverwrist/venice/core/impl/PublishedMessageImpl.java index 54bc420..2827387 100644 --- a/src/com/silverwrist/venice/core/impl/PublishedMessageImpl.java +++ b/src/com/silverwrist/venice/core/impl/PublishedMessageImpl.java @@ -9,9 +9,9 @@ * * The Original Code is the Venice Web Communities System. * - * The Initial Developer of the Original Code is Eric J. Bowersox , + * 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-02 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * Copyright (C) 2001-2004 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. * * Contributor(s): */ @@ -293,6 +293,13 @@ class PublishedMessageImpl implements TopicMessageContext } // end getAttachmentData + public int getAttachmentData(OutputStream here) throws AccessError, DataException, IOException + { + // FUTURE: allow publishing paperclips? + throw new AccessError("There is no attachment data for this message."); + + } // end getAttachmentData + public boolean canHide() { return false; diff --git a/src/com/silverwrist/venice/core/impl/TopicMessageUserContextImpl.java b/src/com/silverwrist/venice/core/impl/TopicMessageUserContextImpl.java index 28bae7c..dd99bb6 100644 --- a/src/com/silverwrist/venice/core/impl/TopicMessageUserContextImpl.java +++ b/src/com/silverwrist/venice/core/impl/TopicMessageUserContextImpl.java @@ -9,9 +9,9 @@ * * The Original Code is the Venice Web Communities System. * - * The Initial Developer of the Original Code is Eric J. Bowersox , + * 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-02 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * Copyright (C) 2001-2004 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. * * Contributor(s): */ @@ -200,6 +200,40 @@ class TopicMessageUserContextImpl implements TopicMessageContext } // end refresh + /*-------------------------------------------------------------------------------- + * Semi-internal operations + *-------------------------------------------------------------------------------- + */ + + final String getScribblingUser() throws DataException + { + if (scribble_uid==-1) + return null; + + Connection conn = null; + try + { // use a database connection to get the user name + conn = env.getConnection(); + refresh(conn); + if (nuked) + return null; // post nuked! + return quickGetUserName(conn,scribble_uid); + + } // end try + catch (SQLException e) + { // turn this into a DataException + logger.error("DB error reading user name: " + e.getMessage(),e); + throw new DataException("unable to retrieve user name: " + e.getMessage(),e); + + } // end catch + finally + { // make sure we release the connection before we go + SQLUtil.shutdown(conn); + + } // end finally + + } // end getScribblingUser + /*-------------------------------------------------------------------------------- * Implementations from interface TopicMessageContext *-------------------------------------------------------------------------------- @@ -392,6 +426,8 @@ class TopicMessageUserContextImpl implements TopicMessageContext public InputStream getAttachmentData() throws AccessError, DataException { + if (logger.isDebugEnabled()) + logger.debug("getAttachmentData() for post " + postid); if (nuked || (scribble_date!=null)) { // this would be an exercise in futility! logger.error("cannot attach to a nuked or scribbled message"); @@ -401,6 +437,7 @@ class TopicMessageUserContextImpl implements TopicMessageContext Connection conn = null; Statement stmt = null; + ResultSet rs = null; InputStream rc = null; try { // open up a database connection @@ -434,7 +471,7 @@ class TopicMessageUserContextImpl implements TopicMessageContext sql.append("SELECT data FROM postattach WHERE postid = ").append(postid).append(';'); // Execute the query! - ResultSet rs = stmt.executeQuery(sql.toString()); + rs = stmt.executeQuery(sql.toString()); if (!(rs.next())) { // there is no attachment data! logger.error("no attachment data to get"); @@ -450,10 +487,12 @@ class TopicMessageUserContextImpl implements TopicMessageContext switch (stgmethod) { // where's our input really coming from case 0: // copy verbatim + logger.debug("stgmethod 0 = straight copy"); real_input = sqldata; break; case 1: // gunzip it first + logger.debug("stgmethod 1 = GZIP decompress"); real_input = new GZIPInputStream(sqldata); break; @@ -463,7 +502,10 @@ class TopicMessageUserContextImpl implements TopicMessageContext } // end switch // Copy to a new stream. - rc = new ByteArrayInputStream(IOUtil.load(real_input)); + byte[] ary = IOUtil.load(real_input); + if (logger.isDebugEnabled()) + logger.debug("loaded data of length " + ary.length); + rc = new ByteArrayInputStream(ary); } // end try catch (SQLException e) @@ -480,6 +522,7 @@ class TopicMessageUserContextImpl implements TopicMessageContext } // end catch finally { // make sure we release the connection before we go + SQLUtil.shutdown(rs); SQLUtil.shutdown(stmt); SQLUtil.shutdown(conn); @@ -489,6 +532,102 @@ class TopicMessageUserContextImpl implements TopicMessageContext } // end getAttachmentData + public int getAttachmentData(OutputStream here) throws AccessError, DataException, IOException + { + if (logger.isDebugEnabled()) + logger.debug("getAttachmentData() for post " + postid); + if (nuked || (scribble_date!=null)) + { // this would be an exercise in futility! + logger.error("cannot attach to a nuked or scribbled message"); + throw new AccessError("You cannot attach data to a message that no longer exists."); + + } // end if + + Connection conn = null; + Statement stmt = null; + ResultSet rs = null; + try + { // open up a database connection + conn = env.getConnection(); + + // make sure we have current data + refresh(conn); + if (nuked || (scribble_date!=null)) + { // this would be an exercise in futility! + logger.error("cannot attach to a nuked or scribbled message"); + throw new AccessError("You cannot attach data to a message that no longer exists."); + + } // end if + + if (mimetype==null) + { // there is no attachment data! + logger.error("no attachment data to get"); + throw new AccessError("There is no attachment data for this message."); + + } // end if + + // This will cause a "hit" on the attachment data. Update that record. + stmt = conn.createStatement(); + 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! + rs = stmt.executeQuery(sql.toString()); + if (!(rs.next())) + { // there is no attachment data! + logger.error("no attachment data to get"); + throw new AccessError("There is no attachment data for this message."); + + } // end if + + // Since the InputStream we get from JDBC will probably go away when the connection is dropped, we + // 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 + logger.debug("stgmethod 0 = straight copy"); + real_input = sqldata; + break; + + case 1: // gunzip it first + logger.debug("stgmethod 1 = GZIP decompress"); + real_input = new GZIPInputStream(sqldata); + break; + + default: + throw new DataException("Unknown storage method value: " + stgmethod); + + } // end switch + + // copy the data and return number of bytes copied + return IOUtil.copy(real_input,here); + + } // end try + catch (SQLException e) + { // turn this into a DataException + logger.error("DB error retrieving attachment: " + e.getMessage(),e); + throw new DataException("unable to retrieve attachment data: " + e.getMessage(),e); + + } // end catch + finally + { // make sure we release the connection before we go + SQLUtil.shutdown(rs); + SQLUtil.shutdown(stmt); + SQLUtil.shutdown(conn); + + } // end finally + + } // end getAttachmentData + public boolean canHide() { return ( ((creator_uid==env.getUserID()) && (!env.isAnonymous())) diff --git a/src/com/silverwrist/venice/core/impl/TopicUserContextImpl.java b/src/com/silverwrist/venice/core/impl/TopicUserContextImpl.java index 1bfb7a2..647312d 100644 --- a/src/com/silverwrist/venice/core/impl/TopicUserContextImpl.java +++ b/src/com/silverwrist/venice/core/impl/TopicUserContextImpl.java @@ -9,9 +9,9 @@ * * The Original Code is the Venice Web Communities System. * - * The Initial Developer of the Original Code is Eric J. Bowersox , + * 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-02 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * Copyright (C) 2001-2004 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. * * Contributor(s): */ @@ -201,6 +201,17 @@ class TopicUserContextImpl implements TopicContext } // end loadBozo + /*-------------------------------------------------------------------------------- + * Semi-internal functions + *-------------------------------------------------------------------------------- + */ + + final int getTopMessage() + { + return top_message; + + } // end getTopMessage + /*-------------------------------------------------------------------------------- * Implementations from interface TopicContext *-------------------------------------------------------------------------------- diff --git a/src/com/silverwrist/venice/db/SQLUtil.java b/src/com/silverwrist/venice/db/SQLUtil.java index b5214ef..5657a27 100644 --- a/src/com/silverwrist/venice/db/SQLUtil.java +++ b/src/com/silverwrist/venice/db/SQLUtil.java @@ -9,9 +9,9 @@ * * The Original Code is the Venice Web Communities System. * - * The Initial Developer of the Original Code is Eric J. Bowersox , + * 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-02 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * Copyright (C) 2001-2004 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. * * Contributor(s): */ diff --git a/src/com/silverwrist/venice/ui/conf/AttachmentContent.java b/src/com/silverwrist/venice/ui/conf/AttachmentContent.java index 08dad82..a203d70 100644 --- a/src/com/silverwrist/venice/ui/conf/AttachmentContent.java +++ b/src/com/silverwrist/venice/ui/conf/AttachmentContent.java @@ -17,11 +17,9 @@ */ package com.silverwrist.venice.ui.conf; -import java.io.InputStream; -import java.io.IOException; +import java.io.*; import com.silverwrist.venice.core.TopicMessageContext; -import com.silverwrist.venice.except.AccessError; -import com.silverwrist.venice.except.DataException; +import com.silverwrist.venice.except.*; import com.silverwrist.venice.ui.ContentExecute; import com.silverwrist.venice.ui.LinkTypes; import com.silverwrist.venice.ui.RequestExec; @@ -40,7 +38,7 @@ public class AttachmentContent extends ThrowableContent implements ContentExecut private InputStream stm; /*-------------------------------------------------------------------------------- - * Constructor + * Constructors *-------------------------------------------------------------------------------- */ @@ -54,6 +52,26 @@ public class AttachmentContent extends ThrowableContent implements ContentExecut } // end constructor + public AttachmentContent(String data, String type, String filename) + { + super(); + this.type = type; + this.filename = filename; + try + { // get the string data and output it + byte[] d = data.getBytes("UTF-8"); + this.length = d.length; + this.stm = new ByteArrayInputStream(d); + + } // end try + catch (UnsupportedEncodingException e) + { // this is not supposed to happen + throw new InternalStateError("encoding not found?!?!?!?"); + + } // end catch + + } // end constructor + /*-------------------------------------------------------------------------------- * Implementations from interface ContentExecute *-------------------------------------------------------------------------------- diff --git a/src/com/silverwrist/venice/ui/servlet/BaseServlet.java b/src/com/silverwrist/venice/ui/servlet/BaseServlet.java index c5cefce..84f499c 100644 --- a/src/com/silverwrist/venice/ui/servlet/BaseServlet.java +++ b/src/com/silverwrist/venice/ui/servlet/BaseServlet.java @@ -9,9 +9,9 @@ * * The Original Code is the Venice Web Communities System. * - * The Initial Developer of the Original Code is Eric J. Bowersox , + * 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-04 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * Copyright (C) 2001-2004 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. * * Contributor(s): */ @@ -166,6 +166,21 @@ public abstract class BaseServlet extends HttpServlet my_output = new ErrorBox("Internal Error!", "No content returned for request: " + the_request.getVerb() + ": /" + default_location,null); + else if (my_output instanceof RuntimeException) + { // throw all RuntimeExceptions we get at this level + logger.error("BaseServlet caught runtime exception" + my_output.getClass().getName() + + " in commonProcess",(Throwable)my_output); + throw new ServletException((Throwable)my_output); + + } // end else if + else if (my_output instanceof VirtualMachineError) + { // OutOfMemoryError, StackOverflowError, and such come here + System.gc(); // garbage collect so we have enough space to handle the error + logger.error("Virtual machine failure " + my_output.getClass().getName() + " in commonProcess", + (Throwable)my_output); + throw new ServletException((Throwable)my_output); + + } // end else if } // end try catch (ThrowableContent tc) diff --git a/web/format/conf/export.jsp b/web/format/conf/export.jsp new file mode 100644 index 0000000..ec8b1b3 --- /dev/null +++ b/web/format/conf/export.jsp @@ -0,0 +1,60 @@ +<%-- + 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) 2004 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + + Contributor(s): +--%> +<%@ page import = "java.util.*" %> +<%@ page import = "com.silverwrist.venice.core.*" %> +<%@ page import = "com.silverwrist.venice.ui.conf.CurrentConference" %> +<%@ page import = "com.silverwrist.venice.ui.view.JSPView" %> +<%@ taglib uri="/tlds/util" prefix="util" %> +<%@ taglib uri="/tlds/community" prefix="comm" %> +<%@ taglib uri="/tlds/conference" prefix="conf" %> +<% + JSPView view = JSPView.get(request); + final List topics = (List)(view.getRequestAttribute("topic.list")); +%> + + Export Messages + Conference: + + + + + + +
+ + <% for (Iterator it=topics.iterator(); it.hasNext(); ) { %> + <% TopicContext t = (TopicContext)(it.next()); %> + + + + + + <% } // end for %> +
+ Select Topics to Export: +
+ + <%= t.getTopicNumber() %>. + <%= t.getName() %> +

+ +
+    +
+ +
diff --git a/web/format/conf/import.jsp b/web/format/conf/import.jsp new file mode 100644 index 0000000..170e46b --- /dev/null +++ b/web/format/conf/import.jsp @@ -0,0 +1,53 @@ +<%-- + 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) 2004 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + + Contributor(s): +--%> +<%@ page import = "java.util.*" %> +<%@ page import = "com.silverwrist.venice.core.*" %> +<%@ page import = "com.silverwrist.venice.ui.conf.CurrentConference" %> +<%@ page import = "com.silverwrist.venice.ui.view.JSPView" %> +<%@ taglib uri="/tlds/util" prefix="util" %> +<%@ taglib uri="/tlds/community" prefix="comm" %> +<%@ taglib uri="/tlds/conference" prefix="conf" %> +<% + JSPView view = JSPView.get(request); +%> + + Import Messages + Conference: + + + + + + +
+
+ Content data to be uploaded: +
+ + Match existing topics in the conference: +
+ + Create new topics if they don't exist +
+
+    +
+
diff --git a/web/format/conf/import_results.jsp b/web/format/conf/import_results.jsp new file mode 100644 index 0000000..ab989e5 --- /dev/null +++ b/web/format/conf/import_results.jsp @@ -0,0 +1,48 @@ +<%-- + 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) 2004 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + + Contributor(s): +--%> +<%@ page import = "java.util.*" %> +<%@ page import = "com.silverwrist.venice.core.*" %> +<%@ page import = "com.silverwrist.venice.ui.conf.CurrentConference" %> +<%@ page import = "com.silverwrist.venice.ui.view.JSPView" %> +<%@ taglib uri="/tlds/util" prefix="util" %> +<%@ taglib uri="/tlds/community" prefix="comm" %> +<%@ taglib uri="/tlds/conference" prefix="conf" %> +<% + JSPView view = JSPView.get(request); + List msgs = (List)(view.getRequestAttribute("output.list")); +%> +Import Messages - Results + + Results of Import + to Conference: + + +
+ + conf/manage_conf.js.vs?cc=&conf= + Return to Manage Conference Menu +

+ <% if (msgs.isEmpty()) { %> + No error messages from import. + <% } else { %> + <% for (Iterator it=msgs.iterator(); it.hasNext(); ) { %> + <% String s = (String)(it.next()); %> + <%= s %>
+ <% } // end for %> + <% } // end if %> +

diff --git a/web/images/classic/export.jpg b/web/images/classic/export.jpg new file mode 100644 index 0000000..611c6a8 Binary files /dev/null and b/web/images/classic/export.jpg differ diff --git a/web/images/classic/import.jpg b/web/images/classic/import.jpg new file mode 100644 index 0000000..6324dc0 Binary files /dev/null and b/web/images/classic/import.jpg differ diff --git a/web/images/gelcap/export.jpg b/web/images/gelcap/export.jpg new file mode 100644 index 0000000..5c84e5e Binary files /dev/null and b/web/images/gelcap/export.jpg differ diff --git a/web/images/gelcap/import.jpg b/web/images/gelcap/import.jpg new file mode 100644 index 0000000..8d12ff0 Binary files /dev/null and b/web/images/gelcap/import.jpg differ