[Logo]
Messages posted by: andowson
Forum Index » Profile for andowson » Messages posted by andowson
Message
「發文時啟用圖形識別確認」目前無法在Control Panel內設定,但JForum 2.1.8已內建這個功能,只是預設是關閉而已。故我們只需手動修改設定檔,不需另外開發程式。
修改方法是請在JForum安裝目錄下的WEB-INF/config/jforum-custom.conf中新增下列設定參數即可:
captcha.posts=true
captcha.ignore.case = true
captcha.min.words = 4
captcha.max.words = 5

又,有關JForum的使用問題請盡量發表在JForum中文社群版面上,以便日後參考,謝謝!
FTPS(FTP Secure or FTP over SSL/TLS)

預先安裝函式庫:ftp4che, log4j
程式碼:
ftp4che.jsp:
<%@ page import="java.io.File"%>
<%@ page import="java.io.IOException"%>
<%@ page import="org.ftp4che.*"%>
<%@ page import="org.ftp4che.util.ftpfile.*"%>
<%@ page import="org.ftp4che.exception.*"%> 
<%@ page import="org.ftp4che.impl.SecureFTPConnection"%>
<%
	String server = "192.168.1.2";
	String username = "andowson";
	String password = "changeit";
	String directory = "download";
	String filename = "C:\\Users\\Andowson\\Desktop\\jspSmartUpload.zip";
	File filePut = new File(filename);
	String filename2 = "C:\\Users\\Andowson\\Desktop\\commons-net-1.4.1.zip";
	File fileGet = new File(filename2);
	String filename3 = "jdk-6u3-windows-i586-p.exe";
	
	FTPConnection ftp = null;
	try {
		ftp = FTPConnectionFactory.getInstance(server, 21, username, password, FTPConnection.AUTH_TLS_FTP_CONNECTION, true);
        ftp.connect();
		System.out.println("Connected to " + server + ".");
		
		// transfer files
		long totalSize = 0L;
		for (FTPFile file : ftp.getDirectoryListing(directory)) {
			System.out.printf("%s %s [%d bytes]\n",
					(file.isDirectory() ? "[D]" : "   "), file.getName(), file.getSize());
			if (!file.isDirectory()) {
				totalSize += file.getSize();
			} 
		}			
		System.out.println("totalSize = " + totalSize/(1024 * 1024) + "MB");
		
		// PASV
		ftp.setPassiveMode(true);
		// CWD
		ftp.changeDirectory(directory);
		// PWD
		System.out.println(ftp.getWorkDirectory());		
		// PUT
		FTPFile fromFile = new FTPFile(filePut);
		FTPFile toFile = new FTPFile(new File(filePut.getName()));
		ftp.uploadFile(fromFile, toFile);
		// GET
		fromFile = new FTPFile(new File(fileGet.getName()));
		toFile = new FTPFile(fileGet);
		ftp.downloadFile(fromFile, toFile);
		// DELE
		ftp.deleteFile(new FTPFile(new File(filename3)));
	} catch (NotConnectedException nce) {
		nce.printStackTrace();
	} catch (FtpFileNotFoundException ffnfe) {
		ffnfe.printStackTrace();
	} catch (IOException e) {
		e.printStackTrace();
	} finally {
		if (ftp != null) {
			ftp.disconnect();
		}
	}
%>

備註:
最近找到了支援FTPS的免費Java FTP Library(採用LGPL授權) -- ftp4che,將原先的程式碼略微修改一下,搭配FileZilla Server測試一下,可以成功執行。
參考資料:
http://www.javaworld.com.tw/jute/post/view?bid=11&id=237813&sty=3
增加檔案大小限制及檔案類型的篩選:
程式碼:
fileupload_control.html:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>File Upload</title>
<style type="text/css">
<!--
.topic {color: #FF0000; font-size: 1.5em; font-weight: bold}
-->
</style>
</head>
<body>
<p class="topic">檔案上傳</p>

<form name="upload" enctype="multipart/form-data" method="post" action="fileupload_control.jsp"> 
<p>上傳檔案: <input type="file" name="file" size="20" maxlength="20" /> </p>
<p>檔案說明: <input type="text" name="filedesc" size="30" maxlength="50" /> </p>
<p> <input type="submit"value="上傳" /> <input type="reset" value="清除" /> </p>
</form>

</body>
</html>


fileupload_control.jsp:
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page import="java.io.File"%>
<%@ page import="java.util.Iterator"%>
<%@ page import="java.util.List"%>
<%@ page import="org.apache.commons.fileupload.*"%>
<%@ page import="org.apache.commons.fileupload.disk.DiskFileItemFactory"%>
<%@ page import="org.apache.commons.fileupload.servlet.ServletFileUpload"%>
<%@ page import="org.apache.commons.io.FilenameUtils"%>
<%!
    int yourMaxMemorySize = 1024 * 1024 * 1024;
	File yourTempDirectory = new File("/tmp");
	int yourMaxRequestSize = 100 * 1024 * 1024;
	boolean writeToFile = true;
	String allowedFileTypes = ".txt .pdf .doc .ppt .xls .csv .dbf .gif .jpg .jpeg .png .swf .htm .html .zip .rar";
%>
<%
	String saveDirectory = application.getRealPath("/upload");

	// Check that we have a file upload request
	boolean isMultipart = ServletFileUpload.isMultipartContent(request);
	out.println("isMultipart=" + isMultipart + "<br>");

	// Create a factory for disk-based file items
	DiskFileItemFactory factory = new DiskFileItemFactory(yourMaxMemorySize, yourTempDirectory);
	
	// Create a new file upload handler
	ServletFileUpload upload = new ServletFileUpload(factory);

	// Set overall request size constraint
	upload.setSizeMax(yourMaxRequestSize);

	//Create a progress listener
	ProgressListener progressListener = new ProgressListener() {
		private long megaBytes = -1;

		public void update(long pBytesRead, long pContentLength, int pItems) {
			long mBytes = pBytesRead / 1000000;
			if (megaBytes == mBytes) {
				return;
			}
			megaBytes = mBytes;
			System.out.println("We are currently reading item "	+ pItems);
			if (pContentLength == -1) {
				System.out.println("So far, " + pBytesRead	+ " bytes have been read.");
			} else {
				System.out.println("So far, " + pBytesRead + " of "	+ pContentLength + " bytes have been read.");
			}
		}
	};
	upload.setProgressListener(progressListener);

	try {
		// Parse the request
		List /* FileItem */items = upload.parseRequest(request);

		// Process the uploaded items
		Iterator iter = items.iterator();
		while (iter.hasNext()) {
			FileItem item = (FileItem) iter.next();

			if (item.isFormField()) {
				// Process a regular form field	
				//processFormField(item);		
				String name = item.getFieldName();
				String value = item.getString("UTF-8");
				out.println(name + "=" + value + "<br />");
			} else {
				// Process a file upload
				//processUploadedFile(item);						
				String fieldName = item.getFieldName();
				String fileName = item.getName();
				String contentType = item.getContentType();
				boolean isInMemory = item.isInMemory();
				long sizeInBytes = item.getSize();
				out.println("fieldName=" + fieldName + "<br />");
				out.println("fileName=" + fileName + "<br />");
				out.println("contentType=" + contentType + "<br />");
				out.println("isInMemory=" + isInMemory + "<br />");
				out.println("sizeInBytes=" + sizeInBytes + "<br />");
				if (fileName != null && !"".equals(fileName)) {
					if (writeToFile) {
						fileName = FilenameUtils.getName(fileName);
						out.println("fileName to be saved=" + fileName + "<br />");
						String extension = FilenameUtils.getExtension(fileName);
						if (allowedFileTypes.indexOf(extension.toLowerCase()) != -1) {
						    File uploadedFile = new File(saveDirectory,	fileName);						
						    item.write(uploadedFile);
						} else {
							out.println("上傳的檔案不能是" + extension + "<br />");
						}
					} else {
						//InputStream uploadedStream = item.getInputStream();
						//...
						//uploadedStream.close();
						// Process a file upload in memory
						byte[] data = item.get();
						out.println("data size=" + data.length + "<br />");
					}
				}
			}
		}
	} catch (FileUploadBase.SizeLimitExceededException ex1) {
		out.println("上傳檔案超過最大檔案允許大小" + yourMaxRequestSize / (1024 * 1024) + "MB !");
	}
%>


另外需要在web.xml中加上下列設定:
<web-app>
  ...
  <listener>
    <listener-class>
      org.apache.commons.fileupload.servlet.FileCleanerCleanup
    </listener-class>
  </listener>
  ...
</web-app>

參考資料:
http://commons.apache.org/fileupload/using.html
1.新增分類或版面後必須再到群組設定權限才會看得到,這是預設的行為模式,避免誤開分類或版面。
2.在允許票選的版面內發表文章時會顯示三顆按鈕:選項,附加檔案,票選主題,按票選主題再把票選的項目填入即可。如果有票選主題進行中,則會顯示在最上方,每人只能單選投票一次。
3.版面管理員要先開一個版主群組,然後設定這個版主群組可以管理的版面,再將要擔任版主的會員加入到這個群組。如果您有三個版面甲、乙、丙,分別給A、B、C管理,則您需要開三個群組甲版主、乙版主、丙版主,然後將A設定到甲板主群組,B設定到乙版主群組,C設定到丙版主群組。
要設定某些版面必須經過審核後才能把文章顯示出來,可以設定一般群組內的權限為需審核才能顯示,一般使用者發表文章後不會立即顯示,會等候版主審核。該版面的版主登入後會看到上方有個待審核文章清單,版主可以選擇核准或拒絕,核准就會顯示出來,拒絕則該文章則被刪除。
管理日誌則可以設定要不要讓一般網友看到版主的管理行為,可分詳細或簡要兩種,詳細的會列出較多的內容,包含原因和文章內容等。

使用說明文件目前還沒有時間做,可能還是先請您參考一下原來網站上英文版的簡要說明或是在本站上發問。
英文的文件網址如下:
http://www.jforum.net/Wiki.jsp
一、報名日期:自即日起至 98 年 2 月 5 日(以郵戳為憑)。
二、面試日期:98 年 2 月 18 日 e-mail 通知書面審查合格者於 98 年 3 月 1 日(星期日)面試。

詳細資訊請見: http://www.cht.com.tw/CompanyCat.php?CatID=4&NewsID=1702&Page=HotNewsDetail
Tuning PostgreSQL for performance
http://www.varlena.com/GeneralBits/Tidbits/perf.html
Performance Tuning PostgreSQL
http://www.revsys.com/writings/postgresql-performance.html
5-Minute Introduction to PostgreSQL Performance
http://www.westnet.com/~gsmith/content/postgresql/pg-5minute.htm
原因是在原來的net.jforum.view.forum.SearchAction類別的buildSearchArgs() method裡request抓的參數名字是forum,而search.htm裡面表單的參數名稱是search_forum,兩者不一致的關係。

解決方法一是:
1.修改表單樣版檔<jforum_installed_path>/templates/default/search.htm

<select class="post" name="search_forum">
改為
<select class="post" name="forum">
2.修改分頁樣版檔<jforum_installed_path>/templates/macros/search_pagination.ftl
將第5行的參數
	<#if (searchArgs.forumId > 0)><#assign params = params +"&search_forum="+ searchArgs.forumId/></#if>

修改為
	<#if (searchArgs.forumId > 0)><#assign params = params +"&forum="+ searchArgs.forumId/></#if>


解決方法二是:
1.修改net/jforum/view/forum/SearchAction.java的buildSearchArgs() method內這幾行
		if (this.request.getParameter("forum") != null) {
			args.setForumId(this.request.getIntParameter("forum"));
		}



		if (this.request.getParameter("search_forum") != null && !"".equals(this.request.getParameter("search_forum"))) {
			args.setForumId(this.request.getIntParameter("search_forum"));
		}

2.修改<jforum_installed_path>/templates/default/forum_show.htm
將第66行的
<input type="hidden" name="forum" value="${forum.id}" />

修改為
<input type="hidden" name="search_forum" value="${forum.id}" />

3.重新載入JForum或重新啟動Tomcat

另外,如果文章有被搬移過版面,則雖然有指定版面但可能會被意外搜尋到,此時可以透過管理介面再重新完整重頭建立索引一次。
此時也意外發現之前v2.1.8漏翻譯了一個字串,可以將它加進去
en_US.properties:
SearchStats.informationUnavailable = Information unavailable at the moment

zh_TW.properties:
SearchStats.informationUnavailable = \u76EE\u524D\u7121\u6CD5\u5F97\u5230\u4EFB\u4F55\u8CC7\u8A0A
1.修改generic_queries.sql,加上KarmaModel.deletePostKarma
# ###########
# KarmaModel
# ###########
...
KarmaModel.deletePostKarma = DELETE FROM jforum_karma WHERE post_id = ?
...


2.修改net/jforum/dao/KarmaDao.java,加上deletePostKarma(int postId) method宣告
public interface KarmaDAO
{
...
	/**
	 * Deletes the karma belonging to some post.
	 * This method will remove the post's karma from the
	 * karma table. 
	 *  
	 * @param postId The id of the post to delete	 
	 */
	public void deletePostKarma(int postId) ;
...
}


3.修改net/jforum/dao/generic/GenericKarmaDao.java,加上deletePostKarma(int postId) method實做
public class GenericKarmaDAO implements net.jforum.dao.KarmaDAO
{
...
	/**
	 * @see net.jforum.dao.KarmaDAO#deletePostKarma(int)
	 */
	public void deletePostKarma(int postId)
	{
		PreparedStatement p = null;		
		try {
			p = JForumExecutionContext.getConnection()
					.prepareStatement(SystemGlobals.getSql("KarmaModel.deletePostKarma"));
			p.setInt(1, postId);
			p.executeUpdate();
		}
		catch (SQLException e) {
			throw new DatabaseException(e);
		}
		finally {
			DbUtils.close(p);
		}
	}
...


4.修改net/jforum/view/forum/PostAction.java,修改delete() method,在Karma處理部分插入karmaDao.deletePostKarma(p.getId());在重算Karma之前
public class PostAction extends Command 
{
...
	public void delete()
	{
                ...
		// Karma
		KarmaDAO karmaDao = DataAccessDriver.getInstance().newKarmaDAO();
		karmaDao.deletePostKarma(p.getId());
		karmaDao.updateUserKarma(p.getUserId());
                ...
	}
...
}


5.重新編譯,並重新載入JForum
一、報名日期:自 97.12.24 (星期三) 至 98.01.06 (星期二)中午 12 點止
二、第一試(資歷論文審查)日期:98.01.13 (星期二)至 98.01.15 (星期四)由數據分公司資歷審查小組上網遴選。
三、第二試通知日期:98.01.16 (星期五),以 Email 通知詳細口試時程及順序表,並請於收到 mail 後回覆是否參加。
四、第二試(口試)日期:98.01.20 (星期二)(若有異動,以通知變更日期為準)。
五、放榜日期:98.01.21 (星期三)下午(若有異動,以通知變更日期為準)。
詳細資訊請見: http://www.cht.com.tw/CompanyCat.php?CatID=533&NewsID=1669&Page=HotNewsDetail
因部分版面一直無人發文,故將其刪除,另部分版面僅有單獨一篇者合併至較適當版面,並新增一其他分區,新增一工作機會版面。
大家好,今天是網站成立兩週年的日子,去年的展望是
1.會員數成長到1000人,啟用率八成
2.發表文章數成長到500篇,發文率8%

先來檢視一下去年網站運作的成果:
1.會員數:
smilie 註冊會員數:1103(達成 smilie
select count(*) from jforum_users where user_regdate < to_date('2009-01-01', 'yyyy-mm-dd')

淨增數:680(1103-423)
成長率:60.76%((680-423)/423)
smilie 已啟用帳號數:832
select count(*) from jforum_users where user_actkey is null and user_regdate < to_date('2009-01-01', 'yyyy-mm-dd')

淨增數:530(832-302)
啟用率:75.43%(832/1103) (未達成 smilie

2.文章數:
發表文章數:450篇(未達成 smilie
select count(*) from jforum_posts where post_time < to_date('2009-01-01', 'yyyy-mm-dd')

淨增數:229(450-221)
成長率:3.62%((229-221)/221)
smilie 主題數:229
select count(*) from jforum_topics where topic_time < to_date('2009-01-01', 'yyyy-mm-dd')

淨增數:90(229-139)
成長率:-35.25%((90-139)/139)

3.發文狀況
smilie 發文人數:33
select count(*) from jforum_users where user_regdate < to_date('2009-01-01', 'yyyy-mm-dd') and user_posts > 0

發文率:3.97%(33/832)(未達成 smilie
smilie 發文排行榜:
1.andowson:304
2.viva:22
3.wu_net2008:16
4:windstorm:14
5.wtom:12
6.fly:11
7.lynx286:10
8.ofather:8
9.~HIM~:8
10.Anonymous:7
select username, user_posts from jforum_users where user_posts > 0 order by user_posts desc limit 10


4.流量統計
最高月參觀者數:7562(2008/10)

整體來說,2008年只有達成一項目標,其他幾項指標可能有過份樂觀。

今年的展望是:
1.會員數成長到2000人,啟用率75%
2.發表文章數成長到750篇,發文率5%
3.流量月最高參觀者數突破10000人
已修改為fly。也希望再見到您發表新文章。
只要在/etc/postfix/main.cf中加上
relayhost = relay SMTP主機的IP或Domain Name
然後重新啟動postfix即可
service postfix restart

參考資料:
http://www.gungeralv.org/notes/archives/2003/06/howto_configure_postfix_to_use_a_remote_smtp_relay_host.php
Trac的刪除、備份跟還原
1.刪除Trac專案:
在Trac中每個專案環境就是一個目錄,所以刪除專案很簡單,就是把對應的目錄刪除掉,然後對應的資料庫也刪除掉即可。

2.備份Trac專案:
可以使用trac-admin的hotcopy指令,
$ trac-admin /path/to/projenv hotcopy /path/to/backupdir

例如:
[andowson@www ~]$ trac-admin /home/andowson/projects/webmail hotcopy /tmp/webmail
Hotcopying /home/andowson/projects/webmail to /tmp/webmail ... Hotcopy done.

檢視一下內容可以發現其實就是整個目錄複製過去而已,所以理論上只要先把Web Server停止後,自己使用OS的copy指令也是OK的
[andowson@www ~]$ ll /tmp/webmail/
總計 36
drwxrwxr-x 2 andowson andowson 4096 12月 21 20:09 attachments
drwxrwxr-x 2 andowson andowson 4096 12月 21 20:09 conf
drwxrwxr-x 2 andowson andowson 4096 12月 21 20:09 htdocs
drwxrwxr-x 2 andowson andowson 4096 12月 21 20:09 log
drwxrwxr-x 2 andowson andowson 4096 12月 21 20:09 plugins
-rw-r--r-- 1 andowson andowson 98 9月 9 2007 README
drwxrwxr-x 2 andowson andowson 4096 12月 21 20:09 templates
-rw-r--r-- 1 andowson andowson 27 9月 9 2007 VERSION
drwxrwxr-x 2 andowson andowson 4096 12月 21 20:09 wiki-macros

資料庫部分可以使用資料庫備份的指令,例如PostgreSQL的pg_dump

3.還原Trac專案
也是很簡單,就是把備份的目錄覆蓋回去即可,先把Web Server停掉,然後把整個目錄結構copy回去,再把資料庫還原回去,然後再重起Web Server即可。

Subverson的備份跟還原
1.備份Subversion的repository
svnadmin hotcopy /path/to/reponame /path/to/backupdir

例如:
svnadmin hotcopy /home/andowson/repos/webmail /tmp/webmailrepo
這個指令單純的將repository的目錄複製一份出來

2.還原Subversion的repository
只要將先前用hotcopy備份的目錄複製回去即可

參考資料:
http://trac.edgewall.org/wiki/TracBackup
http://svnbook.red-bean.com/en/1.1/ch05s03.html
http://wiki.archlinux.org/index.php/Subversion_backup_and_restore
http://rory.cba.tw/rewrite.php/read-95.html
首先,JForum的手動啟用帳號中輸入的是會員ID(整數),不是會員名稱(字串),您的會員ID可以由會員列表前面第一行數字查得(即#那一行)。
第二,驗證碼在當初加入會員時,已發送通知信到您註冊時所使用的電子郵件信箱,如果當初您註冊用的信箱是正確的,您可以到您的信箱中再找找看有沒有那封信。
第三,如果當初註冊時沒收到啟用帳號通知信,目前這個版本的JForum也沒有提供補發驗證碼的功能,如果您比較偏好使用fly這個帳號,有幾種作法:
a.由系統管理者手動啟用帳號,這樣子您會有兩個帳號
b.由系統管理者變更您目前通過認證的這個帳號名稱為fly,將原來的fly改為別的名稱
c.開發補發驗證碼的程式,可以模仿忘記密碼的程式來改,然後您再去申請補發驗證碼,然後再來啟用帳號。目前想到的邏輯如下:
1.在手動啟用帳號的頁面上加入補發驗證碼連結,使用者按下後顯示申請表單畫面
2.使用者同時輸入帳號跟新的電子郵件信箱地址
3.系統檢查該帳號是否已啟用
3.1.如果尚未啟用,則更新該帳號的電子郵件信箱,同時產生新驗證碼,寄送至這個新的電子郵件信箱
3.2如果已啟用,則顯示帳號已啟用畫面(避免帳號被盜用)
4.使用者至其新的電子郵件信箱收信,收到信後再啟用帳號

這幾個作法的優缺點如下:
a方案:優點:簡單,目前系統所提供的功能。缺點:無法確認使用者所填寫之電子郵件信箱是否正確,失去驗證碼機制所要的目的。然後同一個人變成有兩個帳號。
b方案:優點:可以保留目前您這個帳號所發表的文章紀錄。缺點:就是要請系統管理者去處理這件事,還有原先的文章可能會看起來怪怪的。
c方案:優點:可以讓使用者自行處理這件事情。不需要系統管理者介入。也可以回收一些帳號。缺點:就是還要開發程式,需要考量所花的時間成本以及日後與新版本程式相容性的問題。還有就是同一個人還是有兩個帳號。

目前,我比較傾向使用b方案。不知道您是否同意這樣的處理方式?
 
Forum Index » Profile for andowson » Messages posted by andowson
Go to:   

交換連結乌托邦博客 
在本站刊登廣告
練功房推薦書單
SCJP 6.0認證教戰手冊 (附光碟) 雲端策略:雲端運算與虛擬化技術 SCJP Java 6專業認證手冊 Java認證SCJP 6.0/5.0--猛虎出閘 SCWCD 5 猛虎出閘:Java Web 應用程式專業認證 SCWCD專業認證手冊 Head First Servlets and JSP
[版權說明] 本站授權方式:創用CC 姓名標示-非商業性-相同方式分享 3.0 台灣 授權條款
Creative Commons License
Powered by JForum 2.2.0 © JForum Team