package yoonforh.bbs; /** * BBSUtil.java * Copyright (c) 1997-1998 Yoon Kyung Koo. All rights reserved. * * contact via yoonforh@moon.daewoo.co.kr * * first release (ver. 0.01) date 1997/10/07 * * @version 1.2a 1998/06/04 * @author Yoon Kyung Koo */ import java.io.*; import java.util.*; import java.text.*; import java.net.*; import javax.servlet.*; import javax.servlet.http.*; /** * BBSUtil class * This class holds several information about this service-specific path names * and several common methods. */ class BBSUtil { /* these values can be initialized from init parameter of servlet */ private static String dataDir="C:/bbs_data/"; private static String masterKey="password"; /* these values are fixed for convenience */ private static final String printURL="/servlet/BBSPrint"; // yoonforh.bbs.PrintServlet private static final String listURL="/servlet/BBSList"; // yoonforh.bbs.ListServlet private static final String editURL="/servlet/BBSEdit"; // yoonforh.bbs.EditServlet private static final String editResultURL="/servlet/BBSEditResult"; // yoonforh.bbs.EditResultServlet private static final String adminEditURL="/servlet/BBSAdminEdit"; // yoonforh.bbs.AdminEditServlet private static final String adminEditChallengeURL="/servlet/BBSAdminEditChallenge"; // yoonforh.bbs.AdminEditChallengeServlet private static final String adminEditResultURL="/servlet/BBSAdminEditResult"; // yoonforh.bbs.AdminEditResultServlet private static final String deleteURL="/servlet/BBSDelete"; // yoonforh.bbs.DeleteServlet private static final String deleteResultURL="/servlet/BBSDeleteResult"; // yoonforh.bbs.DeleteResultServlet private static final String postURL="/servlet/BBSPost"; // yoonforh.bbs.PostServlet private static final String postResultURL="/servlet/BBSPostResult"; // yoonforh.bbs.PostResultServlet private static final String homeURL="/bbs"; // root home directory private static final String homeImageURL="/images/home.jpg"; private static final String docuImageURL="/images/document.gif"; // prefer transparent gif private static final String threadImageURL="/images/thread.gif"; // prefer transparent gif private static final String bodyStatement="
"; private static final String countFile="BBS_counter"; /** * setInitParameters() * this method set init parameters * @param String dataDir root directory to save data * @param String masterKey master password */ static void setInitParameters(String dataDir, String masterKey) { if (dataDir!=null) BBSUtil.dataDir=dataDir; if (masterKey!=null) BBSUtil.masterKey=masterKey; } /** * getCount() * this method returns current number of data files * @param String category to specify bbs * @return current number of data files(articles) * @exception java.io.IOException */ private synchronized static int getCount(String category) throws IOException { int count; RandomAccessFile file=new RandomAccessFile(new File(dataDir+category+"/"+countFile), "rw"); try { file.seek(0); // set file pointer to beginning try { count=file.readInt(); } catch (IOException ie) { // case no data try { file.writeInt(0); count=0; } catch (IOException ie2) { throw ie2; } } } finally { file.close(); } return count; } // end of getCount() /** * addCount() * this method increases current number of data files * @param String category to specify bbs * @exception java.io.IOException */ private synchronized static void addCount(String category) throws IOException { int count; RandomAccessFile file=new RandomAccessFile(new File(dataDir+category+"/"+countFile), "rw"); try { file.seek(0); // set file pointer to beginning try { count=file.readInt(); } catch (IOException ie) { // case no data try { file.writeInt(0); count=0; } catch (IOException ie2) { throw ie2; } } count++; file.seek(0); // set file pointer to beginning file.writeInt(count); } finally { file.close(); } } // end of addCount() /** * addNextNumber() * this method add a number to prev article's next numbers * @param String category to specify bbs * @param int prev article number * @param int new article number * @return boolean if succeed then true, else false * @see yoonforh.bbs.BBSData * @exception java.io.IOException */ synchronized static boolean addNextNumber(String category, int prevNo, int newNo) throws IOException { BBSData data=null; String fileName=dataDir+category+"/"+prevNo+".dat"; try { data=readData(category, prevNo); } catch (IOException ie) { return false; } if (data==null) return false; data.nextNumbers.addElement(new Integer(newNo)); if (!replaceData(category, data)) return false; return true; } // end of addNextNumber /** * writeData() * this method writes data object into specified file * @param String category to specify bbs * @param BBSData data file to write into file * @return numbers of current articles * @see yoonforh.bbs.BBSData * @exception java.io.IOException */ synchronized static int writeData(String category, BBSData data) throws IOException { // serializing String fileName=null; int count=0; count=getCount(category) + 1; fileName=dataDir+category+"/"+count+".dat"; FileOutputStream f_out=new FileOutputStream(fileName); ObjectOutput s_out=new ObjectOutputStream(f_out); data.articleNo=count; try { /* update previous data's nextNumbers */ if (data.prevNo>0) addNextNumber(category, data.prevNo, data.articleNo); s_out.writeObject(data); s_out.flush(); } finally { s_out.close(); f_out.close(); } addCount(category); return count; } // end of writeData() /** * updateDataWithAuth() * this method writes data object into specified file * @param String category to specify bbs * @param BBSData data file to write into file * @return boolean if succeed then true, else if password mismatch then false * @see yoonforh.bbs.BBSData * @exception java.io.IOException */ private synchronized static boolean updateDataWithAuth(String category, BBSData data) throws IOException { int count=data.articleNo; String fileName=dataDir+category+"/"+count+".dat"; BBSData oldData=readData(category, count); if (!data.passwd.equals(oldData.passwd) && !data.passwd.equals(masterKey)) return false; if (data.passwd.equals(masterKey)) // when masterKey used, clear password data.passwd=null; FileOutputStream f_out=new FileOutputStream(fileName); ObjectOutput s_out=new ObjectOutputStream(f_out); try { s_out.writeObject(data); s_out.flush(); } finally { s_out.close(); f_out.close(); } return true; } // end of updateDataWithAuth() /** * replaceData() * this method simply overwrites an existing file with specified data * @param String category to specify bbs * @param BBSData data file to write into file * @return boolean if succeed then true, else if password mismatch then false * @see yoonforh.bbs.BBSData * @exception java.io.IOException */ private synchronized static boolean replaceData(String category, BBSData data) throws IOException { int count=data.articleNo; String fileName=dataDir+category+"/"+count+".dat"; FileOutputStream f_out=new FileOutputStream(fileName); ObjectOutput s_out=new ObjectOutputStream(f_out); try { s_out.writeObject(data); s_out.flush(); } finally { s_out.close(); f_out.close(); } return true; } // end of replaceData() /** * removeData() * this method deletes data object file * @param String category to specify bbs * @param number article number to delete * @return boolean if succeed to delete file then true, otherwise false */ private synchronized static boolean removeData(String category, int number) { String fileName=null; BBSData data=null; try { data=readData(category, number); } catch (IOException ie) {} if (data == null) return false; /* if child data exist ... */ if (data.nextNumbers !=null && !data.nextNumbers.isEmpty()) { for (Enumeration enum = data.nextNumbers.elements(); enum.hasMoreElements(); ) { int nextNo=((Integer) enum.nextElement()).intValue(); try { BBSData nextData=readData(category, nextNo); if (nextData==null) continue; nextData.prevNo=data.prevNo; // replace next data's prev number with data's prev number replaceData(category, nextData); } catch (IOException ie) {} // ignore update-next-file error } } /* if parent data exist ... */ if (data.prevNo>0) { try { BBSData prevData=readData(category, data.prevNo); if (prevData!=null && prevData.nextNumbers!=null && !prevData.nextNumbers.isEmpty() ) // NOTE: removeElement() finds the object using equals() method if (prevData.nextNumbers.removeElement(new Integer(number))) { /* add next elements to prev data */ /* if child data exist ... */ if (data.nextNumbers !=null && !data.nextNumbers.isEmpty()) { for (Enumeration enum = data.nextNumbers.elements(); enum.hasMoreElements(); ) { prevData.nextNumbers.addElement((Integer) enum.nextElement()); } } replaceData(category, prevData); } } catch (IOException ie) {} // ignore update-prev-file error } fileName=dataDir+category+"/"+number+".dat"; File file=new File(fileName); return file.delete(); } // end of removeData() /** * getGetData() * this method read data object from POST/GET request * @param HttpServletRequest req stream to read * @param boolean isForUpdate specify if this is for update procedure * @return BBSData object read from stream * @see yoonforh.bbs.BBSData * @exception java.io.IOException */ static BBSData getGetData(HttpServletRequest req, boolean isForUpdate) throws ServletException, IOException { BBSData data=null; if (isForUpdate) { String category=req.getParameter("cate"); int articleNo=-1; try { articleNo=Integer.parseInt(req.getParameter("number")); } catch (NumberFormatException nfe) {} data=readData(category, articleNo); } else data=new BBSData(); data.name=req.getParameter("NAME_FIELD"); data.passwd=req.getParameter("PASSWORD_FIELD"); String string=req.getParameter("WEB_FIELD"); if (string.equals("")) { data.webAddress=null; } else { try { data.webAddress=new URL(string); } catch (MalformedURLException me) { try { data.webAddress=new URL("http://"+string); } catch (MalformedURLException me2) { data.webAddress=null; } } } string=req.getParameter("EMAIL_FIELD"); if (string.equals("")) { data.emailAddress=null; } else { try { data.emailAddress=new URL(req.getParameter("EMAIL_FIELD")); } catch (MalformedURLException me) { try { data.emailAddress=new URL("mailto:"+req.getParameter("EMAIL_FIELD")); } catch (MalformedURLException me2) { data.emailAddress=null; } } } data.title=req.getParameter("TITLE_FIELD"); data.data=req.getParameter("COMMENT_FIELD"); data.logDate=new Date(System.currentTimeMillis()); String replyTo=req.getParameter("replyto"); try { data.prevNo=(replyTo==null?-1:Integer.parseInt(replyTo)); } catch (NumberFormatException nfe) {} return data; } // end of getGetData() /** * getGetData() * this method read data object from POST/GET request to show article * @param HttpServletRequest req stream to read * @return BBSData object read from stream * @see yoonforh.bbs.BBSData * @exception java.io.IOException */ static BBSData getGetData(HttpServletRequest req) throws ServletException, IOException { return getGetData(req, false); } /** * getGetDataForUpdate() * this method read data object from POST/GET request for update * @param HttpServletRequest req stream to read * @return BBSData object read from stream * @see yoonforh.bbs.BBSData * @exception java.io.IOException */ static BBSData getGetDataForUpdate(HttpServletRequest req) throws ServletException, IOException { return getGetData(req, true); } /** * getAdminGetData() * this method read data object from POST/GET request for adminer's article edit * @param HttpServletRequest req stream to read * @return BBSData object read from stream * @see yoonforh.bbs.BBSData * @exception java.io.IOException */ static BBSData getAdminGetData(HttpServletRequest req) throws ServletException, IOException { BBSData data=getGetData(req, true); String replyTo=req.getParameter("replyto"); try { data.prevNo=(replyTo==null?-1:Integer.parseInt(replyTo)); } catch (NumberFormatException nfe) {} String nexts=req.getParameter("nexts"); if (nexts != null) { data.nextNumbers.removeAllElements(); StringTokenizer token = new StringTokenizer(nexts, ","); while (token.hasMoreTokens()) { try { String nextNo = token.nextToken(); data.nextNumbers.addElement(new Integer(nextNo)); } catch (NumberFormatException nfe) {} } } else data.nextNumbers=null; return data; } /** * readData() * this method read data object * @param String category to specify bbs * @param count specify which file (nth article) to read * @return BBSData object read from data file * @see yoonforh.bbs.BBSData * @exception java.io.IOException */ static BBSData readData(String category, int count) throws IOException { // de-serialize BBSData data=null; boolean isAccurateNumber=true; if (count<0) { // -1 means last article count=getCount(category); isAccurateNumber=false; } String fileName=dataDir+category+"/"+count+".dat"; FileInputStream f_in=null; boolean notFound=true; while (notFound) { try { f_in=new FileInputStream(fileName); } catch (FileNotFoundException fe) { if (isAccurateNumber) return null; count-=1; if (count<=0) return null; fileName=dataDir+category+"/"+count+".dat"; continue; } notFound=false; } ObjectInput s_in=new ObjectInputStream(f_in); try { data=(BBSData) s_in.readObject(); } catch (ClassNotFoundException cnfe) { data=null; } finally { s_in.close(); f_in.close(); } return data; } // end of readData() /** * readPrevArticle() * this method read data objects * @param String category to specify bbs * @param articleNo specify from which file (nth article) to read * @param nItems specify number of file to read * @return Vector of BBSData objects * @see yoonforh.bbs.BBSData */ private static Vector readPrevArticle(String category, int articleNo, int nItems) { BBSData data=null; Vector vector = new Vector(); int count=0; for (int i=0; (count"+convertToASCII("¾Õ ±Û")+" | ||||||
"); out.println(" | "+data.articleNo+" | "); if (data.webAddress!=null) { out.print(""); printLink(out, data.name, data.webAddress.toString()); out.println(" | "); } else if (data.emailAddress!=null) { out.print(""); printLink(out, data.name, data.emailAddress.toString()); out.println(" | "); } else out.println(""+data.name+" | "); out.println(""+convertToASCII(formatDateSimple(data.logDate))+" | "); out.print(""); printLink(out, data.title, printURL+"?cate="+category+"&number="+data.articleNo); out.println(" | "); out.println("
"+convertToASCII("´ÙÀ½ ±Û")+" | ||||||
"); out.println(" | "+data.articleNo+" | "); if (data.webAddress!=null) { out.print(""); printLink(out, data.name, data.webAddress.toString()); out.println(" | "); } else if (data.emailAddress!=null) { out.print(""); printLink(out, data.name, data.emailAddress.toString()); out.println(" | "); } else out.println(""+data.name+" | "); out.println(""+convertToASCII(formatDateSimple(data.logDate))+" | "); out.print(""); printLink(out, data.title, printURL+"?cate="+category+"&number="+data.articleNo); out.println(" | "); out.println("
"); printLink(out, convertToASCII("ÀÌ¾î¼ ±Û ¾²±â"), postURL+"?cate="+category+"&replyto="+articleNo); out.print(" - "); printLink(out, convertToASCII("¸ñ·Ï º¸±â"), listURL+"?cate="+category+"&start="+(articleNo+9)+"&dir=-1"); out.print(" - "); printLink(out, convertToASCII("»õ±Û ¾²±â"), postURL+"?cate="+category); out.print(" - "); printLink(out, convertToASCII("°íÄ¡±â"), editURL+"?cate="+category+"&number="+articleNo); out.print(" - "); printLink(out, convertToASCII("Áö¿ì±â"), deleteURL+"?cate="+category+"&number="+articleNo); out.println(""); out.println(" |
"); printLink(out, "", homeURL+"/"+category); out.println(" |
"); printLink(out, convertToASCII("ÀÌÀü ¸ñ·Ï º¸±â"), listURL+"?cate="+category+"&start="+beginIndex+"&dir=-1"); out.print(" - "); printLink(out, convertToASCII("´ÙÀ½ ¸ñ·Ï º¸±â"), listURL+"?cate="+category+"&start="+endIndex+"&dir=1"); out.print(" - "); printLink(out, convertToASCII("»õ±Û ¾²±â"), postURL+"?cate="+category); out.println(" |
"); printLink(out, "", homeURL+"/"+category); out.println(" |
"); printLink(out, convertToASCII("Àüü ȨÆäÀÌÁö·Î À̵¿"), homeURL); out.println(" |