2 # -*- coding: utf-8 -*-
4 #= FeedGeneratorから起動するファイルマネージャWEBアプリケーション
6 #Autohr:: Kureha Hisame (http://lunardial.sakura.ne.jp/) & Yui Naruse (http://airemix.com/)
8 #Copyright:: Copyright 2009 FeedBlog Project (http://sourceforge.jp/projects/feedblog/)
14 require "rexml/document"
21 IMGPATH = "./../lunardial/xml/img"
24 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>)"
26 APPTITLE = "FileManager for Ruby version 2.0.0.0"
29 UPLOADLIMIT = 2 * 1024 * 1024
37 # ruby-1.9.x以降ではファイルを開いた際、エンコードの指定を行わないとエラーの原因になります。
38 # ただしruby-1.8.6以前はエンコードの指定に対応していないため、独自メソッドを定義してファイルの入出力を行います。
40 # _arg[0]_ :: 入出力を行うファイルのパス
41 # _arg[1]_ :: モードの指定。例 : w:utf-8(書き込みモード・UTF-8エンコードでファイルを開く)
44 arg[1] = mode[/[^:]+/] if mode && RUBY_VERSION < "1.8.7" && mode.include?(':')
46 f.flock(/\A\w+r/ =~ mode ? File::LOCK_SH : File::LOCK_EX)
72 # テンプレートファイル(*.erb)を読み込み、管理するクラスです
76 # _template_ :: テンプレートファイル(*.erb)のパス
77 # _binding_ :: binding変数
78 def initialize(template, binding)
79 @erb = ERB.new(myopen(template, "r") {|f| f.read}, nil, "-")
83 # テンプレートファイルの文字列を返却するメソッドです
91 # Web上にローカルと同じフォルダ管理機能を利用できるクラスです
95 # _basepath_ :: クラス内で扱う最上位のフォルダ(root)とする実パス
96 def initialize(basepath)
98 @basepath << "/" unless @basepath[-1] == "/"
101 raise "Target dir not found." unless check_dir_exist?(pwd)
104 attr_reader :basepath
105 attr_accessor :relpath_list
107 # ディレクトリ内部のファイル・フォルダ一覧を取得するメソッド
109 filelist = Dir::entries(pwd)
111 filelist.delete("..")
116 # ディレクトリ内部のファイル・フォルダ一覧の詳細情報を取得するメソッド
118 filelist = Dir::entries(pwd)
120 filelist.delete("..")
123 filelist.each { |fname|
125 fileinfo[fname][:ftype] = File.ftype(pwd + "/" + fname)
126 fileinfo[fname][:atime] = File.atime(pwd + "/" + fname)
127 fileinfo[fname][:ctime] = File.ctime(pwd + "/" + fname)
128 fileinfo[fname][:mtime] = File.mtime(pwd + "/" + fname)
129 fileinfo[fname][:size] = File.size(pwd + "/" + fname) / 1000
137 File.ftype(pwd + File.basename(fname))
143 @relpath_list.delete_at(-1) unless @relpath_list.length == 0
144 elsif pathname.match(/([^\w]|\.\.|\/|\.)/) == nil
145 if check_dir_exist?(pwd + "/" + File.basename(pathname))
146 @relpath_list << File.basename(pathname)
148 raise "Target dir not found."
162 if @relpath_list.length == 0
165 @relpath_list.join("/") << "/"
170 def upload(file, fname)
171 if File.exist?(pwd + fname)
172 raise "Target file exist."
174 fname.match(/([^\w]|\.\.)/) == nil
175 raise "Wrong file name."
177 open(pwd + File.basename(fname), "w") do |f|
186 if File.exist?(pwd + File.basename(fname))
187 File.delete(pwd + File.basename(fname))
189 raise "Target file is not exist."
195 if File.exist?(pwd + File.basename(dirname))
196 raise "Target directory is exist."
198 Dir.mkdir(pwd + File.basename(dirname))
202 # 内部が空のディレクトリを消去するメソッド
204 if File.exist?(pwd + File.basename(dirname))
205 Dir.rmdir(pwd + File.basename(dirname))
207 raise "Target directory is not exist."
211 # 対象ディレクトリが存在するかを確認するメソッド
212 def check_dir_exist?(target_dir)
213 unless (File.exist?(target_dir) || File.ftype(target_dir) != "directory")
224 # コントローラ部分に相当する処理を受け持つクラスです
226 def Controller.MultiForm(cgi, session, params, db)
228 case params["action"]
231 filer = WebFiler.new(IMGPATH)
232 filer.relpath_list = db["relpath_list"]
234 if (cgi["updata"].size <= UPLOADLIMIT)
235 filer.upload(cgi["updata"], cgi["updata"].original_filename.gsub(/ /, "_"))
237 db["error"] = "ファイルの容量が大きすぎます!"
240 db["filelist"] = filer.ls.reverse
241 db["fileinfo"] = filer.lsinfo
243 db["info"] = "正常にアップロードが完了しました。" if db["error"] == ""
247 filer = WebFiler.new(IMGPATH)
248 filer.relpath_list = db["relpath_list"]
251 db["filelist"].each do |file|
252 if params["filename_" + file] == "delete" && filer.ftype(file) == "file"
254 elsif params["filename_" + file] == "delete" && filer.ftype(file) == "directory"
258 mes = "対象のディレクトリは空ではありません!<br>"
259 mes << "ディレクトリを削除する場合は、事前にディレクトリ内部の全てのファイルを削除してください。"
265 db["filelist"] = filer.ls.reverse
266 db["fileinfo"] = filer.lsinfo
268 db["info"] = "正常にファイルの削除が完了しました。" if db["error"] == ""
272 filer = WebFiler.new(IMGPATH)
273 filer.relpath_list = db["relpath_list"]
275 filer.mkdir(params["dirname"])
277 db["filelist"] = filer.ls.reverse
278 db["fileinfo"] = filer.lsinfo
280 db["info"] = "正常にディレクトリの作成が完了しました。" if db["error"] == ""
284 filer = WebFiler.new(IMGPATH)
285 filer.relpath_list = db["relpath_list"]
287 filer.cd(params["arg"])
289 db["filelist"] = filer.ls.reverse
290 db["fileinfo"] = filer.lsinfo
291 db["pwd"] = filer.pwd
292 db["relpath_list"] = filer.relpath_list
296 filer = WebFiler.new(IMGPATH)
298 db["filelist"] = filer.ls.reverse
299 db["fileinfo"] = filer.lsinfo
300 db["pwd"] = filer.pwd
301 db["relpath_list"] = filer.relpath_list
308 # SESSION変数、パラメータなどを取得します
310 session = CGI::Session.new(cgi)
311 params = Hash[*cgi.params.to_a.map{|k, v| [k, v[0].to_s]}.flatten]
312 params.each { |k, v| params[k] = cgi[k].read if cgi[k].respond_to?(:read) && k != "updata"}
315 if params["mode"] == "logout"
316 session["login"] = nil
317 session["logini"] = nil
318 session["password"] = nil
324 if session["login"] == "true"
325 db = PStore.new("./work/#{session.session_id}_file.dat")
332 Controller.MultiForm(cgi, session, params, db)
336 if session["login"] != "true"
337 # if session["login"] == "true"
338 # セッションが存在しない場合は強制的にエラーページに遷移
339 htmlwriter = HtmlWriter.new("./erbtemp/fileindex.html.erb", binding)
341 htmlwriter = HtmlWriter.new("./erbtemp/filemanager.html.erb", binding)
346 cgi.out{htmlwriter.to_code}
348 # エラーが発生した場合、それを画面に表示します
349 htmlwriter = HtmlWriter.new("./erbtemp/exception.html.erb", binding)
350 cgi.out{htmlwriter.to_code}
357 # エラーが発生した場合、それを画面に表示します
358 detail = ("%s: %s (%s)\n" %
359 [evar.backtrace[0], evar.message, evar.send('class')]) +
360 evar.backtrace[1..-1].join("\n")
361 puts "content-type: text/html\n\n<plaintext>\n" + detail