# インターフェースのテーブルの幅
TABLEWIDTH = 800
# 画像フォルダの場所を定義
-IMGPATH = "./../lunardial/xml/img"
+IMGPATH = "./../lunardial/xml/img/"
# バージョン情報を示す文字列です
APPVERSION = "- FileManager for Ruby version 2.0.0.0 -<br>Copyright(c) 2009 Kureha.H (<a href=\"http://lunardial.sakura.ne.jp/\" target=\"_blank\">http://lunardial.sakura.ne.jp/</a>) & Yui Naruse (<a href=\"http://airemix.com/\" target=\"_blank\">http://airemix.com/</a>)"
# タイトル領域に表示される文字列です
APPTITLE = "FileManager for Ruby version 2.0.0.0"
+# アップロード可能な最大ファイルサイズ
+UPLOADLIMIT = 2 * 1024 * 1024
+
# = Objectクラス
#
# 基本クラスのオーバーライドを行います
# _arg[1]_ :: モードの指定。例 : w:utf-8(書き込みモード・UTF-8エンコードでファイルを開く)
def myopen(*arg)
mode = arg[1]
- arg[1] = mode[/[^:]+/] if mode && RUBY_VERSION < "1.8.7" && mode.include?(':')
+ rdonly_p = true
+ case mode
+ when String
+ arg[1] = mode[/[^:]+/] if RUBY_VERSION < "1.8.7" && mode.include?(':')
+ rdonly_p = /\A[^:]*[wa+]/ !~ mode
+ when Numeric
+ rdonly_p = !(mode & (IO::WRONY | IO::RDWR))
+ end
open(*arg) do |f|
- f.flock(/\A\w+r/ =~ mode ? File::LOCK_SH : File::LOCK_EX)
+ f.flock(rdonly_p ? File::LOCK_SH : File::LOCK_EX)
return yield(f)
end
end
end
end
+# = WebSecurityExceptionクラス
+#
+# 独自定義の例外クラスです。WebFilerインスタンス内の処理でセキュリティ違反が発生した場合にthrowされます。
+class WebSecurityException < Exception
+end
+
+# = FileExistedExceptionクラス
+#
+# 独自定義の例外クラスです。WebFileインスタンスの処理で、既に存在するファイルに上書きしようとした場合にthrowされます。
+class FileExistedException < Exception
+end
+
# = HtmlWriterクラス
#
# テンプレートファイル(*.erb)を読み込み、管理するクラスです
# _template_ :: テンプレートファイル(*.erb)のパス
# _binding_ :: binding変数
def initialize(template, binding)
- @erb = ERB.new(myopen(template, "r") {|f| f.read}, nil, "-")
+ @erb = ERB.new(myopen(template, "r:utf-8") {|f| f.read}, nil, "-")
@binding = binding
end
# _basepath_ :: クラス内で扱う最上位のフォルダ(root)とする実パス
def initialize(basepath)
@basepath = basepath
- @basepath << "/" unless @basepath[-1] == "/"
+ @basepath << "/" unless @basepath[-1..-1] == "/"
@relpath_list = []
- raise "Target dir not found." unless check_dir_exist?(pwd)
+ raise "Target dir not found." unless File.directory?(pwd)
end
- attr_reader :basepath, :relpath_list
+ # ファイルに使用できない文字列を調べるための正規表現を定義します
+ FILEREGEXP = /\A[-_+~^0-9a-zA-Z]+(\.[-_+~^0-9a-zA-Z]+)*\z/
+
+ attr_reader :basepath
attr_accessor :relpath_list
# ディレクトリ内部のファイル・フォルダ一覧を取得するメソッド
- def dir
+ def ls
filelist = Dir::entries(pwd)
filelist.delete(".")
filelist.delete("..")
- filelist
+ filelist.sort!
end
# ディレクトリ内部のファイル・フォルダ一覧の詳細情報を取得するメソッド
- def ls
+ def lsinfo
filelist = Dir::entries(pwd)
filelist.delete(".")
filelist.delete("..")
def cd(pathname)
if pathname == ".."
@relpath_list.delete_at(-1) unless @relpath_list.length == 0
- elsif pathname.match(/([^\w]|\.\.|\/|\.)/) == nil
- if check_dir_exist?(pwd + "/" + File.basename(pathname))
+ elsif pathname.match(FILEREGEXP)
+ if File.directory?(pwd + "/" + File.basename(pathname))
@relpath_list << File.basename(pathname)
else
- raise "Target dir not found."
+ raise FileExistedException
end
else
-
+ raise WebSecurityException
end
end
+ # ディレクトリを絶対指定で移動するメソッド
+ def cd_abs(relpath_arr)
+ relpath_arr.each { |name|
+ unless name.match(FILEREGEXP)
+ raise WebSecurityException
+ end
+ }
+ @relpath_list = relpath_arr
+ end
+
# 現在のディレクトリを表示するメソッド
def pwd
@basepath + relpath
# ファイルをアップロードするメソッド
def upload(file, fname)
- if File.exist?(pwd + fname)
- raise "Target file exist."
- elsif
- fname.match(/([^\w]|\.\.)/) == nil
- raise "Wrong file name."
- else
+ fname.gsub!(/( | )/, "_")
+ if File.exist?(pwd + File.basename(fname))
+ raise FileExistedException
+ elsif File.basename(fname).match(FILEREGEXP)
open(pwd + File.basename(fname), "w") do |f|
f.binmode
- f.write file
+ f.write file.read
end
+ else
+ raise WebSecurityException
end
end
# ファイルを消去するメソッド
def delete(fname)
- if File.exist?(pwd + File.basename(fname))
+ if File.exist?(pwd + File.basename(fname)) && fname.match(FILEREGEXP)
File.delete(pwd + File.basename(fname))
else
- raise "Target file is not exist."
+ raise WebSecurityException
end
end
# ディレクトリを製作するメソッド
def mkdir(dirname)
+ dirname.gsub!(/( | )/, "_")
if File.exist?(pwd + File.basename(dirname))
- raise "Target directory is exist."
- else
+ raise FileExistedException
+ elsif dirname.match(FILEREGEXP)
Dir.mkdir(pwd + File.basename(dirname))
+ else
+ raise WebSecurityException
end
end
# 内部が空のディレクトリを消去するメソッド
def rmdir(dirname)
- if File.exist?(pwd + File.basename(dirname))
+ if File.exist?(pwd + File.basename(dirname)) && dirname.match(FILEREGEXP)
Dir.rmdir(pwd + File.basename(dirname))
else
- raise "Target directory is not exist."
- end
- end
-
- # 対象ディレクトリが存在するかを確認するメソッド
- def check_dir_exist?(target_dir)
- unless (File.exist?(target_dir) || File.ftype(target_dir) != "directory")
- false
- else
- true
+ raise WebSecurityException
end
end
#
# コントローラ部分に相当する処理を受け持つクラスです
class Controller
+ def self.update_session(session, filer)
+ session["filelist"] = filer.ls.reverse
+ session["fileinfo"] = filer.lsinfo
+ session["pwd"] = filer.pwd
+ session["relpath_list"] = filer.relpath_list.join("/")
+ end
+
def Controller.MultiForm(cgi, session, params, db)
db.transaction do
case params["action"]
# アップロード時
when "upload"
filer = WebFiler.new(IMGPATH)
- filer.relpath_list = db["relpath_list"]
+ filer.relpath_list = params["relpath_list"].split("/")
+ Controller.update_session(session, filer);
- filer.upload(params["updata"], cgi["updata"].original_filename)
+ if (cgi["updata"].size <= UPLOADLIMIT)
+ begin
+ filer.upload(cgi["updata"], cgi["updata"].original_filename)
+ rescue FileExistedException
+ session["error"] = "既に同名のファイルが存在します!"
+ rescue WebSecurityException
+ session["error"] = "ファイル名に使用できない文字列が含まれています!"
+ end
+ else
+ session["error"] = "ファイルの容量が大きすぎます!"
+ end
- db["filelist"] = filer.dir
- db["fileinfo"] = filer.ls
+ Controller.update_session(session, filer);
- db["info"] = "正常にアップロードが完了しました。" if db["error"] == ""
+ session["info"] = "正常にアップロードが完了しました。" if session["error"] == ""
# 削除時
when "delete"
filer = WebFiler.new(IMGPATH)
- filer.relpath_list = db["relpath_list"]
+ filer.relpath_list = params["relpath_list"].split("/")
+ Controller.update_session(session, filer);
- db["dellist"] = []
- db["filelist"].each do |file|
+ session["dellist"] = []
+ count = 0
+ session["filelist"].each do |file|
if params["filename_" + file] == "delete" && filer.ftype(file) == "file"
filer.delete(file)
+ count = count + 1
elsif params["filename_" + file] == "delete" && filer.ftype(file) == "directory"
begin
filer.rmdir(file)
- rescue => ever
+ count = count + 1
+ rescue
mes = "対象のディレクトリは空ではありません!<br>"
mes << "ディレクトリを削除する場合は、事前にディレクトリ内部の全てのファイルを削除してください。"
- db["error"] = mes
+ session["error"] = mes
end
end
end
- db["filelist"] = filer.dir
- db["fileinfo"] = filer.ls
+ Controller.update_session(session, filer);
- db["info"] = "正常にファイルの削除が完了しました。" if db["error"] == ""
+ session["info"] = "正常にファイルの削除が完了しました。" if session["error"] == "" && count != 0
# ディレクトリ製作時
when "mkdir"
filer = WebFiler.new(IMGPATH)
- filer.relpath_list = db["relpath_list"]
+ filer.relpath_list = params["relpath_list"].split("/")
+ Controller.update_session(session, filer);
- filer.mkdir(params["dirname"])
+ begin
+ filer.mkdir(params["dirname"])
+ rescue FileExistedException
+ session["error"] = "既に同名のディレクトリが存在します!"
+ rescue WebSecurityException
+ session["error"] = "ディレクトリ名に使用できない文字列が含まれています!"
+ end
- db["filelist"] = filer.dir
- db["fileinfo"] = filer.ls
+ Controller.update_session(session, filer);
- db["info"] = "正常にディレクトリの作成が完了しました。" if db["error"] == ""
+ session["info"] = "正常にディレクトリの作成が完了しました。" if session["error"] == ""
# ディレクトリ移動時
when "cd"
filer = WebFiler.new(IMGPATH)
- filer.relpath_list = db["relpath_list"]
+ filer.relpath_list = params["relpath_list"].split("/")
+ Controller.update_session(session, filer);
+
+ begin
+ filer.cd(params["arg"])
+ rescue
+ session["error"] = "移動先のディレクトリが見つかりません!"
+ end
+
+ Controller.update_session(session, filer);
+
+ # 絶対位置でのディレクトリ移動時
+ when "cd_abs"
+ filer = WebFiler.new(IMGPATH)
+ filer.relpath_list = params["relpath_list"].split("/")
+ Controller.update_session(session, filer);
- filer.cd(params["arg"])
+ if params["arg"].to_i >= 0
+ begin
+ movepath = []
+ params["arg"].to_i.times { |i|
+ movepath << params["relpath_list"].split("/")[i]
+ }
+ filer.cd_abs(movepath)
+ rescue
+ session["error"] = "移動先のディレクトリが見つかりません!"
+ end
+ else
+ session["error"] = "移動先のディレクトリが見つかりません!"
+ end
- db["filelist"] = filer.dir
- db["fileinfo"] = filer.ls
- db["pwd"] = filer.pwd
- db["relpath_list"] = filer.relpath_list
+ Controller.update_session(session, filer);
+
+ # 表示更新時
+ when "refresh"
+ filer = WebFiler.new(IMGPATH)
+ filer.relpath_list = params["relpath_list"].split("/")
+ Controller.update_session(session, filer);
# 初期表示
else
filer = WebFiler.new(IMGPATH)
-
- db["filelist"] = filer.dir
- db["fileinfo"] = filer.ls
- db["pwd"] = filer.pwd
- db["relpath_list"] = filer.relpath_list
+ Controller.update_session(session, filer);
end
end
end
cgi = CGI.new
session = CGI::Session.new(cgi)
params = Hash[*cgi.params.to_a.map{|k, v| [k, v[0].to_s]}.flatten]
- params.each { |k, v| params[k] = cgi[k].read if cgi[k].respond_to?(:read) }
+ params.each { |k, v| params[k] = cgi[k].read if cgi[k].respond_to?(:read) && k != "updata"}
# ログアウト処理
if params["mode"] == "logout"
# セッションが有効な場合のも実行します
if session["login"] == "true"
db = PStore.new("./work/#{session.session_id}_file.dat")
- db.transaction do
- db["info"] = ""
- db["error"] = ""
- end
+ session["info"] = ""
+ session["error"] = ""
# コントローラ部分
Controller.MultiForm(cgi, session, params, db)
rescue => exception
# エラーが発生した場合、それを画面に表示します
htmlwriter = HtmlWriter.new("./erbtemp/exception.html.erb", binding)
- cgi.out{htmlwriter.to_code}
+ cgi.out{ htmlwriter.to_code }
end
end