require "date"
require "fileutils"
-# ログインID
-LOGINID = "login"
-# ログインパスワード
-PASSWORD = "password"
+# ログイン情報配列
+LOGININFO = [
+{:id => "login", :password => "password", :name => "テストユーザ"}
+]
# インターフェースのテーブルの幅
-TABLEWIDTH = 800
+TABLEWIDTH = 1000
# XMLファイル格納先までの相対パス
XMLPATH = "./../lunardial/xml/"
+# FeedBlogを設置したディレクトリのURL
+HOMEBASE = "https://lunardial.sakura.ne.jp/"
+# 入力されたフルパスURL(HOMEBASE)を置換する文字列
+RELAYPATH = "./"
# loglist.xmlファイルの定義
LISTXMLPATH = "#{XMLPATH}loglist.xml"
# FeedBlog上の表示ページからログ格納ディレクトリまでのパス
FILEMANAGER = "./filemanager.rb"
# XMLに書き込む際、改行部分を<br>のまま保持するか、改行記号に直すか
REPLACEBRTAG = false
+# ファイルの書き込み時にENTRYのIDおよびURLを、FEEDオブジェクトから自動生成した値に置換するか否か
+REPLACEENTRYIDANDURL = false
+# プラグインディレクトリ
+PLUGINDIR = "./plugins/"
+# 記事用初期ファイル名
+INITIALXML = "diary.xml"
# バージョン情報を示す文字列です
APPVERSION = "- FeedGenerator 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>)"
# _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
def to_s
buf = []
- buf.push("<feed #{@attr[:feedattr]}>")
+ # buf.push("<feed #{@attr[:feedattr]}>")
+ buf.push("<feed xml:lang='ja-jp' xmlns='http://www.w3.org/2005/Atom'>");
buf.push("<title type=\"text\">#{@attr[:title]}</title>")
buf.push("<subtitle type=\"text\">#{@attr[:subtitle]}</subtitle>")
buf.push("<link rel=\"self\" type=\"application/atom+xml\" href=\"#{@attr[:self]}\" />")
#
# _feed_ :: Feedオブジェクト
# _entry_ :: Entryオブジェクトの配列
- def self.to_xml(path, feed, entrylist)
+ def self.to_xml(path, feed, entrylist_tmp)
+ buf = []
+ entrylist = entrylist_tmp.dup
+ buf.push("<?xml version=\"1.0\" encoding=\"utf-8\"?>")
+ buf.push("#{feed.to_s}\n")
+ entrylist.each { |entry|
+ if REPLACEENTRYIDANDURL
+ entry.entryid.gsub!(/^[^\?]*\?/, "")
+ entry.entryid = feed.url + "?" + entry.entryid
+ entry.url = feed.url + "#" + entry.entryid
+ end
+ buf.push("#{entry.to_s}\n")
+ }
+ buf.push("</feed>")
+
+ myopen(path, "w") do |f|
+ f.print buf.join("\n")
+ end
+ end
+
+ # XMLファイル出力用メソッドです
+ #
+ # _feed_ :: Feedオブジェクト
+ # _entry_ :: Entryオブジェクトの配列
+ def self.to_xml_plain(path, feed, entrylist)
buf = []
buf.push("<?xml version=\"1.0\" encoding=\"utf-8\"?>")
buf.push("#{feed.to_s}\n")
# 可視・不可視を示すハッシュキーを格納する配列です
@display = {"entryid" => "none", "title" => "",
"summary" => "", "published" => "none",
- "updated" => "none", "url" => "none",
+ "updated" => "none", "url" => "",
"content" => "", "others"=>"none"}
# デバッグモードの場合、全ての入力要素を表示します
return entrylist
end
+ # Atom XMLファイルを読み込んで解析し、テンプレートファイルにしたがってHTMLに変換するメソッドです
+ def self.to_html(xmlpath, destpath, entry_temppath, html_temppath)
+ # 引数チェック - 全必須
+ if xmlpath.empty? or destpath.empty? or entry_temppath.empty? or html_temppath.empty?
+ raise ArgumentError
+ end
+
+ # 必須ファイル存在チェック
+ unless File.exist?(xmlpath) and File.exist?(entry_temppath) and File.exist?(html_temppath)
+ raise IOError
+ end
+
+ # XML読み込み
+ entrylist = Entry.readxml(xmlpath)
+
+ body = ''
+ entrylist.each { |e|
+ # Entry毎のHTML表示部分を生成
+ body << e.to_template(entry_temppath)
+ }
+
+ # HTML全体のテンプレートを生成
+ html_temp = HtmlWriter.new(html_temppath, binding)
+
+ # HTMLに書き込み
+ myopen(destpath, 'w:utf-8') { |f|
+ f.write(CGI.pretty(html_temp.to_code))
+ }
+ end
+
+ # Entryをテンプレートに沿って変形するメソッド
+ def to_template(temppath)
+ erb = HtmlWriter.new(temppath, binding)
+ title = CGI.unescapeHTML(@attr[:title])
+ date = @attr[:published]
+ content = CGI.unescapeHTML(@attr[:content])
+ erb.to_code
+ end
+
# Entry挿入メソッド
def self.insert(path, entry)
feed = Feed.readxml(path)
str.strip!
str.gsub!(/(<\/(?:p|h\d|div)(?:>|>))\n/i, '\1')
str.gsub!(/\n/, '<br>') if REPLACEBRTAG
- str.gsub!(/(<(?:(?!>).)*?)#{Regexp.escape(FEEDXMLDIR)}/) { "#$1#{XMLPATH}" }
+ str.gsub!(/(<(?:(?!>).)*?)#{Regexp.escape(RELAYPATH)}/) { "#$1#{HOMEBASE}" }
str
end
str = CGI.unescapeHTML(str)
str.strip!
str.gsub!(/(\r\n|\n)/, "")
- str.gsub!(/<br>/i, "\n") if REPLACEBRTAG
- str.gsub!(/(<br>|<\/p>|<\/h\d>|<\/div>)(?=[^\n])/i) { "#$1\n" } unless REPLACEBRTAG
- str.gsub!(/(<[^>]*?)#{Regexp.escape(XMLPATH)}/) { "#$1#{FEEDXMLDIR}" }
+ str.gsub!(/<br>|<br[ ]*\/>/i, "\n") if REPLACEBRTAG
+ str.gsub!(/(<br>|<br[ ]*\/>|<\/p>|<\/h\d>|<\/div>)(?=[^\n])/i) { "#$1\n" } unless REPLACEBRTAG
+ str.gsub!(/(<[^>]*?)#{Regexp.escape(HOMEBASE)}/) { "#$1#{RELAYPATH}" }
CGI.escapeHTML(str)
end
str = @attr[:content].dup
str = CGI.unescapeHTML(str)
str.strip!
- str.gsub!(/<br>/i, "\n") if REPLACEBRTAG
- str.gsub!(/(<[^>]*?)#{Regexp.escape(FEEDXMLDIR)}/) { "#$1#{XMLPATH}" }
+ str.gsub!(/<br>|<br[ ]*\/>/i, "\n") if REPLACEBRTAG
+ str.gsub!(/(<[^>]*?)#{Regexp.escape(RELAYPATH)}/) { "#$1#{HOMEBASE}" }
str
end
end
end
+# = Pluginクラス
+#
+# プラグインの処理を行うクラスです
+class FeedGenPluginManager
+ def self.exec(mode, filepath)
+ feed = Feed.readxml(XMLPATH + filepath)
+ entries = Entry.readxml(XMLPATH + filepath)
+ feed.freeze
+ entries.freeze
+ Dir.foreach(PLUGINDIR) do |fn|
+ next unless File.extname(fn) == '.rb'
+ require File.join(PLUGINDIR, fn)
+ plugin_name = "FeedGenPlugins::"
+ plugin_name << File.basename(fn).gsub(/\.rb\Z/, "")
+ plugin_ins = plugin_name.split(/::/).inject(Object) { |c,name| c.const_get(name) }
+ plugin_ins.new.exec(mode, feed, entries)
+ end
+ end
+end
+
# = Controllerクラス
#
# コントローラ部分に相当する処理を受け持つクラスです
unless successed
db["error"] = "日記の新規追加に失敗しました。"
params["mode"] = "error"
+ else
+ # 成功時はプラグイン処理を実施する
+ FeedGenPluginManager.exec("newentry", File.basename(session["filepath"]))
end
# 画面を戻った際の処理
when "back"
unless successed
db["error"] = "日記の編集処理に失敗しました。<br>該当の日記が既に存在しない可能性があります。"
params["mode"] = "error"
+ else
+ # 成功時はプラグイン処理を実施する
+ FeedGenPluginManager.exec("editentry", File.basename(session["filepath"]))
end
when "back"
session["target_filepath"] = params["target_filepath"]
unless successed
db["error"] = "日記の編集処理に失敗しました。<br>該当の日記が既に存在しない可能性があります。"
params["mode"] = "error"
+ else
+ # 成功時はプラグイン処理を実施する
+ FeedGenPluginManager.exec("delentry", File.basename(session["filepath"]))
end
when "back"
session["target_filepath"] = params["target_filepath"]
# 全ファイルの初期化を実行する
# loglist.xmlの初期化
- loglist = LogList.new(["最新の記事"], ["#{FEEDXMLDIR}diary.xml"], LISTXMLPATH)
+ loglist = LogList.new(["最新の記事"], ["#{FEEDXMLDIR}#{INITIALXML}"], LISTXMLPATH)
loglist.to_xml
db["loglist"] = LogList.readxml(LISTXMLPATH)
# loglist.xmlが存在するかチェック
if File.exist?(LISTXMLPATH) == false
# なかった場合はloglist.xmlを自動生成
- loglist = LogList.new(["最新の記事"], ["#{FEEDXMLDIR}diary.xml"], LISTXMLPATH)
+ loglist = LogList.new(["最新の記事"], ["#{FEEDXMLDIR}#{INITIALXML}"], LISTXMLPATH)
loglist.to_xml
Feed.to_xml(XMLPATH + File.basename(loglist.path[0]), Feed.new({}), [])
end
# マルチパートフォームの場合の処理です
def Controller.MultiForm(cgi, session, params, db)
db.transaction do
-
# loglist.xmlをロードします
db["loglist"] = LogList.readxml(LISTXMLPATH)
-
case params["mode"]
# 特定位置に挿入する場合の処理
when "insert"
end
# diary.xmlを移動します
- FileUtils.move(XMLPATH + "diary.xml", XMLPATH + File.basename(db["logpath"]))
+ FileUtils.move(XMLPATH + INITIALXML, XMLPATH + File.basename(db["logpath"]))
# ファイルをアップロードします
file = FileUploader.new
- file.upload("diary.xml", db["importxml"])
+ file.upload(INITIALXML, db["importxml"])
# loglist.xmlを更新します
db["loglist"].path[1, 0] = db["logpath"]
# コントローラー部分
# セッション管理
if session["login"] != "true"
- if (cgi["loginid"] == LOGINID && cgi["password"] == PASSWORD)
- session["login"] = "true"
-
+
+ # ログイン情報を確認
+ LOGININFO.each {|h|
+ if (cgi["loginid"] == h[:id] && cgi["password"] == h[:password])
+ session["login"] = "true"
+ session["name"] = h[:name]
+ break
+ end
+ }
+
+ if (session["login"] == "true")
# ワークフォルダの中をクリーンアップします
filelist = Dir::entries("./work")
# 削除条件 : 最終変更日時から1日(60*60*24sec)かつ、ファイルタイプがファイルの場合
# ログアウト処理
if params["mode"] == "logout"
session["login"] = nil
- session["logini"] = nil
- session["password"] = nil
session.delete
end
File.delete("./work/#{session.session_id}.dat")
# PStoreが破損していた場合はセッション情報を破棄する
session["login"] = nil
- session["logini"] = nil
- session["password"] = nil
session.delete
end
# エラー画面移行時はセッション情報を破棄する
if params["mode"] == "error"
session["login"] = nil
- session["logini"] = nil
- session["password"] = nil
session.delete
end
end