372 lines
10 KiB
Java
372 lines
10 KiB
Java
|
/*
|
||
|
* 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 <http://www.mozilla.org/MPL/>.
|
||
|
*
|
||
|
* 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 Community System.
|
||
|
*
|
||
|
* The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
|
||
|
* 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):
|
||
|
*/
|
||
|
package com.silverwrist.venice.db;
|
||
|
|
||
|
import java.sql.*;
|
||
|
import com.silverwrist.util.StringUtil;
|
||
|
import com.silverwrist.venice.ValidationException;
|
||
|
import com.silverwrist.venice.core.IDUtils;
|
||
|
|
||
|
public class PostLinkDecoder
|
||
|
{
|
||
|
/*--------------------------------------------------------------------------------
|
||
|
* Static data members
|
||
|
*--------------------------------------------------------------------------------
|
||
|
*/
|
||
|
|
||
|
private static final int MAX_LINK_LEN = 130;
|
||
|
private static final int MAX_SIG_LEN = 32;
|
||
|
private static final int MAX_CONF_LEN = 64;
|
||
|
|
||
|
/*--------------------------------------------------------------------------------
|
||
|
* Attributes
|
||
|
*--------------------------------------------------------------------------------
|
||
|
*/
|
||
|
|
||
|
private String signame = null;
|
||
|
private String confname = null;
|
||
|
private short topicnum = -1;
|
||
|
private int first_post = -1;
|
||
|
private int last_post = -1;
|
||
|
|
||
|
/*--------------------------------------------------------------------------------
|
||
|
* Constructor
|
||
|
*--------------------------------------------------------------------------------
|
||
|
*/
|
||
|
|
||
|
public PostLinkDecoder(String data) throws ValidationException
|
||
|
{
|
||
|
if (StringUtil.isStringEmpty(data))
|
||
|
throw new ValidationException("empty string");
|
||
|
if (data.length()>MAX_LINK_LEN)
|
||
|
throw new ValidationException("post link string too long");
|
||
|
|
||
|
// turn the data into a StringBuffer so we can parse it
|
||
|
StringBuffer work = new StringBuffer(data);
|
||
|
|
||
|
// First Test: Bang
|
||
|
int pos = work.toString().indexOf('!');
|
||
|
if (pos>0)
|
||
|
{ // We have "sig!something" ... store off the SIG name
|
||
|
setSIGName(work.substring(0,pos));
|
||
|
work.delete(0,pos+1);
|
||
|
if (work.length()==0)
|
||
|
return; // we had just "sig!" - that's the syntax for a SIG link
|
||
|
|
||
|
} // end if
|
||
|
else if (pos==0)
|
||
|
throw new ValidationException("! at beginning of string");
|
||
|
|
||
|
// Second Test: Dot Number One
|
||
|
pos = work.toString().indexOf('.');
|
||
|
if (pos<0)
|
||
|
{ // there's no dots in here...this must have been either "postlink" or "sig!conference"
|
||
|
if (signame!=null) // it's "sig!conference"
|
||
|
setConferenceName(work.toString());
|
||
|
else // it's "postlink"
|
||
|
setPostRange(work);
|
||
|
return;
|
||
|
|
||
|
} // end if
|
||
|
else if (pos==0)
|
||
|
throw new ValidationException(". at beginning of string");
|
||
|
|
||
|
// Peel off the initial substring.
|
||
|
String conf_or_topic = work.substring(0,pos);
|
||
|
work.delete(0,pos+1);
|
||
|
|
||
|
if (work.length()==0)
|
||
|
{ // we had "conference." or "topic." (or perhaps "sig!conference.")
|
||
|
if (signame==null)
|
||
|
{ // it's either "conference." or "topic." - try topic first
|
||
|
try
|
||
|
{ // try it as a topic number first...
|
||
|
setTopicNumber(conf_or_topic);
|
||
|
|
||
|
} // end try
|
||
|
catch (ValidationException ve)
|
||
|
{ // it's not a topic number - try it as a conference name!
|
||
|
setConferenceName(conf_or_topic);
|
||
|
|
||
|
} // end catch
|
||
|
|
||
|
} // end if
|
||
|
else // it was "sig!conference."...save it off
|
||
|
setConferenceName(conf_or_topic);
|
||
|
|
||
|
return; // all done here...
|
||
|
|
||
|
} // end if
|
||
|
|
||
|
// Third Test: Dot Number Two
|
||
|
pos = work.toString().indexOf('.');
|
||
|
if (pos<0)
|
||
|
{ // we had "conference.topic" or "topic.posts" (or perhaps "sig!conference.topic")
|
||
|
if (signame==null)
|
||
|
{ // we have "conference.topic" or "topic.posts" - have to determine this
|
||
|
boolean is_topic = false; // what does "work" currently hold?
|
||
|
try
|
||
|
{ // try the "topic.posts" possibility first...
|
||
|
setTopicNumber(conf_or_topic);
|
||
|
|
||
|
} // end try
|
||
|
catch (ValidationException ve)
|
||
|
{ // nope, it's gotta be "conference.topic"
|
||
|
setConferenceName(conf_or_topic);
|
||
|
is_topic = true;
|
||
|
|
||
|
} // end if
|
||
|
|
||
|
// complete the parsing here
|
||
|
if (is_topic)
|
||
|
setTopicNumber(work.toString());
|
||
|
else
|
||
|
setPostRange(work);
|
||
|
|
||
|
} // end if
|
||
|
else
|
||
|
{ // it's "sig!conference.topic"...set 'em up accordingly
|
||
|
setConferenceName(conf_or_topic);
|
||
|
setTopicNumber(work.toString());
|
||
|
|
||
|
} // end else
|
||
|
|
||
|
return; // all done
|
||
|
|
||
|
} // end if
|
||
|
else if (pos==0)
|
||
|
throw new ValidationException(". at beginning of string");
|
||
|
|
||
|
// We definitely have "conference.topic.something" (or "sig!conference.topic.sonething") now,
|
||
|
// so save off the conference name and topic number.
|
||
|
setConferenceName(conf_or_topic);
|
||
|
setTopicNumber(work.substring(0,pos));
|
||
|
work.delete(0,pos+1);
|
||
|
|
||
|
if (work.length()==0)
|
||
|
return; // we just had "conference.topic." or "sig!conference.topic.", which is valid
|
||
|
|
||
|
setPostRange(work); // the rest must be the post range!
|
||
|
|
||
|
} // end constructor
|
||
|
|
||
|
/*--------------------------------------------------------------------------------
|
||
|
* Internal functions
|
||
|
*--------------------------------------------------------------------------------
|
||
|
*/
|
||
|
|
||
|
private static boolean isAllDigits(String str)
|
||
|
{
|
||
|
for (int i=0; i<str.length(); i++)
|
||
|
{ // if any character is not a digit, bail out!
|
||
|
if (!(Character.isDigit(str.charAt(i))))
|
||
|
return false;
|
||
|
|
||
|
} // end for
|
||
|
|
||
|
return true;
|
||
|
|
||
|
} // end isAllDigits
|
||
|
|
||
|
private void setSIGName(String name) throws ValidationException
|
||
|
{
|
||
|
if (name.length()>MAX_SIG_LEN)
|
||
|
throw new ValidationException("SIG alias is too long");
|
||
|
if (!(IDUtils.isValidVeniceID(name)))
|
||
|
throw new ValidationException("SIG alias is not a valid Venice identifier");
|
||
|
signame = name;
|
||
|
|
||
|
} // end setSIGName
|
||
|
|
||
|
private void setConferenceName(String name) throws ValidationException
|
||
|
{
|
||
|
if (name.length()>MAX_CONF_LEN)
|
||
|
throw new ValidationException("conference alias is too long");
|
||
|
if (!(IDUtils.isValidVeniceID(name)))
|
||
|
throw new ValidationException("conference alias is not a valid Venice identifier");
|
||
|
confname = name;
|
||
|
|
||
|
} // end setConferenceName
|
||
|
|
||
|
private void setTopicNumber(String val) throws ValidationException
|
||
|
{
|
||
|
if (!isAllDigits(val))
|
||
|
throw new ValidationException("invalid topic number reference");
|
||
|
short temp_val;
|
||
|
try
|
||
|
{ // parse the temp value
|
||
|
temp_val = Short.parseShort(val);
|
||
|
|
||
|
} // end try
|
||
|
catch (NumberFormatException nfe)
|
||
|
{ // if there's a validation exception, it goes here
|
||
|
throw new ValidationException("invalid topic number reference");
|
||
|
|
||
|
} // end catch
|
||
|
|
||
|
topicnum = temp_val;
|
||
|
|
||
|
} // end setTopicNumber
|
||
|
|
||
|
private void setPostRange(StringBuffer buf) throws ValidationException
|
||
|
{
|
||
|
int pos = buf.toString().indexOf('-');
|
||
|
String temp = null;
|
||
|
int temp_val = -1;
|
||
|
if (pos>0)
|
||
|
{ // we've got "temp-something" here...make sure "temp" is a valid post number
|
||
|
temp = buf.substring(0,pos);
|
||
|
buf.delete(0,pos+1);
|
||
|
if (!isAllDigits(temp))
|
||
|
throw new ValidationException("invalid post number reference");
|
||
|
try
|
||
|
{ // parse the temp value
|
||
|
temp_val = Integer.parseInt(temp);
|
||
|
|
||
|
} // end try
|
||
|
catch (NumberFormatException nfe)
|
||
|
{ // if there's a validation exception, it goes here
|
||
|
throw new ValidationException("invalid post number reference");
|
||
|
|
||
|
} // end catch
|
||
|
|
||
|
if (buf.length()==0)
|
||
|
{ // we just had "first-"...set it up
|
||
|
first_post = temp_val;
|
||
|
last_post = -1;
|
||
|
return;
|
||
|
|
||
|
} // end if
|
||
|
|
||
|
} // end if
|
||
|
else if (pos==0)
|
||
|
throw new ValidationException("- at beginning of post range");
|
||
|
|
||
|
// the remaining string must be all digits at this point
|
||
|
if (!isAllDigits(buf.toString()))
|
||
|
throw new ValidationException("invalid post number reference");
|
||
|
try
|
||
|
{ // parse the first value
|
||
|
first_post = Integer.parseInt(buf.toString());
|
||
|
|
||
|
} // end try
|
||
|
catch (NumberFormatException nfe)
|
||
|
{ // if there's a validation exception, it goes here
|
||
|
throw new ValidationException("invalid post number reference");
|
||
|
|
||
|
} // end catch
|
||
|
|
||
|
if (temp!=null)
|
||
|
{ // we converted a "temp_val" above - include it
|
||
|
if (temp_val<first_post)
|
||
|
{ // put the "temp_val" up front
|
||
|
last_post = first_post;
|
||
|
first_post = temp_val;
|
||
|
|
||
|
} // end if
|
||
|
else // reverse order - arrange them correctly
|
||
|
last_post = temp_val;
|
||
|
|
||
|
} // end if
|
||
|
else // we have a "range" of one post
|
||
|
last_post = first_post;
|
||
|
|
||
|
} // end setPostRange
|
||
|
|
||
|
/*--------------------------------------------------------------------------------
|
||
|
* External operations
|
||
|
*--------------------------------------------------------------------------------
|
||
|
*/
|
||
|
|
||
|
public String getSIG()
|
||
|
{
|
||
|
return signame;
|
||
|
|
||
|
} // end getSIG
|
||
|
|
||
|
public String getConference()
|
||
|
{
|
||
|
return confname;
|
||
|
|
||
|
} // end getConference
|
||
|
|
||
|
public short getTopic()
|
||
|
{
|
||
|
return topicnum;
|
||
|
|
||
|
} // end getTopic
|
||
|
|
||
|
public int getFirstPost()
|
||
|
{
|
||
|
return first_post;
|
||
|
|
||
|
} // end getFirstPost
|
||
|
|
||
|
public int getLastPost()
|
||
|
{
|
||
|
return last_post;
|
||
|
|
||
|
} // end getFirstPost
|
||
|
|
||
|
public boolean needDatabaseVerification()
|
||
|
{
|
||
|
return ((signame!=null) || (confname!=null));
|
||
|
|
||
|
} // end needDatabaseVerification
|
||
|
|
||
|
public void verifyNames(Connection conn) throws ValidationException
|
||
|
{
|
||
|
try
|
||
|
{ // do the necessary database stuff
|
||
|
Statement stmt = conn.createStatement();
|
||
|
StringBuffer sql = new StringBuffer();
|
||
|
ResultSet rs;
|
||
|
|
||
|
if (signame!=null)
|
||
|
{ // verify the SIG name against the database
|
||
|
sql.append("SELECT sigid FROM sigs WHERE alias = '").append(SQLUtil.encodeString(signame));
|
||
|
sql.append("';");
|
||
|
rs = stmt.executeQuery(sql.toString());
|
||
|
if (!(rs.next()))
|
||
|
throw new ValidationException("SIG alias not found");
|
||
|
sql.setLength(0);
|
||
|
|
||
|
} // end if
|
||
|
|
||
|
if (confname!=null)
|
||
|
{ // verify the conference name against the database
|
||
|
sql.append("SELECT confid FROM confalias WHERE alias = '").append(SQLUtil.encodeString(confname));
|
||
|
sql.append("';");
|
||
|
rs = stmt.executeQuery(sql.toString());
|
||
|
if (!(rs.next()))
|
||
|
throw new ValidationException("conference alias not found");
|
||
|
|
||
|
} // end if
|
||
|
|
||
|
} // end try
|
||
|
catch (SQLException e)
|
||
|
{ // database error verifying stuff!
|
||
|
throw new ValidationException("unable to verify names in post link");
|
||
|
|
||
|
} // end catch
|
||
|
|
||
|
} // end verifyNames
|
||
|
|
||
|
} // end class PostLinkDecoder
|
||
|
|