pax_global_header00006660000000000000000000000064121363274400014514gustar00rootroot0000000000000052 comment=c6f02733dd284f2c96e8edfdd8a4b0b2e8ed09f3 tdiary-contrib-3.2.2/000077500000000000000000000000001213632744000144525ustar00rootroot00000000000000tdiary-contrib-3.2.2/.gitignore000066400000000000000000000000101213632744000164310ustar00rootroot00000000000000coveragetdiary-contrib-3.2.2/.travis.yml000066400000000000000000000001161213632744000165610ustar00rootroot00000000000000rvm: - ree - 1.9.2 - 1.9.3 - ruby-head script: bundle exec rake spec tdiary-contrib-3.2.2/Gemfile000066400000000000000000000002071213632744000157440ustar00rootroot00000000000000source :rubygems gem 'rake' gem 'rspec' platforms :ruby_18 do gem 'json' gem 'rcov' end gem 'simplecov', :platforms => :ruby_19 tdiary-contrib-3.2.2/Gemfile.lock000066400000000000000000000010451213632744000166740ustar00rootroot00000000000000GEM remote: http://rubygems.org/ specs: diff-lcs (1.2.1) json (1.7.7) multi_json (1.7.1) rake (10.0.3) rcov (1.0.0) rspec (2.13.0) rspec-core (~> 2.13.0) rspec-expectations (~> 2.13.0) rspec-mocks (~> 2.13.0) rspec-core (2.13.1) rspec-expectations (2.13.0) diff-lcs (>= 1.1.3, < 2.0) rspec-mocks (2.13.0) simplecov (0.7.1) multi_json (~> 1.0) simplecov-html (~> 0.7.1) simplecov-html (0.7.1) PLATFORMS ruby DEPENDENCIES json rake rcov rspec simplecov tdiary-contrib-3.2.2/README.en.md000066400000000000000000000004741213632744000163370ustar00rootroot00000000000000# tDiary contrib package This package include some utilities and plugins for tDiary. See documents in each directories. See licenses and copyrights in each theme files. If no license or copyright, it can be distoributed by GPL2, and it has a copyright below: ``` Copyright (c) 2005 TADA Tadashi ``` tdiary-contrib-3.2.2/README.md000066400000000000000000000010231213632744000157250ustar00rootroot00000000000000# tDiary contrib パッケージ このパッケージには、tDiaryに関係したいくつかのユーティリティやプラグ インが収録されています。ドキュメントはそれぞれのツールのディレクトリ に含まれています。 著作権およびライセンスは各テーマのファイルに記述してあるものに従いま すが、特に明記されていない場合、配布条件はGPL2、著作権は以下になりま す。 ``` Copyright (c) 2005 TADA Tadashi ``` tdiary-contrib-3.2.2/Rakefile000066400000000000000000000014361213632744000161230ustar00rootroot00000000000000require 'rubygems' require 'rake' require 'rake/clean' require 'rspec/core/rake_task' CLOBBER.include( "coverage" ) task :default => [:spec] desc 'Run the code in specs' RSpec::Core::RakeTask.new(:spec) do |t| t.pattern = "spec/**/*_spec.rb" end namespace :spec do if defined?(RCov) desc 'Run the code in specs with RCov' RSpec::Core::RakeTask.new(:report) do |t| t.pattern = "spec/**/*_spec.rb" t.rcov = true t.rcov_opts = IO.readlines(File.join('spec', 'rcov.opts')).map {|line| line.chomp.split(" ") }.flatten end else desc 'Run the code in specs with SimpleCov' task :report do ENV['COVERAGE'] = 'simplecov' Rake::Task["spec"].invoke end end end # Local Variables: # mode: ruby # indent-tabs-mode: t # tab-width: 3 # ruby-indent-level: 3 # End: # vim: ts=3 tdiary-contrib-3.2.2/doc/000077500000000000000000000000001213632744000152175ustar00rootroot00000000000000tdiary-contrib-3.2.2/doc/en/000077500000000000000000000000001213632744000156215ustar00rootroot00000000000000tdiary-contrib-3.2.2/doc/en/filter/000077500000000000000000000000001213632744000171065ustar00rootroot00000000000000tdiary-contrib-3.2.2/doc/en/filter/spambayes.txt000066400000000000000000000001571213632744000216360ustar00rootroot00000000000000For detail English : http://www.hinet.mydns.jp/en/?SpamBayes Japanese : http://www.hinet.mydns.jp/?SpamBayes tdiary-contrib-3.2.2/doc/en/plugin.txt000066400000000000000000000000341213632744000176550ustar00rootroot00000000000000== tDiary contrib/plugin == tdiary-contrib-3.2.2/doc/en/style/000077500000000000000000000000001213632744000167615ustar00rootroot00000000000000tdiary-contrib-3.2.2/doc/en/style/hatena.txt000066400000000000000000000005431213632744000207640ustar00rootroot00000000000000== tDiary contrib/sytle/hatena_style == Hatena::Diary compatible style * How to install Copy hatena_style.rb into core/tdiary/ directory, where other styles are. After that, edit tdiary.conf and specify style as 'Hatena'. * TextFormattingRules Refer . All but expression are supported.tdiary-contrib-3.2.2/doc/en/style/markdown.txt000077500000000000000000000010461213632744000213500ustar00rootroot00000000000000== tDiary contrib/sytle/markdown_style == Markdown style * How to install require 'BlueCloth'. get & install from Copy markdown_style.rb into core/tdiary/ directory, where other styles are. After that, edit tdiary.conf and specify style as 'Markdown'. * TextFormattingRules Refer . ** tDiary original feature # =>

& section ## =>

### =>

{{my '20041004p01','test'}} => tDiary's plugin tdiary-contrib-3.2.2/doc/en/util.txt000066400000000000000000000000321213632744000173320ustar00rootroot00000000000000== tDiary contrib/util == tdiary-contrib-3.2.2/doc/ja/000077500000000000000000000000001213632744000156115ustar00rootroot00000000000000tdiary-contrib-3.2.2/doc/ja/filter/000077500000000000000000000000001213632744000170765ustar00rootroot00000000000000tdiary-contrib-3.2.2/doc/ja/filter/antirefspam.history.txt000066400000000000000000000054711213632744000236570ustar00rootroot00000000000000=begin ver 1.0 2005/06/26 ・更新履歴を別ファイルにした ・リンク元のチェックの有無を設定できるようにした (thanks to Kazuhiro NISHIYAMA) ・ブロックしたツッコミをログ(spamcomments)に残すようにした ・一度も設定を行っていない場合にエラーが起きていた不具合を修正 (thanks to Kazuhiro NISHIYAMA) ・"トップページURL" が相対指定になっているときに、チェックをすり抜けてしまうことがあった  不具合を修正 (thanks to Kazuhiro NISHIYAMA) ・"トップページURL" と同様に base_url でもチェックするようにした (thanks to Kazuhiro NISHIYAMA) ・"「リンク元置換リスト」にマッチするリンク元を信頼する" を有効にしており、かつリンク元の  URLの長さが50文字以上だった場合に、チェックをすり抜けてしまっていた不具合を修正   (thanks to Hiroshi Koyasu) ver 0.9 2004/11/24 ・リンク元置換リストにマッチするリンク元を信頼する機能を追加 (thanks to Shun-ichi TAHARA) ・コメントの制限に正規表現を使えるようにした ・HTTP.version_1_2 系を使えなかった場合に動作がおかしかった不具合を修正 ・spamips に出力される時刻の分/秒部分がおかしかったのを修正 ・その他エラーが起きにくいように処理を変更 ver 0.8 2004/11/15 ・プロキシーサーバーを指定する機能を追加 ・ver 0.6m〜0.71 で、Ruby 1.6 系でエラーが出ることがあった不具合を修正 ver 0.71 2004/11/12 ・ver 0.6m と ver 0.7 で、"信頼するリンク元" の指定が適用されなくなっていた不具合を修正 ver 0.7 2004/11/11 ・一部のアンテナで、設定によって更新日時が取れないことがあった問題に対処 ・コメントスパムに対処するため、コメントに制限をかける機能を追加 ver 0.6m 2004/11/07 (MoonWolf) ・ソースのインデント変更 ・if not→unlessへの書き換え等 ver 0.6 2004/11/07 ・トップページURL以外の許容するリンク先を指定できるようにした。 ・設定画面の言語リソースを分割した。 ver 0.5 2004/10/31 ・信頼できるURL に正規表現を使えるようにした ・safeurls, spaurls に、同一の URL が2つ連続で記録される問題に対処した(つもり) ver 0.4 2004/10/20 ・Ruby 1.8.2 (preview2) で動作しなかった不具合を修正 ・接続するポートを80からuri.portに変更 (thanks to MoonWolf) ver 0.3 2004/09/30 ・負荷を下げるための修正をちょっとだけ入れた ver 0.2 2004/09/27 ・信頼できるURLの一覧を設定画面から変更できるようにした ver 0.1 2004/09/15 ・最初のバージョン =end tdiary-contrib-3.2.2/doc/ja/filter/antirefspam.txt000066400000000000000000000075451213632744000221630ustar00rootroot00000000000000# # AntiRefererSpam Plugin # # version 1.0.0G (2005/08/01) # # Copyright (c) 2004-2005 T.Shimomura # You can redistribute it and/or modify it under GPL2. # Please use version 1.0.0 (not 1.0.0G) if GPL doesn't want to be forced on me. # ・これはなにをするもの? tDiary の「本日のリンク元」に、主に海外のアダルトサイトからの大量の アクセス履歴(リファラスパム)が残ってしまうのを防ぐためのプラグイン (厳密にはフィルター)です。 リンク元URLが指すページのHTMLに、日記のアドレスが含まれていなければ 不正なリンク元であるとみなします。 (今のところはこれだけの対処で99%近くをブロックできているみたいです) また、コメントスパムに対処するために、コメントに対して制限をかける 機能もついています。 ・インストール tDiary はバージョン 2.0.0 以降が必要です。2.1 系での動作は未確認。 tDiary をインストールしたディレクトリを $(tdiary_home) としたとき、 plugin/antirefspam.rb を $(tdiary_home)/plugin に、 plugin/ja/antirefspam.rb を $(tdiary_home)/plugin/ja に、 tdiary/filter/antirefspam.rb を $(tdiary_home)/tdiary/filter に、 それぞれコピーしてください。 本プラグインの古いバージョンがある場合は上書きしてかまいません。 古いバージョンで問題なく動作していた場合は、設定を変更する必要も ありません。 ・最低限必要な設定 tDiary の設定画面で、"Anti Referer Spam" の "許容するリンク先の指定" を確認してください。 設定画面に、"トップページURL" と "日記のURL" がカッコつきで書かれて いるはずです。これら以外にリンク先のURLとして許容したいものがあれば、 それを http〜で始まる絶対パス指定で書いてください。 また、tDiary をインストールしてあるサーバーが外部の HTTP サーバーに アクセスする際に HTTP プロキシを経由する必要がある場合は、その設定 も行ってください。 ・さらに細かい設定 [最低限必要な設定]のみでも効果があるはずですが、tDiary の設定画面で "Anti Referer Spam" の「信頼するリンク元の指定」を設定することで、 負荷が軽くなるはずです。 信頼するリンク元には、いくつかのサーチエンジンやアンテナを書いておく とよいでしょう。 詳細な書式については、設定画面に表示されるヒントを参照してください。 ・プラグインが生成するファイル このプラグインは、日記データが存在するディレクトリにAntiRefSpamFilter というディレクトリを作って、その下にいくつかのファイルを作成します。 safeurls 問題ないリンク元とみなした URL の一覧 spamurls 不正なリンク元とみなした URL の一覧 spamips 不正なリンク元とみなした IP の一覧 spamcomments 不正なコメントとみなしたコメントの一覧 safeurls に入るべき URL が、spamurls に登録されてしまった場合は、 その URL を、「信頼するリンク元の指定」で設定してください。 spamurls に入るべき URL が、safeurls に登録されてしまった場合は、 このプラグインを強化する必要があります。 ・このプラグインのバージョン ・日記の URL ・誤判定されてしまった URL を作者に教えてもらえれば対応するかもしれません。 ・FAQ 以下のページにある FAQ を適宜更新します。 http://www.netlife.gr.jp/redbug/diary/?date=20041018#p02 ・連絡先 T.Shimomura tdiary-contrib-3.2.2/doc/ja/filter/comment_key.ja.html000066400000000000000000000250351213632744000226740ustar00rootroot00000000000000 Comment-key Filter & Plugin

コメントキーフィルタ&プラグイン

はじめに

最近、所有者以外が書き込みできるタイプのページ(掲示板やコメント、トラックバックなど)に宣伝目的で大量のデータを書き込む、いわゆるスパム攻撃が激しくなっています。

特に流行のblogなどで被害が顕著ですが、同じように受信出来てしまうtDiaryでも同様のことが起こっています(対抗策が十分でない分、被害を受けやすくなっています)

そこで、tDiaryの持つフィルタ機能とプラグイン機能を利用して、これらのスパムのうちコメントスパムに対して対策を行うのが「コメントキーフィルタ&プラグイン」です。自動的にスパム送信を行うプログラムに対し効果を発揮します。

尚、本フィルタ&プラグインはsheepman発案のコメントスパム対策をフィルタとプラグインのみで実現したものです。

動作環境

動作に必要な条件は以下の通りです。

  • tDiary 2.0.0以上のシステム
  • 自前でプラグイン及びフィルタがインストール出来る

インストール・アンインストール

  • key.rb を tdiary/filter 下に配置します。
  • comment_key.rb を misc/plugin 下に、 ja/cooment_key.rb を misc/plugin/ja 下に配置します。
  • tDiary の設定ページにアクセスし、「プラグイン選択」にて comment_key.rb を有効にしてください。

これでインストールは完了です。フィルタとプラグインの両方をインストールしないと動作しませんので注意してください。

使い方

インストールが完了した時点で、設定ページのプラグインメニューに「コメントキーフィルタ」が表示されます。このページにまずは移動してください。

このページの「コメントキーフィルタを有効にする」のチェックを有効にすることで、とりあえずフィルタが有効になります。

その下にはキーの値を生成する際に使用する文字列を指定します。この文字列がキーの値の元になる文字列の一部となりますので、お好きな文字列を設定してください。この文字列が他の人の日記のものと同一だと、生成されるキーはやはり同一になってしまうのでご注意を。

その下にある「常に同一の鍵文字列を生成する」は通常は必要ありませんのでそのままにしておいてください。

以上が設定し終わると、このフィルタが機能します。

動作原理

本フィルタはsheepmanさんのコメントスパム対策を移植したものなので原理は同じですが、一応説明しておきます。

本プラグイン&フィルタはコメントフォームに対し、値として日付ごとに一意な文字列を持つキー "comment_key" を追加し*1、コメント書き込み時にこのキーとフィルタ内で生成した文字列を比較することで「日記表示時にそのページにあったコメントフォームから書き込んだのか?」を判定します。

判定がNGとなった場合はコメントの保存を行いません。

キーに設定された文字列は、元となるキー文字列のMD5チェックサムになっていて、元となるキー文字列を容易に推測されないようになっています。

*1 日付に関係なく同一の文字列を生成することも出来ますが突破されやすくなります。詳しくはFAQを参照

FAQ

Q1. 最新表示でコメントできない

もしかして、speed_comment.rbプラグインを使っていませんか?その場合、この本プラグイン&フィルタではコメント対象の日付が特定できません。その時は設定ページにある「常に同一の鍵文字列を生成する」のチェックを入れれば一応コメントできるようになります。

ただし、最新表示のみならず日付別表示でも常に同じ鍵文字列を生成するので多少コメントスパムの突破率は上がると思います。

おことわり

このフィルタ&プラグインはコメントスパムを防止する目的で作成されていますが、これを完全に防ぐことはできませんのでご了承ください。

例: 表示された日記のコメントフォームを解析したうえでスパム送信を行うようなプログラムなど

ライセンスなど

「コメントキーフィルタ&プラグイン」はGPLライセンスに従い公開・配布されるものです。

謝辞

このフィルタ&プラグインは、コメントスパムに困っていた時に見つけたsheepmanさんのコメントスパム対策を使いたいんだけど、本体に手を入れたくない。なんとかならないか…と考えて出来たものです。重要な部分はほぼそのまま使わせてもらっています。ありがとうございます。

これでなんとかコメントスパムが減ればいいな…。

履歴

2005/08/31 (Ver.0.5.0)
設定ページのカテゴリに対応(tDiary-2.1.2.20050826以降)
2005/04/17 (Ver.0.4.0)
常に同一の鍵文字列を生成するオプションを追加
2005/03/21 (Ver.0.3.0)
携帯からコメントが出来なくなっていたのを修正
2005/01/25 (Ver.0.2.0)
TrackBack及びPingbackの投稿にも適用されてしまっていたのを修正
2005/01/15 (Ver.0.1.0)
初版公開
Copyright © ハハハハ 2001-2005 All Right Reserved.
E-Mail: rin_ne-at-big.or.jp
tdiary-contrib-3.2.2/doc/ja/filter/spambayes.txt000066400000000000000000000001571213632744000216260ustar00rootroot00000000000000For detail Japanese : http://www.hinet.mydns.jp/?SpamBayes English : http://www.hinet.mydns.jp/en/?SpamBayes tdiary-contrib-3.2.2/doc/ja/plugin.txt000066400000000000000000000010631213632744000176500ustar00rootroot00000000000000== tDiary contrib/plugin == ここに収録されたプラグインは、 * 汎用性が低い * 国際化対応されていない(する意味がない) * tDiaryのバージョンに合わせたアップデートがされていない * tDiary本体または標準プラグインの動作環境から外れている 等の理由でプラグイン集への収録が見送られているものですが、 それぞれはとても有用なプラグインです。 個々の説明は、それぞれのプラグインのディレクトリに入っています。 tdiary-contrib-3.2.2/doc/ja/plugin/000077500000000000000000000000001213632744000171075ustar00rootroot00000000000000tdiary-contrib-3.2.2/doc/ja/plugin/add_bookmark.txt000066400000000000000000000026711213632744000222730ustar00rootroot00000000000000!概要 subtitleの右にソーシャルブックマークへのリンクを埋め込みます。 !使い方 プラグインフォルダに配置するだけで使用可能です。 プラグイン選択画面で有効に変更後、設定画面で埋め込みたいブックマークを選択します。 !ライセンス GPL2 !更新履歴 !!20070215 * サービスから MM/Memo を削除 * サービスに livedoor クリップ と Buzzurl を追加 !!20070109 * サニタイズキャンペーンに伴う修正 !!20050906 * HTML4.01 Strictに準拠 * セクションのURLをエスケープするように変更 !!20050901 * はてなブックマークのURLを修正 !!20050828 * add_subtitle_procに対応 * webshots,LiVEMARK,fc2ブックマークを削除 * 強制的にアイコンを使用するように設定 !!20050602 * はてなブックマークのアイコンの修正 * del.icio.usのURLの修正 !!20050601 * LiVEMARKに対応 * はてなブックマーク、del.icio.us、MM/Memoをアイコンで表示できるようにした。 !!20050528 * @confの値とdayモードの判定方法を変更 * 処理でイテレータを使うように変更 * 英語リソースの追加 * webshotsに対応 * fc2ブックマークに対応 !!20050525 * 初版公開 !参考情報 add_conf_procのチェックボックス処理についてはsearch_control.rb、body_enter_procについてはrandom_google.rbを参考にしました。 tdiary-contrib-3.2.2/doc/ja/plugin/category_to_tag.txt000066400000000000000000000016621213632744000230270ustar00rootroot00000000000000category_to_tag.rb - カテゴリをタグ風に表示します。 ※tDiary 2.1.3.20051012以降でのみ動作します。 ■使い方 インストールするだけで使えるようになります。日記モードのcategory.rbか、 BlogKitのblog-category.rbのいずれかと併用して使います。 なお、これらの併用プラグインよりもあとに読み込まれなければいけません。 プラグイン選択を使う場合には@options['sp.path']で指定したパスの最後の ディレクトリに入れるか、いっそプラグイン選択を使わずに、tDiary本体の pluginディレクトリに入れてしまうのがよいでしょう。 なお、タグの一覧はスタイルシートで「div.tags」を指定することで見栄え を変更できます。append-css.rbを使うといいでしょう。 例: div.day div.tags { text-align: right; font-size: 80%; } tdiary-contrib-3.2.2/doc/ja/plugin/cocoment.txt000066400000000000000000000013221213632744000214550ustar00rootroot00000000000000! 名前 coCommentプラグイン ! 概要 tDiaryをcoComment(http://www.cocomment.com/)に対応させるプラグイン !使い方 プラグインフォルダに入れるだけで動作します。 !ライセンス GPL2 !更新履歴 !!20070309 * mobile_agent? の使用方法を修正 !!20070213 * ケータイ端末からのアクセスは無視するようにした !!20070212 * IE7でのスクリプトエラーに対処(埋め込む Javascript を微調整) !!20070118 * postURLとpostTitleを取得するときにjavascriptを使わないようにした。 !!20070117 * tDiary-contrib 追加に伴って name 属性 comment-form を core に追加 * cocomment-fetchlet を追加 !!20060527 * 初版公開 tdiary-contrib-3.2.2/doc/ja/plugin/google_adsense.txt000066400000000000000000000020431213632744000226250ustar00rootroot00000000000000google_adsense.rb - Googe AdSenseのバナー広告を挿入するプラグイン プラグイン選択で選択し、日記のヘッダやフッタなど、任意の場所に以下の ように指定するだけで使えます。 <%= google_adsense %> バナーのサイズや色は、設定画面から変更可能です。 なお、配布されているgoogle_adsense.rbには、tDiary.Net 用のAdSense IDが書かれているので、このまま使うとtDiary.Netの広告収入 になってしまいます。自分のAdSense IDを使いたい場合には、ファイルの最 初の方にある以下の部分を、自分のIDに合わせて書き換えてください。 google_ad_client = "pub-3317603667498586" ~~~~~~~~~~~~~~~~~~~~この部分がID 2005-10-12追記 セクションターゲット(※)に対応しました。タグは日記の各日付の最初と最後に挿入 されます。 ※https://www.google.com/support/adsense/bin/answer.py?answer=23168&topic=371 tdiary-contrib-3.2.2/doc/ja/plugin/google_analytics.txt000066400000000000000000000005351213632744000231760ustar00rootroot00000000000000google_analytics.rb - Googe Analyticsの解析用コードを挿入する プラグイン選択で選択し、設定画面でProfile IDを指定すれば使えます。 Profile IDは、Analyticsのページでサイトを登録すると表示されるJavaScript中にある、 「UA-xxxxx-x」のうち、「xxxxx-x」の部分のことです。 tdiary-contrib-3.2.2/doc/ja/plugin/image_detail.txt000066400000000000000000000042761213632744000222650ustar00rootroot00000000000000image_detail.rb 機能 JPEGファイルに含まれるExif情報を解析し、各種撮影条件を表示します。 また、位置情報が含まれる場合、周辺地図ををポップアップ表示し、 Googleマップへのリンクを生成します。 更新情報 revision 1.0: ファーストリリース revision 1.1: スマートフォン対応、その他 インストール このPluginはimage.rbが導入されていることを前提としています。 image.rbを有効にしてください。また、image_ex.rbと共存することはできません。 ・ExifParserの導入 image_detail.rbはExifのパーサとして、ExifParserを使用しています。 tdiary/lib/ExifParser/READMEに従って導入してください。 ・Pluginのインストール image_detail.rbを適切な場所に配置してください。多言語用リソースは存在しません。 ・Google Maps API Keyの取得 http://code.google.com/intl/ja/apis/maps/signup.html にてAPIキーを生成し、[設定]-[その他]-[image_gpsの設定]の Google Maps API Keyに生成されたAPIキーを設定してください。 APIキーが設定されていない場合、地図のポップアップ表示および モバイルモードでの地図の表示ができません。 ・CSSの追加 写真と撮影条件をそれっぽく表示するために、CSSを設定する必要があります。 apend_css.rbを使用すると簡単にCSSを追加することができます。 参考に、作者が設定しているCSSを示します。 --ここから img.photo{ float:left; clear:both; } div.photo_detail{ clear:both; display:block; margin:0.5em; padding:0.5em; } div.photo_detail ul{ list-style-type:none; } img.map { outline:solid 5px gray; } --ここまで 使用方法 プラグインの書式は、image.rbと同じです。 画像がJPEGかつExif情報を含む場合各種撮影条件を表示します。 Exif情報に位置情報が含まれている場合、地図をポップアップ表示し、 Googleマップへのリンクを生成します。 制限事項 secureモードには対応していません。 image_ex.rbと同時に使用することはできません。 tdiary-contrib-3.2.2/doc/ja/plugin/image_gps.txt000066400000000000000000000031771213632744000216130ustar00rootroot00000000000000image_gps.rb 機能 アップロードした画像に含まれているGPSの位置情報を使用して、 対応する地図へのリンクを生成します。また、画像ファイルに機種名などの情 報が含まれている場合、タイトル情報として表示する事が可能です。 更新情報 revision 1.7: リンク先をGoogleMapにした。 モバイルモード時も世界測地系に変換する。 インストール このPluginはimage.rbが導入されていることを前提としています。 image.rbを有効にしてください。また、image_ex.rbと共存することはできません。 ・ExifParserの導入 image_gps.rbはExifのパーサとして、ExifParserを使用しています。 tdiary/lib/ExifParser/READMEに従って導入してください。 ・Pluginのインストール image_gps.rbを適切な場所に配置してください。多言語用リソースは存在しません。 使用方法 image.rbと同じです。画像にGPSの情報が含まれている場合は自動的に GoogleMAP(http://maps.google.co.jp/ )へのリンクを生成します。 携帯端末でアクセスした場合は、http://walk.eznavi.jp/ へのリンクを生成します。 auのezナビウォーク対応機種ではezナビウォークを起動するページが表示されます。 それ以外の端末ではhttp://map.navitime.jp/ へリダイレクトされます。 サムネイル画像が指定されている場合は、そちらが優先されます。 制限事項 secureモードには対応していません。 image_ex.rbと同時に使用することはできません。 tdiary-contrib-3.2.2/doc/ja/plugin/image_gps2.txt000066400000000000000000000034401213632744000216660ustar00rootroot00000000000000image_gps2.rb 機能 アップロードした画像に含まれているGPSの位置情報を使用して、 対応する地図をポップアップ表示します。また、画像ファイルに機種名などの情 報が含まれている場合、タイトル情報として表示する事が可能です。 更新情報 revision 0.8: first release. image_gps.rbからフォークしたよ。 インストール このPluginはimage.rbが導入されていることを前提としています。 image.rbを有効にしてください。また、image_ex.rbと共存することはできません。 ・ExifParserの導入 image_gps2.rbはExifのパーサとして、ExifParserを使用しています。 tdiary/lib/ExifParser/READMEに従って導入してください。 ・Pluginのインストール image_gps2.rbを適切な場所に配置してください。多言語用リソースは存在しません。 ・Google MAPS APIキーの設定 このPluginを使用するには、Google MAPS APIのキーを取得し、設定する必要があります。 http://code.google.com/intl/ja/apis/maps/signup.html にてtDiaryのあるドメインの URLを入力し、キーを取得してください。 取得したキーを[設定]-[その他]-[image_gpsの設定]のGoogle Maps API Keyに 設定すると使用できるようになります。 使用方法 image.rbと同じです。画像にGPSの情報が含まれている場合はマウスオーバー でGoogle Maps Static APIを利用した地図をポップアップで表示します。 携帯端末でアクセスした場合は、リンク先がGoogle Maps Static APIで生成した 地図の画像となります。 制限事項 secureモードには対応していません。 image_ex.rbと同時に使用することはできません。 tdiary-contrib-3.2.2/doc/ja/plugin/livedoor_weather.txt000066400000000000000000000074701213632744000232220ustar00rootroot00000000000000! 概要 [[Weather Hacks - livedoor 天気情報|http://weather.livedoor.com/weather_hacks/]]を利用して日記に天気情報を埋め込むプラグイン !使い方 インストールしたら、設定画面で天気情報を取得する都市IDを設定してください。日記更新時に天気情報を取得します。 デフォルトでは日記の一日単位上部に天気情報を埋め込みます。 !!CSS div.lwws { text-align: right; font-size: 0.8em; } 上記のように設定すると見やすくなります。 !!キャッシュファイル 天気情報はxml形式で @cache_path/lwws/YYYYMMDD.xml というファイルに保存しています。 !!プラグイン呼び出し !!!lwws_today 今日の天気を表示します。 !!!lwws_tomorrow 明日の天気を表示します。 !!!lwws_dayaftertomorrow 明後日の天気を表示します。 !!!使い方 例えば(Wikiスタイルの例) ||今日||明日||明後日 ||{{lwws_today}}||{{lwws_tomorrow}}||{{lwws_dayaftertomorrow}} と書くと三日分の天気が表で表示されます。 サイドバーなどに使うとかっこいいかもしれません。 !ToDo *セキュア対応 *キャッシュの削除機能 *(他にあれば募集します) !ライセンス GPL2 !更新履歴 !!20070329 * open-uri の proxy を tdiary.conf から読み込むようにした !!20070214 * feed 生成時の出力を抑制 !!20070206 * NKFを使うのをやめて @conf.to_native を使うようにした * proxy の削除(trunk に追従) * to_native の第二引数として utf-8 を指定 !!20070109 * サニタイズキャンペーンに伴う修正 !!20060712 * lwws_getのバグ修正 !!20060709 * 設定更新時には強制的にキャッシュを再取得するように変更 !!20060702 * lwws_getの処理を変更 !!20060310 * 設定が保存されない不具合の修正 !!20060309 * キャッシュの自動更新を設定可能にする * 自動更新間隔を任意で設定可能にする ** 自動更新間隔を0にするとアクセスするたびにLWWSをたたくようになるので、適当に6-12くらいの数字を入れるのを推奨。 !!20060219 * 携帯閲覧時には画像を非表示 * 画像にtitle要素としてtelopエレメントを追加 !!20060213 * キャッシュファイルを6時間で更新するようにした。 * 任意の日付の天気を表示するlwwsメソッドを追加 !!20060212 * 新規メソッドとしてlwws_today,lwws_tomorrow,lwws_dayaftertomorrowを追加。プラグイン呼び出しとして、任意の場所に天気を表示します。 * 表示項目を変更機能の追加(設定画面)。 * アイコン表示機能の追加(設定画面)。 * 詳細へのリンクは天候に作成するようにした。(アイコンの場合はアイコンに設定) * convert_dateメソッドを追加。date_statusからYYYYMMDD形式の文字列を返します。 * 英語リソースをでっちあげた。(中国語は英語リソースの焼きまわし) * 「℃」を言語リソースに移動 * lwws_to_thmlメソッドで任意の日付を指定可能にした。 !!20060211 * lwws_getメソッドの引数をdateからdate_status(today,tomorrow,dayaftertomorrow)へと変更 * 設定画面の不要なエスケープを修正 * lwws_getメソッドでxmlを保存する時にYYYYMMDD形式になっていないバグを修正 !!20060210 * 最初のリリース * Uconvではなく、NKFを使ってUTF-8を扱うようにした。 * typo(というか、コピペ修正ミス)を直した。 * 最高気温、最低気温が存在する場合には表示するようにした。 * livedoor天気情報へのリンクを作るようにした。 * proxyの情報はamazon.proxyに統合した。tdiary-contrib-3.2.2/doc/ja/plugin/opensearch_ad.txt000066400000000000000000000006451213632744000224500ustar00rootroot00000000000000! 名前 OpenSearch Auto-Discovery プラグイン ! 概要 tDiaryをOpenSearch Auto-Discoveryに対応させるプラグイン !使い方 利用するには OpenSearch description XML をあらかじめ作成する必要があります。 サンプルファイルは http://www.opensearch.org/Specifications/OpenSearch/1.1 にあります。 !ライセンス GPL2 !更新履歴 !!20070117 * tDiary-contrib に追加 tdiary-contrib-3.2.2/doc/ja/plugin/section_footer.txt000066400000000000000000000057341213632744000227030ustar00rootroot00000000000000! 概要 セクションの後ろにナビゲーションを追加するプラグイン。 以下の項目が追加されます。 * タグ(カテゴリ) * このエントリを含むはてなブックマーク * はてなブックマークコメント表示 * このエントリを含む del.icio.us * このエントリを含む livedoor クリップ * このエントリを含む Buzzurl * Permalink !注意事項 * blogkitでは動きません * セキュアな環境では動きません * category_to_tag.rb と同時に使うことはできません * Permalinkやアイコンは用途に合わせてadd_section_leave_procから適当に削ってください * 利用するには [[JSON library for Ruby|http://rubyforge.org/projects/json/]] が必要(lib 以下に配置済み) ! 動作事例 http://www.hsbt.org/diary/ !ライセンス GPL2 ! Changelog !!20070323 * del.icio.us Image API 使用時に ?aggregate を追加 !!20070322 * 画像取得API に対応 !!20070321 * JSON library for Ruby を追加 !!20070215 * アイコンを本家から持ってくるようにした !!20070212 * Buzzurl(http://buzzurl.jp) に対応した !!20070210 * Permalink 生成時の余計なエスケープをしないようにした !!20070206 * NKFを使うのをやめて @conf.to_native を使うようにした * to_native の第二引数として utf-8 を指定 !!20070205 * delicious JSON のキャッシュデータは @cache/delicious/YYYYMM に作成するようにした !!20070204 * 全面的に見直し、追加関係のリンクは生成しないようにした * del.icio.us の JSON API に対応、ブックマーク数を表示できるようにした * はてなブックマーク、livedoor クリップのブックマーク数画像表示APIに対応させた * 上記のAPIを使うようにしたため、まちゅさんのブックマークカウントキャッシュは使わないようにした !!20060107 * リンク追加処理をメソッドとして分離 !!20051229 * [[人気の日記プラグイン (はてなブックマーク + MM/Memo) - まちゅダイアリー (2005-12-27)|http://www.machu.jp/diary/20051227.html#p03]]の改造の取り込み !!20051227 * [[人気の日記プラグイン (はてなブックマーク) - まちゅダイアリー (2005-12-27)|http://www.machu.jp/diary/20051227.html#p02]]の改造の取り込み !!20051207 * 「このエントリを含むdel.icio.us」のリンクを追加 !!20051129 * 「このエントリを含むMM/Memo」のリンクを追加 !!20051124 * 「このエントリをdel.icio.usに追加」のリンクを追加 !!20051121 * 携帯からのアクセスの時には表示しないようにした。 !!20051114 * 最初のリリース ! 謝辞 このプラグインはたださんが作ったcategory_to_tag.rbとえろぺおさんによる[[tDiary の指定したセクションの permalink を求める|http://bigfield.ddo.jp/diary/20051026.html#p01]]をインスパイヤしました。ありがとうございました! tdiary-contrib-3.2.2/doc/ja/plugin/select_theme.txt000066400000000000000000000000511213632744000223050ustar00rootroot00000000000000See: http://arika.org/diary/20050421#p01 tdiary-contrib-3.2.2/doc/ja/style/000077500000000000000000000000001213632744000167515ustar00rootroot00000000000000tdiary-contrib-3.2.2/doc/ja/style/hatena.txt000066400000000000000000000010601213632744000207470ustar00rootroot00000000000000== tDiary contrib/sytle/hatena_style == はてなダイアリー互換スタイルです。 * インストール方法 添付の hatena_style.rb を他のスタイルと同様 core/tdiary/ に投入してください。 その後、 tdiary.conf でスタイルを 'Hatena' と指定すると有効になります * 記法 記法に関してははてなダイアリーのヘルプを参照してください。ここに記載されていることのうち、以外には対応しています。tdiary-contrib-3.2.2/doc/ja/style/markdown.txt000077500000000000000000000015121213632744000213360ustar00rootroot00000000000000== tDiary contrib/sytle/markdown_style == Markdownスタイルです。 * インストール方法 BlueClothが必要です。から入手してインストールしてください。 添付の markdown_style.rb を他のスタイルと同様 core/tdiary/ に投入してください。 その後、 tdiary.conf でスタイルを 'Markdown' と指定すると有効になります * 記法 記法に関してはMarkdown文法紹介を参照してください。 tDiaryでの拡張として#が

に##が

になります。セクションの区切りは#で行います。 tDiaryのプラグインを呼び出すには{{〜}}で囲みます。(例: {{my '20041004p01','test'}} ) tdiary-contrib-3.2.2/doc/ja/util.txt000066400000000000000000000007001213632744000173240ustar00rootroot00000000000000== tDiary contrib/util == ここに収録されたツールは、 * 汎用性が低い * 国際化対応されていない(する意味がない) * tDiaryのバージョンに合わせたアップデートがされていない 等の理由でcoreへの収録が見送られているものですが、 それぞれはとても有用なユーティリティです。 個々の説明は、それぞれのディレクトリに入っています。 tdiary-contrib-3.2.2/filter/000077500000000000000000000000001213632744000157375ustar00rootroot00000000000000tdiary-contrib-3.2.2/filter/antirefspam.rb000066400000000000000000000230051213632744000205750ustar00rootroot00000000000000# # antirefspam.rb # # Copyright (c) 2004-2005 T.Shimomura # You can redistribute it and/or modify it under GPL2. # Please use version 1.0.0 (not 1.0.0G) if GPL doesn't want to be forced on me. # require 'net/http' require 'uri' module TDiary module Filter class AntirefspamFilter < Filter # 有効にすると指定したファイルにデバッグ情報文字列を追記する def debug_out(filename, str) if $debug filename = File.join(@conf.data_path,"AntiRefSpamFilter",filename) File::open(filename, "a+") {|f| f.puts str } end end # str に指定された文字列が適切なリンク先を含んでいるかをチェック def isIncludeMyUrl(str) # str に日記のURLが含まれているかどうか base_url = @conf.base_url unless base_url.empty? if str.include? base_url return true end end # str にトップページURLが含まれているかどうか unless @conf.index_page.empty? if @conf.index_page.index(URI.regexp(%w[http https])) == 0 if str.include? @conf.index_page return true end end end # str に許容するリンク先が含まれているかどうか if (myurl = @conf['antirefspam.myurl']) && !myurl.empty? if str.include? myurl return true end #url = myurl.gsub("/", "\\/").gsub(":", "\\:") #exp = Regexp.new(url) exp = Regexp.union(myurl) if exp =~ str return true end end return false end def referer_filter(referer) conf_disable = @conf['antirefspam.disable'] != nil ? @conf['antirefspam.disable'].to_s : '' conf_checkreftable = @conf['antirefspam.checkreftable'] != nil ? @conf['antirefspam.checkreftable'].to_s : '' conf_trustedurl = @conf['antirefspam.trustedurl'] != nil ? @conf['antirefspam.trustedurl'].to_s : '' conf_proxy_server = @conf['antirefspam.proxy_server'] != nil && @conf['antirefspam.proxy_server'].size > 0 ? @conf['antirefspam.proxy_server'].to_s : nil conf_proxy_port = @conf['antirefspam.proxy_port'] != nil && @conf['antirefspam.proxy_port'].size > 0 ? @conf['antirefspam.proxy_port'].to_s : nil if conf_disable == 'true' or # リンク元チェックが有効ではない場合はスルーする referer == nil or # リンク元が無い referer.size <= 1 or # 一部のアンテナで更新時刻が取れなくなる問題に対応するため、リンク元が1文字以内の場合は許容 isIncludeMyUrl(referer) # 自分の日記内からのリンクは信頼する then return true end # "信頼できるURL" を1つずつ取り出してrefererと合致するかチェックする conf_trustedurl.each_line do |trusted| trusted.sub!(/\r?\n|\r/,'') next if trusted =~ /\A(\#|\s*)\z/ # #または空白で始まる行は読み飛ばす # まずは "信頼できる URL" が referer に含まれるかどうか if referer.include? trusted debug_out("trusted", trusted+" (include?) "+referer) return true end # 含まれなかった場合は "信頼できる URL" を正規表現とみなして再チェック begin #if referer =~ Regexp.new( trusted.gsub("/", "\\/").gsub(":", "\\:") ) if referer =~ Regexp.union( trusted ) debug_out("trusted", trusted+" (=~) "+referer) return true end rescue debug_out("error_config", "trustedurl: "+trusted) end end # URL置換リストを見る if conf_checkreftable == 'true' # "URL置換リスト" を1つずつ取り出してrefererと合致するかチェックする @conf.referer_table.each do |url, name| begin if /#{url}/i =~ referer && url != '^(.{50}).*$' debug_out("trusted", url+" (=~referer_table) "+referer) return true end rescue debug_out("error_config", "referer_table: "+url) end end end @work_path = File.join(@conf.data_path,"AntiRefSpamFilter") @spamurl_list = File.join(@work_path,"spamurls") # referer spam のリンク元一覧 @spamip_list = File.join(@work_path,"spamips") # referer spam のIP一覧 @safeurl_list = File.join(@work_path,"safeurls") # おそらくは問題のないリンク元一覧 # ディレクトリ/ファイルが存在しなければ作る unless File.exist? @work_path Dir::mkdir(@work_path) end unless File.exist? @spamurl_list File::open(@spamurl_list, "a").close end unless File.exist? @safeurl_list File::open(@safeurl_list, "a").close end uri = URI.parse(referer) temp_filename = File.join(@work_path,uri.host) # チェック時には対象のドメイン名を持った一時ファイルを作る begin File::open(temp_filename, File::RDONLY | File::CREAT | File::EXCL).close # 一度 SPAM URL とみなしたら以後は以後は拒否 spamurls = IO::readlines(@spamurl_list).map {|url| url.chomp } if spamurls.include? referer return false end # 一度 SPAM URL でないと判断したら以後は許可 safeurls = IO::readlines(@safeurl_list).map {|url| url.chomp } if safeurls.include? referer return true end # リンク元 URL の HTML を引っ張ってくる Net::HTTP.version_1_2 # おまじないらしい body = "" begin Net::HTTP::Proxy(conf_proxy_server, conf_proxy_port).start(uri.host, uri.port) do |http| if uri.path == "" response, = http.get("/") else response, = http.get(uri.request_uri) end body = response.body end # body に日記の URL が含まれていなければ SPAM とみなす unless isIncludeMyUrl(body) File::open(@spamurl_list, "a+") {|f| f.puts referer } File::open(@spamip_list, "a+") {|f| f.puts [@cgi.remote_addr, Time.now.utc.strftime("%Y/%m/%d %H:%M:%S UTC")].join("\t") } return false else File::open(@safeurl_list, "a+") {|f| f.puts referer } end rescue # エラーが出た場合は @spamurl_list に入れない&リンク元にも入れない return false end rescue StandardError, TimeoutError # 現在チェック中なら、今回はリンク元に勘定しない return false ensure begin File::delete(temp_filename) rescue end end return true end def log_spamcomment( diary, comment ) @work_path = File.join(@conf.data_path,"AntiRefSpamFilter") @spamcomment_list = File.join(@work_path,"spamcomments") # comment spam の一覧 # ディレクトリ/ファイルが存在しなければ作る unless File.exist? @work_path Dir::mkdir(@work_path) end unless File.exist? @spamcomment_list File::open(@spamcomment_list, "a").close end File::open(@spamcomment_list, "a+") {|f| f.puts "From: "+comment.name+" <"+comment.mail+">" f.puts "To: "+diary.date.to_s f.puts "Date: "+comment.date.to_s f.puts comment.body f.puts ".\n\n" } end def comment_filter( diary, comment ) # ツッコミに日本語(ひらがな/カタカナ)が含まれていなければ不許可 if @conf['antirefspam.comment_kanaonly'] != nil if @conf['antirefspam.comment_kanaonly'].to_s == 'true' unless comment.body =~ /[ぁ-んァ-ヴー]/ log_spamcomment( diary, comment ) return false end end end # ツッコミの文字数が指定した上限以内でないなら不許可 maxsize = @conf['antirefspam.comment_maxsize'].to_i if maxsize > 0 unless comment.body.size <= maxsize log_spamcomment( comment ) return false end end # NGワードが1つでも含まれていたら不許可 if @conf['antirefspam.comment_ngwords'] != nil ngwords = @conf['antirefspam.comment_ngwords'] ngwords.to_s.each_line do |ngword| ngword.sub!(/\r?\n|\r/,'') if comment.body.downcase.include? ngword.downcase log_spamcomment( comment ) return false end # 含まれなかった場合は "NGワード" を正規表現とみなして再チェック begin if comment.body =~ Regexp.new( ngword, Regexp::MULTILINE ) log_spamcomment( comment ) return false end rescue debug_out("error_config", "comment_ngwords: "+ngword) end end end return true end end end end tdiary-contrib-3.2.2/filter/commentkey.rb000066400000000000000000000014461213632744000204440ustar00rootroot00000000000000# # comment_key.rb: Comment-key filter Ver.0.5.0 # included TDiary::Filter::CommentKeyFilter class # # caution: # * This filter must use together plugin 'comment_key.rb'. # # see: # http://www20.big.or.jp/~rin_ne/soft/tdiary/commentkey.htm # # Copyright (c) 2005 Hahahaha # Distributed under the GPL # module TDiary module Filter class CommentkeyFilter < Filter def comment_filter( diary, comment ) return true unless @conf['comment_key.enable'] return true if /^(?:TrackBack|Pingback)$/ =~ comment.name require 'digest/md5' keyprefix = @conf['comment_key.prefix'] || 'tdiary' vkey = Digest::MD5.hexdigest(keyprefix + (@conf['comment_key.nodate'] == 'true' ? "" : @cgi.params['date'][0])) vkey == @cgi.params['comment_key'][0] end end end end tdiary-contrib-3.2.2/filter/commentsize.rb000066400000000000000000000006051213632744000206220ustar00rootroot00000000000000# # comment_size.rb: included TDiary::Filter::CommentSizeFilter class # module TDiary module Filter class CommentsizeFilter < Filter def comment_filter( diary, comment ) return false if comment.body.size > @conf['comment.size'] true end def referer_filter( referer ) true end end end end tdiary-contrib-3.2.2/filter/hidecomment.rb000066400000000000000000000004561213632744000205650ustar00rootroot00000000000000# # ref. http://www.cozmixng.org/retro/projects/tdiary/ticket/60 # module TDiary::Filter class HidecommentFilter < Filter def comment_filter( diary, comment ) comment.show = false # ツッコミを非表示にするが true # spam扱いにはしない end end end tdiary-contrib-3.2.2/filter/iplookup.rb000066400000000000000000000032171213632744000201310ustar00rootroot00000000000000# # iplookup.rb: included TDiary::Filter::IplookupFilter class # # # Copyright (c) 2008 SHIBATA Hiroshi # Distributed under the GPL2 # require 'resolv' module TDiary module Filter class IplookupFilter < Filter def iplookup_init if @conf.options.include?('iplookup.ip.list') @iplookup_ip_list = @conf.options['iplookup.ip.list'] else @iplookup_ip_list = "bsb.spamlookup.net\nopm.blitzed.org\n" + "niku.2ch.net\ndnsbl.spam-champuru.livedoor.com" end end def black_ip?( address ) chance = 2 ip = address.gsub(/^(\d+)\.(\d+)\.(\d+)\.(\d+)$/, '\4.\3.\2.\1') @iplookup_ip_list.split(/\n+/).each do |dnsbl| begin address = Resolv.getaddress( "#{ip}.#{dnsbl}" ) return true rescue Resolv::ResolvTimeout if chance > 0 chance -= 1 retry end rescue Resolv::ResolvError rescue Exception end end return false end def comment_filter( diary, comment ) iplookup_init return false if black_ip?( @cgi.remote_addr ) return true end def referer_filter( referer ) iplookup_init return false if black_ip?( @cgi.remote_addr ) return true end end end end tdiary-contrib-3.2.2/filter/plugin/000077500000000000000000000000001213632744000172355ustar00rootroot00000000000000tdiary-contrib-3.2.2/filter/plugin/antirefspam.rb000066400000000000000000000052671213632744000221050ustar00rootroot00000000000000# # antirefspam.rb # # Copyright (c) 2004-2005 T.Shimomura # You can redistribute it and/or modify it under GPL2. # Please use version 1.0.0 (not 1.0.0G) if GPL doesn't want to be forced on me. # add_conf_proc( 'antirefspam', 'Anti Referer Spam', 'security') do if @mode == 'saveconf' @conf['antirefspam.disable'] = @cgi.params['antirefspam.disable'][0] @conf['antirefspam.trustedurl'] = @cgi.params['antirefspam.trustedurl'][0] @conf['antirefspam.checkreftable'] = @cgi.params['antirefspam.checkreftable'][0] @conf['antirefspam.myurl'] = @cgi.params['antirefspam.myurl'][0] @conf['antirefspam.proxy_server'] = @cgi.params['antirefspam.proxy_server'][0] @conf['antirefspam.proxy_port'] = @cgi.params['antirefspam.proxy_port'][0] @conf['antirefspam.comment_kanaonly'] = @cgi.params['antirefspam.comment_kanaonly'][0] @conf['antirefspam.comment_maxsize'] = @cgi.params['antirefspam.comment_maxsize'][0] @conf['antirefspam.comment_ngwords'] = @cgi.params['antirefspam.comment_ngwords'][0] end <<-HTML #{@antispamref_html_antispamref}

#{@antispamref_html_myurl}

#{@antispamref_html_proxy}

server : port :

#{@antispamref_html_trustedurl}

#{@antispamref_html_comment}

#{@antispamref_html_comment_maxsize}

#{@antispamref_html_comment_ngwords}

#{@antispamref_html_faq} HTML end tdiary-contrib-3.2.2/filter/plugin/commentkey.rb000066400000000000000000000030601213632744000217340ustar00rootroot00000000000000# # comment_key.rb: Comment-key plugin Ver.0.5.0 # # functions: # * add "comment_key" key in comment form. # # caution: # * This plugin must use together filter 'comment_key.rb'. # # see: # http://www20.big.or.jp/~rin_ne/soft/tdiary/commentkey.htm # # Copyright (c) 2005 Hahahaha # Distributed under the GPL # alias :orig_comment_name_label :comment_name_label alias :orig_comment_name_label_short :comment_name_label_short def comment_name_label comment_key( orig_comment_name_label ) end def comment_name_label_short comment_key( orig_comment_name_label_short ) end def comment_key( label ) return label unless @conf['comment_key.enable'] require 'digest/md5' keyprefix = @conf['comment_key.prefix'] || 'tdiary' vkey = Digest::MD5.hexdigest(keyprefix + (@conf['comment_key.nodate'] == 'true' ? "" : @date.strftime( '%Y%m%d' ))) %Q!\n#{label}! end # configuration if TDIARY_VERSION >= '2.1.2.20050826' then add_conf_proc( 'comment_key', @comment_key_label_conf, 'security' ) do comment_key_conf end else add_conf_proc( 'comment_key', @comment_key_label_conf ) do comment_key_conf end end def comment_key_conf if @mode == 'saveconf' then @conf['comment_key.enable'] = 'true' == @cgi.params['comment_key_enable'][0] ? true : false @conf['comment_key.prefix'] = @cgi.params['comment_key_prefix'][0] @conf['comment_key.nodate'] = @cgi.params['comment_key_nodate'][0] end @conf['comment_key.prefix'] = 'tdiary' unless @conf['comment_key.prefix'] comment_key_conf_html end tdiary-contrib-3.2.2/filter/plugin/commentsize.rb000066400000000000000000000005671213632744000221270ustar00rootroot00000000000000add_conf_proc( 'comment_size' , @comment_size_conf, 'security') do if @mode == 'saveconf' then @conf['comment.size'] = @cgi.params['comment.size'][0] end @conf['comment.size'] = 0 unless @conf['comment.size'] result = <<-HTML

#{@comment_size}

#{@comment_size_desc}

Bytes

HTML end tdiary-contrib-3.2.2/filter/plugin/en/000077500000000000000000000000001213632744000176375ustar00rootroot00000000000000tdiary-contrib-3.2.2/filter/plugin/en/iplookup.rb000066400000000000000000000003601213632744000220250ustar00rootroot00000000000000# en/iplookup.rb # # Copyright (c) 2005 SHIBATA Hiroshi # Distributed under the GPL @iplookup_label = 'IP Blacklist' @iplookup_ip_label = 'IP Blacklist Services' @iplookup_ip_label_desc = 'List of IP Blacklist Services' tdiary-contrib-3.2.2/filter/plugin/en/spambayes.rb000066400000000000000000000032411213632744000221500ustar00rootroot00000000000000# Copyright (C) 2007, KURODA Hiraku # You can redistribute it and/or modify it under GPL2. class SpambayesConfig module Res module_function def title "Bayes filter" end def check_comment "Check comments" end def check_referer "Check referers" end def token_list(type) "#{type}-token list" end def rebuild_db "Rebuild database" end def use_bayes_filter "Use Bayes-filter" end def use_filter_to_referer "Use Bayes-filter to referer" end def save_error_log "Save error-log at cache-directory" end def threshold "Threshold" end def receiver_addr "Mail TO" end def register_ham "Register as HAM" end def register_spam "Register as spam" end def comment_processed "Comments processed" end def token "token" end def probability(type) "#{type}-probability" end def score_in_db(type) "score in #{type}-database" end def execute_after_click_OK "Execute if you click OK" end def registered_as(type) "registered as #{type}" end def rebuild_db_after_click_OK "Rebuild database from corpus if you click OK" end def processed_referer "Referer processed" end def token_of_referer "token of referer" end def mail "Mail address" end def posted_host_addr "Host-IP from which comment posted" end def name "Name" end def referer "Referer" end def url_in_comment "URL in comment" end def comment_body_and_keyword "Text in comment and Keyword in search-engine's referer" end def no_token_exist "(No token exists)" end def spam_rate "Rate of spam" end end end tdiary-contrib-3.2.2/filter/plugin/iplookup.rb000066400000000000000000000023471213632744000214320ustar00rootroot00000000000000# iplookup.rb # # Copyright (c) 2005 SHIBATA Hiroshi # Distributed under the GPL # if TDIARY_VERSION >= '2.1.2.20050825' then add_conf_proc( 'iplookup', @iplookup_label, 'security' ) do iplookup_conf_proc end else add_conf_proc( 'iplookup', @iplookup_label ) do iplookup_conf_proc end end def iplookup_conf_proc if @mode == 'saveconf' then if @cgi.params['iplookup.ip.list'] && @cgi.params['iplookup.ip.list'][0] @conf['iplookup.ip.list'] = @cgi.params['iplookup.ip.list'][0] else @conf['iplookup.ip.list'] = nil end if @cgi.params['iplookup.safe_ip.list'] && @cgi.params['iplookup.safe_ip.list'][0] @conf['iplookup.safe_ip.list'] = @cgi.params['iplookup.safe_ip.list'][0] else @conf['iplookup.safe_ip.list'] = nil end end # initialize DNSBL list @conf['iplookup.ip.list'] = "bsb.spamlookup.net\nopm.blitzed.org\nniku.2ch.net" unless @conf['iplookup.ip.list'] result = <<-HTML

#{@iplookup_ip_label}

#{@iplookup_ip_label_desc}

HTML end tdiary-contrib-3.2.2/filter/plugin/ja/000077500000000000000000000000001213632744000176275ustar00rootroot00000000000000tdiary-contrib-3.2.2/filter/plugin/ja/antirefspam.rb000066400000000000000000000071411213632744000224700ustar00rootroot00000000000000# # antirefspam.rb # # Copyright (c) 2004-2005 T.Shimomura # You can redistribute it and/or modify it under GPL2. # Please use version 1.0.0 (not 1.0.0G) if GPL doesn't want to be forced on me. # @antispamref_html_antispamref = <<-TEXT

リンク元に制限をかける

リファラスパムを防ぐために、refererに対して制限をかけることができます。

TEXT @antispamref_html_disable = <<-TEXT refererに対して制限をかけない TEXT @antispamref_html_myurl = <<-TEXT

許容するリンク先の指定

トップページURL(#{h(if @conf.index_page.empty? then "未設定" else @conf.index_page end)})と日記のURL(#{h(if @conf.base_url.empty? then "不明" else @conf.base_url end)})以外にリンク先として許容するURLを指定します。 正規表現も利用可能です。

TEXT @antispamref_html_proxy = <<-TEXT

HTTPプロキシーサーバーの指定

このプラグインは、リンク元に指定された HTTP サーバーにアクセスして、リンク元のHTML を取得します。 このアクセスに HTTP プロキシを経由する必要がある場合は以下で設定してください。
例 : server : proxy.foo.com port : 8080

TEXT @antispamref_html_trustedurl = <<-TEXT

信頼するリンク元の指定

ヒント:

  • 1行に1つの URL を書いてください。
  • \#で始まる行、空行は無視されます。
  • "信頼するリンク元" は2段階に分けてチェックされます。
    • 1回目は、正規表現を使っていないものとしてチェックします。書かれた URL がリンク元に 含まれてさえいれば、信頼するリンク元とみなします。
      例 : リンク元が http://www.foo.com/bar/ や http://www.foo.com/baz/ の場合、 URL には http://www.foo.com/ と書けばよい。
    • 2回目は、正規表現を使っているものとしてチェックします。この場合、URL中 の : (コロン) と / (スラッシュ) は 内部でエスケープされます。正規表現を使う場合、リンク元の全体にマッチする必要がある点に注意してください。
      例 : リンク元が http://aaa.foo.com/bar/ や http://bbb.foo.com/baz/ の場合、 URL には http://\\w+\.foo\.com/.* と書けばよい。

TEXT @antispamref_html_checkreftable = <<-TEXT 「リンク元置換リスト」にマッチするリンク元を信頼する。 TEXT @antispamref_html_comment = <<-TEXT

ツッコミに制限をかける

コメントスパムを防ぐために、コメントに対して様々な制限をかけることができます。

TEXT @antispamref_html_comment_kanaonly = <<-TEXT ツッコミにひらがな/カタカナが含まれていない場合は拒否する。 TEXT @antispamref_html_comment_maxsize = <<-TEXT ツッコミ文字列の長さの上限を指定(文字数) TEXT @antispamref_html_comment_ngwords = <<-TEXT 以下の単語がツッコミに含まれていた場合は拒否する
(正規表現も利用可能です。正規表現は複数行モードで動作します。 正規表現の先頭と末尾に \/ はつけないでください)
TEXT @antispamref_html_faq = <<-TEXT

FAQ

その他、最新のFAQは http://www.netlife.gr.jp/redbug/diary/?date=20041018\#p02 を参照してください。

TEXT tdiary-contrib-3.2.2/filter/plugin/ja/commentkey.rb000066400000000000000000000016731213632744000223360ustar00rootroot00000000000000# Japanese resource of comment_key.rb # # Copyright (c) 2005 Hahahaha # Distributed under the GPL # @comment_key_label_conf = 'コメントキーフィルタ' def comment_key_conf_html <<-"HTML"

#{@comment_key_label_conf}

コメントキーフィルタを有効にする

コメントキーフィルタのために使用される鍵の先頭文字列を指定します。なお、この文字列はMD5にてエンコードされるため、出力HTML内に直接表現されることはありません。

常に同一の鍵文字列を生成する

HTML end tdiary-contrib-3.2.2/filter/plugin/ja/commentsize.rb000066400000000000000000000004221213632744000225070ustar00rootroot00000000000000if /conf/ =~ @mode then @comment_size_conf = 'コメントサイズ制限' @comment_size_desc = 'ツッコミの最大サイズをByteで指定してください。日本語は一文字で約3Bytesとなります。' @comment_size = 'コメントサイズ制限' end tdiary-contrib-3.2.2/filter/plugin/ja/iplookup.rb000066400000000000000000000004501213632744000220150ustar00rootroot00000000000000# ja/iplookup.rb # # Copyright (c) 2008 SHIBATA Hiroshi # Distributed under the GPL2 @iplookup_label = 'IPブラックリスト' @iplookup_ip_label = 'IPブラックリストサービス' @iplookup_ip_label_desc = 'IPブラックリストサービスの一覧' tdiary-contrib-3.2.2/filter/plugin/ja/spambayes.rb000066400000000000000000000036511213632744000221450ustar00rootroot00000000000000# Copyright (C) 2007, KURODA Hiraku # You can redistribute it and/or modify it under GPL2. class SpambayesConfig module Res module_function def title "Bayesフィルタ" end def check_comment "ツッコミを確認する" end def check_referer "リンク元を確認する" end def token_list(type) "#{type}トークン一覧" end def rebuild_db "データベースの再構築" end def use_bayes_filter "Bayesフィルタを使う" end def use_filter_to_referer "リンク元にBayesフィルタを使う" end def save_error_log "エラーログをキャッシュディレクトリに保存" end def threshold "閾値" end def receiver_addr "宛先メールアドレス" end def register_ham "ハムとして登録" end def register_spam "スパムとして登録" end def comment_processed "ツッコミを処理しました" end def token "トークン" end def probability(type) "#{type}率" end def score_in_db(type) "#{type}データベースでのスコア" end def execute_after_click_OK "OKを押すと実行します" end def registered_as(type) "#{type}として登録しました" end def rebuild_db_after_click_OK "OKを押すとコーパスからデータベースを再作成します" end def processed_referer "リンク元を処理しました" end def token_of_referer "リンク元のトークン" end def mail "メールアドレス" end def posted_host_addr "投稿ホストのIP" end def name "名前" end def referer "リンク元" end def url_in_comment "コメント中のURL" end def comment_body_and_keyword "コメント本文と検索リンク元のキーワード" end def no_token_exist "(トークンがありません)" end def spam_rate "スパム率" end end end tdiary-contrib-3.2.2/filter/plugin/spambayes.rb000066400000000000000000000326361213632744000215600ustar00rootroot00000000000000# Copyright (C) 2007, KURODA Hiraku # You can redistribute it and/or modify it under GPL2. require "bayes" add_conf_proc("spambayes", SpambayesConfig::Res.title, "security") do spambayes_conf_proc end def spambayes_conf_proc SpambayesConfig.new(@mode, @cgi, @conf).show end module ::TDiary module Filter class Filter; end class SpambayesFilter < Filter class Comment; end class Referer; end end end end class SpambayesConfig Comment = ::TDiary::Filter::SpambayesFilter::Comment Referer = ::TDiary::Filter::SpambayesFilter::Referer RE_FILENAME_BODY = /\d+[a-z0-9]+/ RE_SPAM_FILE = /^S#{RE_FILENAME_BODY}$/o RE_HAM_FILE = /^H#{RE_FILENAME_BODY}$/o RE_DOUBT_FILE = /^D#{RE_FILENAME_BODY}$/o RE_FILENAME = /^[SHD]#{RE_FILENAME_BODY}$/o def initialize(mode, cgi, conf) @mode = mode @cgi = cgi @conf = conf filter_path = conf.filter_path || "#{PATH}/tdiary/filter" require "#{filter_path}/spambayes" unless ::TDiary::Filter::SpambayesFilter.const_defined?(:Misc) extend ::TDiary::Filter::SpambayesFilter::Misc ::TDiary::Filter::SpambayesFilter::Misc.conf = conf bayes_filter end def save_mode? @mode=="saveconf" end def add_spam(data) t = data.token return if t.empty? bayes_filter.spam << t if t.any?{|i| !bayes_filter.spam.include?(i)} bayes_filter.spam << t while (bayes_filter.estimate(t)||0.0) <= threshold @db_updated = true end def add_ham(data, with_add_comment=false) t = data.token return if t.empty? bayes_filter.ham << t if t.any?{|i| !bayes_filter.ham.include?(i)} bayes_filter.ham << t while (bayes_filter.estimate(t)||1.0) > threshold @db_updated = true add_comment(data) if data.is_a?(Comment) && with_add_comment end def save_db bayes_filter.save if @db_updated @db_updated = false end def show case @cgi.params["sb_mode"][0] when "show_comment" show_all_comment when "process_comment" process_comment + show_config when "show_ham_tokens" show_db_token_list(:ham) when "show_spam_tokens" show_db_token_list(:spam) when "confirm_ham" confirm(:ham) when "confirm_spam" confirm(:spam) when "register_ham" register(:ham) + show_config when "register_spam" register(:spam) + show_config when "confirm_rebuild_db" confirm_rebuild_db when "rebuild_db" rebuild_db + show_config when "show_all_referer" show_all_referer when "process_referer" process_referer + show_config when "show_comment_token" show_comment_token when "show_referer_token" show_referer_token when "save_config" save_config + show_config else show_config end end def save_config return "" unless save_mode? r = "" @conf[conf_use] = @cgi.params[conf_use][0] || nil @conf[conf_for_referer] = @cgi.params[conf_for_referer][0] || nil @conf[conf_log] = @cgi.params[conf_log][0] || nil @conf[conf_mail] = @cgi.params[conf_mail][0] || nil cpt_ham = (@cgi.params[conf_threshold_ham][0]||threshold_ham).to_f cpt_spam = (@cgi.params[conf_threshold][0]||threshold).to_f if 0
  • #{Res.check_comment}
  • #{Res.check_referer}
  • #{Res.token_list("Spam")}
  • #{Res.token_list("Ham")}
  • #{Res.rebuild_db}

    • #{Res.use_bayes_filter} :
    • #{Res.use_filter_to_referer} :
    • #{Res.save_error_log} :
    • #{Res.threshold}: 0 <= Ham < <= Doubt <= < Spam <= 1.0
    • #{Res.receiver_addr} :
    EOT end def show_comment(data, name=nil) r = < #{data.name}(#{data.mail}) / #{data.date}
    #{CGI.escapeHTML(data.body)}
    EOT rate = bayes_filter.estimate(data.token) r << "#{Res.spam_rate} : #{rate}" if rate if name r << <


    token EOT end r end def show_all_comment r = "" spam_list = Dir["#{bayes_cache}/S*"].map{|i| File.basename(i)}.sort ham_list = Dir["#{bayes_cache}/H*"].map{|i| File.basename(i)}.sort doubt_list = Dir["#{bayes_cache}/D*"].map{|i| File.basename(i)}.sort r << "

    Ham

      " ham_list.each do |f| data = Comment.load(data_file(f)) r << "
    • \n#{show_comment(data, f)}\n
    • \n" end r << "

    Doubt

      " doubt_list.each do |f| data = Comment.load(data_file(f)) r << "
    • \n#{show_comment(data, f)}\n
    • \n" end r << "

    Spam

      " spam_list.each do |f| data = Comment.load(data_file(f)) r << "
    • \n#{show_comment(data, f)}\n
    • \n" end r << "
    " r << "" r << "" r end def data_file(f) raise "InvalidData: #{CGI.escapeHTML(f)}" unless /^O?[SHD]\d+[a-z0-9]+$/ =~ f "#{bayes_cache}/#{f}" end def register_data(f, type) require "fileutils" case type when :ham prefix = "H" when :spam prefix = "S" else prefix = "D" end if RE_FILENAME =~ f new_name = "#{corpus_path}/#{prefix}#{f[/^[SHD](#{RE_FILENAME_BODY})$/o, 1]}" FileUtils.mv(data_file(f), new_name) end end def process_comment return "" unless save_mode? @cgi.params.each do |k, v| next unless k=~/^[SHD]\d+[a-z0-9]+$/ v = v[0] data = Comment.load(data_file(k)) case v when "spam" add_spam(data) when "ham" add_ham(data, k !~ RE_HAM_FILE) else raise "INVALID VALUE:#{k}" end register_data(k, v=="spam" ? :spam : :ham) end @cgi.params.keys.select{|k| k=~/\Aprocess_[SHD]\d+[a-z0-9]+\z/}.each do |k| FileUtils.rm_f(data_file(k[/^process_(.*)$/, 1])) end save_db "

    #{Res.comment_processed}


    " end def comment_date(data) data.diary_date.strftime("%Y%m%d") end def add_comment(data) comment = ::TDiary::Comment.new(data.name, data.mail, data.body, data.date) cgi = Struct.new(:params, :referer, :request_method, :remote_addr, :script_name).new("", "", "", "", "") cgi.params = Hash.new{[]}.update("name"=>[data.name], "mail"=>[data.mail], "body"=>[data.body], "date"=>[comment_date(data)]) cgi.remote_addr = data.remote_addr io = force_filtering do @conf.io_class.new(::TDiary::TDiaryComment.new(cgi, "day.rhtml", @conf)) end io.transaction(data.diary_date) do |diaries| diary = diaries[comment_date(data)] if diary without_filtering do diary.add_comment(comment) end ::TDiary::TDiaryBase::DIRTY_COMMENT else ::TDiary::TDiaryBase::DIRTY_NONE end end end def token_table(label, tokens, prefix) return "" if tokens.empty? r = "

    #{label}

    \n" r << "" bf = bayes_filter tokens = tokens.sort do |a, b| a=prefix+a b=prefix+b sa = bf.score(a) || 1.1 sb = bf.score(b) || 1.1 sa==sb ? a<=>b : sb<=>sa end tokens.each do |t| pt = prefix+t r << "\n" end r << "
    #{Res.token}#{Res.probability("Spam")}
    #{t}#{bf[pt] ? format("%10.4f", bf[pt]) : "Doubt"}
    " end def show_token_list(token_list) tl = {} token_list.uniq.each do |t| k = case t when /^A (.*)/ :addr when /^M (.*)/ :mail when /^N (.*)/ :name when /^R (.*)/ :referer when /^U (.*)/ :url else :body end tl[k] ||= [] tl[k] << ($1 ? $1 : t) end r = "" [[:body, Res.comment_body_and_keyword, ""], [:referer, Res.referer, "R "], [:url, Res.url_in_comment, "U "], [:name, Res.name, "N "], [:mail, Res.mail, "M "], [:addr, Res.posted_host_addr, "A "]].each do |i| key, label, prefix = i r << token_table(label, tl[key]||[], prefix) end if r.strip.empty? Res.no_token_exist else r end end def show_db_token_list(type) r = "

    #{Res.token_list(type.to_s.upcase)}

    " r << "

    #{bayes_filter.class.name}

    " show_token_list(bayes_filter.send(type).keys) end def confirm(type) r = "

    " id = @cgi.params["comment_id"][0] case type when :ham r << Res.register_ham when :spam r << Res.register_spam end r << "

    " r << "" r << "" r << "

    #{Res.execute_after_click_OK}

    " r << "
    " << show_comment(Comment.load(data_file(id))) end def register(type) return "" unless save_mode? id = @cgi.params["comment_id"][0] data = Comment.load(data_file(id)) r = "" case type when :ham add_ham(data, true) when :spam add_spam(data) end r << Res.registered_as(type) save_db register_data(id, type) r << show_comment(data) << "
    " end def confirm_rebuild_db <#{Res.rebuild_db_after_click_OK}

    EOT end def rebuild_db return "NotSave" unless save_mode? bayes_filter(true).save r = "" spams = Dir["#{corpus_path}/S*"] hams = Dir["#{corpus_path}/H*"] all = [] while spams.size>0 and hams.size>0 all << spams.shift all << hams.shift end all.concat(spams) all.concat(hams) all.each do |f| n = f[/^#{Regexp.escape("#{corpus_path}/")}(.*)$/, 1] next unless RE_FILENAME =~ n data = Comment.load(f) case n[/^./] when "S" add_spam(data) when "H" add_ham(data) end end PStore.new(referer_corpus).transaction(true) do |db| (db["spam"]||[]).each do |ref| add_spam(ref) end (db["ham"]||[]).each do |ref| add_ham(ref) end end bayes_filter.save "" end def show_referer_list(referer_list, type) h = "r"+type[0, 1] r = "

    #{type.upcase}

    \n" r << "
      \n" referer_list.uniq.sort.each do |l| r << "
    • #{l.viewable_html}
      \n" r << "from #{l.remote_addr}
      \n" rate = bayes_filter.estimate(l.token) r << "#{Res.spam_rate} : #{rate}
      \n" if rate r << "
      \n" r << "
      \n" r << "token" r << "
    • " end r << "
    \n" r << "\n" end def show_all_referer r = "" spams = Referer.load_list(referer_cache("spam")) hams = Referer.load_list(referer_cache("ham")) doubts = Referer.load_list(referer_cache("doubt")) r << show_referer_list(hams, "ham") r << show_referer_list(spams, "spam") r << show_referer_list(doubts, "doubt") r << "\n" end def process_referer return "" unless save_mode? spams = [] hams = [] @cgi.params.each do |k, v| next unless k=~/^r([shd])(.*)$/ type = $1 referer = Referer.from_html($2) v = v[0] case v when "spam" add_spam(referer) if type=~/^[dh]/ spams << referer when "ham" add_ham(referer) if type=~/^[ds]/ hams << referer end end bayes_filter.save ["ham", "spam", "doubt"].each do |k| size = (@cgi.params[k[0, 1]+"size"][0]||"0").to_i Referer.truncate_list(referer_cache(k), size) end PStore.new(referer_corpus).transaction do |db| spams.concat(db['spam']||[]) hams.concat(db['ham']||[]) db["spam"] = spams.uniq db["ham"] = hams.uniq end "

    #{Res.processed_referer}


    " end def show_comment_token c = Comment.load(data_file(@cgi.params["comment_id"][0])) show_token_list(c.token) end def show_referer_token ref = Referer.from_html(@cgi.params["referer"][0]||"") url = CGI.escapeHTML(ref.referer) "#{url}"+show_token_list(ref.token) end end tdiary-contrib-3.2.2/filter/plugin/zh/000077500000000000000000000000001213632744000176565ustar00rootroot00000000000000tdiary-contrib-3.2.2/filter/plugin/zh/iplookup.rb000066400000000000000000000003601213632744000220440ustar00rootroot00000000000000# zh/iplookup.rb # # Copyright (c) 2005 SHIBATA Hiroshi # Distributed under the GPL @iplookup_label = 'IP Blacklist' @iplookup_ip_label = 'IP Blacklist Services' @iplookup_ip_label_desc = 'List of IP Blacklist Services' tdiary-contrib-3.2.2/filter/rblcheck.rb000066400000000000000000000014311213632744000200400ustar00rootroot00000000000000# rblcheck.rb # Copyright (c) 2004 MoonWolf # Distributed under the GPL # # options: # @options['rblcheck.list'] = [ # 'bl.moonwollf.com', # RBL list # ] require 'socket' module TDiary module Filter class RblcheckFilter < Filter alias :_filter :referer_filter alias :_filter :comment_filter private def _filter( *args ) rev_addr = @cgi.remote_addr.split(".").reverse.join(".") @conf['rblcheck.list'].each {|rbl| addr = "#{rev_addr}.#{rbl}" begin host = Socket.getaddrinfo(addr, "http")[0][3] case host when "127.0.0.2" return false end rescue SocketError end } true end end end end tdiary-contrib-3.2.2/filter/spambayes.rb000066400000000000000000000305421213632744000202540ustar00rootroot00000000000000# Copyright (C) 2007, KURODA Hiraku # You can redistribute it and/or modify it under GPL2. require "bayes" module TDiary::Filter class SpambayesFilter < Filter class TokenList < Bayes::TokenList def initialize super(Bayes::CHARSET::UTF8) end end module Misc @@without_filtering = nil @@force_filtering = nil def without_filtering? @@without_filtering || (@conf[conf_use]||"").size==0 end def without_filtering orig = @@without_filtering @@without_filtering = true yield ensure @@without_filtering = orig end def force_filtering?; @@force_filtering; end def force_filtering orig = @@force_filtering @@force_filtering = true yield ensure @@force_filtering = orig end @@conf = nil def self.conf=(conf) @@conf ||= conf end def self.conf; @@conf; end def self.to_native(s) s ? @@conf.to_native(CGI.unescape(s)).gsub(/[\x00-\x20]/, " ") : "" end PREFIX = "spambayes" def conf_filter; "#{PREFIX}.filter"; end def conf_mail; "#{PREFIX}.mail"; end def conf_threshold; "#{PREFIX}.threshold"; end def conf_threshold_ham; "#{PREFIX}.threshold_ham"; end def conf_use; "#{PREFIX}.use"; end def conf_log; "#{PREFIX}.log"; end def conf_for_referer; "#{PREFIX}.for_referer"; end def cache_path @conf.cache_path || "#{@conf.data_path}cache" end def bayes_cache Dir.mkdir(cache_path) unless File.exist?(cache_path) r = "#{cache_path}/bayes" Dir.mkdir(r) unless File.exist?(r) r end def referer_cache(key) "#{bayes_cache}/referer_#{key}.log" end def referer_corpus "#{corpus_path}/referer.db" end def unescape_referer(referer) @conf.to_native(CGI.unescape(referer)).gsub(/[\x00-\x20]+/, " ") end def debug_log "#{bayes_cache}/debug.log" end def debug(*args) open(debug_log, "a") do |f| f.puts(*args) end end def corpus_path r = "#{bayes_cache}/corpus" Dir.mkdir(r) unless File.exist?(r) r end def bayes_db "#{@conf.data_path}/bayes.db" end def bayes_filter(reset=false) if reset @bayes_filter = nil File.delete(bayes_db) if File.exist?(bayes_db) end case @conf[conf_filter] when /graham/i @bayes_filter ||= Bayes::PaulGraham.new(bayes_db, Bayes::CHARSET::UTF8) else @bayes_filter ||= Bayes::PlainBayes.new(bayes_db, Bayes::CHARSET::UTF8) end convert_to_utf8 unless @bayes_filter.charset==Bayes::CHARSET::UTF8 @bayes_filter end def convert_to_utf8 require "bayes/convert" require "kconv" @bayes_filter.convert(Bayes::CHARSET::UTF8, Bayes::CHARSET::EUC) @bayes_filter.save comments = [] ["S", "H", "D"].each do |c| comments.concat(Dir["#{bayes_cache}/#{c}*"]) end ["S", "H"].each do |c| comments.concat(Dir["#{corpus_path}/#{c}*"]) end comments.each do |f| Comment.load(f).convert_to_utf8.save(f) end end def threshold (@conf[conf_threshold]||"0.95").to_f end def threshold_ham (@conf[conf_threshold_ham]||"0.05").to_f end def url(path=nil) if /^https?:\/\// =~ (path||"") path else File.join(@conf.base_url, (path||"")) end end def index_url url(@conf.index) end def update_url url(@conf.update) end end class Comment attr_reader :name, :date, :mail, :body, :remote_addr, :diary_date def self.load(file_name) r = nil open(file_name) do |f| f.flock(File::LOCK_SH) r = Marshal.load(f) end raise "NoData" unless r.is_a?(self) r end def initialize(comment, cgi) @name = comment.name || "" @date = comment.date || Time.now @mail = comment.mail || "" @body = comment.body || "" @remote_addr = cgi.remote_addr || "" d = cgi.params['date'][0] || Time.now.strftime("%Y%m%d") @diary_date = Time::local(*d.scan(/^(\d{4})(\d\d)(\d\d)$/)[0]) + 12*60*60 end def convert_to_utf8 @name = @name.kconv(Kconv::UTF8, Kconv::EUC) @body = @body.kconv(Kconv::UTF8, Kconv::EUC) self end def save(filename) open(filename, "w") do |f| f.flock(File::LOCK_SH) f.rewind Marshal.dump(self, f) end end def digest Digest::MD5.hexdigest([@name, @date, @mail, @body, @remote_addr, @diary_date].join) end RE_URL = %r[(?:https?|ftp)://[a-zA-Z0-9;/?:@&=+$,\-_.!~*\'()%]+] def token r = TokenList.new if @name.empty? r.push("", "N") else r.add_message(@name, "N") end r.add_mail_addr(@mail, "M") b = @body.dup b.gsub!(RE_URL) do |m| r.add_url(m, "U") "" end r.add_message(b) r.add_host(@remote_addr, "A") r end def cache_name @date.strftime("%Y%m%d%H%M%S")+digest end end class Referer @@specials = {} def self.load_list(f) r = [] open(f) do |f| f.flock(File::LOCK_SH) r << Marshal.load(f) until f.eof? end r rescue [] end def self.truncate_list(fn, size) return unless File.exist?(fn) open(fn, "a+") do |f| f.flock(File::LOCK_EX) buff = [] buff << Marshal.load(f) until f.eof? buff.slice!(0, size) f.truncate(0) buff.each do |i| Marshal.dump(i, f) end end end def self.from_link(link) if /^(.*?)_(.*)$/=~link addr = $1 url = $2 new(CGI.unescape(url), addr ? CGI.unescape(addr) : nil) end end def self.from_html(html) if /^(.*?)_(.*)$/=~html addr = $1 url = $2 new(CGI.unescapeHTML(url), addr ? CGI.unescapeHTML(addr) : nil) end end attr_reader :referer, :remote_addr def initialize(referer, remote_addr = nil) @referer = referer @remote_addr = remote_addr end def hash @referer.hash end def eql?(dst) (self.class == dst.class) and (@referer == dst.referer) end def to_s Misc.to_native(@referer) end def to_html CGI.escapeHTML(@remote_addr||"") + "_" + CGI.escapeHTML(@referer) end def to_link CGI.escape(@remote_addr||"") + "_" + CGI.escape(@referer) end def <=>(o) to_s <=> o.to_s end def split_url base, request, anchor = @referer.scan(/^(.*?)(?:\?(.*?)(?:\#(.*))?)?$/)[0] end def token if l=special? m = l+"_token" if respond_to?(m) r = send(m) else r = special_token(@@specials[l]) end else r = TokenList.new base, request, anchor = split_url r.add_url(base, "R") r.add_message(Misc.to_native(request)) if request r.add_message(Misc.to_native(anchor)) if anchor end r.add_host(@remote_addr, "A") if @remote_addr r end def viewable_html if l=special? m = l+"_html" if respond_to?(m) r = send(m) else r = special_html(@@specials[l]) end else r = to_s end CGI.escapeHTML(r||"") end def special? r = @@specials.find do |n, a| a[0] =~ @referer end r ? r[0] : false end def self.special(name, regexp, label = nil) name = name.to_s label ||= name.capitalize @@specials[name.to_s] = [regexp, label] end def special_html(special) re, label = special "#{label}: " + Misc.to_native(@referer[re, 1]) end def special_token(special) re = special[0] r = TokenList.new r.add_message(Misc.to_native(@referer[re, 1])) r end RE_QUERY_SEP = /[&;]|$/ RE_QUERY_HEAD = /\?(?:.*#{RE_QUERY_SEP})?/o RE_GOOGLE_HOSTS = /.*\.google\.(?:(?:co\.)?[a-z]{2}|com(?:\.[a-z]{2})?)/o RE_GOOGLE = %r[^https?://#{RE_GOOGLE_HOSTS}/.*#{RE_QUERY_HEAD}(?:as_)?q=(.*?)#{RE_QUERY_SEP}]o special :google, RE_GOOGLE RE_GOOGLE_IP = /209\.85\.\d{3}\.\d{1,3}|72\.14\.\d{3}\.\d{1,3}/ RE_GOOGLE_CACHE = %r[^https?://#{RE_GOOGLE_IP}/search#{RE_QUERY_HEAD}q=cache:[^:]+:(.*?)(?:(?:\+|\s+)(.*?))?#{RE_QUERY_SEP}]o special :google_cache, RE_GOOGLE_CACHE def google_cache_token r = TokenList.new RE_GOOGLE_CACHE =~ @referer ref = "http://#{CGI.unescape($1)}" words = $2 r.add_url(ref, "R") r.add_message(Misc.to_native(words)) end def google_cache_html RE_GOOGLE_CACHE =~ @referer ref = "http://#{CGI.unescape($1)}" words = $2 "Google(Cache): #{ref} #{Misc.to_native(words)}" end RE_EZ_GOOGLE = %r[^https?://ezsch\.ezweb\.ne\.jp/search/ezGoogleMain\.php#{RE_QUERY_HEAD}query=(.*?)#{RE_QUERY_SEP}]o special :ez_google, RE_EZ_GOOGLE, "Google(ezweb)" RE_EZWEB = %r[^https?://ezsch\.ezweb\.ne\.jp/.*?#{RE_QUERY_HEAD}query=(.*?)#{RE_QUERY_SEP}] special :ezweb, RE_EZWEB, "EZweb" RE_GOO = %r[^http://search\.goo\.ne\.jp/.*?#{RE_QUERY_HEAD}MT=(.*?)#{RE_QUERY_SEP}]o special :goo, RE_GOO RE_NIFTY = %r[^https?://search\.nifty\.com/.*?#{RE_QUERY_HEAD}Text=(.*?)#{RE_QUERY_SEP}]o special :nifty, RE_NIFTY RE_LIVESEARCH = %r[^https?://search\.live\.com/.*?#{RE_QUERY_HEAD}q=(.*?)#{RE_QUERY_SEP}]o special :livesearch, RE_LIVESEARCH, "Live Search" RE_BIGLOBE = %r[^https?://.*search\.biglobe\.ne\.jp/.*?#{RE_QUERY_HEAD}q=(.*?)#{RE_QUERY_SEP}]o special :biglobe, RE_BIGLOBE RE_MSN = %r[^https?://search\.msn\.co\.jp/.*?#{RE_QUERY_HEAD}q=(.*?)#{RE_QUERY_SEP}]o special :msn, RE_MSN, "MSN" RE_INFOSEEK = %r[^https?://search\.www\.infoseek\.co\.jp/.*?#{RE_QUERY_HEAD}qt=(.*?)#{RE_QUERY_SEP}]o special :infoseek, RE_INFOSEEK RE_HATENA_B = %r[^https?://b\.hatena\.ne\.jp/[^/]+/(.*?)(?:\?.*)?$]o special :hatena_b, RE_HATENA_B, "Hatena::Bookmark" RE_YAHOO = %r[^https?://.*\.yahoo\.co(?:m|\.[a-z]{2})/.*?#{RE_QUERY_HEAD}p=(.*?)#{RE_QUERY_SEP}]o special :yahoo, RE_YAHOO RE_BAIDU = %r[^https?://.*\.baidu\.jp/.*?#{RE_QUERY_HEAD}wd=(.*?)#{RE_QUERY_SEP}]o special :baidu, RE_BAIDU end include Misc def initialize( cgi, conf ) super Misc.conf = conf end def ham?(tokens) e = bayes_filter.estimate(tokens) || (threshold_ham+threshold)/2 case when ethreshold false else nil end end def comment_filter(diary, comment) return false if force_filtering? return true if without_filtering? r = true data = Comment.new(comment, @cgi) base_url = "#{update_url}?conf=spambayes;mode=conf;sb_mode=" spam_url = "Register as spam : #{base_url}confirm_spam" ham_url = "Register as ham : #{base_url}confirm_ham" case ham?(data.token) when true r = true tag = "HAM" url = spam_url when false r = false tag = "SPAM" url = ham_url else r = false tag = "DOUBT" url = "#{spam_url}\n#{ham_url}" end cn = tag[0,1]+data.cache_name data.save("#{bayes_cache}/#{cn}") url.gsub!(/(\n|\z)/){";comment_id=#{cn}#$1"} require "socket" require "time" subject = "#{tag}:#{data.body.gsub(/\n/, " ")}".scan(/.{1,8}/e).map{|b| @conf.to_mail(b)} subject = subject.map{|i| "=?ISO-2022-JP?B?"+[i].pack("m").chomp+"?="}.join("\n ") addr = @conf[conf_mail] body = < To: #{addr} Date: #{Time.now.rfc2822} Message-Id: Subject: #{subject} MIME-Version: 1.0 Content-Type: text/plain; charset="iso-2022-jp" Content-Transfer-Encoding: 7bit Errors-To: #{addr} X-Mailer: tDiary #{TDIARY_VERSION} X-URL: http://www.tdiary.org/ Filter treated comment as #{tag}. #{url} ---- Target: #{index_url}/?date=#{data.diary_date.strftime("%Y%m%d")} Name: #{data.name} Mail: #{data.mail} IP : #{data.remote_addr} Body:------ #{data.body.scan(/.{1,40}/).map{|l| @conf.to_mail(l)}.join("\n")} EOT begin plugin = TDiary::Plugin.new("conf"=>@conf, "mode"=>"comment", "diaries"=>nil, "cgi"=>@cgi, "years"=>nil, "cache_path"=>cache_path, "date"=>data.diary_date, "comment"=>comment, "last_modified"=>nil) plugin.comment_mail(body, addr) if /^.*@.*/ =~ addr rescue ArgumentError end r rescue Exception => e debug "---- comment_filter ----", Time.now, e.message, e.class.name, e.backtrace.join("\n") r end def referer_filter(referer) return true if without_filtering? || !(@conf[conf_for_referer]) r = true referer = Referer.new(referer, ENV["REMOTE_ADDR"]) token = referer.token case ham?(token) when true key = "ham" when false r = false key = "spam" else r = false key = "doubt" end open(referer_cache(key), "a") do |f| f.flock(File::LOCK_SH) Marshal.dump(referer, f) end r rescue Exception => e debug "---- referer_filter ----", Time.now, e.message, e.class.name, e.backtrace.join("\n") raise end end end tdiary-contrib-3.2.2/filter/spamlookup.rb000066400000000000000000000013631213632744000204610ustar00rootroot00000000000000# # spamlookup.rb: included TDiary::Filter::SpamlookupFilter class # require 'resolv' require 'uri' module TDiary module Filter class SpamlookupFilter < Filter def black_domain?( domain ) begin Resolv.getaddress( "#{domain}.rbl.bulkfeeds.jp" ) return true rescue end false end def black_url?( body ) URI.extract( body, %w[http] ) do |url| domain = URI.parse( url ).host.sub( /\.$/, '' ) return true if black_domain?( domain ) end false end def comment_filter( diary, comment ) !black_url?( comment.body ) end def referer_filter( referer ) !black_url?( referer ) end end end end tdiary-contrib-3.2.2/io/000077500000000000000000000000001213632744000150615ustar00rootroot00000000000000tdiary-contrib-3.2.2/io/dbi_io/000077500000000000000000000000001213632744000163065ustar00rootroot00000000000000tdiary-contrib-3.2.2/io/dbi_io/ChangeLog000066400000000000000000000013621213632744000200620ustar00rootroot000000000000002007-02-18 sasasin * dbi_io.rb: delete restore_referer and store_referer impl. * tdiary_table.sql: add referervolatile table definition. * plugin/refererDbiIO.rb: add new plugin for referer. 2005-12-27 Kazuhiko * dbi_io.rb (store_referer): ignore invalid referers. 2005-12-20 Kazuhiko * dbi_io.rb.fast (transaction): lock whole transaction exlusively. (store_referer): update different entries only. 2005-12-11 Kazuhiko * dbi_io.rb (store_comment): delete possible duplicate comments. (restore_referer): quote diary_id. (calendar): fix a bug in a multi-user environment. 2005-12-10 Kazuhiko * dbi_io.rb: code cleanup. tdiary-contrib-3.2.2/io/dbi_io/README.ja000077500000000000000000000025651213632744000175720ustar00rootroot00000000000000!dbi_io データベース名('tDiaryDB') データベースに接続するユーザ データベースに接続するパスワード 作者。今後、マルチユーザ対応するときに使います。 !!データベースの作成 !!! PostgreSQLの場合 $ createdb -h -U -E EUC-JP Password: $ psql -h -U -f tdiary_table.sql Password: CREATE DATABASE !!tdiary.confの編集 #require 'tdiary/pstoreio' #@io_class = TDiary::PStoreIO require 'tdiary/dbi_io' @io_class = TDiary::DbiIO #-- dbi_ioの場合の設定 -- @dbi_driver_url = 'dbi:Pg:' # URLを設定します。 @dbi_user = '' # DBのアカウント @dbi_passwd = ' # DBのパスワード @dbi_author = '' # author !! プラグインのインストール リンク元の保存・表示のために、プラグインを以下のいずれかの 方法でインストールする必要があります (1) tdiary.confの@option['sp.path']に、このディレクトリに あるpluginのパスを追加し、設定画面からrefererDbiIO.rb を有効にする。 (2) tDiaryのインストール先にあるpluginディレクトリに、 plugin/refererDbiIO.rbをコピーする。 tdiary-contrib-3.2.2/io/dbi_io/dbi_io.rb000077500000000000000000000137701213632744000200730ustar00rootroot00000000000000# -*- coding: utf-8 -*- # # dbi_io.rb: DBI IO for tDiary 2.x. # # NAME dbi_io # # DESCRIPTION tDiary向けDBI用IOクラス # 詳細は、README.jaを参照してください # # Copyright (C) 2003 ma2tak # (C) 2004 moonwolf # (C) 2005 Kazuhiko # (C) 2012 hsbt # # You can distribute this under GPL. require 'tdiary/io/base' require 'tempfile' require 'dbi' module TDiary module CommentIO def restore_comment(diaries) begin diaries.each do |date, diary_object| @dbh.select_all("SELECT diary_id, name, mail, last_modified, visible, no, author, comment FROM commentdata WHERE author=? AND diary_id=? ORDER BY no;", @dbi_author, date) do |diary_id, name, mail, last_modified, visible, no, author, comment| comment = Comment.new(name, mail, comment, Time.at(last_modified.to_i)) comment.show = visible diary_object.add_comment(comment) end end rescue Errno::ENOENT end end def store_comment(diaries) begin diaries.each do |date, diary| no = 0 diary.each_comment(diary.count_comments(true)) do |com| no += 1 param = [com.name, com.mail, com.date.to_i, com.visible?, com.body, @dbi_author, date, no] sth = @dbh.execute("UPDATE commentdata SET name=?, mail=?, last_modified=?, visible=?, comment=? WHERE author=? AND diary_id=? AND no=?;", *param) if sth.rows == 0 @dbh.execute("INSERT INTO commentdata (name, mail, last_modified, visible, comment, author, diary_id, no) VALUES (?,?,?,?,?,?,?,?);", *param) end end @dbh.execute("DELETE FROM commentdata where author=? AND diary_id=? AND no>?", @dbi_author, date, no) end rescue Errno::ENOENT end end end module RefererIO def restore_referer(diaries) return end def store_referer(diaries) return end end class DbiIO < BaseIO include CommentIO include RefererIO def initialize(tdiary) @tdiary = tdiary @dbi_url = tdiary.conf.dbi_driver_url @dbi_user = tdiary.conf.dbi_user @dbi_passwd = tdiary.conf.dbi_passwd @dbi_author = tdiary.conf.dbi_author || 'default' @dbh = DBI.connect(@dbi_url, @dbi_user, @dbi_passwd) load_styles end class << self def load_cgi_conf(conf) end def save_cgi_conf(conf, result) end end # # block must be return boolean which dirty diaries. # def transaction(date) File.open("#{Dir.tmpdir}/dbi_io.lock", 'w') do |file| file.flock(File::LOCK_EX) @dbh.transaction do date_string = date.strftime("%Y%m%d") diaries = {} cache = @tdiary.restore_parser_cache(date, 'defaultio') if cache diaries.update(cache) else restore(date_string, diaries) restore_comment(diaries) restore_referer(diaries) end @old_referers = {} diaries.each_pair{|k,v| @old_referers[k] = v.instance_variable_get('@referers').dup} dirty = yield(diaries) if iterator? store(diaries) if dirty & TDiary::TDiaryBase::DIRTY_DIARY != 0 store_comment(diaries) if dirty & TDiary::TDiaryBase::DIRTY_COMMENT != 0 store_referer(diaries) if dirty & TDiary::TDiaryBase::DIRTY_REFERER != 0 if dirty or not cache @tdiary.store_parser_cache(date, 'defaultio', diaries) end end end end def calendar calendar = Hash.new{|hash, key| hash[key] = []} sql = "SELECT year, month FROM diarydata WHERE author=? GROUP BY year, month ORDER BY year, month;" @dbh.select_all(sql, @dbi_author) do |year, month| calendar[year] << month end calendar end def diary_factory(date, title, body, style = 'tDiary') styled_diary_factory(date, title, body, style) end # HNF移行ツールのため、作成 def restore_diary(date) diaries = {} restore(date, diaries, false) diaries end private def restore(date, diaries, month=true) sql = "SELECT diary_id, title, last_modified, visible, body, style FROM DiaryData WHERE author='#{@dbi_author}' and diary_id='#{date}';" if month == true if /(\d\d\d\d)(\d\d)(\d\d)/ =~ date sql = "SELECT diary_id, title, last_modified, visible, body, style FROM DiaryData WHERE author='#{@dbi_author}' AND year='#{$1}' AND month='#{$2}';" end end @dbh.select_all(sql) do |diary_id, title, last_modified, visible, body, style| style = 'tdiary' if style.nil? || style.empty? style = style.downcase diary = eval("#{style(style)}::new(diary_id, title, body, Time::at(last_modified.to_i))") diary.show(visible) diaries[diary_id] = diary end end def store(diaries) diaries.each do |date, diary| # save diaries if /(\d\d\d\d)(\d\d)(\d\d)/ =~ date year = $1 month = $2 day = $3 end visible = (diary.visible? ? "true" : "false") param = [year, month, day, diary.title, diary.last_modified.to_i, visible, diary.to_src, diary.style, @dbi_author, date] sth = @dbh.execute("UPDATE diarydata SET year=?, month=?, day=?, title=?, last_modified=?, visible=?, body=?, style=? WHERE author=? AND diary_id=?", *param) if sth.rows == 0 @dbh.execute("INSERT INTO diarydata (year, month, day, title, last_modified, visible, body, style, author, diary_id) VALUES (?,?,?,?,?,?,?,?,?,?);", *param) end end end # 追加メソッド for test def delete(diaries) diaries.each do |date, diary| sql = "DELETE FROM diarydata WHERE author=#{@dbi_author} AND diary_id=#{date};" @dbh.execute(sql) end end end end tdiary-contrib-3.2.2/io/dbi_io/plugin/000077500000000000000000000000001213632744000176045ustar00rootroot00000000000000tdiary-contrib-3.2.2/io/dbi_io/plugin/refererDbiIO.rb000066400000000000000000000045461213632744000224430ustar00rootroot00000000000000# # refererDbiIO.rb: load/save and show today's referer for DBI IO # $Revision: 1.1 $ # # Copyright (C) 2003 ma2tak # (C) 2004 moonwolf # (C) 2005 Kazuhiko # (C) 2007 sasasin # # You can distribute this under GPL. # def referer_transaction( diary = nil, save = false ) return if @conf.io_class.to_s != 'TDiary::DbiIO' File.open("#{@conf.data_path}/dbi_io_ref.lock", 'w') {|file| file.flock(File::LOCK_EX) dbh = DBI.connect(@conf.dbi_driver_url, @conf.dbi_user, @conf.dbi_passwd) dbh.transaction{ if diary.respond_to?( :date ) then table = 'refererdata' ymd = diary.date.strftime('%Y%m%d') begin sql = "SELECT diary_id, count, ref FROM " + table + " WHERE author=? AND diary_id=?;" dbh.select_all(sql, @conf.dbi_author || 'default', ymd) {|diary_id, count, ref| yield(ref.chomp, count.to_i) } rescue Errno::ENOENT end else table = 'referervolatile' ymd = nil begin sql = "SELECT diary_id, count, ref FROM " + table + " WHERE author=?;" dbh.select_all(sql, @conf.dbi_author || 'default') {|diary_id, count, ref| yield(ref.chomp, count.to_i) ymd = diary_id } rescue Errno::ENOENT end end if @mode =~ /^(append|replace)$/ and !diary.respond_to?( :date ) then if !ymd or (@date.strftime( '%Y%m%d' ) > ymd) then ymd = nil diary.clear_referers begin dbh.execute("TRUNCATE TABLE " + table + ";") rescue Errno::ENOENT end save = false end end if save then unless ymd then ymd = (@date ? @date : Time::now).strftime( '%Y%m%d' ) end no = 0 diary.each_referer(diary.count_referers) {|count,ref| no += 1 param = [count, @conf.dbi_author, ymd, ref] begin sth = dbh.execute("UPDATE " + table + " SET count=? WHERE author=? AND diary_id=? AND ref=?;", *param) if sth.rows==0 no = dbh.select_one("SELECT MAX(no) FROM " + table + " WHERE author=? AND diary_id=?", @conf.dbi_author, ymd).first.to_i + 1 param << no dbh.execute("INSERT INTO " + table + " (count, author, diary_id, ref, no ) VALUES (?,?,?,?,?);", *param) end rescue DBI::ProgrammingError $stderr.puts "invalid referer:#{ref}" end } end } } end tdiary-contrib-3.2.2/io/dbi_io/tdiary_table.sql000077500000000000000000000025301213632744000214750ustar00rootroot00000000000000CREATE TABLE diarydata ( author TEXT NOT NULL, diary_id VARCHAR(8) NOT NULL, year VARCHAR(4) NOT NULL, month VARCHAR(2) NOT NULL, day VARCHAR(2) NOT NULL, title TEXT NULL, last_modified INTEGER NOT NULL, visible BOOLEAN NOT NULL, body TEXT NOT NULL, style TEXT NULL, CONSTRAINT diarydata_pkey PRIMARY KEY (author, diary_id) ); CREATE TABLE commentdata ( author TEXT NOT NULL, diary_id VARCHAR(8) NOT NULL, no INTEGER NOT NULL, name TEXT NULL, mail TEXT NULL, last_modified INTEGER NOT NULL, visible BOOLEAN NOT NULL, comment TEXT NULL, CONSTRAINT commentdata_pkey PRIMARY KEY (author, diary_id, no) ); CREATE TABLE refererdata ( author TEXT NOT NULL, diary_id VARCHAR(8) NOT NULL, no INTEGER NOT NULL, count INTEGER NOT NULL, ref TEXT NOT NULL, CONSTRAINT refererdata_pkey PRIMARY KEY (author, diary_id, no) ); CREATE TABLE referervolatile ( author TEXT NOT NULL, diary_id VARCHAR(8) NOT NULL, no INTEGER NOT NULL, count INTEGER NOT NULL, ref TEXT NOT NULL, CONSTRAINT referervolatile_pkey PRIMARY KEY (author, diary_id, no) ); tdiary-contrib-3.2.2/js/000077500000000000000000000000001213632744000150665ustar00rootroot00000000000000tdiary-contrib-3.2.2/js/appstore.js000066400000000000000000000056411213632744000172670ustar00rootroot00000000000000/* * appstore.js : embeded iTunes information * * Copyright (C) 2011 by tamoot * You can distribute it under GPL. */ $( function() { function appstore_desc(text) { return jQuery('').addClass("amazon-price").text(text).append("
    "); }; function appstore_detail(app_url, app_id, appstore_a) { var params = { output : 'json', id : app_id }; var price = "$"; if($('html').attr('lang') == 'ja-JP') { $.extend(params, { lang : 'ja_jp', country : 'JP' }); price = "\\" }; $.ajax({ type : 'GET', url : 'http://ax.itunes.apple.com/WebObjects/MZStoreServices.woa/wa/wsLookup?', data : params, dataType : 'jsonp', // // callback on error.. // error : function() { var itunes_a = jQuery('').attr({ target : "_blank", href : app_url }).addClass("amazon-detail"); $(appstore_a).prepend(itunes_a); }, // // append dom // success : function(data) { app = data["results"][0]; if(app == null) { appstore_a.text('Search Error: ' + app_url); return }; $(appstore_a).addClass("amazon-detail"); var appstore_spand = jQuery('').addClass("amazon-detail"); $(appstore_a).append(appstore_spand); appstore_spand.prepend(jQuery('').attr({ src : app["artworkUrl100"], width : 128, height : 128 }).addClass("amazon-detail").addClass("left")); var appstore_spandd = jQuery(''); appstore_spandd.addClass("amazon-detail-desc"); appstore_spand.append(appstore_spandd); appstore_spandd.append(jQuery('').addClass("amazon-title").text(app["trackCensoredName"] + " ")); appstore_spandd.append(appstore_desc(app["version"])); appstore_spandd.append(appstore_desc(app["releaseDate"])); appstore_spandd.append(appstore_desc(app["sellerName"])); appstore_spandd.append(appstore_desc(price + app["price"])); appstore_spandd.append(appstore_desc(app["supportedDevices"].join(', '))); appstore_spand.append('
    '); } }); }; function appstore(target) { $('.appstore', target).each( function() { var appstore_url = $(this).attr('href'); var appstore_id = $(this).attr('data-appstoreid') appstore_detail(appstore_url, appstore_id, this); }); }; // for AutoPagerize $(window).bind('AutoPagerize_DOMNodeInserted', function(event) { appstore(event.target); }); // for AuthPatchWork // NOTE: jQuery.bind() cannot handle an event that include a dot charactor. // see http://todayspython.blogspot.com/2011/06/autopager-autopagerize.html if(window.addEventListener) { window.addEventListener('AutoPatchWork.DOMNodeInserted', function(event) { appstore(event.target); }, false); } else if(window.attachEvent) { window.attachEvent('onAutoPatchWork.DOMNodeInserted', function(event) { appstore(event.target); }); }; appstore(document); }); tdiary-contrib-3.2.2/js/comment_emoji_autocomplete.js000066400000000000000000000372451213632744000230450ustar00rootroot00000000000000/* * emoji_autocomplete.js : Support the automatic input of the emoji, * using jQuery UI autocomplete. * * Copyright (C) 2013 by tamoot * You can distribute it under GPL. */ $(function() { var config = new Object(); config.candidates = [":blush:",":scream:",":smirk:",":smiley:",":stuck_out_tongue_closed_eyes:",":stuck_out_tongue_winking_eye:",":rage:",":disappointed:",":sob:",":kissing_heart:",":wink:",":pensive:",":confounded:",":flushed:",":relaxed:",":mask:",":heart:",":broken_heart:",":sunny:",":umbrella:",":cloud:",":snowflake:",":snowman:",":zap:",":cyclone:",":foggy:",":ocean:",":cat:",":dog:",":mouse:",":hamster:",":rabbit:",":wolf:",":frog:",":tiger:",":koala:",":bear:",":pig:",":pig_nose:",":cow:",":boar:",":monkey_face:",":monkey:",":horse:",":racehorse:",":camel:",":sheep:",":elephant:",":panda_face:",":snake:",":bird:",":baby_chick:",":hatched_chick:",":hatching_chick:",":chicken:",":penguin:",":turtle:",":bug:",":honeybee:",":ant:",":beetle:",":snail:",":octopus:",":tropical_fish:",":fish:",":whale:",":whale2:",":dolphin:",":cow2:",":ram:",":rat:",":water_buffalo:",":tiger2:",":rabbit2:",":dragon:",":goat:",":rooster:",":dog2:",":pig2:",":mouse2:",":ox:",":dragon_face:",":blowfish:",":crocodile:",":dromedary_camel:",":leopard:",":cat2:",":poodle:",":paw_prints:",":bouquet:",":cherry_blossom:",":tulip:",":four_leaf_clover:",":rose:",":sunflower:",":hibiscus:",":maple_leaf:",":leaves:",":fallen_leaf:",":herb:",":mushroom:",":cactus:",":palm_tree:",":evergreen_tree:",":deciduous_tree:",":chestnut:",":seedling:",":blossom:",":ear_of_rice:",":shell:",":globe_with_meridians:",":sun_with_face:",":full_moon_with_face:",":new_moon_with_face:",":new_moon:",":waxing_crescent_moon:",":first_quarter_moon:",":waxing_gibbous_moon:",":full_moon:",":waning_gibbous_moon:",":last_quarter_moon:",":waning_crescent_moon:",":last_quarter_moon_with_face:",":first_quarter_moon_with_face:",":moon:",":earth_africa:",":earth_americas:",":earth_asia:",":volcano:",":milky_way:",":partly_sunny:",":octocat:",":squirrel:",":bamboo:",":gift_heart:",":dolls:",":school_satchel:",":mortar_board:",":flags:",":fireworks:",":sparkler:",":wind_chime:",":rice_scene:",":jack_o_lantern:",":ghost:",":santa:",":christmas_tree:",":gift:",":bell:",":no_bell:",":tanabata_tree:",":tada:",":confetti_ball:",":balloon:",":crystal_ball:",":cd:",":dvd:",":floppy_disk:",":camera:",":video_camera:",":movie_camera:",":computer:",":tv:",":iphone:",":phone:",":telephone:",":telephone_receiver:",":pager:",":fax:",":minidisc:",":vhs:",":sound:",":speaker:",":mute:",":loudspeaker:",":mega:",":hourglass:",":hourglass_flowing_sand:",":alarm_clock:",":watch:",":radio:",":satellite:",":loop:",":mag:",":mag_right:",":unlock:",":lock:",":lock_with_ink_pen:",":closed_lock_with_key:",":key:",":bulb:",":flashlight:",":high_brightness:",":low_brightness:",":electric_plug:",":battery:",":calling:",":email:",":mailbox:",":postbox:",":bath:",":bathtub:",":shower:",":toilet:",":wrench:",":nut_and_bolt:",":hammer:",":seat:",":moneybag:",":yen:",":dollar:",":pound:",":euro:",":credit_card:",":money_with_wings:",":e-mail:",":inbox_tray:",":outbox_tray:",":envelope:",":incoming_envelope:",":postal_horn:",":mailbox_closed:",":mailbox_with_mail:",":mailbox_with_no_mail:",":door:",":smoking:",":bomb:",":gun:",":hocho:",":pill:",":syringe:",":page_facing_up:",":page_with_curl:",":bookmark_tabs:",":bar_chart:",":chart_with_upwards_trend:",":chart_with_downwards_trend:",":scroll:",":clipboard:",":calendar:",":date:",":card_index:",":file_folder:",":open_file_folder:",":scissors:",":pushpin:",":paperclip:",":black_nib:",":pencil2:",":straight_ruler:",":triangular_ruler:",":closed_book:",":green_book:",":blue_book:",":orange_book:",":notebook:",":notebook_with_decorative_cover:",":ledger:",":books:",":bookmark:",":name_badge:",":microscope:",":telescope:",":newspaper:",":football:",":basketball:",":soccer:",":baseball:",":tennis:",":8ball:",":rugby_football:",":bowling:",":golf:",":mountain_bicyclist:",":bicyclist:",":horse_racing:",":snowboarder:",":swimmer:",":surfer:",":ski:",":spades:",":hearts:",":clubs:",":diamonds:",":gem:",":ring:",":trophy:",":musical_score:",":musical_keyboard:",":violin:",":space_invader:",":video_game:",":black_joker:",":flower_playing_cards:",":game_die:",":dart:",":mahjong:",":clapper:",":memo:",":pencil:",":book:",":art:",":microphone:",":headphones:",":trumpet:",":saxophone:",":guitar:",":shoe:",":sandal:",":high_heel:",":lipstick:",":boot:",":shirt:",":tshirt:",":necktie:",":womans_clothes:",":dress:",":running_shirt_with_sash:",":jeans:",":kimono:",":bikini:",":ribbon:",":tophat:",":crown:",":womans_hat:",":mans_shoe:",":closed_umbrella:",":briefcase:",":handbag:",":pouch:",":purse:",":eyeglasses:",":fishing_pole_and_fish:",":coffee:",":tea:",":sake:",":baby_bottle:",":beer:",":beers:",":cocktail:",":tropical_drink:",":wine_glass:",":fork_and_knife:",":pizza:",":hamburger:",":fries:",":poultry_leg:",":meat_on_bone:",":spaghetti:",":curry:",":fried_shrimp:",":bento:",":sushi:",":fish_cake:",":rice_ball:",":rice_cracker:",":rice:",":ramen:",":stew:",":oden:",":dango:",":egg:",":bread:",":doughnut:",":custard:",":icecream:",":ice_cream:",":shaved_ice:",":birthday:",":cake:",":cookie:",":chocolate_bar:",":candy:",":lollipop:",":honey_pot:",":apple:",":green_apple:",":tangerine:",":lemon:",":cherries:",":grapes:",":watermelon:",":strawberry:",":peach:",":melon:",":banana:",":pear:",":pineapple:",":sweet_potato:",":eggplant:",":tomato:",":corn:",":alien:",":angel:",":anger:",":angry:",":anguished:",":astonished:",":baby:",":blue_heart:",":blush:",":boom:",":bow:",":bowtie:",":boy:",":bride_with_veil:",":broken_heart:",":bust_in_silhouette:",":busts_in_silhouette:",":clap:",":cold_sweat:",":collision:",":confounded:",":confused:",":construction_worker:",":cop:",":couple_with_heart:",":couple:",":couplekiss:",":cry:",":crying_cat_face:",":cupid:",":dancer:",":dancers:",":dash:",":disappointed:",":dizzy_face:",":dizzy:",":droplet:",":ear:",":exclamation:",":expressionless:",":eyes:",":facepunch:",":family:",":fearful:",":feelsgood:",":feet:",":finnadie:",":fire:",":fist:",":flushed:",":frowning:",":girl:",":goberserk:",":godmode:",":green_heart:",":grey_exclamation:",":grey_question:",":grimacing:",":grin:",":grinning:",":guardsman:",":haircut:",":hand:",":hankey:",":hear_no_evil:",":heart_eyes_cat:",":heart_eyes:",":heart:",":heartbeat:",":heartpulse:",":hurtrealbad:",":hushed:",":imp:",":information_desk_person:",":innocent:",":japanese_goblin:",":japanese_ogre:",":joy_cat:",":joy:",":kiss:",":kissing_cat:",":kissing_closed_eyes:",":kissing_heart:",":kissing_smiling_eyes:",":kissing:",":laughing:",":lips:",":love_letter:",":man_with_gua_pi_mao:",":man_with_turban:",":man:",":mask:",":massage:",":metal:",":muscle:",":musical_note:",":nail_care:",":neckbeard:",":neutral_face:",":no_good:",":no_mouth:",":nose:",":notes:",":ok_hand:",":ok_woman:",":older_man:",":older_woman:",":open_hands:",":open_mouth:",":pensive:",":persevere:",":person_frowning:",":person_with_blond_hair:",":person_with_pouting_face:",":point_down:",":point_left:",":point_right:",":point_up_2:",":point_up:",":poop:",":pouting_cat:",":pray:",":princess:",":punch:",":purple_heart:",":question:",":rage:",":rage1:",":rage2:",":rage3:",":rage4:",":raised_hand:",":raised_hands:",":relaxed:",":relieved:",":revolving_hearts:",":runner:",":running:",":satisfied:",":scream_cat:",":scream:",":see_no_evil:",":shit:",":skull:",":sleeping:",":sleepy:",":smile_cat:",":smile:",":smiley_cat:",":smiley:",":smiling_imp:",":smirk_cat:",":smirk:",":sob:",":sparkling_heart:",":sparkles:",":speak_no_evil:",":speech_balloon:",":star:",":star2:",":stuck_out_tongue_closed_eyes:",":stuck_out_tongue_winking_eye:",":stuck_out_tongue:",":sunglasses:",":suspect:",":sweat_drops:",":sweat_smile:",":sweat:",":thought_balloon:",":-1:",":thumbsdown:",":thumbsup:",":+1:",":tired_face:",":tongue:",":triumph:",":trollface:",":two_hearts:",":two_men_holding_hands:",":two_women_holding_hands:",":unamused:",":v:",":walking:",":wave:",":weary:",":wink2:",":wink:",":woman:",":worried:",":yellow_heart:",":yum:",":zzz:",":109:",":house:",":house_with_garden:",":school:",":office:",":post_office:",":hospital:",":bank:",":convenience_store:",":love_hotel:",":hotel:",":wedding:",":church:",":department_store:",":european_post_office:",":city_sunrise:",":city_sunset:",":japanese_castle:",":european_castle:",":tent:",":factory:",":tokyo_tower:",":japan:",":mount_fuji:",":sunrise_over_mountains:",":sunrise:",":stars:",":statue_of_liberty:",":bridge_at_night:",":carousel_horse:",":rainbow:",":ferris_wheel:",":fountain:",":roller_coaster:",":ship:",":speedboat:",":boat:",":sailboat:",":rowboat:",":anchor:",":rocket:",":airplane:",":helicopter:",":steam_locomotive:",":tram:",":mountain_railway:",":bike:",":aerial_tramway:",":suspension_railway:",":mountain_cableway:",":tractor:",":blue_car:",":oncoming_automobile:",":car:",":red_car:",":taxi:",":oncoming_taxi:",":articulated_lorry:",":bus:",":oncoming_bus:",":rotating_light:",":police_car:",":oncoming_police_car:",":fire_engine:",":ambulance:",":minibus:",":truck:",":train:",":station:",":train2:",":bullettrain_front:",":bullettrain_side:",":light_rail:",":monorail:",":railway_car:",":trolleybus:",":ticket:",":fuelpump:",":vertical_traffic_light:",":traffic_light:",":warning:",":construction:",":beginner:",":atm:",":slot_machine:",":busstop:",":barber:",":hotsprings:",":checkered_flag:",":crossed_flags:",":izakaya_lantern:",":moyai:",":circus_tent:",":performing_arts:",":round_pushpin:",":triangular_flag_on_post:",":jp:",":kr:",":cn:",":us:",":fr:",":es:",":it:",":ru:",":gb:",":uk:",":de:",":100:",":1234:",":one:",":two:",":three:",":four:",":five:",":six:",":seven:",":eight:",":nine:",":keycap_ten:",":zero:",":hash:",":symbols:",":arrow_backward:",":arrow_down:",":arrow_forward:",":arrow_left:",":capital_abcd:",":abcd:",":abc:",":arrow_lower_left:",":arrow_lower_right:",":arrow_right:",":arrow_up:",":arrow_upper_left:",":arrow_upper_right:",":arrow_double_down:",":arrow_double_up:",":arrow_down_small:",":arrow_heading_down:",":arrow_heading_up:",":leftwards_arrow_with_hook:",":arrow_right_hook:",":left_right_arrow:",":arrow_up_down:",":arrow_up_small:",":arrows_clockwise:",":arrows_counterclockwise:",":rewind:",":fast_forward:",":information_source:",":ok:",":twisted_rightwards_arrows:",":repeat:",":repeat_one:",":new:",":top:",":up:",":cool:",":free:",":ng:",":cinema:",":koko:",":signal_strength:",":u5272:",":u5408:",":u55b6:",":u6307:",":u6708:",":u6709:",":u6e80:",":u7121:",":u7533:",":u7a7a:",":u7981:",":sa:",":restroom:",":mens:",":womens:",":baby_symbol:",":no_smoking:",":parking:",":wheelchair:",":metro:",":baggage_claim:",":accept:",":wc:",":potable_water:",":put_litter_in_its_place:",":secret:",":congratulations:",":m:",":passport_control:",":left_luggage:",":customs:",":ideograph_advantage:",":cl:",":sos:",":id:",":no_entry_sign:",":underage:",":no_mobile_phones:",":do_not_litter:",":non-potable_water:",":no_bicycles:",":no_pedestrians:",":children_crossing:",":no_entry:",":eight_spoked_asterisk:",":eight_pointed_black_star:",":heart_decoration:",":vs:",":vibration_mode:",":mobile_phone_off:",":chart:",":currency_exchange:",":aries:",":taurus:",":gemini:",":cancer:",":leo:",":virgo:",":libra:",":scorpius:",":sagittarius:",":capricorn:",":aquarius:",":pisces:",":ophiuchus:",":six_pointed_star:",":negative_squared_cross_mark:",":a:",":b:",":ab:",":o2:",":diamond_shape_with_a_dot_inside:",":recycle:",":end:",":on:",":soon:",":clock1:",":clock130:",":clock10:",":clock1030:",":clock11:",":clock1130:",":clock12:",":clock1230:",":clock2:",":clock230:",":clock3:",":clock330:",":clock4:",":clock430:",":clock5:",":clock530:",":clock6:",":clock630:",":clock7:",":clock730:",":clock8:",":clock830:",":clock9:",":clock930:",":heavy_dollar_sign:",":copyright:",":registered:",":tm:",":x:",":heavy_exclamation_mark:",":bangbang:",":interrobang:",":o:",":heavy_multiplication_x:",":heavy_plus_sign:",":heavy_minus_sign:",":heavy_division_sign:",":white_flower:",":heavy_check_mark:",":ballot_box_with_check:",":radio_button:",":link:",":curly_loop:",":wavy_dash:",":part_alternation_mark:",":trident:",":black_square:",":white_square:",":white_check_mark:",":black_square_button:",":white_square_button:",":black_circle:",":white_circle:",":red_circle:",":large_blue_circle:",":large_blue_diamond:",":large_orange_diamond:",":small_blue_diamond:",":small_orange_diamond:",":small_red_triangle:",":small_red_triangle_down:",":shipit:"]; var regrep = ":.+$"; function widgetPosition(){ var caretPosition = Measurement.caretPos($("textarea[name=body]")); return { left: caretPosition.left + "px", top: caretPosition.top + 20 + "px", width: "auto" }; } function matchedEmoji(val){ terms = val.split("\n"); term = terms[ terms.length - 1]; var matched = term.match(regrep); if( matched == null ){ return false; } return true; } function typedEmoji( term ) { var array = term.split(":"); return array[ array.length - 1 ]; } $( "textarea[name=body]" ) .bind( "keydown", function( event ) { if ( event.keyCode === $.ui.keyCode.TAB && $( this ).data( "autocomplete" ).menu.active ) { event.preventDefault(); } }) .autocomplete({ delay: 500, //filtering source: function( request, response ) { if(matchedEmoji(request.term)){ response( $.ui.autocomplete.filter( config.candidates, typedEmoji( request.term ) ) ); } }, // prevent value inserted on focus focus: function() { return false; }, // replace textarea select: function( event, ui ) { // no match data ... if (ui.item.value == null){ return false; } var terms = this.value.split(":"); // remove the current typed emoji terms.pop(); // add the selected item terms.push( ui.item.value.replace(/:/g, "") ); this.value = terms.join( ":" ) + ":"; return false; }, // re-positioning supports excluding IE. open: function(){ if (! document.uniqueID) { $(".ui-autocomplete").css(widgetPosition()) } } }) // customize autocomplate item $.ui.autocomplete.prototype._renderItem = function( ul, item ) { var icon_img = null; if (item.value != null){ png_basename = item.value.replace(/:/g, ""); if (png_basename == '+1'){ png_basename = 'plus1' } icon_img = $("").attr('src', 'http://www.emoji-cheat-sheet.com/graphics/emojis/' + png_basename + '.png') .css('width', '20').css('height', '20'); } var label_a = $("
    ") .append(icon_img) .append(item.label) return $( "
  • " ) .data( "item.autocomplete", item ) .append(label_a) .appendTo( ul ); }; // customize filter and result $.ui.autocomplete.filter = function(array, term) { var matcher = new RegExp( $.ui.autocomplete.escapeRegex(term), "i" ); var aryMatches = $.grep( array, function(value) { return matcher.test(value.label || value.value || value); }); if (aryMatches.length == 0){ aryMatches.push({ label: 'no match found', value: null }); } return aryMatches; }; }); tdiary-contrib-3.2.2/js/datepicker.js000066400000000000000000000034361213632744000175450ustar00rootroot00000000000000/* * datepicker.js : datepicker using jQuery-UI * http://jqueryui.com/demos/datepicker/ * * Copyright (C) 2012 by tamoot * You can redistribute it and/or modify it under GPL. */ $( function() { function setDateText(date) { var dates = date.split("/"); $("#year" ).val(dates[0]); $("#month").val(dates[1]); $("#day" ).val(dates[2]); } function dateTextFromField() { var y = parseInt( $("#year" ).val() ); var m = parseInt( $("#month").val() ); var d = parseInt( $("#day" ).val() ); if( y > 0 && 13 > m && m > 0 && 32 > d && d > 0 ){ $("#datepicker-input").val(y + "/" + m + "/" + d); } } var datepicker_dom = $(""); var datepicker_trigger = $("") .addClass("ui-icon") .addClass("ui-icon-calendar") .addClass("datepicker-trigger"); var datepicker_input = $("", { id: "datepicker-input", name: "datepicker", style: "display: none;", type: "text" } ); datepicker_dom.append(datepicker_input); datepicker_dom.append(datepicker_trigger); datepicker_dom.insertAfter("span.day"); $("#datepicker-input").datepicker({ onSelect: function(dateText, inst){ setDateText(dateText); }, beforeShow: function(input ,inst){ dateTextFromField(); }, dateFormat: "yy/m/d" }); $(".datepicker-trigger").click(function() { $("#datepicker-input").datepicker("show"); }); var icon = $(".ui-icon-calendar"); icon.css({"display":"inline","position":"absolute","margin-top":"5px"}); icon.after($("").css({"margin-left":"16px"})); icon.hover(function(){ $(this).css({"cursor":"pointer"}); }); }); tdiary-contrib-3.2.2/js/editor.js000066400000000000000000000052271213632744000167200ustar00rootroot00000000000000/** * editor.js - support writing using wiki/gfm notation. * * Copyright (C) 2012 by MATSUOKA Kohei * You can distribute it under GPL. */ /* utility functions */ $.fn.extend({ insertAtCaret2: function(beforeText, afterText){ var elem = this.get(0); elem.focus(); if(jQuery.browser.msie){ this.insertAtCaret(beforeText + afterText); }else{ var orig = elem.value; var posStart = elem.selectionStart; var posEnd = posStart + beforeText.length; elem.value = orig.substr(0, posStart) + beforeText + afterText + orig.substr(posStart); elem.setSelectionRange(posEnd, posEnd); } } }); $(function() { var form = $("textarea"); var targetArea = $("div.update > div.form").first(); var notations = { wiki: { h3: function(){ form.insertAtCaret("! ") }, h4: function(){ form.insertAtCaret("!! ") }, a: function(){ form.insertAtCaret2("", "[[|]]") }, em: function(){ form.insertAtCaret2("''", "''") }, strong: function(){ form.insertAtCaret2("'''", "'''") }, del: function(){ form.insertAtCaret2("==", "=='") }, pre: function(){ form.insertAtCaret2("\n<<<\n", "\n>>>\n") }, bq: function(){ form.insertAtCaret("\"\" ") }, ul: function(){ form.insertAtCaret("* ") }, ol: function(){ form.insertAtCaret("# ") }, table: function(){ form.insertAtCaret( "\n||body1||body2\n||body3||body4\n") }, plugin: function(){ form.insertAtCaret2( "", $.makePluginTag("plugin_name")) } }, gfm: { h3: function(){ form.insertAtCaret("# ") }, h4: function(){ form.insertAtCaret("## ") }, a: function(){ form.insertAtCaret2("", "[]()") }, em: function(){ form.insertAtCaret2("*", "*") }, strong: function(){ form.insertAtCaret2("**", "**") }, pre: function(){ form.insertAtCaret2("\n```\n", "\n```\n") }, code: function(){ form.insertAtCaret2("`", "`") }, bq: function(){ form.insertAtCaret("> ") }, ul: function(){ form.insertAtCaret("* ") }, ol: function(){ form.insertAtCaret("1. ") }, table: function(){ form.insertAtCaret( "\nhead1|head2\n----|----\nbody1|body2\nbody3|body4\n") }, plugin: function(){ form.insertAtCaret2( "", $.makePluginTag("plugin_name")) } } }; var toolbox = $("
      "); $.each(notations[$tDiary.style], function(key, callback) { var button = $("') .click(function() { saveCheckedDate(plugins[0].commit.date); notify.hide(); }) ); var notify = $('
      プラグインの更新が見つかりました。
      ') .append(close) .append(ul); return notify; } $.get(url, function(plugins) { var now = new Date(); var checkedDate = loadCheckedDate(); var updates = $.grep(plugins, function(plugin) { // TODO: 条件を追加する(使用中プラグイン) if (checkedDate) { return (checkedDate < plugin.commit.date); } else { var age = parseInt((now - new Date(plugin.commit.date)) / 1000 / 3600 / 24); return (age < 7); } }); if (updates.length > 0) { $('form.update').before(createNotify(updates)); } $tDiary.updates = updates; }); }); tdiary-contrib-3.2.2/js/prettify/000077500000000000000000000000001213632744000167345ustar00rootroot00000000000000tdiary-contrib-3.2.2/js/prettify/lang-apollo.js000066400000000000000000000017331213632744000215030ustar00rootroot00000000000000PR.registerLangHandler(PR.createSimpleLexer([["com",/^#[^\n\r]*/,null,"#"],["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r \xa0"],["str",/^"(?:[^"\\]|\\[\S\s])*(?:"|$)/,null,'"']],[["kwd",/^(?:ADS|AD|AUG|BZF|BZMF|CAE|CAF|CA|CCS|COM|CS|DAS|DCA|DCOM|DCS|DDOUBL|DIM|DOUBLE|DTCB|DTCF|DV|DXCH|EDRUPT|EXTEND|INCR|INDEX|NDX|INHINT|LXCH|MASK|MSK|MP|MSU|NOOP|OVSK|QXCH|RAND|READ|RELINT|RESUME|RETURN|ROR|RXOR|SQUARE|SU|TCR|TCAA|OVSK|TCF|TC|TS|WAND|WOR|WRITE|XCH|XLQ|XXALQ|ZL|ZQ|ADD|ADZ|SUB|SUZ|MPY|MPR|MPZ|DVP|COM|ABS|CLA|CLZ|LDQ|STO|STQ|ALS|LLS|LRS|TRA|TSQ|TMI|TOV|AXT|TIX|DLY|INP|OUT)\s/, null],["typ",/^(?:-?GENADR|=MINUS|2BCADR|VN|BOF|MM|-?2CADR|-?[1-6]DNADR|ADRES|BBCON|[ES]?BANK=?|BLOCK|BNKSUM|E?CADR|COUNT\*?|2?DEC\*?|-?DNCHAN|-?DNPTR|EQUALS|ERASE|MEMORY|2?OCT|REMADR|SETLOC|SUBRO|ORG|BSS|BES|SYN|EQU|DEFINE|END)\s/,null],["lit",/^'(?:-*(?:\w|\\[!-~])(?:[\w-]*|\\[!-~])[!=?]?)?/],["pln",/^-*(?:[!-z]|\\[!-~])(?:[\w-]*|\\[!-~])[!=?]?/],["pun",/^[^\w\t\n\r "'-);\\\xa0]+/]]),["apollo","agc","aea"]); tdiary-contrib-3.2.2/js/prettify/lang-clj.js000066400000000000000000000026441213632744000207670ustar00rootroot00000000000000/* Copyright (C) 2011 Google Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var a=null; PR.registerLangHandler(PR.createSimpleLexer([["opn",/^[([{]+/,a,"([{"],["clo",/^[)\]}]+/,a,")]}"],["com",/^;[^\n\r]*/,a,";"],["pln",/^[\t\n\r \xa0]+/,a,"\t\n\r \xa0"],["str",/^"(?:[^"\\]|\\[\S\s])*(?:"|$)/,a,'"']],[["kwd",/^(?:def|if|do|let|quote|var|fn|loop|recur|throw|try|monitor-enter|monitor-exit|defmacro|defn|defn-|macroexpand|macroexpand-1|for|doseq|dosync|dotimes|and|or|when|not|assert|doto|proxy|defstruct|first|rest|cons|defprotocol|deftype|defrecord|reify|defmulti|defmethod|meta|with-meta|ns|in-ns|create-ns|import|intern|refer|alias|namespace|resolve|ref|deref|refset|new|set!|memfn|to-array|into-array|aset|gen-class|reduce|map|filter|find|nil?|empty?|hash-map|hash-set|vec|vector|seq|flatten|reverse|assoc|dissoc|list|list?|disj|get|union|difference|intersection|extend|extend-type|extend-protocol|prn)\b/,a], ["typ",/^:[\dA-Za-z-]+/]]),["clj"]); tdiary-contrib-3.2.2/js/prettify/lang-css.js000066400000000000000000000015351213632744000210050ustar00rootroot00000000000000PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\f\r ]+/,null," \t\r\n "]],[["str",/^"(?:[^\n\f\r"\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*"/,null],["str",/^'(?:[^\n\f\r'\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*'/,null],["lang-css-str",/^url\(([^"')]*)\)/i],["kwd",/^(?:url|rgb|!important|@import|@page|@media|@charset|inherit)(?=[^\w-]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*)\s*:/i],["com",/^\/\*[^*]*\*+(?:[^*/][^*]*\*+)*\//],["com", /^(?:<\!--|--\>)/],["lit",/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],["lit",/^#[\da-f]{3,6}/i],["pln",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i],["pun",/^[^\s\w"']+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[["kwd",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[["str",/^[^"')]+/]]),["css-str"]); tdiary-contrib-3.2.2/js/prettify/lang-go.js000066400000000000000000000004321213632744000206150ustar00rootroot00000000000000PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r \xa0"],["pln",/^(?:"(?:[^"\\]|\\[\S\s])*(?:"|$)|'(?:[^'\\]|\\[\S\s])+(?:'|$)|`[^`]*(?:`|$))/,null,"\"'"]],[["com",/^(?:\/\/[^\n\r]*|\/\*[\S\s]*?\*\/)/],["pln",/^(?:[^"'/`]|\/(?![*/]))+/]]),["go"]); tdiary-contrib-3.2.2/js/prettify/lang-hs.js000066400000000000000000000010711213632744000206220ustar00rootroot00000000000000PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t-\r ]+/,null,"\t\n \r "],["str",/^"(?:[^\n\f\r"\\]|\\[\S\s])*(?:"|$)/,null,'"'],["str",/^'(?:[^\n\f\r'\\]|\\[^&])'?/,null,"'"],["lit",/^(?:0o[0-7]+|0x[\da-f]+|\d+(?:\.\d+)?(?:e[+-]?\d+)?)/i,null,"0123456789"]],[["com",/^(?:--+[^\n\f\r]*|{-(?:[^-]|-+[^}-])*-})/],["kwd",/^(?:case|class|data|default|deriving|do|else|if|import|in|infix|infixl|infixr|instance|let|module|newtype|of|then|type|where|_)(?=[^\d'A-Za-z]|$)/, null],["pln",/^(?:[A-Z][\w']*\.)*[A-Za-z][\w']*/],["pun",/^[^\d\t-\r "'A-Za-z]+/]]),["hs"]); tdiary-contrib-3.2.2/js/prettify/lang-lisp.js000066400000000000000000000013631213632744000211630ustar00rootroot00000000000000var a=null; PR.registerLangHandler(PR.createSimpleLexer([["opn",/^\(+/,a,"("],["clo",/^\)+/,a,")"],["com",/^;[^\n\r]*/,a,";"],["pln",/^[\t\n\r \xa0]+/,a,"\t\n\r \xa0"],["str",/^"(?:[^"\\]|\\[\S\s])*(?:"|$)/,a,'"']],[["kwd",/^(?:block|c[ad]+r|catch|con[ds]|def(?:ine|un)|do|eq|eql|equal|equalp|eval-when|flet|format|go|if|labels|lambda|let|load-time-value|locally|macrolet|multiple-value-call|nil|progn|progv|quote|require|return-from|setq|symbol-macrolet|t|tagbody|the|throw|unwind)\b/,a], ["lit",/^[+-]?(?:[#0]x[\da-f]+|\d+\/\d+|(?:\.\d+|\d+(?:\.\d*)?)(?:[de][+-]?\d+)?)/i],["lit",/^'(?:-*(?:\w|\\[!-~])(?:[\w-]*|\\[!-~])[!=?]?)?/],["pln",/^-*(?:[_a-z]|\\[!-~])(?:[\w-]*|\\[!-~])[!=?]?/i],["pun",/^[^\w\t\n\r "'-);\\\xa0]+/]]),["cl","el","lisp","scm"]); tdiary-contrib-3.2.2/js/prettify/lang-lua.js000066400000000000000000000010501213632744000207660ustar00rootroot00000000000000PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r \xa0"],["str",/^(?:"(?:[^"\\]|\\[\S\s])*(?:"|$)|'(?:[^'\\]|\\[\S\s])*(?:'|$))/,null,"\"'"]],[["com",/^--(?:\[(=*)\[[\S\s]*?(?:]\1]|$)|[^\n\r]*)/],["str",/^\[(=*)\[[\S\s]*?(?:]\1]|$)/],["kwd",/^(?:and|break|do|else|elseif|end|false|for|function|if|in|local|nil|not|or|repeat|return|then|true|until|while)\b/,null],["lit",/^[+-]?(?:0x[\da-f]+|(?:\.\d+|\d+(?:\.\d*)?)(?:e[+-]?\d+)?)/i], ["pln",/^[_a-z]\w*/i],["pun",/^[^\w\t\n\r \xa0][^\w\t\n\r "'+=\xa0-]*/]]),["lua"]); tdiary-contrib-3.2.2/js/prettify/lang-ml.js000066400000000000000000000021211213632744000206150ustar00rootroot00000000000000PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r \xa0"],["com",/^#(?:if[\t\n\r \xa0]+(?:[$_a-z][\w']*|``[^\t\n\r`]*(?:``|$))|else|endif|light)/i,null,"#"],["str",/^(?:"(?:[^"\\]|\\[\S\s])*(?:"|$)|'(?:[^'\\]|\\[\S\s])(?:'|$))/,null,"\"'"]],[["com",/^(?:\/\/[^\n\r]*|\(\*[\S\s]*?\*\))/],["kwd",/^(?:abstract|and|as|assert|begin|class|default|delegate|do|done|downcast|downto|elif|else|end|exception|extern|false|finally|for|fun|function|if|in|inherit|inline|interface|internal|lazy|let|match|member|module|mutable|namespace|new|null|of|open|or|override|private|public|rec|return|static|struct|then|to|true|try|type|upcast|use|val|void|when|while|with|yield|asr|land|lor|lsl|lsr|lxor|mod|sig|atomic|break|checked|component|const|constraint|constructor|continue|eager|event|external|fixed|functor|global|include|method|mixin|object|parallel|process|protected|pure|sealed|trait|virtual|volatile)\b/], ["lit",/^[+-]?(?:0x[\da-f]+|(?:\.\d+|\d+(?:\.\d*)?)(?:e[+-]?\d+)?)/i],["pln",/^(?:[_a-z][\w']*[!#?]?|``[^\t\n\r`]*(?:``|$))/i],["pun",/^[^\w\t\n\r "'\xa0]+/]]),["fs","ml"]); tdiary-contrib-3.2.2/js/prettify/lang-n.js000066400000000000000000000025701213632744000204520ustar00rootroot00000000000000var a=null; PR.registerLangHandler(PR.createSimpleLexer([["str",/^(?:'(?:[^\n\r'\\]|\\.)*'|"(?:[^\n\r"\\]|\\.)*(?:"|$))/,a,'"'],["com",/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\n\r]*)/,a,"#"],["pln",/^\s+/,a," \r\n\t\xa0"]],[["str",/^@"(?:[^"]|"")*(?:"|$)/,a],["str",/^<#[^#>]*(?:#>|$)/,a],["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,a],["com",/^\/\/[^\n\r]*/,a],["com",/^\/\*[\S\s]*?(?:\*\/|$)/, a],["kwd",/^(?:abstract|and|as|base|catch|class|def|delegate|enum|event|extern|false|finally|fun|implements|interface|internal|is|macro|match|matches|module|mutable|namespace|new|null|out|override|params|partial|private|protected|public|ref|sealed|static|struct|syntax|this|throw|true|try|type|typeof|using|variant|virtual|volatile|when|where|with|assert|assert2|async|break|checked|continue|do|else|ensures|for|foreach|if|late|lock|new|nolate|otherwise|regexp|repeat|requires|return|surroundwith|unchecked|unless|using|while|yield)\b/, a],["typ",/^(?:array|bool|byte|char|decimal|double|float|int|list|long|object|sbyte|short|string|ulong|uint|ufloat|ulong|ushort|void)\b/,a],["lit",/^@[$_a-z][\w$@]*/i,a],["typ",/^@[A-Z]+[a-z][\w$@]*/,a],["pln",/^'?[$_a-z][\w$@]*/i,a],["lit",/^(?:0x[\da-f]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+-]?\d+)?)[a-z]*/i,a,"0123456789"],["pun",/^.[^\s\w"-$'./@`]*/,a]]),["n","nemerle"]); tdiary-contrib-3.2.2/js/prettify/lang-proto.js000066400000000000000000000004561213632744000213610ustar00rootroot00000000000000PR.registerLangHandler(PR.sourceDecorator({keywords:"bytes,default,double,enum,extend,extensions,false,group,import,max,message,option,optional,package,repeated,required,returns,rpc,service,syntax,to,true",types:/^(bool|(double|s?fixed|[su]?int)(32|64)|float|string)\b/,cStyleComments:!0}),["proto"]); tdiary-contrib-3.2.2/js/prettify/lang-scala.js000066400000000000000000000016231213632744000212760ustar00rootroot00000000000000PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r \xa0"],["str",/^"(?:""(?:""?(?!")|[^"\\]|\\.)*"{0,3}|(?:[^\n\r"\\]|\\.)*"?)/,null,'"'],["lit",/^`(?:[^\n\r\\`]|\\.)*`?/,null,"`"],["pun",/^[!#%&(--:-@[-^{-~]+/,null,"!#%&()*+,-:;<=>?@[\\]^{|}~"]],[["str",/^'(?:[^\n\r'\\]|\\(?:'|[^\n\r']+))'/],["lit",/^'[$A-Z_a-z][\w$]*(?![\w$'])/],["kwd",/^(?:abstract|case|catch|class|def|do|else|extends|final|finally|for|forSome|if|implicit|import|lazy|match|new|object|override|package|private|protected|requires|return|sealed|super|throw|trait|try|type|val|var|while|with|yield)\b/], ["lit",/^(?:true|false|null|this)\b/],["lit",/^(?:0(?:[0-7]+|x[\da-f]+)l?|(?:0|[1-9]\d*)(?:(?:\.\d+)?(?:e[+-]?\d+)?f?|l?)|\\.\d+(?:e[+-]?\d+)?f?)/i],["typ",/^[$_]*[A-Z][\d$A-Z_]*[a-z][\w$]*/],["pln",/^[$A-Z_a-z][\w$]*/],["com",/^\/(?:\/.*|\*(?:\/|\**[^*/])*(?:\*+\/?)?)/],["pun",/^(?:\.+|\/)/]]),["scala"]); tdiary-contrib-3.2.2/js/prettify/lang-sql.js000066400000000000000000000032261213632744000210130ustar00rootroot00000000000000PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r \xa0"],["str",/^(?:"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')/,null,"\"'"]],[["com",/^(?:--[^\n\r]*|\/\*[\S\s]*?(?:\*\/|$))/],["kwd",/^(?:add|all|alter|and|any|as|asc|authorization|backup|begin|between|break|browse|bulk|by|cascade|case|check|checkpoint|close|clustered|coalesce|collate|column|commit|compute|constraint|contains|containstable|continue|convert|create|cross|current|current_date|current_time|current_timestamp|current_user|cursor|database|dbcc|deallocate|declare|default|delete|deny|desc|disk|distinct|distributed|double|drop|dummy|dump|else|end|errlvl|escape|except|exec|execute|exists|exit|fetch|file|fillfactor|for|foreign|freetext|freetexttable|from|full|function|goto|grant|group|having|holdlock|identity|identitycol|identity_insert|if|in|index|inner|insert|intersect|into|is|join|key|kill|left|like|lineno|load|match|merge|national|nocheck|nonclustered|not|null|nullif|of|off|offsets|on|open|opendatasource|openquery|openrowset|openxml|option|or|order|outer|over|percent|plan|precision|primary|print|proc|procedure|public|raiserror|read|readtext|reconfigure|references|replication|restore|restrict|return|revoke|right|rollback|rowcount|rowguidcol|rule|save|schema|select|session_user|set|setuser|shutdown|some|statistics|system_user|table|textsize|then|to|top|tran|transaction|trigger|truncate|tsequal|union|unique|update|updatetext|use|user|using|values|varying|view|waitfor|when|where|while|with|writetext)(?=[^\w-]|$)/i, null],["lit",/^[+-]?(?:0x[\da-f]+|(?:\.\d+|\d+(?:\.\d*)?)(?:e[+-]?\d+)?)/i],["pln",/^[_a-z][\w-]*/i],["pun",/^[^\w\t\n\r "'\xa0][^\w\t\n\r "'+\xa0-]*/]]),["sql"]); tdiary-contrib-3.2.2/js/prettify/lang-tex.js000066400000000000000000000004351213632744000210130ustar00rootroot00000000000000PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r \xa0"],["com",/^%[^\n\r]*/,null,"%"]],[["kwd",/^\\[@-Za-z]+/],["kwd",/^\\./],["typ",/^[$&]/],["lit",/[+-]?(?:\.\d+|\d+(?:\.\d*)?)(cm|em|ex|in|pc|pt|bp|mm)/i],["pun",/^[()=[\]{}]+/]]),["latex","tex"]); tdiary-contrib-3.2.2/js/prettify/lang-vb.js000066400000000000000000000032611213632744000206220ustar00rootroot00000000000000PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0\u2028\u2029]+/,null,"\t\n\r \xa0

"],["str",/^(?:["\u201c\u201d](?:[^"\u201c\u201d]|["\u201c\u201d]{2})(?:["\u201c\u201d]c|$)|["\u201c\u201d](?:[^"\u201c\u201d]|["\u201c\u201d]{2})*(?:["\u201c\u201d]|$))/i,null,'"“”'],["com",/^['\u2018\u2019].*/,null,"'‘’"]],[["kwd",/^(?:addhandler|addressof|alias|and|andalso|ansi|as|assembly|auto|boolean|byref|byte|byval|call|case|catch|cbool|cbyte|cchar|cdate|cdbl|cdec|char|cint|class|clng|cobj|const|cshort|csng|cstr|ctype|date|decimal|declare|default|delegate|dim|directcast|do|double|each|else|elseif|end|endif|enum|erase|error|event|exit|finally|for|friend|function|get|gettype|gosub|goto|handles|if|implements|imports|in|inherits|integer|interface|is|let|lib|like|long|loop|me|mod|module|mustinherit|mustoverride|mybase|myclass|namespace|new|next|not|notinheritable|notoverridable|object|on|option|optional|or|orelse|overloads|overridable|overrides|paramarray|preserve|private|property|protected|public|raiseevent|readonly|redim|removehandler|resume|return|select|set|shadows|shared|short|single|static|step|stop|string|structure|sub|synclock|then|throw|to|try|typeof|unicode|until|variant|wend|when|while|with|withevents|writeonly|xor|endif|gosub|let|variant|wend)\b/i, null],["com",/^rem.*/i],["lit",/^(?:true\b|false\b|nothing\b|\d+(?:e[+-]?\d+[dfr]?|[dfilrs])?|(?:&h[\da-f]+|&o[0-7]+)[ils]?|\d*\.\d+(?:e[+-]?\d+)?[dfr]?|#\s+(?:\d+[/-]\d+[/-]\d+(?:\s+\d+:\d+(?::\d+)?(\s*(?:am|pm))?)?|\d+:\d+(?::\d+)?(\s*(?:am|pm))?)\s+#)/i],["pln",/^(?:(?:[a-z]|_\w)\w*|\[(?:[a-z]|_\w)\w*])/i],["pun",/^[^\w\t\n\r "'[\]\xa0\u2018\u2019\u201c\u201d\u2028\u2029]+/],["pun",/^(?:\[|])/]]),["vb","vbs"]); tdiary-contrib-3.2.2/js/prettify/lang-vhdl.js000066400000000000000000000026511213632744000211520ustar00rootroot00000000000000PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r \xa0"]],[["str",/^(?:[box]?"(?:[^"]|"")*"|'.')/i],["com",/^--[^\n\r]*/],["kwd",/^(?:abs|access|after|alias|all|and|architecture|array|assert|attribute|begin|block|body|buffer|bus|case|component|configuration|constant|disconnect|downto|else|elsif|end|entity|exit|file|for|function|generate|generic|group|guarded|if|impure|in|inertial|inout|is|label|library|linkage|literal|loop|map|mod|nand|new|next|nor|not|null|of|on|open|or|others|out|package|port|postponed|procedure|process|pure|range|record|register|reject|rem|report|return|rol|ror|select|severity|shared|signal|sla|sll|sra|srl|subtype|then|to|transport|type|unaffected|units|until|use|variable|wait|when|while|with|xnor|xor)(?=[^\w-]|$)/i, null],["typ",/^(?:bit|bit_vector|character|boolean|integer|real|time|string|severity_level|positive|natural|signed|unsigned|line|text|std_u?logic(?:_vector)?)(?=[^\w-]|$)/i,null],["typ",/^'(?:active|ascending|base|delayed|driving|driving_value|event|high|image|instance_name|last_active|last_event|last_value|left|leftof|length|low|path_name|pos|pred|quiet|range|reverse_range|right|rightof|simple_name|stable|succ|transaction|val|value)(?=[^\w-]|$)/i,null],["lit",/^\d+(?:_\d+)*(?:#[\w.\\]+#(?:[+-]?\d+(?:_\d+)*)?|(?:\.\d+(?:_\d+)*)?(?:e[+-]?\d+(?:_\d+)*)?)/i], ["pln",/^(?:[a-z]\w*|\\[^\\]*\\)/i],["pun",/^[^\w\t\n\r "'\xa0][^\w\t\n\r "'\xa0-]*/]]),["vhdl","vhd"]); tdiary-contrib-3.2.2/js/prettify/lang-wiki.js000066400000000000000000000010371213632744000211550ustar00rootroot00000000000000PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\d\t a-gi-z\xa0]+/,null,"\t \xa0abcdefgijklmnopqrstuvwxyz0123456789"],["pun",/^[*=[\]^~]+/,null,"=*~^[]"]],[["lang-wiki.meta",/(?:^^|\r\n?|\n)(#[a-z]+)\b/],["lit",/^[A-Z][a-z][\da-z]+[A-Z][a-z][^\W_]+\b/],["lang-",/^{{{([\S\s]+?)}}}/],["lang-",/^`([^\n\r`]+)`/],["str",/^https?:\/\/[^\s#/?]*(?:\/[^\s#?]*)?(?:\?[^\s#]*)?(?:#\S*)?/i],["pln",/^(?:\r\n|[\S\s])[^\n\r#*=A-[^`h{~]*/]]),["wiki"]); PR.registerLangHandler(PR.createSimpleLexer([["kwd",/^#[a-z]+/i,null,"#"]],[]),["wiki.meta"]); tdiary-contrib-3.2.2/js/prettify/lang-xq.js000066400000000000000000000553121213632744000206470ustar00rootroot00000000000000PR.registerLangHandler(PR.createSimpleLexer([["var pln",/^\$[\w-]+/,null,"$"]],[["pln",/^[\s=][<>][\s=]/],["lit",/^@[\w-]+/],["tag",/^<\/?[a-z](?:[\w-.:]*\w)?|\/?>$/i],["com",/^\(:[\S\s]*?:\)/],["pln",/^[(),/;[\]{}]$/],["str",/^(?:"(?:[^"\\{]|\\[\S\s])*(?:"|$)|'(?:[^'\\{]|\\[\S\s])*(?:'|$))/,null,"\"'"],["kwd",/^(?:xquery|where|version|variable|union|typeswitch|treat|to|then|text|stable|sortby|some|self|schema|satisfies|returns|return|ref|processing-instruction|preceding-sibling|preceding|precedes|parent|only|of|node|namespace|module|let|item|intersect|instance|in|import|if|function|for|follows|following-sibling|following|external|except|every|else|element|descending|descendant-or-self|descendant|define|default|declare|comment|child|cast|case|before|attribute|assert|ascending|as|ancestor-or-self|ancestor|after|eq|order|by|or|and|schema-element|document-node|node|at)\b/], ["typ",/^(?:xs:yearMonthDuration|xs:unsignedLong|xs:time|xs:string|xs:short|xs:QName|xs:Name|xs:long|xs:integer|xs:int|xs:gYearMonth|xs:gYear|xs:gMonthDay|xs:gDay|xs:float|xs:duration|xs:double|xs:decimal|xs:dayTimeDuration|xs:dateTime|xs:date|xs:byte|xs:boolean|xs:anyURI|xf:yearMonthDuration)\b/,null],["fun pln",/^(?:xp:dereference|xinc:node-expand|xinc:link-references|xinc:link-expand|xhtml:restructure|xhtml:clean|xhtml:add-lists|xdmp:zip-manifest|xdmp:zip-get|xdmp:zip-create|xdmp:xquery-version|xdmp:word-convert|xdmp:with-namespaces|xdmp:version|xdmp:value|xdmp:user-roles|xdmp:user-last-login|xdmp:user|xdmp:url-encode|xdmp:url-decode|xdmp:uri-is-file|xdmp:uri-format|xdmp:uri-content-type|xdmp:unquote|xdmp:unpath|xdmp:triggers-database|xdmp:trace|xdmp:to-json|xdmp:tidy|xdmp:subbinary|xdmp:strftime|xdmp:spawn-in|xdmp:spawn|xdmp:sleep|xdmp:shutdown|xdmp:set-session-field|xdmp:set-response-encoding|xdmp:set-response-content-type|xdmp:set-response-code|xdmp:set-request-time-limit|xdmp:set|xdmp:servers|xdmp:server-status|xdmp:server-name|xdmp:server|xdmp:security-database|xdmp:security-assert|xdmp:schema-database|xdmp:save|xdmp:role-roles|xdmp:role|xdmp:rethrow|xdmp:restart|xdmp:request-timestamp|xdmp:request-status|xdmp:request-cancel|xdmp:request|xdmp:redirect-response|xdmp:random|xdmp:quote|xdmp:query-trace|xdmp:query-meters|xdmp:product-edition|xdmp:privilege-roles|xdmp:privilege|xdmp:pretty-print|xdmp:powerpoint-convert|xdmp:platform|xdmp:permission|xdmp:pdf-convert|xdmp:path|xdmp:octal-to-integer|xdmp:node-uri|xdmp:node-replace|xdmp:node-kind|xdmp:node-insert-child|xdmp:node-insert-before|xdmp:node-insert-after|xdmp:node-delete|xdmp:node-database|xdmp:mul64|xdmp:modules-root|xdmp:modules-database|xdmp:merging|xdmp:merge-cancel|xdmp:merge|xdmp:md5|xdmp:logout|xdmp:login|xdmp:log-level|xdmp:log|xdmp:lock-release|xdmp:lock-acquire|xdmp:load|xdmp:invoke-in|xdmp:invoke|xdmp:integer-to-octal|xdmp:integer-to-hex|xdmp:http-put|xdmp:http-post|xdmp:http-options|xdmp:http-head|xdmp:http-get|xdmp:http-delete|xdmp:hosts|xdmp:host-status|xdmp:host-name|xdmp:host|xdmp:hex-to-integer|xdmp:hash64|xdmp:hash32|xdmp:has-privilege|xdmp:groups|xdmp:group-serves|xdmp:group-servers|xdmp:group-name|xdmp:group-hosts|xdmp:group|xdmp:get-session-field-names|xdmp:get-session-field|xdmp:get-response-encoding|xdmp:get-response-code|xdmp:get-request-username|xdmp:get-request-user|xdmp:get-request-url|xdmp:get-request-protocol|xdmp:get-request-path|xdmp:get-request-method|xdmp:get-request-header-names|xdmp:get-request-header|xdmp:get-request-field-names|xdmp:get-request-field-filename|xdmp:get-request-field-content-type|xdmp:get-request-field|xdmp:get-request-client-certificate|xdmp:get-request-client-address|xdmp:get-request-body|xdmp:get-current-user|xdmp:get-current-roles|xdmp:get|xdmp:function-name|xdmp:function-module|xdmp:function|xdmp:from-json|xdmp:forests|xdmp:forest-status|xdmp:forest-restore|xdmp:forest-restart|xdmp:forest-name|xdmp:forest-delete|xdmp:forest-databases|xdmp:forest-counts|xdmp:forest-clear|xdmp:forest-backup|xdmp:forest|xdmp:filesystem-file|xdmp:filesystem-directory|xdmp:exists|xdmp:excel-convert|xdmp:eval-in|xdmp:eval|xdmp:estimate|xdmp:email|xdmp:element-content-type|xdmp:elapsed-time|xdmp:document-set-quality|xdmp:document-set-property|xdmp:document-set-properties|xdmp:document-set-permissions|xdmp:document-set-collections|xdmp:document-remove-properties|xdmp:document-remove-permissions|xdmp:document-remove-collections|xdmp:document-properties|xdmp:document-locks|xdmp:document-load|xdmp:document-insert|xdmp:document-get-quality|xdmp:document-get-properties|xdmp:document-get-permissions|xdmp:document-get-collections|xdmp:document-get|xdmp:document-forest|xdmp:document-delete|xdmp:document-add-properties|xdmp:document-add-permissions|xdmp:document-add-collections|xdmp:directory-properties|xdmp:directory-locks|xdmp:directory-delete|xdmp:directory-create|xdmp:directory|xdmp:diacritic-less|xdmp:describe|xdmp:default-permissions|xdmp:default-collections|xdmp:databases|xdmp:database-restore-validate|xdmp:database-restore-status|xdmp:database-restore-cancel|xdmp:database-restore|xdmp:database-name|xdmp:database-forests|xdmp:database-backup-validate|xdmp:database-backup-status|xdmp:database-backup-purge|xdmp:database-backup-cancel|xdmp:database-backup|xdmp:database|xdmp:collection-properties|xdmp:collection-locks|xdmp:collection-delete|xdmp:collation-canonical-uri|xdmp:castable-as|xdmp:can-grant-roles|xdmp:base64-encode|xdmp:base64-decode|xdmp:architecture|xdmp:apply|xdmp:amp-roles|xdmp:amp|xdmp:add64|xdmp:add-response-header|xdmp:access|trgr:trigger-set-recursive|trgr:trigger-set-permissions|trgr:trigger-set-name|trgr:trigger-set-module|trgr:trigger-set-event|trgr:trigger-set-description|trgr:trigger-remove-permissions|trgr:trigger-module|trgr:trigger-get-permissions|trgr:trigger-enable|trgr:trigger-disable|trgr:trigger-database-online-event|trgr:trigger-data-event|trgr:trigger-add-permissions|trgr:remove-trigger|trgr:property-content|trgr:pre-commit|trgr:post-commit|trgr:get-trigger-by-id|trgr:get-trigger|trgr:document-scope|trgr:document-content|trgr:directory-scope|trgr:create-trigger|trgr:collection-scope|trgr:any-property-content|thsr:set-entry|thsr:remove-term|thsr:remove-synonym|thsr:remove-entry|thsr:query-lookup|thsr:lookup|thsr:load|thsr:insert|thsr:expand|thsr:add-synonym|spell:suggest-detailed|spell:suggest|spell:remove-word|spell:make-dictionary|spell:load|spell:levenshtein-distance|spell:is-correct|spell:insert|spell:double-metaphone|spell:add-word|sec:users-collection|sec:user-set-roles|sec:user-set-password|sec:user-set-name|sec:user-set-description|sec:user-set-default-permissions|sec:user-set-default-collections|sec:user-remove-roles|sec:user-privileges|sec:user-get-roles|sec:user-get-description|sec:user-get-default-permissions|sec:user-get-default-collections|sec:user-doc-permissions|sec:user-doc-collections|sec:user-add-roles|sec:unprotect-collection|sec:uid-for-name|sec:set-realm|sec:security-version|sec:security-namespace|sec:security-installed|sec:security-collection|sec:roles-collection|sec:role-set-roles|sec:role-set-name|sec:role-set-description|sec:role-set-default-permissions|sec:role-set-default-collections|sec:role-remove-roles|sec:role-privileges|sec:role-get-roles|sec:role-get-description|sec:role-get-default-permissions|sec:role-get-default-collections|sec:role-doc-permissions|sec:role-doc-collections|sec:role-add-roles|sec:remove-user|sec:remove-role-from-users|sec:remove-role-from-role|sec:remove-role-from-privileges|sec:remove-role-from-amps|sec:remove-role|sec:remove-privilege|sec:remove-amp|sec:protect-collection|sec:privileges-collection|sec:privilege-set-roles|sec:privilege-set-name|sec:privilege-remove-roles|sec:privilege-get-roles|sec:privilege-add-roles|sec:priv-doc-permissions|sec:priv-doc-collections|sec:get-user-names|sec:get-unique-elem-id|sec:get-role-names|sec:get-role-ids|sec:get-privilege|sec:get-distinct-permissions|sec:get-collection|sec:get-amp|sec:create-user-with-role|sec:create-user|sec:create-role|sec:create-privilege|sec:create-amp|sec:collections-collection|sec:collection-set-permissions|sec:collection-remove-permissions|sec:collection-get-permissions|sec:collection-add-permissions|sec:check-admin|sec:amps-collection|sec:amp-set-roles|sec:amp-remove-roles|sec:amp-get-roles|sec:amp-doc-permissions|sec:amp-doc-collections|sec:amp-add-roles|search:unparse|search:suggest|search:snippet|search:search|search:resolve-nodes|search:resolve|search:remove-constraint|search:parse|search:get-default-options|search:estimate|search:check-options|prof:value|prof:reset|prof:report|prof:invoke|prof:eval|prof:enable|prof:disable|prof:allowed|ppt:clean|pki:template-set-request|pki:template-set-name|pki:template-set-key-type|pki:template-set-key-options|pki:template-set-description|pki:template-in-use|pki:template-get-version|pki:template-get-request|pki:template-get-name|pki:template-get-key-type|pki:template-get-key-options|pki:template-get-id|pki:template-get-description|pki:need-certificate|pki:is-temporary|pki:insert-trusted-certificates|pki:insert-template|pki:insert-signed-certificates|pki:insert-certificate-revocation-list|pki:get-trusted-certificate-ids|pki:get-template-ids|pki:get-template-certificate-authority|pki:get-template-by-name|pki:get-template|pki:get-pending-certificate-requests-xml|pki:get-pending-certificate-requests-pem|pki:get-pending-certificate-request|pki:get-certificates-for-template-xml|pki:get-certificates-for-template|pki:get-certificates|pki:get-certificate-xml|pki:get-certificate-pem|pki:get-certificate|pki:generate-temporary-certificate-if-necessary|pki:generate-temporary-certificate|pki:generate-template-certificate-authority|pki:generate-certificate-request|pki:delete-template|pki:delete-certificate|pki:create-template|pdf:make-toc|pdf:insert-toc-headers|pdf:get-toc|pdf:clean|p:status-transition|p:state-transition|p:remove|p:pipelines|p:insert|p:get-by-id|p:get|p:execute|p:create|p:condition|p:collection|p:action|ooxml:runs-merge|ooxml:package-uris|ooxml:package-parts-insert|ooxml:package-parts|msword:clean|mcgm:polygon|mcgm:point|mcgm:geospatial-query-from-elements|mcgm:geospatial-query|mcgm:circle|math:tanh|math:tan|math:sqrt|math:sinh|math:sin|math:pow|math:modf|math:log10|math:log|math:ldexp|math:frexp|math:fmod|math:floor|math:fabs|math:exp|math:cosh|math:cos|math:ceil|math:atan2|math:atan|math:asin|math:acos|map:put|map:map|map:keys|map:get|map:delete|map:count|map:clear|lnk:to|lnk:remove|lnk:insert|lnk:get|lnk:from|lnk:create|kml:polygon|kml:point|kml:interior-polygon|kml:geospatial-query-from-elements|kml:geospatial-query|kml:circle|kml:box|gml:polygon|gml:point|gml:interior-polygon|gml:geospatial-query-from-elements|gml:geospatial-query|gml:circle|gml:box|georss:point|georss:geospatial-query|georss:circle|geo:polygon|geo:point|geo:interior-polygon|geo:geospatial-query-from-elements|geo:geospatial-query|geo:circle|geo:box|fn:zero-or-one|fn:years-from-duration|fn:year-from-dateTime|fn:year-from-date|fn:upper-case|fn:unordered|fn:true|fn:translate|fn:trace|fn:tokenize|fn:timezone-from-time|fn:timezone-from-dateTime|fn:timezone-from-date|fn:sum|fn:subtract-dateTimes-yielding-yearMonthDuration|fn:subtract-dateTimes-yielding-dayTimeDuration|fn:substring-before|fn:substring-after|fn:substring|fn:subsequence|fn:string-to-codepoints|fn:string-pad|fn:string-length|fn:string-join|fn:string|fn:static-base-uri|fn:starts-with|fn:seconds-from-time|fn:seconds-from-duration|fn:seconds-from-dateTime|fn:round-half-to-even|fn:round|fn:root|fn:reverse|fn:resolve-uri|fn:resolve-QName|fn:replace|fn:remove|fn:QName|fn:prefix-from-QName|fn:position|fn:one-or-more|fn:number|fn:not|fn:normalize-unicode|fn:normalize-space|fn:node-name|fn:node-kind|fn:nilled|fn:namespace-uri-from-QName|fn:namespace-uri-for-prefix|fn:namespace-uri|fn:name|fn:months-from-duration|fn:month-from-dateTime|fn:month-from-date|fn:minutes-from-time|fn:minutes-from-duration|fn:minutes-from-dateTime|fn:min|fn:max|fn:matches|fn:lower-case|fn:local-name-from-QName|fn:local-name|fn:last|fn:lang|fn:iri-to-uri|fn:insert-before|fn:index-of|fn:in-scope-prefixes|fn:implicit-timezone|fn:idref|fn:id|fn:hours-from-time|fn:hours-from-duration|fn:hours-from-dateTime|fn:floor|fn:false|fn:expanded-QName|fn:exists|fn:exactly-one|fn:escape-uri|fn:escape-html-uri|fn:error|fn:ends-with|fn:encode-for-uri|fn:empty|fn:document-uri|fn:doc-available|fn:doc|fn:distinct-values|fn:distinct-nodes|fn:default-collation|fn:deep-equal|fn:days-from-duration|fn:day-from-dateTime|fn:day-from-date|fn:data|fn:current-time|fn:current-dateTime|fn:current-date|fn:count|fn:contains|fn:concat|fn:compare|fn:collection|fn:codepoints-to-string|fn:codepoint-equal|fn:ceiling|fn:boolean|fn:base-uri|fn:avg|fn:adjust-time-to-timezone|fn:adjust-dateTime-to-timezone|fn:adjust-date-to-timezone|fn:abs|feed:unsubscribe|feed:subscription|feed:subscribe|feed:request|feed:item|feed:description|excel:clean|entity:enrich|dom:set-pipelines|dom:set-permissions|dom:set-name|dom:set-evaluation-context|dom:set-domain-scope|dom:set-description|dom:remove-pipeline|dom:remove-permissions|dom:remove|dom:get|dom:evaluation-context|dom:domains|dom:domain-scope|dom:create|dom:configuration-set-restart-user|dom:configuration-set-permissions|dom:configuration-set-evaluation-context|dom:configuration-set-default-domain|dom:configuration-get|dom:configuration-create|dom:collection|dom:add-pipeline|dom:add-permissions|dls:retention-rules|dls:retention-rule-remove|dls:retention-rule-insert|dls:retention-rule|dls:purge|dls:node-expand|dls:link-references|dls:link-expand|dls:documents-query|dls:document-versions-query|dls:document-version-uri|dls:document-version-query|dls:document-version-delete|dls:document-version-as-of|dls:document-version|dls:document-update|dls:document-unmanage|dls:document-set-quality|dls:document-set-property|dls:document-set-properties|dls:document-set-permissions|dls:document-set-collections|dls:document-retention-rules|dls:document-remove-properties|dls:document-remove-permissions|dls:document-remove-collections|dls:document-purge|dls:document-manage|dls:document-is-managed|dls:document-insert-and-manage|dls:document-include-query|dls:document-history|dls:document-get-permissions|dls:document-extract-part|dls:document-delete|dls:document-checkout-status|dls:document-checkout|dls:document-checkin|dls:document-add-properties|dls:document-add-permissions|dls:document-add-collections|dls:break-checkout|dls:author-query|dls:as-of-query|dbk:convert|dbg:wait|dbg:value|dbg:stopped|dbg:stop|dbg:step|dbg:status|dbg:stack|dbg:out|dbg:next|dbg:line|dbg:invoke|dbg:function|dbg:finish|dbg:expr|dbg:eval|dbg:disconnect|dbg:detach|dbg:continue|dbg:connect|dbg:clear|dbg:breakpoints|dbg:break|dbg:attached|dbg:attach|cvt:save-converted-documents|cvt:part-uri|cvt:destination-uri|cvt:basepath|cvt:basename|cts:words|cts:word-query-weight|cts:word-query-text|cts:word-query-options|cts:word-query|cts:word-match|cts:walk|cts:uris|cts:uri-match|cts:train|cts:tokenize|cts:thresholds|cts:stem|cts:similar-query-weight|cts:similar-query-nodes|cts:similar-query|cts:shortest-distance|cts:search|cts:score|cts:reverse-query-weight|cts:reverse-query-nodes|cts:reverse-query|cts:remainder|cts:registered-query-weight|cts:registered-query-options|cts:registered-query-ids|cts:registered-query|cts:register|cts:query|cts:quality|cts:properties-query-query|cts:properties-query|cts:polygon-vertices|cts:polygon|cts:point-longitude|cts:point-latitude|cts:point|cts:or-query-queries|cts:or-query|cts:not-query-weight|cts:not-query-query|cts:not-query|cts:near-query-weight|cts:near-query-queries|cts:near-query-options|cts:near-query-distance|cts:near-query|cts:highlight|cts:geospatial-co-occurrences|cts:frequency|cts:fitness|cts:field-words|cts:field-word-query-weight|cts:field-word-query-text|cts:field-word-query-options|cts:field-word-query-field-name|cts:field-word-query|cts:field-word-match|cts:entity-highlight|cts:element-words|cts:element-word-query-weight|cts:element-word-query-text|cts:element-word-query-options|cts:element-word-query-element-name|cts:element-word-query|cts:element-word-match|cts:element-values|cts:element-value-ranges|cts:element-value-query-weight|cts:element-value-query-text|cts:element-value-query-options|cts:element-value-query-element-name|cts:element-value-query|cts:element-value-match|cts:element-value-geospatial-co-occurrences|cts:element-value-co-occurrences|cts:element-range-query-weight|cts:element-range-query-value|cts:element-range-query-options|cts:element-range-query-operator|cts:element-range-query-element-name|cts:element-range-query|cts:element-query-query|cts:element-query-element-name|cts:element-query|cts:element-pair-geospatial-values|cts:element-pair-geospatial-value-match|cts:element-pair-geospatial-query-weight|cts:element-pair-geospatial-query-region|cts:element-pair-geospatial-query-options|cts:element-pair-geospatial-query-longitude-name|cts:element-pair-geospatial-query-latitude-name|cts:element-pair-geospatial-query-element-name|cts:element-pair-geospatial-query|cts:element-pair-geospatial-boxes|cts:element-geospatial-values|cts:element-geospatial-value-match|cts:element-geospatial-query-weight|cts:element-geospatial-query-region|cts:element-geospatial-query-options|cts:element-geospatial-query-element-name|cts:element-geospatial-query|cts:element-geospatial-boxes|cts:element-child-geospatial-values|cts:element-child-geospatial-value-match|cts:element-child-geospatial-query-weight|cts:element-child-geospatial-query-region|cts:element-child-geospatial-query-options|cts:element-child-geospatial-query-element-name|cts:element-child-geospatial-query-child-name|cts:element-child-geospatial-query|cts:element-child-geospatial-boxes|cts:element-attribute-words|cts:element-attribute-word-query-weight|cts:element-attribute-word-query-text|cts:element-attribute-word-query-options|cts:element-attribute-word-query-element-name|cts:element-attribute-word-query-attribute-name|cts:element-attribute-word-query|cts:element-attribute-word-match|cts:element-attribute-values|cts:element-attribute-value-ranges|cts:element-attribute-value-query-weight|cts:element-attribute-value-query-text|cts:element-attribute-value-query-options|cts:element-attribute-value-query-element-name|cts:element-attribute-value-query-attribute-name|cts:element-attribute-value-query|cts:element-attribute-value-match|cts:element-attribute-value-geospatial-co-occurrences|cts:element-attribute-value-co-occurrences|cts:element-attribute-range-query-weight|cts:element-attribute-range-query-value|cts:element-attribute-range-query-options|cts:element-attribute-range-query-operator|cts:element-attribute-range-query-element-name|cts:element-attribute-range-query-attribute-name|cts:element-attribute-range-query|cts:element-attribute-pair-geospatial-values|cts:element-attribute-pair-geospatial-value-match|cts:element-attribute-pair-geospatial-query-weight|cts:element-attribute-pair-geospatial-query-region|cts:element-attribute-pair-geospatial-query-options|cts:element-attribute-pair-geospatial-query-longitude-name|cts:element-attribute-pair-geospatial-query-latitude-name|cts:element-attribute-pair-geospatial-query-element-name|cts:element-attribute-pair-geospatial-query|cts:element-attribute-pair-geospatial-boxes|cts:document-query-uris|cts:document-query|cts:distance|cts:directory-query-uris|cts:directory-query-depth|cts:directory-query|cts:destination|cts:deregister|cts:contains|cts:confidence|cts:collections|cts:collection-query-uris|cts:collection-query|cts:collection-match|cts:classify|cts:circle-radius|cts:circle-center|cts:circle|cts:box-west|cts:box-south|cts:box-north|cts:box-east|cts:box|cts:bearing|cts:arc-intersection|cts:and-query-queries|cts:and-query-options|cts:and-query|cts:and-not-query-positive-query|cts:and-not-query-negative-query|cts:and-not-query|css:get|css:convert|cpf:success|cpf:failure|cpf:document-set-state|cpf:document-set-processing-status|cpf:document-set-last-updated|cpf:document-set-error|cpf:document-get-state|cpf:document-get-processing-status|cpf:document-get-last-updated|cpf:document-get-error|cpf:check-transition|alert:spawn-matching-actions|alert:rule-user-id-query|alert:rule-set-user-id|alert:rule-set-query|alert:rule-set-options|alert:rule-set-name|alert:rule-set-description|alert:rule-set-action|alert:rule-remove|alert:rule-name-query|alert:rule-insert|alert:rule-id-query|alert:rule-get-user-id|alert:rule-get-query|alert:rule-get-options|alert:rule-get-name|alert:rule-get-id|alert:rule-get-description|alert:rule-get-action|alert:rule-action-query|alert:remove-triggers|alert:make-rule|alert:make-log-action|alert:make-config|alert:make-action|alert:invoke-matching-actions|alert:get-my-rules|alert:get-all-rules|alert:get-actions|alert:find-matching-rules|alert:create-triggers|alert:config-set-uri|alert:config-set-trigger-ids|alert:config-set-options|alert:config-set-name|alert:config-set-description|alert:config-set-cpf-domain-names|alert:config-set-cpf-domain-ids|alert:config-insert|alert:config-get-uri|alert:config-get-trigger-ids|alert:config-get-options|alert:config-get-name|alert:config-get-id|alert:config-get-description|alert:config-get-cpf-domain-names|alert:config-get-cpf-domain-ids|alert:config-get|alert:config-delete|alert:action-set-options|alert:action-set-name|alert:action-set-module-root|alert:action-set-module-db|alert:action-set-module|alert:action-set-description|alert:action-remove|alert:action-insert|alert:action-get-options|alert:action-get-name|alert:action-get-module-root|alert:action-get-module-db|alert:action-get-module|alert:action-get-description|zero-or-one|years-from-duration|year-from-dateTime|year-from-date|upper-case|unordered|true|translate|trace|tokenize|timezone-from-time|timezone-from-dateTime|timezone-from-date|sum|subtract-dateTimes-yielding-yearMonthDuration|subtract-dateTimes-yielding-dayTimeDuration|substring-before|substring-after|substring|subsequence|string-to-codepoints|string-pad|string-length|string-join|string|static-base-uri|starts-with|seconds-from-time|seconds-from-duration|seconds-from-dateTime|round-half-to-even|round|root|reverse|resolve-uri|resolve-QName|replace|remove|QName|prefix-from-QName|position|one-or-more|number|not|normalize-unicode|normalize-space|node-name|node-kind|nilled|namespace-uri-from-QName|namespace-uri-for-prefix|namespace-uri|name|months-from-duration|month-from-dateTime|month-from-date|minutes-from-time|minutes-from-duration|minutes-from-dateTime|min|max|matches|lower-case|local-name-from-QName|local-name|last|lang|iri-to-uri|insert-before|index-of|in-scope-prefixes|implicit-timezone|idref|id|hours-from-time|hours-from-duration|hours-from-dateTime|floor|false|expanded-QName|exists|exactly-one|escape-uri|escape-html-uri|error|ends-with|encode-for-uri|empty|document-uri|doc-available|doc|distinct-values|distinct-nodes|default-collation|deep-equal|days-from-duration|day-from-dateTime|day-from-date|data|current-time|current-dateTime|current-date|count|contains|concat|compare|collection|codepoints-to-string|codepoint-equal|ceiling|boolean|base-uri|avg|adjust-time-to-timezone|adjust-dateTime-to-timezone|adjust-date-to-timezone|abs)\b/], ["pln",/^[\w:-]+/],["pln",/^[\t\n\r \xa0]+/]]),["xq","xquery"]); tdiary-contrib-3.2.2/js/prettify/lang-yaml.js000066400000000000000000000006341213632744000211560ustar00rootroot00000000000000var a=null; PR.registerLangHandler(PR.createSimpleLexer([["pun",/^[:>?|]+/,a,":|>?"],["dec",/^%(?:YAML|TAG)[^\n\r#]+/,a,"%"],["typ",/^&\S+/,a,"&"],["typ",/^!\S*/,a,"!"],["str",/^"(?:[^"\\]|\\.)*(?:"|$)/,a,'"'],["str",/^'(?:[^']|'')*(?:'|$)/,a,"'"],["com",/^#[^\n\r]*/,a,"#"],["pln",/^\s+/,a," \t\r\n"]],[["dec",/^(?:---|\.\.\.)(?:[\n\r]|$)/],["pun",/^-/],["kwd",/^\w+:[\n\r ]/],["pln",/^\w+/]]),["yaml","yml"]); tdiary-contrib-3.2.2/js/prettify/prettify.css000066400000000000000000000012431213632744000213140ustar00rootroot00000000000000.pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee}tdiary-contrib-3.2.2/js/prettify/prettify.js000066400000000000000000000325001213632744000211400ustar00rootroot00000000000000var q=null;window.PR_SHOULD_USE_CONTINUATION=!0; (function(){function L(a){function m(a){var f=a.charCodeAt(0);if(f!==92)return f;var b=a.charAt(1);return(f=r[b])?f:"0"<=b&&b<="7"?parseInt(a.substring(1),8):b==="u"||b==="x"?parseInt(a.substring(2),16):a.charCodeAt(1)}function e(a){if(a<32)return(a<16?"\\x0":"\\x")+a.toString(16);a=String.fromCharCode(a);if(a==="\\"||a==="-"||a==="["||a==="]")a="\\"+a;return a}function h(a){for(var f=a.substring(1,a.length-1).match(/\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\[0-3][0-7]{0,2}|\\[0-7]{1,2}|\\[\S\s]|[^\\]/g),a= [],b=[],o=f[0]==="^",c=o?1:0,i=f.length;c122||(d<65||j>90||b.push([Math.max(65,j)|32,Math.min(d,90)|32]),d<97||j>122||b.push([Math.max(97,j)&-33,Math.min(d,122)&-33]))}}b.sort(function(a,f){return a[0]-f[0]||f[1]-a[1]});f=[];j=[NaN,NaN];for(c=0;ci[0]&&(i[1]+1>i[0]&&b.push("-"),b.push(e(i[1])));b.push("]");return b.join("")}function y(a){for(var f=a.source.match(/\[(?:[^\\\]]|\\[\S\s])*]|\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\\d+|\\[^\dux]|\(\?[!:=]|[()^]|[^()[\\^]+/g),b=f.length,d=[],c=0,i=0;c=2&&a==="["?f[c]=h(j):a!=="\\"&&(f[c]=j.replace(/[A-Za-z]/g,function(a){a=a.charCodeAt(0);return"["+String.fromCharCode(a&-33,a|32)+"]"}));return f.join("")}for(var t=0,s=!1,l=!1,p=0,d=a.length;p=5&&"lang-"===b.substring(0,5))&&!(o&&typeof o[1]==="string"))c=!1,b="src";c||(r[f]=b)}i=d;d+=f.length;if(c){c=o[1];var j=f.indexOf(c),k=j+c.length;o[2]&&(k=f.length-o[2].length,j=k-c.length);b=b.substring(5);B(l+i,f.substring(0,j),e,p);B(l+i+j,c,C(b,c),p);B(l+i+k,f.substring(k),e,p)}else p.push(l+i,b)}a.e=p}var h={},y;(function(){for(var e=a.concat(m), l=[],p={},d=0,g=e.length;d=0;)h[n.charAt(k)]=r;r=r[1];n=""+r;p.hasOwnProperty(n)||(l.push(r),p[n]=q)}l.push(/[\S\s]/);y=L(l)})();var t=m.length;return e}function u(a){var m=[],e=[];a.tripleQuotedStrings?m.push(["str",/^(?:'''(?:[^'\\]|\\[\S\s]|''?(?=[^']))*(?:'''|$)|"""(?:[^"\\]|\\[\S\s]|""?(?=[^"]))*(?:"""|$)|'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$))/,q,"'\""]):a.multiLineStrings?m.push(["str",/^(?:'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$)|`(?:[^\\`]|\\[\S\s])*(?:`|$))/, q,"'\"`"]):m.push(["str",/^(?:'(?:[^\n\r'\\]|\\.)*(?:'|$)|"(?:[^\n\r"\\]|\\.)*(?:"|$))/,q,"\"'"]);a.verbatimStrings&&e.push(["str",/^@"(?:[^"]|"")*(?:"|$)/,q]);var h=a.hashComments;h&&(a.cStyleComments?(h>1?m.push(["com",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,q,"#"]):m.push(["com",/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\n\r]*)/,q,"#"]),e.push(["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,q])):m.push(["com",/^#[^\n\r]*/, q,"#"]));a.cStyleComments&&(e.push(["com",/^\/\/[^\n\r]*/,q]),e.push(["com",/^\/\*[\S\s]*?(?:\*\/|$)/,q]));a.regexLiterals&&e.push(["lang-regex",/^(?:^^\.?|[!+-]|!=|!==|#|%|%=|&|&&|&&=|&=|\(|\*|\*=|\+=|,|-=|->|\/|\/=|:|::|;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|[?@[^]|\^=|\^\^|\^\^=|{|\||\|=|\|\||\|\|=|~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\s*(\/(?=[^*/])(?:[^/[\\]|\\[\S\s]|\[(?:[^\\\]]|\\[\S\s])*(?:]|$))+\/)/]);(h=a.types)&&e.push(["typ",h]);a=(""+a.keywords).replace(/^ | $/g, "");a.length&&e.push(["kwd",RegExp("^(?:"+a.replace(/[\s,]+/g,"|")+")\\b"),q]);m.push(["pln",/^\s+/,q," \r\n\t\xa0"]);e.push(["lit",/^@[$_a-z][\w$@]*/i,q],["typ",/^(?:[@_]?[A-Z]+[a-z][\w$@]*|\w+_t\b)/,q],["pln",/^[$_a-z][\w$@]*/i,q],["lit",/^(?:0x[\da-f]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+-]?\d+)?)[a-z]*/i,q,"0123456789"],["pln",/^\\[\S\s]?/,q],["pun",/^.[^\s\w"-$'./@\\`]*/,q]);return x(m,e)}function D(a,m){function e(a){switch(a.nodeType){case 1:if(k.test(a.className))break;if("BR"===a.nodeName)h(a), a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)e(a);break;case 3:case 4:if(p){var b=a.nodeValue,d=b.match(t);if(d){var c=b.substring(0,d.index);a.nodeValue=c;(b=b.substring(d.index+d[0].length))&&a.parentNode.insertBefore(s.createTextNode(b),a.nextSibling);h(a);c||a.parentNode.removeChild(a)}}}}function h(a){function b(a,d){var e=d?a.cloneNode(!1):a,f=a.parentNode;if(f){var f=b(f,1),g=a.nextSibling;f.appendChild(e);for(var h=g;h;h=g)g=h.nextSibling,f.appendChild(h)}return e} for(;!a.nextSibling;)if(a=a.parentNode,!a)return;for(var a=b(a.nextSibling,0),e;(e=a.parentNode)&&e.nodeType===1;)a=e;d.push(a)}var k=/(?:^|\s)nocode(?:\s|$)/,t=/\r\n?|\n/,s=a.ownerDocument,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=s.defaultView.getComputedStyle(a,q).getPropertyValue("white-space"));var p=l&&"pre"===l.substring(0,3);for(l=s.createElement("LI");a.firstChild;)l.appendChild(a.firstChild);for(var d=[l],g=0;g=0;){var h=m[e];A.hasOwnProperty(h)?window.console&&console.warn("cannot override language handler %s",h):A[h]=a}}function C(a,m){if(!a||!A.hasOwnProperty(a))a=/^\s*=o&&(h+=2);e>=c&&(a+=2)}}catch(w){"console"in window&&console.log(w&&w.stack?w.stack:w)}}var v=["break,continue,do,else,for,if,return,while"],w=[[v,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"], "catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],F=[w,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],G=[w,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"], H=[G,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"],w=[w,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"],I=[v,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"], J=[v,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"],v=[v,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],K=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/,N=/\S/,O=u({keywords:[F,H,w,"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END"+ I,J,v],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),A={};k(O,["default-code"]);k(x([],[["pln",/^[^]*(?:>|$)/],["com",/^<\!--[\S\s]*?(?:--\>|$)/],["lang-",/^<\?([\S\s]+?)(?:\?>|$)/],["lang-",/^<%([\S\s]+?)(?:%>|$)/],["pun",/^(?:<[%?]|[%?]>)/],["lang-",/^]*>([\S\s]+?)<\/xmp\b[^>]*>/i],["lang-js",/^]*>([\S\s]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\S\s]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]), ["default-markup","htm","html","mxml","xhtml","xml","xsl"]);k(x([["pln",/^\s+/,q," \t\r\n"],["atv",/^(?:"[^"]*"?|'[^']*'?)/,q,"\"'"]],[["tag",/^^<\/?[a-z](?:[\w-.:]*\w)?|\/?>$/i],["atn",/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^\s"'>]*(?:[^\s"'/>]|\/(?=\s)))/],["pun",/^[/<->]+/],["lang-js",/^on\w+\s*=\s*"([^"]+)"/i],["lang-js",/^on\w+\s*=\s*'([^']+)'/i],["lang-js",/^on\w+\s*=\s*([^\s"'>]+)/i],["lang-css",/^style\s*=\s*"([^"]+)"/i],["lang-css",/^style\s*=\s*'([^']+)'/i],["lang-css", /^style\s*=\s*([^\s"'>]+)/i]]),["in.tag"]);k(x([],[["atv",/^[\S\s]+/]]),["uq.val"]);k(u({keywords:F,hashComments:!0,cStyleComments:!0,types:K}),["c","cc","cpp","cxx","cyc","m"]);k(u({keywords:"null,true,false"}),["json"]);k(u({keywords:H,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:K}),["cs"]);k(u({keywords:G,cStyleComments:!0}),["java"]);k(u({keywords:v,hashComments:!0,multiLineStrings:!0}),["bsh","csh","sh"]);k(u({keywords:I,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}), ["cv","py"]);k(u({keywords:"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["perl","pl","pm"]);k(u({keywords:J,hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb"]);k(u({keywords:w,cStyleComments:!0,regexLiterals:!0}),["js"]);k(u({keywords:"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes", hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),["coffee"]);k(x([],[["str",/^[\S\s]+/]]),["regex"]);window.prettyPrintOne=function(a,m,e){var h=document.createElement("PRE");h.innerHTML=a;e&&D(h,e);E({g:m,i:e,h:h});return h.innerHTML};window.prettyPrint=function(a){function m(){for(var e=window.PR_SHOULD_USE_CONTINUATION?l.now()+250:Infinity;p=0){var k=k.match(g),f,b;if(b= !k){b=n;for(var o=void 0,c=b.firstChild;c;c=c.nextSibling)var i=c.nodeType,o=i===1?o?b:c:i===3?N.test(c.nodeValue)?b:o:o;b=(f=o===b?void 0:o)&&"CODE"===f.tagName}b&&(k=f.className.match(g));k&&(k=k[1]);b=!1;for(o=n.parentNode;o;o=o.parentNode)if((o.tagName==="pre"||o.tagName==="code"||o.tagName==="xmp")&&o.className&&o.className.indexOf("prettyprint")>=0){b=!0;break}b||((b=(b=n.className.match(/\blinenums\b(?::(\d+))?/))?b[1]&&b[1].length?+b[1]:!0:!1)&&D(n,b),d={g:k,h:n,i:b},E(d))}}p * You can distribute it under GPL. */ $(function() { $('div.main').on('click', 'button.lazy_referer', function(e) { var button = $(this); button.attr("disabled", "disabled"); $.get(button.data('endpoint'), function (data) { button.after($(data)); button.hide(); }, 'html'); }); }); tdiary-contrib-3.2.2/js/show_and_hide.js000066400000000000000000000020641213632744000202210ustar00rootroot00000000000000/* * show_and_hide.js : javascript for show_and_hide.rb plugin of tDiary * * Copyright (C) 2011 by tamoot * You can distribute it under GPL. */ $( function() { function show_and_hide(target) { $('.show_and_hide_toggle', target).each( function() { $(this).click( function() { $('.show_and_hide#'+$(this).attr('data-showandhideid')).slideToggle(400); }); }); }; // for AutoPagerize $(window).bind('AutoPagerize_DOMNodeInserted', function(event) { show_and_hide(event.target); }); // for AuthPatchWork // NOTE: jQuery.bind() cannot handle an event that include a dot charactor. // see http://todayspython.blogspot.com/2011/06/autopager-autopagerize.html if(window.addEventListener) { window.addEventListener('AutoPatchWork.DOMNodeInserted', function(event) { show_and_hide(event.target); }, false); } else if(window.attachEvent) { window.attachEvent('onAutoPatchWork.DOMNodeInserted', function(event) { show_and_hide(event.target); }); }; show_and_hide(document) $('.show_and_hide').hide(); }); tdiary-contrib-3.2.2/js/socialbutton.js000066400000000000000000000061551213632744000201410ustar00rootroot00000000000000/** * socialbutton.js - * * Copyright (C) 2011 by MATSUOKA Kohei * You can distribute it under GPL. */ /** * SYNOPSIS * * you can set options at socialbutton.rb * * $tDiary.plugin.socialbutton.enables = * ['twitter', 'hatena', 'facebook_like', 'evernote']; * * $tDiary.plugin.socialbutton.options = { * twitter: { via: 'machu' } * }; * */ $(function() { // load config from tDiary plugin (socialbutton.rb) var config = $tDiary.plugin.socialbutton; // set options for jQuery.socialbutton var callbacks = { twitter: function(url, title) { return { url: url, text: title, button: 'horizontal', lang: $('html').attr('lang').substr(0,2) }; }, hatena: function(url, title) { return { url: url, title: title, button: 'standard' }; }, facebook_like: function(url, title) { return { url: url, button: 'button_count', locale: $('html').attr('lang').replace('-', '_') }; }, evernote: function(url, title) { return { url: url, title: title, button: 'article-clipper-jp' }; }, google_plusone: function(url, title) { return { href: url, size: 'medium', lang: $('html').attr('lang') }; }, pinterest: function(url, title) { return { url: url, media: $('p img:first', $('div.section h3 a[name=' + url.substr(-3) + ']').parent().parent()).attr('src'), description: title, button: 'horizontal', }; }, }; function socialbutton(target) { $('.socialbuttons').css('height', '1em') var bottom = $(window).height() + $(window).scrollTop(); $($tDiary.blogkit ? '.day' : '.section') .filter(function() { return bottom > $(this).offset().top; }) .filter(function() { return $(this).find('.socialbutton').size() == 0 }) .each(function() { if ($tDiary.blogkit) { var link = $(this).children('h2').find('a:first').get(0); var url = link ? link.href : document.URL; var title = $(this).children('h2').find('.title').text(); } else { var url = $(this).children('h3').children('a').get(0).href; var title = $(this).children('h3').children('a').attr('title'); } if (url && title) { // console.debug('loading socialbutton: ' + title); var socialbuttons = $(this).find('.socialbuttons'); append_button(url, title, socialbuttons); } }); } function append_button(url, title, socialbuttons) { $.each(config.enables, function(i, service) { var options = callbacks[service](url, title.replace(/"/g, '"')); $.extend(options, config.options[service]); $('') .css("float", "left") .css("margin-right", "0.5em") .appendTo(socialbuttons) .socialbutton(service, options); }); } $(window).bind('scroll', function(event) { socialbutton(document); }); socialbutton(document); }); tdiary-contrib-3.2.2/js/twitter_anywhere.js000066400000000000000000000011611213632744000210270ustar00rootroot00000000000000/* * twitter_anywhere.js : use Twitter@Anywhere * * Copyright (C) 2012 by tamoot * You can distribute it under GPL. */ $( function() { // load config from tDiary plugin (twitter_anywhere.rb) var config = $tDiary.plugin.twitter_anywhere; // hovarcards var expand = config.hovercards.expand_default; $.each(config.selectors, function(i, css){ twttr.anywhere(function(twitter) { twitter(css).hovercards(expand); }); }); }); // tweet box function showTweetBox(option) { twttr.anywhere(function (T) { T("#tweetbox").tweetBox(option); }); } tdiary-contrib-3.2.2/js/yahoo_kousei.js000066400000000000000000000010661213632744000201250ustar00rootroot00000000000000$( function() { $( '.plugin_yahoo_search_result_raw' ).each( function( index ) { $(this).click( function() { var pos = $($('td', $(this)).get(3)).text().split(','); sp = parseInt(pos[0]); ep = parseInt(pos[1]); var o = $( 'textarea[name="body"]' ).get( 0 ); o.focus(); if ( jQuery.browser.msie ) { var range = document.selection.createRange(); range.collapse(); range.moveStart( 'character', sp ); range.moveEnd( 'character', ep ); range.select(); } else { o.setSelectionRange( sp , sp + ep ); } } ); } ); } ); tdiary-contrib-3.2.2/lib/000077500000000000000000000000001213632744000152205ustar00rootroot00000000000000tdiary-contrib-3.2.2/lib/bayes.rb000066400000000000000000000107521213632744000166550ustar00rootroot00000000000000# Copyright (C) 2007, KURODA Hiraku # You can redistribute it and/or modify it under GPL2. require "pstore" module Bayes module CHARSET def self.setup_re(m) o = $KCODE $KCODE = m::KCODE m.const_set(:RE_MESSAGE_TOKEN, Regexp.union(m::RE_KATAKANA, m::RE_KANJI, /[a-zA-Z]+/)) $KCODE=o end module EUC KCODE = "e" KATAKANA = "\xa5\xa2-\xa5\xf3" BAR = "\xa1\xbc" KANJI = "\xb0\xa1-\xfc\xfe" RE_KATAKANA = /[#{KATAKANA}#{BAR}]{2,}/eo RE_KANJI = /[#{KANJI}]{2,}/eo CHARSET.setup_re(self) end module UTF8 KCODE = "u" def self.c2u(c) [c].pack("U") end def self.utf_range(a, b) "#{c2u(a)}-#{c2u(b)}" end KATAKANA = utf_range(0x30a0, 0x30ff) BAR = c2u(0x30fc) KANJI = utf_range(0x4e00, 0x9faf) RE_KATAKANA = /[#{KATAKANA}#{BAR}]{2,}/uo RE_KANJI = /[#{KANJI}]{2,}/uo CHARSET.setup_re(self) end end class TokenList < Array attr_reader :charset def initialize(charset=nil) unless charset charset = case $KCODE when /^e/i CHARSET::EUC else CHARSET::UTF8 end end @charset = charset end alias _concat concat def concat(array, prefix=nil) if prefix _concat(array.map{|i| "#{prefix} #{i.to_s}"}) else _concat(array) end end alias _push push def push(item, prefix=nil) if prefix _push("#{prefix} #{item.to_s}") else _push(item) end end def add_host(host, prefix=nil) if /^(?:\d{1,3}\.){3}\d{1,3}$/ =~ host while host.size>0 push(host, prefix) host = host[/^(.*?)\.?\d+$/, 1] end else push(host, prefix) h = host while /^(.*?)[-_.](.*)$/=~h h = $2 push($1, prefix) push(h, prefix) end end self end def add_url(url, prefix=nil) if %r[^(?:https?|ftp)://(.*?)(?::\d+)?/(.*?)\/?(\?.*)?$] =~ url host, path = $1, $2 add_host(host, prefix) if path.size>0 push(path, prefix) p = path re = %r[^(.*)[-_./](.*?)$] while re=~p p = $1 push($2, prefix) push(p, prefix) end end end self end def add_message(message, prefix=nil) concat(message.scan(@charset::RE_MESSAGE_TOKEN), prefix) self end def add_mail_addr(addr, prefix=nil) push(addr, prefix) name, host = addr.split(/@/) return self if (name||"").empty? host ||= "" push(name, prefix) add_host(host, prefix) self end end class FilterBase attr_reader :spam, :ham, :db_name, :charset def initialize(db_name=nil, charset=nil) @spam = self.class::Corpus.new @ham = self.class::Corpus.new @charset = charset @db_name = db_name if db_name && File.exist?(db_name) PStore.new(db_name).transaction(true) do |db| @spam = db["spam"] @ham = db["ham"] @charset = db["charset"] end end end def save(db_name=nil) db_name ||= @db_name @db_name ||= db_name return unless @db_name PStore.new(@db_name).transaction do |db| db["spam"] = @spam db["ham"] = @ham db["charset"] = @charset yield(db) if block_given? end end def [](token) score(token) end end class PlainBayes < FilterBase class Corpus < Hash def initialize super(0.0) end def <<(src) s = src.size.to_f src.each do |i| self[i] += 1/s end end end def score(token) return nil unless @spam.include?(token) || @ham.include?(token) s = @spam[token] h = @ham[token] s/(s+h) end def estimate(tokens, take=15) s = tokens.uniq.map{|i| score(i)}.compact.sort{|a, b| (0.5-a).abs <=> (0.5-b)}.reverse[0...take] return nil if s.empty? || s.include?(1.0) && s.include?(0.0) prod = s.inject(1.0){|r, i| r*i} return prod/(prod+s.inject(1.0){|r, i| r*(1-i)}) end end class PaulGraham < FilterBase class Corpus < Hash attr_reader :count def initialize super(0) @count = 0 end def <<(src) @count += 1 src.each do |i| self[i] += 1 end end end def score(token) return 0.4 unless @spam.include?(token) or @ham.include?(token) g = @ham.count==0 ? 0.0 : [1.0, 2*@ham[token]/@ham.count.to_f].min b = @spam.count==0 ? 0.0 : [1.0, @spam[token]/@spam.count.to_f].min r = [0.01, [0.99, b/(g+b)].min].max r end def estimate(tokens, take=15) s = tokens.uniq.map{|i| score(i)}.compact.sort{|a, b| (0.5-a).abs <=> (0.5-b)}.reverse[0...take] return nil if s.empty? || s.include?(1.0) && s.include?(0.0) prod = s.inject(1.0){|r, i| r*i} return prod/(prod+s.inject(1.0){|r, i| r*(1-i)}) end end end tdiary-contrib-3.2.2/lib/bayes/000077500000000000000000000000001213632744000163235ustar00rootroot00000000000000tdiary-contrib-3.2.2/lib/bayes/convert.rb000066400000000000000000000012311213632744000203250ustar00rootroot00000000000000# Copyright (C) 2008, KURODA Hiraku # You can redistribute it and/or modify it under GPL2. require "bayes" require "kconv" module Bayes module CHARSET module EUC KCONV = Kconv::EUC end module UTF8 KCONV = Kconv::UTF8 end end class FilterBase def convert_corpus(corpus, to_code, from_code) r = self.class::Corpus.new corpus.each do |k, v| r[k.kconv(to_code::KCONV, from_code::KCONV)] = v end r end private :convert_corpus def convert(to_code, from_code) @charset = to_code @ham = convert_corpus(@ham, to_code, from_code) @spam = convert_corpus(@spam, to_code, from_code) end end end tdiary-contrib-3.2.2/lib/exifparser/000077500000000000000000000000001213632744000173705ustar00rootroot00000000000000tdiary-contrib-3.2.2/lib/exifparser/BUGS000066400000000000000000000000401213632744000200450ustar00rootroot00000000000000* DO NOT USE WITH ruby-libexif! tdiary-contrib-3.2.2/lib/exifparser/ChangeLog000066400000000000000000000136411213632744000211470ustar00rootroot000000000000002008-01-17 kp * lib/exifparser/tag.rb: Fix Rational method call for Ruby1.8.x Thu Dec 12 16:21:39 2002 Ryuichi Tamura * lib/exifparser/tag.rb (Exif::Tag::Exif::LightSource#to_s): complete missing returned values that are introduced in Exif standard 2.2. Thu Dec 12 04:05:42 2002 Ryuichi Tamura * lib/exifparser/tag.rb: EXIF tag set should include 'InteroperabilityIFDPointer' Tue Dec 10 23:26:46 2002 Ryuichi Tamura * lib/exifparser/scan.rb, lib/exifparser/tag.rb, lib/exifparser/makernote/*.rb: namespaces introduced to prevent name collision. Tue Dec 10 21:43:13 2002 Ryuichi Tamura * lib/exifparser/*.rb, lib/exifparser/makernote/*.rb: fin_read_n() now simply returns byte stream, not pack("C*")'ed. use String#unpack, Array#unpack to decode stream (see utils.rb). All the class/routines that use input stream changed accordingly. Sun Dec 8 19:01:13 2002 Ryuichi Tamura * lib/exifparser/tag.rb (Exif::Tag): missing tag classes completed to make conformable with Exif Standard 2.2 (backward compatible newest standard). (Exif::Tag::Flash#to_s): returned value make comformable to Exif Standard 2.2. (Exif::Tag::PixelXDimension, Exif::Tag::PixelYDimension): renamed from 'ExifImageWidth' and 'ExifImageLength'. Sun Dec 8 15:27:27 2002 Ryuichi Tamura * Apply following fixes/contributions by Noguchi Shingo. * lib/exifparser/makernote/nikon2.rb, lib/exifparser/makernote/minolta.rb: new files. * lib/exifparser/scan.rb (Exif::Scanner#scan): Tag::Model object was generated by Tag::Model. This bug is fixed by Noguchi Shingo. (Exif::Scanner#scan): use @byteOrder_module to instantiate makernote object. In many models, the byteorder of Makernote seems the same as that of IFDs. * lib/exifparser/makernote/*.rb (Exif::Makernote::XXX#initialize): ditto. * lib/exifparser/makernote/nikon.rb: new tag classes introduced, some of them are fixed. * lib/exifparser/makernote/prove.rb: added new conditionals to return newly introduced models (Nikon, Nikon2, Minolta). * lib/exifparser/tag.rb (Exif::Tag::Makernote#_format0, Exif::Tag::Makernote#to_s): the functionality of these methods should be exchanged. * lib/exifparser/tag.rb (Exif::Tag::UserComment#to_s): wrong pack parameter. * lib/exifparser/tag.rb (Exif::Tag::CustomRendered): new tag class. * lib/exifparser/tag.rb (Exif::Tag::DigitalZoonRation): ditto. * lib/exifparser/tag.rb (Exif::Tag::FocalLengthIn35mmFilm): ditto. * lib/exifparser/tag.rb (Exif::Tag::SceneCaptureType): ditto. * lib/exifparser/tag.rb (Exif::Tag::GainControl): ditto. * lib/exifparser/tag.rb (Exif::Tag::Contrast): ditto. * lib/exifparser/tag.rb (Exif::Tag::Saturation): ditto. * lib/exifparser/tag.rb (Exif::Tag::Sharpness): ditto. * lib/exifparser/tag.rb (Exif::Tag::DeviceSettingDescription): ditto. * lib/exifparser/tag.rb (Exif::Tag::SubjectDistanceRange): ditto. Wed Nov 20 13:28:16 2002 Ryuichi Tamura * lib/exifparser/utils.rb: Utils::Pack::Motorola, Utils::Pack::Intel: new modules. these are extended to objects that require decode data. * lib/exifparser/scan.rb: __byteOrder__() is obsoleted. objects that require decode data will extend appropriate decode modules according to the byte order. (Exif::Scanner#scan_IFD): ditto. (Exif::Scanner#scan): check condition for valid EXIF identifier is relaxed because some model does not provide the correct one. * lib/exifparser/tag.rb (Exif::Tag::Format): now returns a pair of sizeof(format) and formatter module. (Exif::Tag::Formatter): modules provide 'format' method that returns its name as string. (Exif::Tag::Base#initialize): does not require byteorder argument. needs count information instead. (Exif::Tag::Base#inspect): now shows format information. (Exif::Tag::Base#__byteOrder__): obsoleted. decode modules will be extended instead(see above). (Exif::Tag::XXX): Tag classes now do not include format modules in advance. these modules will extended according to the value of 'format' field of the data. * lib/exifparser/makernote/fujifilm.rb, lib/exifparser/makernote/nikon.rb, lib/exifparser/makernote/canon.rb, lib/exifparser/makernote/olympus.rb: applies the same changes as described above. Wed Nov 13 18:59:08 2002 Ryuichi Tamura * lib/exifparser/tag.rb (Exif::Tag::ExifVersion#to_s): fixed typo. Tue Nov 12 16:34:00 2002 Ryuichi Tamura * lib/exifparser/scan.rb (Exif::Scanner#scan): some maker does not provide any identifier. So pass Exif::Tag::Make object to MakerNote.prove(), and use Exif::Tag::Make.value to prove the maker. (Exif::Scanner#get_app1_datasize): wrong shift length. * lib/exifparser/makernote/prove.rb: ditto. * lib/exifparser/makernote/prove.rb: added Canon makernote parsing class. 2002-11-11 15:52 tam * lib/exifparser/methods.rb: removed 2002-11-11 15:49 tam * lib/exifparser/tag.rb: Exif::Tag::ExifImageWidth, Exif::Tag::ExifImageLength - added processData() to workaround. Exif::Tag::Base#to_name: should not use Module#nesting. revert to original behaviour. 2002-11-11 14:48 tam * lib/exifparser/: tag.rb, thumbnail.rb: tag.rb (Exif::Tag::ExifImageLength, Exif::Tag::ExifImageHeight): should include Formatter::UShort. 2002-11-11 12:21 tam * lib/: exifparser.rb, exifparser/methods.rb, exifparser/tag.rb: exifparser/tag.rb (Exif::Tag::Base#name): use Module#module_nesting. 2002-11-10 22:28 tam * lib/: exifparser.rb, exifparser/scan.rb, exifparser/tag.rb, exifparser/makernote/olympus.rb: exifparser/tag.rb, exifparser/scan.rb: apply patches by noguchi shingo(noguchi@daifukuya.com) to fix bugs, inadequate tag representation (tag#to_s). exifparser/makernote/olympus.rb: tag 'CameraID' should be packed "C*" when to_s'ed. tdiary-contrib-3.2.2/lib/exifparser/README000066400000000000000000000003211213632744000202440ustar00rootroot00000000000000Ruby Exif parser - Exif tag parser written in pure Ruby = Install $ ruby install.rb config $ ruby install.rb setup # ruby install.rb install = License Ruby's = Author Ryuichi Tamura (r-tam@fsinet.or.jp) tdiary-contrib-3.2.2/lib/exifparser/install.rb000066400000000000000000000521401213632744000213650ustar00rootroot00000000000000# # This file is automatically generated. DO NOT MODIFY! # # install.rb # # Copyright (c) 2000-2002 Minero Aoki # # This program is free software. # You can distribute/modify this program under the terms of # the GNU Lesser General Public License version 2. # ### begin compat.rb unless Enumerable.instance_methods.include? 'inject' then module Enumerable def inject( result ) each do |i| result = yield(result, i) end result end end end def File.read_all( fname ) File.open(fname, 'rb') {|f| return f.read } end def File.write( fname, str ) File.open(fname, 'wb') {|f| f.write str } end ### end compat.rb ### begin config.rb if i = ARGV.index(/\A--rbconfig=/) then file = $' ARGV.delete_at(i) require file else require 'rbconfig' end class ConfigTable c = ::Config::CONFIG rubypath = c['bindir'] + '/' + c['ruby_install_name'] major = c['MAJOR'].to_i minor = c['MINOR'].to_i teeny = c['TEENY'].to_i version = "#{major}.#{minor}" # ruby ver. >= 1.4.4? newpath_p = ((major >= 2) or ((major == 1) and ((minor >= 5) or ((minor == 4) and (teeny >= 4))))) re = Regexp.new('\A' + Regexp.quote(c['prefix'])) subprefix = lambda {|path| re === path and path.sub(re, '$prefix') } if c['rubylibdir'] then # 1.6.3 < V stdruby = subprefix.call(c['rubylibdir']) siteruby = subprefix.call(c['sitedir']) versite = subprefix.call(c['sitelibdir']) sodir = subprefix.call(c['sitearchdir']) elsif newpath_p then # 1.4.4 <= V <= 1.6.3 stdruby = "$prefix/lib/ruby/#{version}" siteruby = subprefix.call(c['sitedir']) versite = siteruby + '/' + version sodir = "$site-ruby/#{c['arch']}" else # V < 1.4.4 stdruby = "$prefix/lib/ruby/#{version}" siteruby = "$prefix/lib/ruby/#{version}/site_ruby" versite = siteruby sodir = "$site-ruby/#{c['arch']}" end DESCRIPTER = [ [ 'prefix', [ c['prefix'], 'path', 'path prefix of target environment' ] ], [ 'std-ruby', [ stdruby, 'path', 'the directory for standard ruby libraries' ] ], [ 'site-ruby-common', [ siteruby, 'path', 'the directory for version-independent non-standard ruby libraries' ] ], [ 'site-ruby', [ versite, 'path', 'the directory for non-standard ruby libraries' ] ], [ 'bin-dir', [ '$prefix/bin', 'path', 'the directory for commands' ] ], [ 'rb-dir', [ '$site-ruby', 'path', 'the directory for ruby scripts' ] ], [ 'so-dir', [ sodir, 'path', 'the directory for ruby extentions' ] ], [ 'data-dir', [ '$prefix/share', 'path', 'the directory for shared data' ] ], [ 'ruby-path', [ rubypath, 'path', 'path to set to #! line' ] ], [ 'ruby-prog', [ rubypath, 'name', 'the ruby program using for installation' ] ], [ 'make-prog', [ 'make', 'name', 'the make program to compile ruby extentions' ] ], [ 'without-ext', [ 'no', 'yes/no', 'does not compile/install ruby extentions' ] ] ] SAVE_FILE = 'config.save' def ConfigTable.each_name( &block ) keys().each( &block ) end def ConfigTable.keys DESCRIPTER.collect {|k,*dummy| k } end def ConfigTable.each_definition( &block ) DESCRIPTER.each( &block ) end def ConfigTable.get_entry( name ) name, ent = DESCRIPTER.assoc(name) ent end def ConfigTable.get_entry!( name ) get_entry(name) or raise ArgumentError, "no such config: #{name}" end def ConfigTable.add_entry( name, vals ) ConfigTable::DESCRIPTER.push [name,vals] end def ConfigTable.remove_entry( name ) get_entry name or raise ArgumentError, "no such config: #{name}" DESCRIPTER.delete_if {|n,arr| n == name } end def ConfigTable.config_key?( name ) get_entry(name) ? true : false end def ConfigTable.bool_config?( name ) ent = get_entry(name) or return false ent[1] == 'yes/no' end def ConfigTable.value_config?( name ) ent = get_entry(name) or return false ent[1] != 'yes/no' end def ConfigTable.path_config?( name ) ent = get_entry(name) or return false ent[1] == 'path' end class << self alias newobj new def new c = newobj() c.__send__ :init c end def load c = newobj() File.file? SAVE_FILE or raise InstallError, "#{File.basename $0} config first" File.foreach( SAVE_FILE ) do |line| k, v = line.split( '=', 2 ) c.instance_eval { @table[k] = v.strip } end c end end def initialize @table = {} end def init DESCRIPTER.each do |k, (default, vname, desc, default2)| @table[k] = default end end private :init def save File.open( SAVE_FILE, 'w' ) {|f| @table.each do |k, v| f.printf "%s=%s\n", k, v if v end } end def []=( k, v ) ConfigTable.config_key? k or raise InstallError, "unknown config option #{k}" if ConfigTable.path_config? k then @table[k] = (v[0,1] != '$') ? File.expand_path(v) : v else @table[k] = v end end def []( key ) @table[key] or return nil @table[key].gsub( %r<\$([^/]+)> ) { self[$1] } end def set_raw( key, val ) @table[key] = val end def get_raw( key ) @table[key] end end class MetaConfigEnvironment def self.eval_file( file ) return unless File.file? file new.instance_eval File.read_all(file), file, 1 end private def config_names ConfigTable.keys end def config?( name ) ConfigTable.config_key? name end def bool_config?( name ) ConfigTable.bool_config? name end def value_config?( name ) ConfigTable.value_config? name end def path_config?( name ) ConfigTable.path_config? name end def add_config( name, argname, default, desc ) ConfigTable.add_entry name,[default,argname,desc] end def add_path_config( name, default, desc ) add_config name, 'path', default, desc end def add_bool_config( name, default, desc ) add_config name, 'yes/no', default ? 'yes' : 'no', desc end def set_config_default( name, default ) if bool_config? name then ConfigTable.get_entry!(name)[0] = default ? 'yes' : 'no' else ConfigTable.get_entry!(name)[0] = default end end def remove_config( name ) ent = ConfigTable.get_entry(name) ConfigTable.remove_entry name ent end end ### end config.rb ### begin fileop.rb module FileOperations def mkdir_p( dname, prefix = nil ) dname = prefix + dname if prefix $stderr.puts "mkdir -p #{dname}" if verbose? return if no_harm? # does not check '/'... it's too abnormal case dirs = dname.split(%r_(?=/)_) if /\A[a-z]:\z/i === dirs[0] then disk = dirs.shift dirs[0] = disk + dirs[0] end dirs.each_index do |idx| path = dirs[0..idx].join('') Dir.mkdir path unless dir? path end end def rm_f( fname ) $stderr.puts "rm -f #{fname}" if verbose? return if no_harm? if File.exist? fname or File.symlink? fname then File.chmod 0777, fname File.unlink fname end end def rm_rf( dn ) $stderr.puts "rm -rf #{dn}" if verbose? return if no_harm? Dir.chdir dn Dir.foreach('.') do |fn| next if fn == '.' next if fn == '..' if dir? fn then verbose_off { rm_rf fn } else verbose_off { rm_f fn } end end Dir.chdir '..' Dir.rmdir dn end def mv( src, dest ) rm_f dest begin File.link src, dest rescue File.write dest, File.read_all(src) File.chmod File.stat(src).mode, dest end rm_f src end def install( from, dest, mode, prefix = nil ) $stderr.puts "install #{from} #{dest}" if verbose? return if no_harm? realdest = prefix + dest if prefix if dir? realdest then realdest += '/' + File.basename(from) end str = File.read_all(from) if diff? str, realdest then verbose_off { rm_f realdest if File.exist? realdest } File.write realdest, str File.chmod mode, realdest File.open( objdir + '/InstalledFiles', 'a' ) {|f| f.puts realdest } end end def diff?( orig, targ ) return true unless File.exist? targ orig != File.read_all(targ) end def command( str ) $stderr.puts str if verbose? system str or raise RuntimeError, "'system #{str}' failed" end def ruby( str ) command config('ruby-prog') + ' ' + str end def dir?( dname ) # for corrupted windows stat() File.directory?( (dname[-1,1] == '/') ? dname : dname + '/' ) end def all_files( dname ) Dir.open( dname ) {|d| return d.find_all {|n| File.file? "#{dname}/#{n}" } } end def all_dirs( dname ) Dir.open( dname ) {|d| return d.find_all {|n| dir? "#{dname}/#{n}" } - %w(. ..) } end end ### end fileop.rb ### begin base.rb class InstallError < StandardError; end class Installer Version = '3.1.2' Copyright = 'Copyright (c) 2000-2002 Minero Aoki' @toplevel = nil def self.declear_toplevel_installer( inst ) @toplevel and raise ArgumentError, 'more than one toplevel installer decleared' @toplevel = inst end def self.toplevel_installer @toplevel end FILETYPES = %w( bin lib ext data ) include FileOperations def initialize( config, opt, srcroot, objroot ) @config = config @options = opt @srcdir = File.expand_path(srcroot) @objdir = File.expand_path(objroot) @currdir = '.' end def inspect "#<#{type} #{__id__}>" end # # configs/options # def get_config( key ) @config[key] end alias config get_config def set_config( key, val ) @config[key] = val end def no_harm? @options['no-harm'] end def verbose? @options['verbose'] end def verbose_off save, @options['verbose'] = @options['verbose'], false yield @options['verbose'] = save end # # srcdir/objdir # attr_reader :srcdir alias srcdir_root srcdir alias package_root srcdir def curr_srcdir "#{@srcdir}/#{@currdir}" end attr_reader :objdir alias objdir_root objdir def curr_objdir "#{@objdir}/#{@currdir}" end def srcfile( path ) curr_srcdir + '/' + path end def srcexist?( path ) File.exist? srcfile(path) end def srcdirectory?( path ) dir? srcfile(path) end def srcfile?( path ) File.file? srcfile(path) end def srcentries( path = '.' ) Dir.open( curr_srcdir + '/' + path ) {|d| return d.to_a - %w(. ..) - hookfilenames } end def srcfiles( path = '.' ) srcentries(path).find_all {|fname| File.file? File.join(curr_srcdir, path, fname) } end def srcdirectories( path = '.' ) srcentries(path).find_all {|fname| dir? File.join(curr_srcdir, path, fname) } end def dive_into( rel ) return unless dir? "#{@srcdir}/#{rel}" dir = File.basename(rel) Dir.mkdir dir unless dir? dir save = Dir.pwd Dir.chdir dir $stderr.puts '---> ' + rel if verbose? @currdir = rel yield Dir.chdir save $stderr.puts '<--- ' + rel if verbose? @currdir = File.dirname(rel) end # # config # def exec_config exec_task_traverse 'config' end def config_dir_bin( rel ) end def config_dir_lib( rel ) end def config_dir_ext( rel ) extconf if extdir? curr_srcdir end def extconf opt = @options['config-opt'].join(' ') command "#{config('ruby-prog')} #{curr_srcdir}/extconf.rb #{opt}" end def config_dir_data( rel ) end # # setup # def exec_setup exec_task_traverse 'setup' end def setup_dir_bin( relpath ) all_files( curr_srcdir ).each do |fname| add_rubypath "#{curr_srcdir}/#{fname}" end end SHEBANG_RE = /\A\#!\s*\S*ruby\S*/ def add_rubypath( path ) $stderr.puts %Q if verbose? return if no_harm? tmpfile = File.basename(path) + '.tmp' begin File.open( path ) {|r| File.open( tmpfile, 'w' ) {|w| first = r.gets return unless SHEBANG_RE === first # reject '/usr/bin/env ruby' w.print first.sub( SHEBANG_RE, '#!' + config('ruby-path') ) w.write r.read } } mv tmpfile, File.basename(path) ensure rm_f tmpfile if File.exist? tmpfile end end def setup_dir_lib( relpath ) end def setup_dir_ext( relpath ) if extdir? curr_srcdir then make end end def make command config('make-prog') end def setup_dir_data( relpath ) end # # install # def exec_install exec_task_traverse 'install' end def install_dir_bin( rel ) install_files targfiles, config('bin-dir') + '/' + rel, 0755 end def install_dir_lib( rel ) install_files targfiles, config('rb-dir') + '/' + rel, 0644 end def install_dir_ext( rel ) if extdir? curr_srcdir then install_dir_ext_main File.dirname(rel) end end def install_dir_ext_main( rel ) install_files allext('.'), config('so-dir') + '/' + rel, 0555 end def install_dir_data( rel ) install_files targfiles, config('data-dir') + '/' + rel, 0644 end def install_files( list, dest, mode ) mkdir_p dest, @options['install-prefix'] list.each do |fname| install fname, dest, mode, @options['install-prefix'] end end def targfiles (targfilenames() - hookfilenames()).collect {|fname| File.exist?(fname) ? fname : File.join(curr_srcdir(), fname) } end def targfilenames [ curr_srcdir(), '.' ].inject([]) {|ret, dir| ret | all_files(dir) } end def hookfilenames %w( pre-%s post-%s pre-%s.rb post-%s.rb ).collect {|fmt| %w( config setup install clean ).collect {|t| sprintf fmt, t } }.flatten end def allext( dir ) _allext(dir) or raise InstallError, "no extention exists: Have you done 'ruby #{$0} setup' ?" end DLEXT = /\.#{ ::Config::CONFIG['DLEXT'] }\z/ def _allext( dir ) Dir.open( dir ) {|d| return d.find_all {|fname| DLEXT === fname } } end # # clean # def exec_clean exec_task_traverse 'clean' rm_f 'config.save' rm_f 'InstalledFiles' end def clean_dir_bin( rel ) end def clean_dir_lib( rel ) end def clean_dir_ext( rel ) clean end def clean command config('make-prog') + ' clean' if File.file? 'Makefile' end def clean_dir_data( rel ) end # # lib # def exec_task_traverse( task ) run_hook 'pre-' + task FILETYPES.each do |type| if config('without-ext') == 'yes' and type == 'ext' then $stderr.puts 'skipping ext/* by user option' if verbose? next end traverse task, type, task + '_dir_' + type end run_hook 'post-' + task end def traverse( task, rel, mid ) dive_into( rel ) { run_hook 'pre-' + task __send__ mid, rel.sub( %r_\A.*?(?:/|\z)_, '' ) all_dirs( curr_srcdir ).each do |d| traverse task, rel + '/' + d, mid end run_hook 'post-' + task } end def run_hook( name ) try_run_hook curr_srcdir + '/' + name or try_run_hook curr_srcdir + '/' + name + '.rb' end def try_run_hook( fname ) return false unless File.file? fname env = self.dup begin env.instance_eval File.read_all(fname), fname, 1 rescue raise InstallError, "hook #{fname} failed:\n" + $!.message end true end def extdir?( dir ) File.exist? dir + '/MANIFEST' end end ### end base.rb ### begin toplevel.rb class ToplevelInstaller < Installer TASKS = [ [ 'config', 'saves your configurations' ], [ 'show', 'shows current configuration' ], [ 'setup', 'compiles extention or else' ], [ 'install', 'installs files' ], [ 'clean', "does `make clean' for each extention" ] ] def initialize( root ) super nil, {'verbose' => true}, root, '.' Installer.declear_toplevel_installer self end def execute run_metaconfigs case task = parsearg_global() when 'config' @config = ConfigTable.new else @config = ConfigTable.load end parsearg_TASK task exectask task end def run_metaconfigs MetaConfigEnvironment.eval_file "#{srcdir_root}/#{metaconfig}" end def metaconfig 'metaconfig' end def exectask( task ) if task == 'show' then exec_show else try task end end def try( task ) $stderr.printf "#{File.basename $0}: entering %s phase...\n", task if verbose? begin __send__ 'exec_' + task rescue $stderr.printf "%s failed\n", task raise end $stderr.printf "#{File.basename $0}: %s done.\n", task if verbose? end # # processing arguments # def parsearg_global task_re = /\A(?:#{TASKS.collect {|i| i[0] }.join '|'})\z/ while arg = ARGV.shift do case arg when /\A\w+\z/ task_re === arg or raise InstallError, "wrong task: #{arg}" return arg when '-q', '--quiet' @options['verbose'] = false when '--verbose' @options['verbose'] = true when '-h', '--help' print_usage $stdout exit 0 when '-v', '--version' puts "#{File.basename $0} version #{Version}" exit 0 when '--copyright' puts Copyright exit 0 else raise InstallError, "unknown global option '#{arg}'" end end raise InstallError, 'no task or global option given' end def parsearg_TASK( task ) mid = "parsearg_#{task}" if respond_to? mid, true then __send__ mid else ARGV.empty? or raise InstallError, "#{task}: unknown options: #{ARGV.join ' '}" end end def parsearg_config re = /\A--(#{ConfigTable.keys.join '|'})(?:=(.*))?\z/ @options['config-opt'] = [] while i = ARGV.shift do if /\A--?\z/ === i then @options['config-opt'] = ARGV.dup break end m = re.match(i) or raise InstallError, "config: unknown option #{i}" name, value = m.to_a[1,2] if value then if ConfigTable.bool_config?(name) then /\A(y(es)?|n(o)?|t(rue)?|f(alse))\z/i === value or raise InstallError, "config: --#{name} allows only yes/no for argument" value = (/\Ay(es)?|\At(rue)/i === value) ? 'yes' : 'no' end else ConfigTable.bool_config?(name) or raise InstallError, "config: --#{name} requires argument" value = 'yes' end @config[name] = value end end def parsearg_install @options['no-harm'] = false @options['install-prefix'] = '' while a = ARGV.shift do case a when /\A--no-harm\z/ @options['no-harm'] = true when /\A--prefix=(.*)\z/ path = $1 path = File.expand_path(path) unless path[0,1] == '/' @options['install-prefix'] = path else raise InstallError, "install: unknown option #{a}" end end end def print_usage( out ) out.puts out.puts 'Usage:' out.puts " ruby #{File.basename $0} " out.puts " ruby #{File.basename $0} [] []" fmt = " %-20s %s\n" out.puts out.puts 'Global options:' out.printf fmt, '-q,--quiet', 'suppress message outputs' out.printf fmt, ' --verbose', 'output messages verbosely' out.printf fmt, '-h,--help', 'print this message' out.printf fmt, '-v,--version', 'print version and quit' out.printf fmt, '--copyright', 'print copyright and quit' out.puts out.puts 'Tasks:' TASKS.each do |name, desc| out.printf " %-10s %s\n", name, desc end out.puts out.puts 'Options for config:' ConfigTable.each_definition do |name, (default, arg, desc, default2)| out.printf " %-20s %s [%s]\n", '--'+ name + (ConfigTable.bool_config?(name) ? '' : '='+arg), desc, default2 || default end out.printf " %-20s %s [%s]\n", '--rbconfig=path', 'your rbconfig.rb to load', "running ruby's" out.puts out.puts 'Options for install:' out.printf " %-20s %s [%s]\n", '--no-harm', 'only display what to do if given', 'off' out.puts end # # config # def exec_config super @config.save end # # show # def exec_show ConfigTable.each_name do |k| v = @config.get_raw(k) if not v or v.empty? then v = '(not specified)' end printf "%-10s %s\n", k, v end end end ### end toplevel.rb if $0 == __FILE__ then begin installer = ToplevelInstaller.new( File.dirname($0) ) installer.execute rescue raise if $DEBUG $stderr.puts $!.message $stderr.puts "try 'ruby #{$0} --help' for usage" exit 1 end end tdiary-contrib-3.2.2/lib/exifparser/lib/000077500000000000000000000000001213632744000201365ustar00rootroot00000000000000tdiary-contrib-3.2.2/lib/exifparser/lib/exifparser.rb000066400000000000000000000146451213632744000226450ustar00rootroot00000000000000# # #= exifparser.rb - Exif tag parser written in pure ruby # #Author:: Ryuchi Tamura (r-tam@fsinet.or.jp) #Copyright:: Copyright (C) 2002 Ryuichi Tamura. # # $Id: exifparser.rb,v 1.1.1.1 2002/12/16 07:59:00 tam Exp $ # #== INTRODUCTION # #There are 2 classes you work with. ExifParser class is #the Exif tag parser that parses all tags defined EXIF-2.2 standard, #and many of extension tags uniquely defined by some digital equipment #manufacturers. Currently, part of tags defined by FujiFilm, and #Olympus is supported. After initialized with the path to image file #of EXIF format, ExifParser will provides which tags are available in #the image, and how you work with them. # #Tags availble from ExifParser is objects defined under Exif::Tag module, #with its name being the class name. For example if you get "Make" tag #from ExifParser, it is Exif::Tag::DateTime object. Inspecting it looks #following: # # # # #here, ID is Tag ID defined in EXIF-2.2 standard, IFD is the name of #Image File Directory, Name is String representation of tag ID, Format is #string that shows how the data is formatted, and Value is the value of #the tag. This is retrieved by Exif::Tag::Make#value. # #Another example. If you want to know whether flash was fired when the image #was generated, ExifParser returns Exif::Tag::Flash object: # # tag = exif['Flash'] # p tag # => # # p tag.value # => 1 # #It may happen that diffrent IFDs have the same tag name. In this case, #use Exif#tag(tagname, IFD) # #The value of the tag above, 1, is not clearly understood #(supposed to be 'true', though). Exif::Tag::Flash#to_s will provides #more human-readable form as String. # # tag.to_s #=> "Flash fired." # #many of these sentences are cited from Exif-2.2 standard. # #== USAGE # require 'exifparser' # # exif = ExifParser.new("fujifilm.jpg") # # 1. get a tag value by its name('Make') or its ID (0x010f) # exif['Make'] #=> 'FUJIFILM' # exif[0x010f] #=> 'FUJIFILM' # # if the specified tag is not found, nil is returned. # # 2. to see the image has the value of specified tag # exif.tag?('DateTime') #=> true # exif.tag?('CameraID') #=> false # # 3. get all the tags contained in the image. # # exif.tags # # or, if you want to know all the tags defined in specific IFD, # # exif.tags(:IFD0) # get all the tags defined in IFD0 # # you can traverse each tag and work on it. # # exif.each do |tag| # p tag.to_s # end # # # each tag in IFD0 # exif.each(:IFD0) do |ifd0_tag| # p ifd0_tag.to_s # end # # 4. extract thumbnail # # File.open("thumb.jpg") do |dest| # exif.thumbnail dest # end # # dest object must respond to '<<'. # require 'exifparser/scan' module Exif class Parser # # create a new object. fpath is String. # def initialize(fpath) @fpath = fpath @scanner = nil File.open(fpath, "rb") do |f| @scanner = Exif::Scanner.new(f) @scanner.scan end @IFD0 = @scanner.result[:IFD0] @IFD1 = @scanner.result[:IFD1] @Exif = @scanner.result[:Exif] @GPS = @scanner.result[:GPS] @Interoperability = @scanner.result[:Interoperability] @MakerNote = @scanner.result[:MakerNote] @thumbnail = @scanner.result[:Thumbnail] end def inspect sprintf("#<%s filename=\"%s\" entries: IFD0(%d) IFD1(%d) Exif(%d) GPS(%d) Interoperability(%d) MakerNote(%d)>", self.class, @fpath, @IFD0.length, @IFD1.length, @Exif.length, @GPS.length, @Interoperability.length, @MakerNote.length) end # # return true if specified tagid is defined or has some value. # def tag?(tagid) search_tag(tagid) ? true : false end # # search tag on the specific IFD # def tag(tagname, ifd=nil) search_tag(tagname, ifd) end # # search the specified tag values. return value is object of # classes defined under Exif::Tag module. # def [](tagname) self.tag(tagname) end # # set the specified tag to the specified value. # XXX NOT IMPLEMETED XXX # def []=(tag, value) # not implemented end # # extract the thumbnail image to dest. dest should respond to # '<<' method. # def thumbnail(dest) dest << @thumbnail end # # return the size of the thumbnail image # def thumbnail_size @thumbnail.size end # # return all the tags in the image. # # if argument ifd is specified, every tags defined in the # specified IFD are passed to block. # # return value is object of classes defined under Exif::Tag module. # # allowable arguments are: # * :IFD0 # * :IFD1 # * :Exif # * :GPS # * :Interoperability # * :MakerNote (if exist) def tags(ifd=nil) if ifd @scanner.result[ifd] else [ @IFD0, @IFD1, @Exif, @GPS, @Interoperability, @MakerNote ].flatten end end # # execute given block with block argument being every tags defined # in all the IFDs contained in the image. # # if argument ifd is specified, every tags defined in the # specified IFD are passed to block. # # return value is object of classes defined under Exif::Tag module. # # allowable arguments are: # * :IFD0 # * :IFD1 # * :Exif # * :GPS # * :Interoperability # * :MakerNote def each(ifd=nil) if ifd @scanner.result[ifd].each{ |tag| yield tag } else [ @IFD0, @IFD1, @Exif, @GPS, @Interoperability, @MakerNote ].flatten.each do |tag| yield tag end end end private def search_tag(tagID, ifd=nil) if ifd @scanner.result(ifd).find do |tag| case tagID when Fixnum tag.tagID.hex == tagID when String tag.name == tagID end end else [ @IFD0, @IFD1, @Exif, @GPS, @Interoperability, @MakerNote ].flatten.find do |tag| case tagID when Fixnum tag.tagID.hex == tagID when String tag.name == tagID end end end end end # module Parser end # module Exif ExifParser = Exif::Parser tdiary-contrib-3.2.2/lib/exifparser/lib/exifparser/000077500000000000000000000000001213632744000223065ustar00rootroot00000000000000tdiary-contrib-3.2.2/lib/exifparser/lib/exifparser/makernote/000077500000000000000000000000001213632744000242735ustar00rootroot00000000000000tdiary-contrib-3.2.2/lib/exifparser/lib/exifparser/makernote/canon.rb000066400000000000000000000240731213632744000257240ustar00rootroot00000000000000# # exifparser/makernote/nikon.rb - # # Copyright (C) 2002 Ryuichi Tamura (r-tam@fsinet.or.jp) # # $Revision: 1.1.1.1 $ # $Date: 2002/12/16 07:59:00 $ # require 'exifparser/tag' require 'exifparser/utils' module Exif module Tag module MakerNote # # 0x0000 - Unknown # # # 0x0001 - Tag0x0001 # class Tag0x0001 < Base def processData @formatted = [] partition_data(@count) do |part| @formatted.push _formatData(part) end end def value numTags = @formatted[0] / 2 ret = {} return ret if numTags < 2 # # offset 1 : Macro mode # ret["Macro mode"] = case @formatted[1] when 1 "Macro" when 2 "Normal" else "Unknown" end return ret if numTags < 3 # # offset 2 : if nonzero, length of self-timer in 10ths of a second. # selftimer_length = @formatted[2] return ret if numTags < 5 # # offset 4 : Flash mode # ret["Flash mode"] = case @formatted[4] when 0 "flash not fired" when 1 "auto" when 2 "on" when 3 "red-eye reduction" when 4 "slow synchro" when 5 "auto + redeye reduction" when 6 "on + redeye reduction" when 16 "external flash" else "unknown" end return ret if numTags < 6 # # offset 5: Contiuous drive mode # ret["Continuous drive mode"] = case @formatted[5] when 0 if selftimer_length != 0 "Timer = #{selftimer_length/10.0}sec." else "Single" end when 1 "Continuous" end return ret if numTags < 8 # # offset 7: Focus Mode # ret["Focus Mode"] = case @formatted[7] when 0 "One-Shot" when 1 "AI Servo" when 2 "AI Focus" when 3 "MF" when 4 "Single" when 5 "Continuous" when 6 "MF" else "Unknown" end return ret if numTags < 11 # # offset 10: Image size # ret["Image Size"] = case @formatted[10] when 0 "Large" when 1 "Medium" when "Small" else "Unknown" end return ret if numTags < 12 # # offset 11: "Easy shooting" mode # ret["Easy shooting mode"] = case @formatted[11] when 0 "Full auto" when 1 "Manual" when 2 "Landscape" when 3 "Fast Shutter" when 4 "Slow Shutter" when 5 "Night" when 6 "B&W" when 7 "Sepia" when 8 "Portrait" when 9 "Sports" when 10 "Macro / Close-Up" when 11 "Pan Focus" else "Unknown" end return ret if numTags < 14 # # offset 13: Contrast # ret["Contrast"] = case @formatted[13] when 0xffff "Low" when 0x0000 "Normal" when 0x0001 "High" else "Unknown" end return ret if numTags < 15 # # offset 14: Saturation # ret["Saturation"] = case @formatted[14] when 0xffff "Low" when 0x0000 "Normal" when 0x0001 "High" else "Unknown" end return ret if numTags < 16 # # offset 15: Contrast # ret["Sharpness"] = case @formatted[15] when 0xffff "Low" when 0x0000 "Normal" when 0x0001 "High" else "Unknown" end return ret if numTags < 17 # # offset 16: ISO # ret["ISO"] = case @formatted[16] when 0 "ISOSpeedRatings" when 15 "Auto" when 16 50 when 17 100 when 18 200 when 19 400 else "Unknown" end return ret if numTags < 18 # # offset 17: Metering mode # ret['Metering mode'] = case @formatted[17] when 3 "Evaluative" when 4 "Partial" when 5 "Center-weighted" else "Unknown" end ret end end # # 0x0003 - Tag0x0003 # class Tag0x0003 < Base end # # 0x0004 - Tag0x0004 # class Tag0x0004 < Base def processData @formatted = [] partition_data(@count) do |part| @formatted.push _formatData(part) end end def value numTags = @formatted[0] / 2 ret = {} return hash if numTags < 8 # offset 7 : white balance ret['White balance'] = case @formatted[7] when 0 "Auto" when 1 "Sunny" when 2 "Cloudy" when 3 "Tungsten" when 4 "Florescent" when 5 "Flash" when 6 "Custom" else "Unknown" end return ret if numTags < 10 # offset 9: Sequence number (if in a continuous burst) ret['Sequence number'] = @formatted[9] return ret if numTags < 15 # offset 14: Auto Focus point used ret['Auto Focus point used'] = @formatted[14] return ret if numTags < 16 ret['Flash bias'] = case @formatted[15] when 0xffc0 "-2 EV" when 0xffcc "-1.67 EV" when 0xffd0 "-1.50 EV" when 0xffd4 "-1.33 EV" when 0xffe0 "-1 EV" when 0xffec "-0.67 EV" when 0xfff0 "-0.50 EV" when 0xfff4 "-0.33 EV" when 0x0000 "0 EV" when 0x000c "0.33 EV" when 0x0010 "0.50 EV" when 0x0014 "0.67 EV" when 0x0020 "1 EV" when 0x002c "1.33 EV" when 0x0030 "1.50 EV" when 0x0034 "1.67 EV" when 0x0040 "2 EV" else "Unknown" end return ret if numTags < 20 ret['Subject Distance'] = @formatted[19] ret end end # # 0x0006 - ImageType # class ImageType < Base end # # 0x0007 - FirmwareVersion # class FirmwareVersion < Base end # # 0x0008 - ImageNumber # class ImageNumber < Base end # # 0x0009 - OwnerName # class OwnerName < Base end # # 0x000a - Unknown # # # 0x000c - CameraSerialNumber # class CameraSerialNumber < Base def to_s hi = @formatted / 0x10000 low = @formatted % 0x10000 "%04X%05d"%[hi, low] end end # # 0x000d - Unknown # # # 0x000f - CustomFunctions # class CustomFunctions < Base def processData @formatted = [] partition_data(@count) do |part| @formatted.push _formatData(part) end end end end CanonIFDTable = { 0x0000 => Unknown, 0x0001 => MakerNote::Tag0x0001, 0x0003 => MakerNote::Tag0x0003, 0x0004 => MakerNote::Tag0x0004, 0x0006 => MakerNote::ImageType, 0x0007 => MakerNote::FirmwareVersion, 0x0008 => MakerNote::ImageNumber, 0x0009 => MakerNote::OwnerName, 0x000a => Unknown, 0x000c => MakerNote::CameraSerialNumber, 0x000d => Unknown, 0x000f => MakerNote::CustomFunctions } end class Canon def initialize(fin, tiff_origin, dataPos, byteOrder_module) @fin = fin @tiffHeader0 = tiff_origin @dataPos = dataPos @byteOrder_module = byteOrder_module self.extend @byteOrder_module end def scan_IFD # # Canon MakerNote starts from 0 # @fin.pos = @dataPos + 0 # # get the number of tags # numDirs = decode_ushort(fin_read_n(2)) # # now scan them # 1.upto(numDirs) { curpos_tag = @fin.pos tag = parseTagID(fin_read_n(2)) tagclass = Tag.find(tag.hex, Tag::CanonIFDTable) unit, formatter = Tag::Format::Unit[decode_ushort(fin_read_n(2))] count = decode_ulong(fin_read_n(4)) tagdata = fin_read_n(4) obj = tagclass.new(tag, "MakerNote", count) obj.extend formatter, @byteOrder_module obj.pos = curpos_tag if unit * count > 4 curpos = @fin.pos begin @fin.pos = @tiffHeader0 + decode_ulong(tagdata) obj.dataPos = @fin.pos obj.data = fin_read_n(unit*count) ensure @fin.pos = curpos end else obj.dataPos = @fin.pos - 4 obj.data = tagdata end obj.processData yield obj } end private def fin_read_n(n) @fin.read(n) end end end tdiary-contrib-3.2.2/lib/exifparser/lib/exifparser/makernote/fujifilm.rb000066400000000000000000000165001213632744000264270ustar00rootroot00000000000000# # exifparser/makernote/fujifilm.rb - # # Copyright (C) 2002 Ryuichi Tamura (r-tam@fsinet.or.jp) # # $Revision: 1.1.1.1 $ # $Date: 2002/12/16 07:59:00 $ # # Tested against FinePix 6900Z # require 'exifparser/tag' require 'exifparser/utils' # #== References #http://www.ba.wakwak.com/%7Etsuruzoh/Computer/Digicams/exif-e.html # module Exif module Tag module MakerNote # # 0x0000 - Version # class Version < Base end # # 0x1000 - Quality # class Quality < Base end # # 0x1001 - Sharpness # class Sharpness < Base def to_s case @formatted when 1,2 'Weak' when 3 'Standard' when 4 'Strong' else 'Unknown' end end end # # 0x1002 - White # class White < Base def to_s case @formatted when 0 'Auto' when 256 'Daylight' when 512 'Cloudy' when 768 'DaylightColor-fluorescence' when 769 'DaywhiteColor-fluorescence' when 770 'WhiteColor-fluorescence' when 1024 'Incandescence' when 3840 'Custom white balance' else 'Unknown' end end end # # 0x1003 - Color # class Color < Base def to_s case @formatted when 0 'Normal(STD)' when 256 'High(HARD)' when 'Low(ORG)' else 'Unknown' end end end # # 0x1004 - Tone # class Tone < Base def to_s case @formatted when 0 'Normal(STD)' when 256 'High(HARD)' when 512 'Low(ORG)' else 'Unknown' end end end # # 0x1010 - FlashMode # class FlashMode < Base def to_s case @formatted when 0 'Auto' when 1 'On' when 2 'Off' when 3 'Red-eye reduction' else 'Unknown' end end end # # 0x1011 - FlashStrength # class FlashStrength < Base end # # 0x1020 - Macro # class Macro < Base def to_s case @formatted when 0 'Off' when 1 'On' else 'Unknown' end end end # # 0x1021 - Focus mode # class FocusMode < Base def to_s case @formatted when 0 'Auto focus' when 1 'Manual focus' else 'Unknown' end end end # # 0x1030 - SlowSync # class SlowSync < Base def to_s case @formatted when 0 'Off' when 1 'On' else 'Unknown' end end end # # 0x1031 - PictureMode # class PictureMode < Base def to_s case @formatted when 0 'Auto' when 1 'Portrait scene' when 2 'Landscape scene' when 4 'Sports scene' when 5 'Night scene' when 6 'Program Auto Exposure' when 256 'Aperture prior Auto Exposure' when 512 'Shutter prior Auto Exposure' when 768 'Manual exposure' else 'Unknown' end end end # # 0x1032 - Unknown # # # 0x1100 - Cont_Bracket # class Cont_Bracket < Base def to_s case @formatted when 0 'Off' when 1 'On' else 'Unknown' end end def name 'Continuous/AutoBracket' end end # # 0x1200 - Unknown # # # 0x1300 - Blur warning # class BlurWarning < Base def to_s case @formatted when 0 'No blur warning' when 1 'Blur warning' else 'Unknown' end end end # # 0x1301 - Focus warning # class FocusWarning < Base def to_s case @formatted when 0 'Auto Focus good' when 1 'Out of Focus' else 'Unknown' end end end # # 0x1302 - AE warning # class AutoExposureWarning < Base def to_s case @formatted when 0 'Auto exposure good' when 1 'Over exposure' else 'Unknown' end end end end # # Tags used in Fujifilm makernote # FujifilmIFDTable = { 0x0000 => MakerNote::Version, 0x1000 => MakerNote::Quality, 0x1001 => MakerNote::Sharpness, 0x1002 => MakerNote::White, 0x1003 => MakerNote::Color, 0x1004 => MakerNote::Tone, 0x1010 => MakerNote::FlashMode, 0x1011 => MakerNote::FlashStrength, 0x1020 => MakerNote::Macro, 0x1021 => MakerNote::FocusMode, 0x1030 => MakerNote::SlowSync, 0x1031 => MakerNote::PictureMode, 0x1032 => Unknown, 0x1100 => MakerNote::Cont_Bracket, 0x1200 => Unknown, 0x1300 => MakerNote::BlurWarning, 0x1301 => MakerNote::FocusWarning, 0x1302 => MakerNote::AutoExposureWarning } end class Fujifilm def initialize(fin, tiff_origin, dataPos, byteOrder_module) @fin = fin @tiffHeader0 = tiff_origin @dataPos = dataPos @byteOrder_module = Utils::Decode::Intel # force Intel self.extend @byteOrder_module end def scan_IFD # # Fujifilm MakerNote starts from 8 byte from the origin # @fin.pos = @dataPos + 8 offset = decode_ushort(fin_read_n(2)) @fin.pos = @dataPos + offset # # get the number of tags # numDirs = decode_ushort(fin_read_n(2)) # # now scan them # 1.upto(numDirs) { curpos_tag = @fin.pos tag = parseTagID(fin_read_n(2)) tagclass = Tag.find(tag.hex, Tag::FujifilmIFDTable) unit, formatter = Tag::Format::Unit[decode_ushort(fin_read_n(2))] count = decode_ulong(fin_read_n(4)) tagdata = fin_read_n(4) obj = tagclass.new(tag, "MakerNote", count) obj.extend formatter, @byteOrder_module obj.pos = curpos_tag if unit * count > 4 curpos = @fin.pos begin @fin.pos = @dataPos + decode_ulong(tagdata) obj.dataPos = @fin.pos obj.data = fin_read_n(unit*count) ensure @fin.pos = curpos end else obj.dataPos = @fin.pos - 4 obj.data = tagdata end obj.processData yield obj } end private def fin_read_n(n) @fin.read(n) end end end tdiary-contrib-3.2.2/lib/exifparser/lib/exifparser/makernote/minolta.rb000066400000000000000000000032141213632744000262630ustar00rootroot00000000000000# # exifparser/makernote/minolta.rb # # $Revision: 1.2 $ # $Date: 2003/05/13 15:41:28 $ # require 'exifparser/tag' require 'exifparser/utils' module Exif module Tag module MakerNote end MinoltaIFDTable = { } end class Minolta def initialize(fin, tiff_origin, dataPos, byteOrder_module) @fin = fin @tiffHeader0 = tiff_origin @dataPos = dataPos @byteOrder_module = byteOrder_module self.extend @byteOrder_module end def scan_IFD # # Minolta MakerNote starts from 0 byte from the origin # @fin.pos = @dataPos + 0 # # get the number of tags # numDirs = decode_ushort(fin_read_n(2)) # # now scan them # 1.upto(numDirs) { curpos_tag = @fin.pos tag = parseTagID(fin_read_n(2)) tagclass = Tag.find(tag.hex, Tag::MinoltaIFDTable) unit, formatter = Tag::Format::Unit[decode_ushort(fin_read_n(2))] count = decode_ulong(fin_read_n(4)) tagdata = fin_read_n(4) obj = tagclass.new(tag, "MakerNote", count) obj.extend formatter, @byteOrder_module obj.pos = curpos_tag if unit * count > 4 curpos = @fin.pos begin @fin.pos = @tiffHeader0 + decode_ulong(tagdata) obj.dataPos = @fin.pos obj.data = fin_read_n(unit*count) ensure @fin.pos = curpos end else obj.dataPos = @fin.pos - 4 obj.data = tagdata end obj.processData yield obj } end private def fin_read_n(n) @fin.read(n) end end end tdiary-contrib-3.2.2/lib/exifparser/lib/exifparser/makernote/mk_nikonflensname.rb000077500000000000000000000020551213632744000303230ustar00rootroot00000000000000#!/usr/bin/env ruby # # mk_nikonflensname.rb # # .. makes the Ruby source code of hash table: Nikon EXIF LensParameters => Lens model name. # This is for Exif::Makernote::Tag::LensParameters class # in exifparser/nmakernote/nikon2.rb # # usage : ruby mk_nikonlens_hash.rb nikonmn.cpp >nikonflensname.rb # ("nikonmn.cpp" is a exiv2(http://www.exiv2.org/)'s nikon makernote module source code. ) # # Copyright (c) 2009 N.KASHIJUKU # You can redistribute it and/or modify it under GPL2. # print < "#{$8} #{$9}"] str.sub!("f/", "F") if str.include?("Nikon") print str + ",\n" end end end print < "" } end end end EEOS tdiary-contrib-3.2.2/lib/exifparser/lib/exifparser/makernote/nikon.rb000066400000000000000000000116131213632744000257400ustar00rootroot00000000000000# # exifparser/makernote/nikon.rb - # # Copyright (C) 2002 Ryuichi Tamura (r-tam@fsinet.or.jp) # # $Revision: 1.1.1.1 $ # $Date: 2002/12/16 07:59:00 $ # require 'exifparser/tag' require 'exifparser/utils' module Exif module Tag module MakerNote # # 0x0003 - Quality # class Quality < Base def to_s n = @formatted.to_i - 1 (s, q) = n.divmod(3) f = case s when 0 'VGA' when 1 'SVGA' when 2 'SXGA' when 3 'UXGA' else 'Unknown size' end f << ' ' << case q when 0 'Basic' when 1 'Normal' when 2 'Fine' else 'Unknown quality' end f end end # # 0x0004 - ColorMode # class ColorMode < Base def to_s case @formatted when 1 'Color' when 2 'Monochrome' else 'Unknown' end end end # # 0x0005 - ImageAdjustment # class ImageAdjustment < Base def to_s case @formatted when 0 'Normal' when 1 'Bright+' when 2 'Bright-' when 3 'Contrast+' when 4 'Contrast-' else 'Unknown' end end end # # 0x0006 - CCDSensitivity # class CCDSensitivity < Base def to_s case @formatted when 0 'ISO80' when 2 'ISO160' when 4 'ISO320' when 5 'ISO100' else "Unknown(#{@formatted})" end end end # # 0x0007 - WhiteBalance # class WhiteBalance < Base def to_s case @formatted when 0 'Auto' when 1 'Preset' when 2 'Daylight' when 3 'Incandescense' when 4 'Fluorescence' when 5 'Cloudy' when 6 'SpeedLight' else "Unknown(#{@formatted})" end end end # # 0x0008 - Focus # class Focus < Base def to_s n = @formatted.numerator d = @formatted.denominator (n == 1 && d == 0) ? 'Pan Focus' : "#{n}/#{d}" end end # # 0x000a - DigitalZoom # class DigitalZoom < Base def to_s n = @formatted.numerator d = @formatted.denominator (n == 0 && d == 100) ? 'None' : "%0.1f"%[n.to_f/d.to_f] end end # # 0x000b - Converter # class Converter < Base def to_s case @formatted when 0 'None' when 1 'Fisheye' else 'Unknown' end end end end NikonIFDTable = { 0x0003 => MakerNote::Quality, 0x0004 => MakerNote::ColorMode, 0x0005 => MakerNote::ImageAdjustment, 0x0006 => MakerNote::CCDSensitivity, 0x0007 => MakerNote::WhiteBalance, 0x0008 => MakerNote::Focus, 0x000a => MakerNote::DigitalZoom, 0x000b => MakerNote::Converter } end class Nikon def initialize(fin, tiff_origin, dataPos, byteOrder_module) @fin = fin @tiffHeader0 = tiff_origin @dataPos = dataPos @byteOrder_module = byteOrder_module self.extend @byteOrder_module end def scan_IFD # # Nikon MakerNote starts from 8 byte from the origin. # @fin.pos = @dataPos + 8 # # get the number of tags # num_dirs = decode_ushort(fin_read_n(2)) # # now scan them # 1.upto(num_dirs) { curpos_tag = @fin.pos tag = parseTagID(fin_read_n(2)) tagclass = Tag.find(tag.hex, Tag::NikonIFDTable) unit, formatter = Tag::Format::Unit[decode_ushort(fin_read_n(2))] count = decode_ulong(fin_read_n(4)) tagdata = fin_read_n(4) obj = tagclass.new(tag, "MakerNote", count) obj.extend formatter, @byteOrder_module obj.pos = curpos_tag if unit * count > 4 curpos = @fin.pos begin @fin.pos = @tiffHeader0 + decode_ulong(tagdata) obj.dataPos = @fin.pos obj.data = fin_read_n(unit*count) ensure @fin.pos = curpos end else obj.dataPos = @fin.pos - 4 obj.data = tagdata end obj.processData yield obj } end private def fin_read_n(n) @fin.read(n) end end end tdiary-contrib-3.2.2/lib/exifparser/lib/exifparser/makernote/nikon2.rb000066400000000000000000000345241213632744000260300ustar00rootroot00000000000000# # exif/makernote/nikon2.rb # # $Revision: 1.3 $ # $Date: 2003/04/27 13:54:52 $ # #== Reference # #http://www.ba.wakwak.com/%7Etsuruzoh/Computer/Digicams/exif-e.html # require 'exifparser/tag' require 'exifparser/utils' require 'exifparser/makernote/nikonflensname' module Exif # # Tags used in Nikon Makernote # module Tag module MakerNote # # Shared Datas between Tags # module SharedData @@nikon_serial_no = nil # written by NikonCameaSerialNumber Tag @@release_count = nil # written by ReleaseCount Tag end # # Subclass for Tags need shared datas # class NikonBase < Base include SharedData end # # 0x0001 - Data Version # class DataVersion < Base end # # 0x0002 - ISOUsed # # class ISOUsed < Base # end # # 0x0003 - ColorMode # class ColorMode < Base end # # 0x0004 - ImageQuality # class ImageQuality < Base end # # 0x0005 - Whitebalance # class Whitebalance < Base end # # 0x0006 - ImageSharpening # class ImageSharpening < Base end # # 0x0007 - FocusingMode # class FocusingMode < Base end # # 0x0008 - FlashSetting # class FlashSetting < Base end # # 0x0009 - SpeedlightMode # class SpeedlightMode < Base end # # 0x000d - ProgramShift # class ProgramShift < Base def to_s case @formatted when [0xfc, 0x01, 0x06, 0x00] "-2/3EV" when [0xfd, 0x01, 0x06, 0x00] "-1/2EV" when [0xfe, 0x01, 0x06, 0x00] "-1/3EV" when [0x00, 0x01, 0x06, 0x00] "+0EV" when [0x02, 0x01, 0x06, 0x00] "+1/3EV" when [0x03, 0x01, 0x06, 0x00] "+1/2EV" when [0x04, 0x01, 0x06, 0x00] "+2/3EV" else "" end end end # # 0x000e - ExposureDifference # class ExposureDifference < Base def to_s case @formatted when [0xf7, 0x01, 0x0c, 0x00] "-2/3EV" when [0xf9, 0x01, 0x0c, 0x00] "-1/2EV" when [0xfc, 0x01, 0x0c, 0x00] "-1/3EV" when [0x00, 0x01, 0x0c, 0x00] "+0EV" when [0x04, 0x01, 0x0c, 0x00] "+1/3EV" when [0x06, 0x01, 0x0c, 0x00] "+1/2EV" when [0x08, 0x01, 0x0c, 0x00] "+2/3EV" else "" end end end # # 0x000f - ISOSelection # class ISOSelection < Base end # # 0x0010 - DataDump # class DataDump < Base end # # 0x0012 - Speedlight Bias # class SpeedlightBias < Base def to_s case @formatted when [0xfc, 0x01, 0x06, 0x00] "-2/3EV" when [0xfd, 0x01, 0x06, 0x00] "-1/2EV" when [0xfe, 0x01, 0x06, 0x00] "-1/3EV" when [0x00, 0x01, 0x06, 0x00] "+0EV" when [0x02, 0x01, 0x06, 0x00] "+1/3EV" when [0x03, 0x01, 0x06, 0x00] "+1/2EV" when [0x04, 0x01, 0x06, 0x00] "+2/3EV" else "" end end end # # 0x001d - NikonCameraSerialNumber # class NikonCameraSerialNumber < NikonBase def processData super @@nikon_serial_no = @formatted # This value is used for LensParamaters tag. end end # # 0x0022 ActiveD_Lighting # class ActiveD_Lighting < Base def to_s case @formatted when 0 "Off" when 1 "Low" when 3 "Normal" when 5 "Hight" when 7 "Extra High" when 65535 "Auto" else "" end end end # # 0x0023 - PictureControl # class PictureControl < Base def to_s @formatted[4,20].pack('C*') end end # # 0x0080 - ImageAdjustment # class ImageAdjustment < Base end # # 0x0081 - Tone Compensation # class ToneCompensation < Base end # # 0x0082 - Adapter # class Adapter < Base end # # 0x0083 - LensType # class LensType < Base def to_s data = @formatted[0] isVR = (data[3] == 1 ? "Yes":"No") isG = (data[2] == 1 ? "Yes":"No") isD = (data[1] == 1 ? "Yes":"No") isMF = (data[0] == 1 ? "Yes":"No") "VR:#{isVR}, G:#{isG}, D:#{isD}, MF:#{isMF}" end end # # 0x0084 - LensSpecification # class LensSpecification < Base def processData @formatted = [] partition_data(@count) do |data| @formatted.push _formatData(data) end end def to_s if @formatted[0] != @formatted[1] "#{@formatted[0]}-#{@formatted[1]}mm, F#{@formatted[2].to_f}-#{@formatted[3].to_f}" else "#{@formatted[0]}mm, F#{@formatted[2].to_f} (Prime Lens)" end end end # # 0x0085 - ManualForcusDistance # class ManualForcusDistance < Base end # # 0x0086 - DigitalZoom # class DigitalZoom < Base end # # 0x0088 - AFFocusPosition # class AFFocusPosition < Base end # # 0x008D - CameraColorMode # class CameraColorMode < Base end # # 0x008F - SceneMode # class SceneMode < Base end # # 0x0090 - LightSource # class LightSource < Base end # # 0x0095 - LongtimeExposureNR # class LongtimeExposureNR < Base end # # 0x0098 - LensParamaters # class LensParameters < NikonBase def _format0(data) data.unpack("C*").collect{|e| e.to_i} end def to_hex str = "" @formatted.each do |dat| str += sprintf("%02x ", dat) end return str end XLAT0 = [0xc1,0xbf,0x6d,0x0d,0x59,0xc5,0x13,0x9d,0x83,0x61,0x6b,0x4f,0xc7,0x7f,0x3d,0x3d, 0x53,0x59,0xe3,0xc7,0xe9,0x2f,0x95,0xa7,0x95,0x1f,0xdf,0x7f,0x2b,0x29,0xc7,0x0d, 0xdf,0x07,0xef,0x71,0x89,0x3d,0x13,0x3d,0x3b,0x13,0xfb,0x0d,0x89,0xc1,0x65,0x1f, 0xb3,0x0d,0x6b,0x29,0xe3,0xfb,0xef,0xa3,0x6b,0x47,0x7f,0x95,0x35,0xa7,0x47,0x4f, 0xc7,0xf1,0x59,0x95,0x35,0x11,0x29,0x61,0xf1,0x3d,0xb3,0x2b,0x0d,0x43,0x89,0xc1, 0x9d,0x9d,0x89,0x65,0xf1,0xe9,0xdf,0xbf,0x3d,0x7f,0x53,0x97,0xe5,0xe9,0x95,0x17, 0x1d,0x3d,0x8b,0xfb,0xc7,0xe3,0x67,0xa7,0x07,0xf1,0x71,0xa7,0x53,0xb5,0x29,0x89, 0xe5,0x2b,0xa7,0x17,0x29,0xe9,0x4f,0xc5,0x65,0x6d,0x6b,0xef,0x0d,0x89,0x49,0x2f, 0xb3,0x43,0x53,0x65,0x1d,0x49,0xa3,0x13,0x89,0x59,0xef,0x6b,0xef,0x65,0x1d,0x0b, 0x59,0x13,0xe3,0x4f,0x9d,0xb3,0x29,0x43,0x2b,0x07,0x1d,0x95,0x59,0x59,0x47,0xfb, 0xe5,0xe9,0x61,0x47,0x2f,0x35,0x7f,0x17,0x7f,0xef,0x7f,0x95,0x95,0x71,0xd3,0xa3, 0x0b,0x71,0xa3,0xad,0x0b,0x3b,0xb5,0xfb,0xa3,0xbf,0x4f,0x83,0x1d,0xad,0xe9,0x2f, 0x71,0x65,0xa3,0xe5,0x07,0x35,0x3d,0x0d,0xb5,0xe9,0xe5,0x47,0x3b,0x9d,0xef,0x35, 0xa3,0xbf,0xb3,0xdf,0x53,0xd3,0x97,0x53,0x49,0x71,0x07,0x35,0x61,0x71,0x2f,0x43, 0x2f,0x11,0xdf,0x17,0x97,0xfb,0x95,0x3b,0x7f,0x6b,0xd3,0x25,0xbf,0xad,0xc7,0xc5, 0xc5,0xb5,0x8b,0xef,0x2f,0xd3,0x07,0x6b,0x25,0x49,0x95,0x25,0x49,0x6d,0x71,0xc7] XLAT1 = [0xa7,0xbc,0xc9,0xad,0x91,0xdf,0x85,0xe5,0xd4,0x78,0xd5,0x17,0x46,0x7c,0x29,0x4c, 0x4d,0x03,0xe9,0x25,0x68,0x11,0x86,0xb3,0xbd,0xf7,0x6f,0x61,0x22,0xa2,0x26,0x34, 0x2a,0xbe,0x1e,0x46,0x14,0x68,0x9d,0x44,0x18,0xc2,0x40,0xf4,0x7e,0x5f,0x1b,0xad, 0x0b,0x94,0xb6,0x67,0xb4,0x0b,0xe1,0xea,0x95,0x9c,0x66,0xdc,0xe7,0x5d,0x6c,0x05, 0xda,0xd5,0xdf,0x7a,0xef,0xf6,0xdb,0x1f,0x82,0x4c,0xc0,0x68,0x47,0xa1,0xbd,0xee, 0x39,0x50,0x56,0x4a,0xdd,0xdf,0xa5,0xf8,0xc6,0xda,0xca,0x90,0xca,0x01,0x42,0x9d, 0x8b,0x0c,0x73,0x43,0x75,0x05,0x94,0xde,0x24,0xb3,0x80,0x34,0xe5,0x2c,0xdc,0x9b, 0x3f,0xca,0x33,0x45,0xd0,0xdb,0x5f,0xf5,0x52,0xc3,0x21,0xda,0xe2,0x22,0x72,0x6b, 0x3e,0xd0,0x5b,0xa8,0x87,0x8c,0x06,0x5d,0x0f,0xdd,0x09,0x19,0x93,0xd0,0xb9,0xfc, 0x8b,0x0f,0x84,0x60,0x33,0x1c,0x9b,0x45,0xf1,0xf0,0xa3,0x94,0x3a,0x12,0x77,0x33, 0x4d,0x44,0x78,0x28,0x3c,0x9e,0xfd,0x65,0x57,0x16,0x94,0x6b,0xfb,0x59,0xd0,0xc8, 0x22,0x36,0xdb,0xd2,0x63,0x98,0x43,0xa1,0x04,0x87,0x86,0xf7,0xa6,0x26,0xbb,0xd6, 0x59,0x4d,0xbf,0x6a,0x2e,0xaa,0x2b,0xef,0xe6,0x78,0xb6,0x4e,0xe0,0x2f,0xdc,0x7c, 0xbe,0x57,0x19,0x32,0x7e,0x2a,0xd0,0xb8,0xba,0x29,0x00,0x3c,0x52,0x7d,0xa8,0x49, 0x3b,0x2d,0xeb,0x25,0x49,0xfa,0xa3,0xaa,0x39,0xa7,0xc5,0xa7,0x50,0x11,0x36,0xfb, 0xc6,0x67,0x4a,0xf5,0xa5,0x12,0x65,0x7e,0xb0,0xdf,0xaf,0x4e,0xb3,0x61,0x7f,0x2f] def to_s data = @formatted lens_data = "" version = data[0, 4].pack('C*') case version when "0100" lens_data = data[6, 7] when "0101" lens_data = data[11, 7] when "0201", "0202", "0203" decryptted = decrypt_data(data[4..(data.length - 1)], @@nikon_serial_no, @@release_count) lens_data = decryptted[7, 7] when "0204" decryptted = decrypt_data(data[4..(data.length - 1)], @@nikon_serial_no, @@release_count) lens_data = decryptted[8, 7] end return "" if lens_data.length == 0 self.extend NikonFmount ret = Tag::NikonFmount::LensName[lens_data] return ret != nil ? ret : "" end def decrypt_data(data, serial, count) serialno = serial.to_i if serialno == 0 if serial[0,3] == "D50" serialno = 0x22 else serialno = 0x60 end end key = 0 4.times do |i| key ^= ((count >> (i*8)) & 0xff) end ci = XLAT0[serialno & 0xff] cj = XLAT1[key] ck = 0x60; pdata = [] data.each do |dat| cj += ((ci * ck) & 0xff) cj &= 0xff ck += 1 pdata.push(dat ^= cj) end return pdata end end # # 0x00a7 - ReleaseCount # class ReleaseCount < NikonBase def processData super @@release_count = @formatted # This value is used for LensParamaters tag. end end # # 0x00a9 - ImageOptimization # class ImageOptimization < Base end # # 0x00aa - Saturation # class Saturation < Base end end Nikon2IFDTable = { 0x0001 => MakerNote::DataVersion, # 0x0002 => MakerNote::ISOUsed, 0x0003 => MakerNote::ColorMode, 0x0004 => MakerNote::ImageQuality, 0x0005 => MakerNote::Whitebalance, 0x0006 => MakerNote::ImageSharpening, 0x0007 => MakerNote::FocusingMode, 0x0008 => MakerNote::FlashSetting, 0x0009 => MakerNote::SpeedlightMode, 0x000d => MakerNote::ProgramShift, 0x000e => MakerNote::ExposureDifference, 0x000f => MakerNote::ISOSelection, 0x0010 => MakerNote::DataDump, 0x0012 => MakerNote::SpeedlightBias, 0x001d => MakerNote::NikonCameraSerialNumber, 0x0022 => MakerNote::ActiveD_Lighting, 0x0023 => MakerNote::PictureControl, 0x0080 => MakerNote::ImageAdjustment, 0x0081 => MakerNote::ToneCompensation, 0x0082 => MakerNote::Adapter, 0x0083 => MakerNote::LensType, 0x0084 => MakerNote::LensSpecification, 0x0085 => MakerNote::ManualForcusDistance, 0x0086 => MakerNote::DigitalZoom, 0x0088 => MakerNote::AFFocusPosition, 0x008D => MakerNote::CameraColorMode, 0x008F => MakerNote::SceneMode, 0x0090 => MakerNote::LightSource, 0x0095 => MakerNote::LongtimeExposureNR, 0x0098 => MakerNote::LensParameters, 0x00a7 => MakerNote::ReleaseCount, 0x00a9 => MakerNote::ImageOptimization, 0x00aa => MakerNote::Saturation } end class Nikon2 def initialize(fin, tiff_origin, dataPos, byteOrder_module) @fin = fin @tiffHeader0 = tiff_origin @dataPos = dataPos @nikonOffset = 0 @fin.pos = dataPos magic = fin_read_n(6) if magic == "Nikon\000" @nikonOffset = 18 # D100, E5700, etc.. fin_read_n(4) @tiffHeader0 = @fin.pos bo = @fin.read(2) case bo when "MM" byteOrder_module = Utils::Decode::Motorola when "II" byteOrder_module = Utils::Decode::Intel else raise RuntimeError, "Unknown byte order" end end @byteOrder_module = byteOrder_module self.extend @byteOrder_module end def scan_IFD # # Nikon D1 series MakerNote starts from 0 byte from the origin. # @fin.pos = @dataPos + @nikonOffset # # get the number of tags # num_dirs = decode_ushort(fin_read_n(2)) # # now scan them # 1.upto(num_dirs) { curpos_tag = @fin.pos tag = parseTagID(fin_read_n(2)) tagclass = Tag.find(tag.hex, Tag::Nikon2IFDTable) unit, formatter = Tag::Format::Unit[decode_ushort(fin_read_n(2))] count = decode_ulong(fin_read_n(4)) tagdata = fin_read_n(4) obj = tagclass.new(tag, "MakerNote", count) obj.extend formatter, @byteOrder_module obj.pos = curpos_tag if unit * count > 4 curpos = @fin.pos begin @fin.pos = @tiffHeader0 + decode_ulong(tagdata) obj.dataPos = @fin.pos obj.data = fin_read_n(unit*count) ensure @fin.pos = curpos end else obj.dataPos = @fin.pos - 4 obj.data = tagdata end obj.processData yield obj } end private def fin_read_n(n) @fin.read(n) end end end tdiary-contrib-3.2.2/lib/exifparser/lib/exifparser/makernote/nikonflensname.rb000066400000000000000000001171531213632744000276370ustar00rootroot00000000000000module Exif module Tag module NikonFmount LensName = { [0x01, 0x58, 0x50, 0x50, 0x14, 0x14, 0x02] => "Nikon AF Nikkor 50mm F1.8", [0x02, 0x42, 0x44, 0x5C, 0x2A, 0x34, 0x02] => "Nikon AF Zoom-Nikkor 35-70mm F3.3-4.5", [0x02, 0x42, 0x44, 0x5C, 0x2A, 0x34, 0x08] => "Nikon AF Zoom-Nikkor 35-70mm F3.3-4.5", [0x03, 0x48, 0x5C, 0x81, 0x30, 0x30, 0x02] => "Nikon AF Zoom-Nikkor 70-210mm F4", [0x04, 0x48, 0x3C, 0x3C, 0x24, 0x24, 0x03] => "Nikon AF Nikkor 28mm F2.8", [0x05, 0x54, 0x50, 0x50, 0x0C, 0x0C, 0x04] => "Nikon AF Nikkor 50mm F1.4", [0x06, 0x54, 0x53, 0x53, 0x24, 0x24, 0x06] => "Nikon AF Micro-Nikkor 55mm F2.8", [0x07, 0x40, 0x3C, 0x62, 0x2C, 0x34, 0x03] => "Nikon AF Zoom-Nikkor 28-85mm F3.5-4.5", [0x08, 0x40, 0x44, 0x6A, 0x2C, 0x34, 0x04] => "Nikon AF Zoom-Nikkor 35-105mm F3.5-4.5", [0x09, 0x48, 0x37, 0x37, 0x24, 0x24, 0x04] => "Nikon AF Nikkor 24mm F2.8", [0x0A, 0x48, 0x8E, 0x8E, 0x24, 0x24, 0x03] => "Nikon AF Nikkor 300mm F2.8 IF-ED", [0x0A, 0x48, 0x8E, 0x8E, 0x24, 0x24, 0x05] => "Nikon AF Nikkor 300mm F2.8 IF-ED N", [0x0B, 0x48, 0x7C, 0x7C, 0x24, 0x24, 0x05] => "Nikon AF Nikkor 180mm F2.8 IF-ED", [0x0D, 0x40, 0x44, 0x72, 0x2C, 0x34, 0x07] => "Nikon AF Zoom-Nikkor 35-135mm F3.5-4.5", [0x0E, 0x48, 0x5C, 0x81, 0x30, 0x30, 0x05] => "Nikon AF Zoom-Nikkor 70-210mm F4", [0x0F, 0x58, 0x50, 0x50, 0x14, 0x14, 0x05] => "Nikon AF Nikkor 50mm F1.8 N", [0x10, 0x48, 0x8E, 0x8E, 0x30, 0x30, 0x08] => "Nikon AF Nikkor 300mm F4 IF-ED", [0x11, 0x48, 0x44, 0x5C, 0x24, 0x24, 0x08] => "Nikon AF Zoom-Nikkor 35-70mm F2.8", [0x12, 0x48, 0x5C, 0x81, 0x30, 0x3C, 0x09] => "Nikon AF Nikkor 70-210mm F4-5.6", [0x13, 0x42, 0x37, 0x50, 0x2A, 0x34, 0x0B] => "Nikon AF Zoom-Nikkor 24-50mm F3.3-4.5", [0x14, 0x48, 0x60, 0x80, 0x24, 0x24, 0x0B] => "Nikon AF Zoom-Nikkor 80-200mm F2.8 ED", [0x15, 0x4C, 0x62, 0x62, 0x14, 0x14, 0x0C] => "Nikon AF Nikkor 85mm F1.8", [0x17, 0x3C, 0xA0, 0xA0, 0x30, 0x30, 0x0F] => "Nikon Nikkor 500mm F4 P ED IF", [0x17, 0x3C, 0xA0, 0xA0, 0x30, 0x30, 0x11] => "Nikon Nikkor 500mm F4 P ED IF", [0x18, 0x40, 0x44, 0x72, 0x2C, 0x34, 0x0E] => "Nikon AF Zoom-Nikkor 35-135mm F3.5-4.5 N", [0x1A, 0x54, 0x44, 0x44, 0x18, 0x18, 0x11] => "Nikon AF Nikkor 35mm F2", [0x1B, 0x44, 0x5E, 0x8E, 0x34, 0x3C, 0x10] => "Nikon AF Zoom-Nikkor 75-300mm F4.5-5.6", [0x1C, 0x48, 0x30, 0x30, 0x24, 0x24, 0x12] => "Nikon AF Nikkor 20mm F2.8", [0x1D, 0x42, 0x44, 0x5C, 0x2A, 0x34, 0x12] => "Nikon AF Zoom-Nikkor 35-70mm F3.3-4.5 N", [0x1E, 0x54, 0x56, 0x56, 0x24, 0x24, 0x13] => "Nikon AF Micro-Nikkor 60mm F2.8", [0x1F, 0x54, 0x6A, 0x6A, 0x24, 0x24, 0x14] => "Nikon AF Micro-Nikkor 105mm F2.8", [0x20, 0x48, 0x60, 0x80, 0x24, 0x24, 0x15] => "Nikon AF Zoom-Nikkor 80-200mm F2.8 ED", [0x21, 0x40, 0x3C, 0x5C, 0x2C, 0x34, 0x16] => "Nikon AF Zoom-Nikkor 28-70mm F3.5-4.5", [0x22, 0x48, 0x72, 0x72, 0x18, 0x18, 0x16] => "Nikon AF DC-Nikkor 135mm F2", [0x23, 0x30, 0xBE, 0xCA, 0x3C, 0x48, 0x17] => "Nikon Zoom-Nikkor 1200-1700mm F5.6-8 P ED IF", [0x24, 0x48, 0x60, 0x80, 0x24, 0x24, 0x1A] => "Nikon AF Zoom-Nikkor 80-200mm F2.8D ED", [0x25, 0x48, 0x44, 0x5c, 0x24, 0x24, 0x1B] => "Nikon AF Zoom-Nikkor 35-70mm F2.8D", [0x25, 0x48, 0x44, 0x5c, 0x24, 0x24, 0x52] => "Nikon AF Zoom-Nikkor 35-70mm F2.8D", [0x26, 0x40, 0x3C, 0x5C, 0x2C, 0x34, 0x1C] => "Nikon AF Zoom-Nikkor 28-70mm F3.5-4.5D", [0x27, 0x48, 0x8E, 0x8E, 0x24, 0x24, 0x1D] => "Nikon AF-I Nikkor 300mm F2.8D IF-ED", [0x27, 0x48, 0x8E, 0x8E, 0x24, 0x24, 0xF1] => "Nikon AF-I Nikkor 300mm F2.8D IF-ED + TC-14E", [0x27, 0x48, 0x8E, 0x8E, 0x24, 0x24, 0xE1] => "Nikon AF-I Nikkor 300mm F2.8D IF-ED + TC-17E", [0x27, 0x48, 0x8E, 0x8E, 0x24, 0x24, 0xF2] => "Nikon AF-I Nikkor 300mm F2.8D IF-ED + TC-20E", [0x28, 0x3C, 0xA6, 0xA6, 0x30, 0x30, 0x1D] => "Nikon AF-I Nikkor 600mm F4D IF-ED", [0x28, 0x3C, 0xA6, 0xA6, 0x30, 0x30, 0xF1] => "Nikon AF-I Nikkor 600mm F4D IF-ED + TC-14E", [0x28, 0x3C, 0xA6, 0xA6, 0x30, 0x30, 0xE1] => "Nikon AF-I Nikkor 600mm F4D IF-ED + TC-17E", [0x28, 0x3C, 0xA6, 0xA6, 0x30, 0x30, 0xF2] => "Nikon AF-I Nikkor 600mm F4D IF-ED + TC-20E", [0x2A, 0x54, 0x3C, 0x3C, 0x0C, 0x0C, 0x26] => "Nikon AF Nikkor 28mm F1.4D", [0x2B, 0x3C, 0x44, 0x60, 0x30, 0x3C, 0x1F] => "Nikon AF Zoom-Nikkor 35-80mm F4-5.6D", [0x2C, 0x48, 0x6A, 0x6A, 0x18, 0x18, 0x27] => "Nikon AF DC-Nikkor 105mm F2D", [0x2D, 0x48, 0x80, 0x80, 0x30, 0x30, 0x21] => "Nikon AF Micro-Nikkor 200mm F4D IF-ED", [0x2E, 0x48, 0x5C, 0x82, 0x30, 0x3C, 0x22] => "Nikon AF Nikkor 70-210mm F4-5.6D", [0x2E, 0x48, 0x5C, 0x82, 0x30, 0x3C, 0x28] => "Nikon AF Nikkor 70-210mm F4-5.6D", [0x2F, 0x48, 0x30, 0x44, 0x24, 0x24, 0x29] => "Nikon AF Zoom-Nikkor 20-35mm F2.8D IF", [0x30, 0x48, 0x98, 0x98, 0x24, 0x24, 0x24] => "Nikon AF-I Nikkor 400mm F2.8D IF-ED", [0x30, 0x48, 0x98, 0x98, 0x24, 0x24, 0xF1] => "Nikon AF-I Nikkor 400mm F2.8D IF-ED + TC-14E", [0x30, 0x48, 0x98, 0x98, 0x24, 0x24, 0xE1] => "Nikon AF-I Nikkor 400mm F2.8D IF-ED + TC-17E", [0x30, 0x48, 0x98, 0x98, 0x24, 0x24, 0xF2] => "Nikon AF-I Nikkor 400mm F2.8D IF-ED + TC-20E", [0x31, 0x54, 0x56, 0x56, 0x24, 0x24, 0x25] => "Nikon AF Micro-Nikkor 60mm F2.8D", [0x32, 0x54, 0x6A, 0x6A, 0x24, 0x24, 0x35] => "Nikon AF Micro-Nikkor 105mm F2.8D", [0x33, 0x48, 0x2D, 0x2D, 0x24, 0x24, 0x31] => "Nikon AF Nikkor 18mm F2.8D", [0x34, 0x48, 0x29, 0x29, 0x24, 0x24, 0x32] => "Nikon AF Fisheye Nikkor 16mm F2.8D", [0x35, 0x3C, 0xA0, 0xA0, 0x30, 0x30, 0x33] => "Nikon AF-I Nikkor 500mm F4D IF-ED", [0x35, 0x3C, 0xA0, 0xA0, 0x30, 0x30, 0xF1] => "Nikon AF-I Nikkor 500mm F4D IF-ED + TC-14E", [0x35, 0x3C, 0xA0, 0xA0, 0x30, 0x30, 0xE1] => "Nikon AF-I Nikkor 500mm F4D IF-ED + TC-17E", [0x35, 0x3C, 0xA0, 0xA0, 0x30, 0x30, 0xF2] => "Nikon AF-I Nikkor 500mm F4D IF-ED + TC-20E", [0x36, 0x48, 0x37, 0x37, 0x24, 0x24, 0x34] => "Nikon AF Nikkor 24mm F2.8D", [0x37, 0x48, 0x30, 0x30, 0x24, 0x24, 0x36] => "Nikon AF Nikkor 20mm F2.8D", [0x38, 0x4C, 0x62, 0x62, 0x14, 0x14, 0x37] => "Nikon AF Nikkor 85mm F1.8D", [0x3A, 0x40, 0x3C, 0x5C, 0x2C, 0x34, 0x39] => "Nikon AF Zoom-Nikkor 28-70mm F3.5-4.5D", [0x3B, 0x48, 0x44, 0x5C, 0x24, 0x24, 0x3A] => "Nikon AF Zoom-Nikkor 35-70mm F2.8D N", [0x3C, 0x48, 0x60, 0x80, 0x24, 0x24, 0x3B] => "Nikon AF Zoom-Nikkor 80-200mm F2.8D ED", [0x3D, 0x3C, 0x44, 0x60, 0x30, 0x3C, 0x3E] => "Nikon AF Zoom-Nikkor 35-80mm F4-5.6D", [0x3E, 0x48, 0x3C, 0x3C, 0x24, 0x24, 0x3D] => "Nikon AF Nikkor 28mm F2.8D", [0x3F, 0x40, 0x44, 0x6A, 0x2C, 0x34, 0x45] => "Nikon AF Zoom-Nikkor 35-105mm F3.5-4.5D", [0x41, 0x48, 0x7c, 0x7c, 0x24, 0x24, 0x43] => "Nikon AF Nikkor 180mm F2.8D IF-ED", [0x42, 0x54, 0x44, 0x44, 0x18, 0x18, 0x44] => "Nikon AF Nikkor 35mm F2D", [0x43, 0x54, 0x50, 0x50, 0x0C, 0x0C, 0x46] => "Nikon AF Nikkor 50mm F1.4D", [0x44, 0x44, 0x60, 0x80, 0x34, 0x3C, 0x47] => "Nikon AF Zoom-Nikkor 80-200mm F4.5-5.6D", [0x45, 0x40, 0x3C, 0x60, 0x2C, 0x3C, 0x48] => "Nikon AF Zoom-Nikkor 28-80mm F3.5-5.6D", [0x46, 0x3C, 0x44, 0x60, 0x30, 0x3C, 0x49] => "Nikon AF Zoom-Nikkor 35-80mm F4-5.6D N", [0x47, 0x42, 0x37, 0x50, 0x2A, 0x34, 0x4A] => "Nikon AF Zoom-Nikkor 24-50mm F3.3-4.5D", [0x48, 0x48, 0x8E, 0x8E, 0x24, 0x24, 0x4B] => "Nikon AF-S Nikkor 300mm F2.8D IF-ED", [0x48, 0x48, 0x8E, 0x8E, 0x24, 0x24, 0xF1] => "Nikon AF-S Nikkor 300mm F2.8D IF-ED + TC-14E", [0x48, 0x48, 0x8E, 0x8E, 0x24, 0x24, 0xE1] => "Nikon AF-S Nikkor 300mm F2.8D IF-ED + TC-17E", [0x48, 0x48, 0x8E, 0x8E, 0x24, 0x24, 0xF2] => "Nikon AF-S Nikkor 300mm F2.8D IF-ED + TC-20E", [0x49, 0x3C, 0xA6, 0xA6, 0x30, 0x30, 0x4C] => "Nikon AF-S Nikkor 600mm F4D IF-ED", [0x49, 0x3C, 0xA6, 0xA6, 0x30, 0x30, 0xF1] => "Nikon AF-S Nikkor 600mm F4D IF-ED + TC-14E", [0x49, 0x3C, 0xA6, 0xA6, 0x30, 0x30, 0xE1] => "Nikon AF-S Nikkor 600mm F4D IF-ED + TC-17E", [0x49, 0x3C, 0xA6, 0xA6, 0x30, 0x30, 0xF2] => "Nikon AF-S Nikkor 600mm F4D IF-ED + TC-20E", [0x4A, 0x54, 0x62, 0x62, 0x0C, 0x0C, 0x4D] => "Nikon AF Nikkor 85mm F1.4D IF", [0x4B, 0x3C, 0xA0, 0xA0, 0x30, 0x30, 0x4E] => "Nikon AF-S Nikkor 500mm F4D IF-ED", [0x4B, 0x3C, 0xA0, 0xA0, 0x30, 0x30, 0xF1] => "Nikon AF-S Nikkor 500mm F4D IF-ED + TC-14E", [0x4B, 0x3C, 0xA0, 0xA0, 0x30, 0x30, 0xE1] => "Nikon AF-S Nikkor 500mm F4D IF-ED + TC-17E", [0x4B, 0x3C, 0xA0, 0xA0, 0x30, 0x30, 0xF2] => "Nikon AF-S Nikkor 500mm F4D IF-ED + TC-20E", [0x4C, 0x40, 0x37, 0x6E, 0x2C, 0x3C, 0x4F] => "Nikon AF Zoom-Nikkor 24-120mm F3.5-5.6D IF", [0x4D, 0x40, 0x3C, 0x80, 0x2C, 0x3C, 0x62] => "Nikon AF Zoom-Nikkor 28-200mm F3.5-5.6D IF", [0x4E, 0x48, 0x72, 0x72, 0x18, 0x18, 0x51] => "Nikon AF DC-Nikkor 135mm F2D", [0x4F, 0x40, 0x37, 0x5C, 0x2C, 0x3C, 0x53] => "Nikon IX-Nikkor 24-70mm F3.5-5.6", [0x50, 0x48, 0x56, 0x7C, 0x30, 0x3C, 0x54] => "Nikon IX-Nikkor 60-180mm F4-5.6", [0x53, 0x48, 0x60, 0x80, 0x24, 0x24, 0x57] => "Nikon AF Zoom-Nikkor 80-200mm F2.8D ED", [0x53, 0x48, 0x60, 0x80, 0x24, 0x24, 0x60] => "Nikon AF Zoom-Nikkor 80-200mm F2.8D ED", [0x54, 0x44, 0x5C, 0x7C, 0x34, 0x3C, 0x58] => "Nikon AF Zoom-Micro Nikkor 70-180mm F4.5-5.6D ED", [0x56, 0x48, 0x5C, 0x8E, 0x30, 0x3C, 0x5A] => "Nikon AF Zoom-Nikkor 70-300mm F4-5.6D ED", [0x59, 0x48, 0x98, 0x98, 0x24, 0x24, 0x5D] => "Nikon AF-S Nikkor 400mm F2.8D IF-ED", [0x59, 0x48, 0x98, 0x98, 0x24, 0x24, 0xF1] => "Nikon AF-S Nikkor 400mm F2.8D IF-ED + TC-14E", [0x59, 0x48, 0x98, 0x98, 0x24, 0x24, 0xE1] => "Nikon AF-S Nikkor 400mm F2.8D IF-ED + TC-17E", [0x59, 0x48, 0x98, 0x98, 0x24, 0x24, 0xF2] => "Nikon AF-S Nikkor 400mm F2.8D IF-ED + TC-20E", [0x5A, 0x3C, 0x3E, 0x56, 0x30, 0x3C, 0x5E] => "Nikon IX-Nikkor 30-60mm F4-5.6", [0x5B, 0x44, 0x56, 0x7C, 0x34, 0x3C, 0x5F] => "Nikon IX-Nikkor 60-180mm F4.5-5.6", [0x5D, 0x48, 0x3C, 0x5C, 0x24, 0x24, 0x63] => "Nikon AF-S Zoom-Nikkor 28-70mm F2.8D IF-ED", [0x5E, 0x48, 0x60, 0x80, 0x24, 0x24, 0x64] => "Nikon AF-S Zoom-Nikkor 80-200mm F2.8D IF-ED", [0x5F, 0x40, 0x3C, 0x6A, 0x2C, 0x34, 0x65] => "Nikon AF Zoom-Nikkor 28-105mm F3.5-4.5D IF", [0x60, 0x40, 0x3C, 0x60, 0x2C, 0x3C, 0x66] => "Nikon AF Zoom-Nikkor 28-80mm F3.5-5.6D", [0x61, 0x44, 0x5E, 0x86, 0x34, 0x3C, 0x67] => "Nikon AF Zoom-Nikkor 75-240mm F4.5-5.6D", [0x63, 0x48, 0x2B, 0x44, 0x24, 0x24, 0x68] => "Nikon AF-S Nikkor 17-35mm F2.8D IF-ED", [0x64, 0x00, 0x62, 0x62, 0x24, 0x24, 0x6A] => "Nikon PC Micro-Nikkor 85mm F2.8D", [0x65, 0x44, 0x60, 0x98, 0x34, 0x3C, 0x6B] => "Nikon AF VR Zoom-Nikkor 80-400mm F4.5-5.6D ED", [0x66, 0x40, 0x2D, 0x44, 0x2C, 0x34, 0x6C] => "Nikon AF Zoom-Nikkor 18-35mm F3.5-4.5D IF-ED", [0x67, 0x48, 0x37, 0x62, 0x24, 0x30, 0x6D] => "Nikon AF Zoom-Nikkor 24-85mm F2.8-4D IF", [0x68, 0x42, 0x3C, 0x60, 0x2A, 0x3C, 0x6E] => "Nikon AF Zoom-Nikkor 28-80mm F3.3-5.6G", [0x69, 0x48, 0x5C, 0x8E, 0x30, 0x3C, 0x6F] => "Nikon AF Zoom-Nikkor 70-300mm F4-5.6G", [0x6A, 0x48, 0x8E, 0x8E, 0x30, 0x30, 0x70] => "Nikon AF-S Nikkor 300mm F4D IF-ED", [0x6B, 0x48, 0x24, 0x24, 0x24, 0x24, 0x71] => "Nikon AF Nikkor ED 14mm F2.8D", [0x6D, 0x48, 0x8E, 0x8E, 0x24, 0x24, 0x73] => "Nikon AF-S Nikkor 300mm F2.8D IF-ED II", [0x6E, 0x48, 0x98, 0x98, 0x24, 0x24, 0x74] => "Nikon AF-S Nikkor 400mm F2.8D IF-ED II", [0x6F, 0x3C, 0xA0, 0xA0, 0x30, 0x30, 0x75] => "Nikon AF-S Nikkor 500mm F4D IF-ED II", [0x70, 0x3C, 0xA6, 0xA6, 0x30, 0x30, 0x76] => "Nikon AF-S Nikkor 600mm F4D IF-ED II", [0x72, 0x48, 0x4C, 0x4C, 0x24, 0x24, 0x77] => "Nikon Nikkor 45mm F2.8 P", [0x74, 0x40, 0x37, 0x62, 0x2C, 0x34, 0x78] => "Nikon AF-S Zoom-Nikkor 24-85mm F3.5-4.5G IF-ED", [0x75, 0x40, 0x3C, 0x68, 0x2C, 0x3C, 0x79] => "Nikon AF Zoom-Nikkor 28-100mm F3.5-5.6G", [0x76, 0x58, 0x50, 0x50, 0x14, 0x14, 0x7A] => "Nikon AF Nikkor 50mm F1.8D", [0x77, 0x48, 0x5C, 0x80, 0x24, 0x24, 0x7B] => "Nikon AF-S VR Zoom-Nikkor 70-200mm F2.8G IF-ED", [0x78, 0x40, 0x37, 0x6E, 0x2C, 0x3C, 0x7C] => "Nikon AF-S VR Zoom-Nikkor 24-120mm F3.5-5.6G IF-ED", [0x79, 0x40, 0x3C, 0x80, 0x2C, 0x3C, 0x7F] => "Nikon AF Zoom-Nikkor 28-200mm F3.5-5.6G IF-ED", [0x7A, 0x3C, 0x1F, 0x37, 0x30, 0x30, 0x7E] => "Nikon AF-S DX Zoom-Nikkor 12-24mm F4G IF-ED", [0x7B, 0x48, 0x80, 0x98, 0x30, 0x30, 0x80] => "Nikon AF-S VR Zoom-Nikkor 200-400mm F4G IF-ED", [0x7D, 0x48, 0x2B, 0x53, 0x24, 0x24, 0x82] => "Nikon AF-S DX Zoom-Nikkor 17-55mm F2.8G IF-ED", [0x7F, 0x40, 0x2D, 0x5C, 0x2C, 0x34, 0x84] => "Nikon AF-S DX Zoom-Nikkor 18-70mm F3.5-4.5G IF-ED", [0x80, 0x48, 0x1A, 0x1A, 0x24, 0x24, 0x85] => "Nikon AF DX Fisheye-Nikkor 10.5mm F2.8G ED", [0x81, 0x54, 0x80, 0x80, 0x18, 0x18, 0x86] => "Nikon AF-S VR Nikkor 200mm F2G IF-ED", [0x82, 0x48, 0x8E, 0x8E, 0x24, 0x24, 0x87] => "Nikon AF-S VR Nikkor 300mm F2.8G IF-ED", [0x83, 0x00, 0xB0, 0xB0, 0x5A, 0x5A, 0x88] => "Nikon FSA-L2, EDG 65, 800mm F13 G", [0x89, 0x3C, 0x53, 0x80, 0x30, 0x3C, 0x8B] => "Nikon AF-S DX Zoom-Nikkor 55-200mm F4-5.6G ED", [0x8A, 0x54, 0x6A, 0x6A, 0x24, 0x24, 0x8C] => "Nikon AF-S VR Micro-Nikkor 105mm F2.8G IF-ED", [0x8B, 0x40, 0x2D, 0x80, 0x2C, 0x3C, 0x8D] => "Nikon AF-S DX VR Zoom-Nikkor 18-200mm F3.5-5.6G IF-ED", [0x8B, 0x40, 0x2D, 0x80, 0x2C, 0x3C, 0xFD] => "Nikon AF-S DX VR Zoom-Nikkor 18-200mm F3.5-5.6G IF-ED", [0x8B, 0x40, 0x2D, 0x80, 0x2C, 0x3C, 0xFD] => "Nikon AF-S DX VR Zoom-Nikkor 18-200mm F3.5-5.6G IF-ED II", [0x8C, 0x40, 0x2D, 0x53, 0x2C, 0x3C, 0x8E] => "Nikon AF-S DX Zoom-Nikkor 18-55mm F3.5-5.6G ED", [0x8D, 0x44, 0x5C, 0x8E, 0x34, 0x3C, 0x8F] => "Nikon AF-S VR Zoom-Nikkor 70-300mm F4.5-5.6G IF-ED", [0x8F, 0x40, 0x2D, 0x72, 0x2C, 0x3C, 0x91] => "Nikon AF-S DX Zoom-Nikkor 18-135mm F3.5-5.6G IF-ED", [0x90, 0x3B, 0x53, 0x80, 0x30, 0x3C, 0x92] => "Nikon AF-S DX VR Zoom-Nikkor 55-200mm F4-5.6G IF-ED", [0x92, 0x48, 0x24, 0x37, 0x24, 0x24, 0x94] => "Nikon AF-S Zoom-Nikkor 14-24mm F2.8G ED", [0x93, 0x48, 0x37, 0x5C, 0x24, 0x24, 0x95] => "Nikon AF-S Zoom-Nikkor 24-70mm F2.8G ED", [0x94, 0x40, 0x2D, 0x53, 0x2C, 0x3C, 0x96] => "Nikon AF-S DX Zoom-Nikkor 18-55mm F3.5-5.6G ED II", [0x95, 0x4C, 0x37, 0x37, 0x2C, 0x2C, 0x97] => "Nikon PC-E Nikkor 24mm F3.5D ED", [0x95, 0x00, 0x37, 0x37, 0x2C, 0x2C, 0x97] => "Nikon PC-E Nikkor 24mm F3.5D ED", [0x96, 0x48, 0x98, 0x98, 0x24, 0x24, 0x98] => "Nikon AF-S VR Nikkor 400mm F2.8G ED", [0x97, 0x3C, 0xA0, 0xA0, 0x30, 0x30, 0x99] => "Nikon AF-S VR Nikkor 500mm F4G ED", [0x98, 0x3C, 0xA6, 0xA6, 0x30, 0x30, 0x9A] => "Nikon AF-S VR Nikkor 600mm F4G ED", [0x99, 0x40, 0x29, 0x62, 0x2C, 0x3C, 0x9B] => "Nikon AF-S DX VR Zoom-Nikkor 16-85mm F3.5-5.6G ED", [0x9A, 0x40, 0x2D, 0x53, 0x2C, 0x3C, 0x9C] => "Nikon AF-S DX VR Zoom-Nikkor 18-55mm F3.5-5.6G", [0x9B, 0x54, 0x4C, 0x4C, 0x24, 0x24, 0x9D] => "Nikon PC-E Micro Nikkor 45mm F2.8D ED", [0x9B, 0x00, 0x4C, 0x4C, 0x24, 0x24, 0x9D] => "Nikon PC-E Micro Nikkor 45mm F2.8D ED", [0x9C, 0x54, 0x56, 0x56, 0x24, 0x24, 0x9E] => "Nikon AF-S Micro Nikkor 60mm F2.8G ED", [0x9D, 0x54, 0x62, 0x62, 0x24, 0x24, 0x9F] => "Nikon PC-E Micro Nikkor 85mm F2.8D", [0x9D, 0x00, 0x62, 0x62, 0x24, 0x24, 0x9F] => "Nikon PC-E Micro Nikkor 85mm F2.8D", [0x9E, 0x40, 0x2D, 0x6A, 0x2C, 0x3C, 0xA0] => "Nikon AF-S DX VR Zoom-Nikkor 18-105mm F3.5-5.6G ED", [0x9F, 0x58, 0x44, 0x44, 0x14, 0x14, 0xA1] => "Nikon AF-S DX Nikkor 35mm F1.8G", [0xA0, 0x54, 0x50, 0x50, 0x0C, 0x0C, 0xA2] => "Nikon AF-S Nikkor 50mm F1.4G", [0xA1, 0x40, 0x18, 0x37, 0x2C, 0x34, 0xA3] => "Nikon AF-S DX Nikkor 10-24mm F3.5-4.5G ED", [0xA2, 0x48, 0x5C, 0x80, 0x24, 0x24, 0xA4] => "Nikon AF-S Nikkor 70-200mm F2.8G ED VR II", [0xA3, 0x3C, 0x29, 0x44, 0x30, 0x30, 0xA5] => "Nikon AF-S Nikkor 16-35mm F4G ED VR", [0xA4, 0x54, 0x37, 0x37, 0x0C, 0x0C, 0xA6] => "Nikon AF-S Nikkor 24mm F1.4G ED", [0xA5, 0x40, 0x3C, 0x8E, 0x2C, 0x3C, 0xA7] => "Nikon AF-S Nikkor 28-300mm F3.5-5.6G ED VR", [0xA6, 0x48, 0x8E, 0x8E, 0x24, 0x24, 0xA8] => "Nikon AF-S VR Nikkor 300mm F2.8G IF-ED II", [0xA7, 0x4B, 0x62, 0x62, 0x2C, 0x2C, 0xA9] => "Nikon AF-S DX Micro Nikkor 85mm F3.5G ED VR", [0xA8, 0x48, 0x80, 0x98, 0x30, 0x30, 0xAA] => "Nikon AF-S VR Zoom-Nikkor 200-400mm F4G IF-ED II", [0xA9, 0x54, 0x80, 0x80, 0x18, 0x18, 0xAB] => "Nikon AF-S Nikkor 200mm F2G ED VR II", [0xAA, 0x3C, 0x37, 0x6E, 0x30, 0x30, 0xAC] => "Nikon AF-S Nikkor 24-120mm F4G ED VR", [0xAC, 0x38, 0x53, 0x8E, 0x34, 0x3C, 0xAE] => "Nikon AF-S DX VR Nikkor 55-300mm 4.5-5.6G ED", [0xAE, 0x54, 0x62, 0x62, 0x0C, 0x0C, 0xB0] => "Nikon AF-S Nikkor 85mm F1.4G", [0xAF, 0x54, 0x44, 0x44, 0x0C, 0x0C, 0xB1] => "Nikon AF-S Nikkor 35mm F1.4G", [0xB0, 0x4C, 0x50, 0x50, 0x14, 0x14, 0xB2] => "Nikon AF-S Nikkor 50mm F1.8G", [0xB1, 0x48, 0x48, 0x48, 0x24, 0x24, 0xB3] => "Nikon AF-S DX Micro Nikkor 40mm F2.8G", [0xB3, 0x4C, 0x62, 0x62, 0x14, 0x14, 0xB5] => "Nikon AF-S Nikkor 85mm F1.8G", [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02] => "Nikon TC-16A", [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08] => "Nikon TC-16A", [0xFE, 0x47, 0x00, 0x00, 0x24, 0x24, 0x4B] => "Sigma 4.5mm F2.8 EX DC HSM Circular Fisheye", [0x26, 0x48, 0x11, 0x11, 0x30, 0x30, 0x1C] => "Sigma 8mm F4 EX Circular Fisheye", [0x79, 0x40, 0x11, 0x11, 0x2C, 0x2C, 0x1C] => "Sigma 8mm F3.5 EX Circular Fisheye", [0xDC, 0x48, 0x19, 0x19, 0x24, 0x24, 0x4B] => "Sigma 10mm F2.8 EX DC HSM Fisheye", [0x02, 0x3F, 0x24, 0x24, 0x2C, 0x2C, 0x02] => "Sigma 14mm F3.5", [0x48, 0x48, 0x24, 0x24, 0x24, 0x24, 0x4B] => "Sigma 14mm F2.8 EX Aspherical HSM", [0x26, 0x48, 0x27, 0x27, 0x24, 0x24, 0x1C] => "Sigma 15mm F2.8 EX Diagonal Fisheye", [0x26, 0x58, 0x31, 0x31, 0x14, 0x14, 0x1C] => "Sigma 20mm F1.8 EX DG Aspherical RF", [0x26, 0x58, 0x37, 0x37, 0x14, 0x14, 0x1C] => "Sigma 24mm F1.8 EX DG Aspherical Macro", [0xE1, 0x58, 0x37, 0x37, 0x14, 0x14, 0x1C] => "Sigma 24mm F1.8 EX DG Aspherical Macro", [0x02, 0x46, 0x37, 0x37, 0x25, 0x25, 0x02] => "Sigma 24mm F2.8 Super Wide II Macro", [0x26, 0x58, 0x3C, 0x3C, 0x14, 0x14, 0x1C] => "Sigma 28mm F1.8 EX DG Aspherical Macro", [0x48, 0x54, 0x3E, 0x3E, 0x0C, 0x0C, 0x4B] => "Sigma 30mm F1.4 EX DC HSM", [0xF8, 0x54, 0x3E, 0x3E, 0x0C, 0x0C, 0x4B] => "Sigma 30mm F1.4 EX DC HSM", [0xDE, 0x54, 0x50, 0x50, 0x0C, 0x0C, 0x4B] => "Sigma 50mm F1.4 EX DG HSM", [0x02, 0x48, 0x50, 0x50, 0x24, 0x24, 0x02] => "Sigma Macro 50mm F2.8", [0x32, 0x54, 0x50, 0x50, 0x24, 0x24, 0x35] => "Sigma Macro 50mm F2.8 EX DG", [0xE3, 0x54, 0x50, 0x50, 0x24, 0x24, 0x35] => "Sigma Macro 50mm F2.8 EX DG", [0x79, 0x48, 0x5C, 0x5C, 0x24, 0x24, 0x1C] => "Sigma Macro 70mm F2.8 EX DG", [0x9B, 0x54, 0x62, 0x62, 0x0C, 0x0C, 0x4B] => "Sigma 85mm F1.4 EX DG HSM", [0x02, 0x48, 0x65, 0x65, 0x24, 0x24, 0x02] => "Sigma Macro 90mm F2.8", [0x32, 0x54, 0x6A, 0x6A, 0x24, 0x24, 0x35] => "Sigma Macro 105mm F2.8 EX DG", [0xE5, 0x54, 0x6A, 0x6A, 0x24, 0x24, 0x35] => "Sigma Macro 105mm F2.8 EX DG", [0x48, 0x48, 0x76, 0x76, 0x24, 0x24, 0x4B] => "Sigma APO Macro 150mm F2.8 EX DG HSM", [0xF5, 0x48, 0x76, 0x76, 0x24, 0x24, 0x4B] => "Sigma APO Macro 150mm F2.8 EX DG HSM", [0x48, 0x4C, 0x7C, 0x7C, 0x2C, 0x2C, 0x4B] => "Sigma APO Macro 180mm F3.5 EX DG HSM", [0x48, 0x4C, 0x7D, 0x7D, 0x2C, 0x2C, 0x4B] => "Sigma APO Macro 180mm F3.5 EX DG HSM", [0x48, 0x54, 0x8E, 0x8E, 0x24, 0x24, 0x4B] => "Sigma APO 300mm F2.8 EX DG HSM", [0xFB, 0x54, 0x8E, 0x8E, 0x24, 0x24, 0x4B] => "Sigma APO 300mm F2.8 EX DG HSM", [0x26, 0x48, 0x8E, 0x8E, 0x30, 0x30, 0x1C] => "Sigma APO Tele Macro 300mm F4", [0x02, 0x2F, 0x98, 0x98, 0x3D, 0x3D, 0x02] => "Sigma APO 400mm F5.6", [0x26, 0x3C, 0x98, 0x98, 0x3C, 0x3C, 0x1C] => "Sigma APO Tele Macro 400mm F5.6", [0x02, 0x37, 0xA0, 0xA0, 0x34, 0x34, 0x02] => "Sigma APO 500mm F4.5", [0x48, 0x44, 0xA0, 0xA0, 0x34, 0x34, 0x4B] => "Sigma APO 500mm F4.5 EX HSM", [0xF1, 0x44, 0xA0, 0xA0, 0x34, 0x34, 0x4B] => "Sigma APO 500mm F4.5 EX DG HSM", [0x02, 0x34, 0xA0, 0xA0, 0x44, 0x44, 0x02] => "Sigma APO 500mm F7.2", [0x02, 0x3C, 0xB0, 0xB0, 0x3C, 0x3C, 0x02] => "Sigma APO 800mm F5.6", [0x48, 0x3C, 0xB0, 0xB0, 0x3C, 0x3C, 0x4B] => "Sigma APO 800mm F5.6 EX HSM", [0x9E, 0x38, 0x11, 0x29, 0x34, 0x3C, 0x4B] => "Sigma 8-16mm F4.5-5.6 DC HSM", [0xA1, 0x41, 0x19, 0x31, 0x2C, 0x2C, 0x4B] => "Sigma 10-20mm F3.5 EX DC HSM", [0x48, 0x3C, 0x19, 0x31, 0x30, 0x3C, 0x4B] => "Sigma 10-20mm F4-5.6 EX DC HSM", [0xF9, 0x3C, 0x19, 0x31, 0x30, 0x3C, 0x4B] => "Sigma 10-20mm F4-5.6 EX DC HSM", [0x48, 0x38, 0x1F, 0x37, 0x34, 0x3C, 0x4B] => "Sigma 12-24mm F4.5-5.6 EX DG Aspherical HSM", [0xF0, 0x38, 0x1F, 0x37, 0x34, 0x3C, 0x4B] => "Sigma 12-24mm F4.5-5.6 EX DG Aspherical HSM", [0x26, 0x40, 0x27, 0x3F, 0x2C, 0x34, 0x1C] => "Sigma 15-30mm F3.5-4.5 EX DG Aspherical DF", [0x48, 0x48, 0x2B, 0x44, 0x24, 0x30, 0x4B] => "Sigma 17-35mm F2.8-4 EX DG Aspherical HSM", [0x26, 0x54, 0x2B, 0x44, 0x24, 0x30, 0x1C] => "Sigma 17-35mm F2.8-4 EX Aspherical", [0x9D, 0x48, 0x2B, 0x50, 0x24, 0x24, 0x4B] => "Sigma 17-50mm F2.8 EX DC OS HSM", [0x7A, 0x47, 0x2B, 0x5C, 0x24, 0x34, 0x4B] => "Sigma 17-70mm F2.8-4.5 DC Macro Asp. IF HSM", [0x7A, 0x48, 0x2B, 0x5C, 0x24, 0x34, 0x4B] => "Sigma 17-70mm F2.8-4.5 DC Macro Asp. IF HSM", [0x7F, 0x48, 0x2B, 0x5C, 0x24, 0x34, 0x1C] => "Sigma 17-70mm F2.8-4.5 DC Macro Asp. IF", [0x26, 0x40, 0x2D, 0x44, 0x2B, 0x34, 0x1C] => "Sigma 18-35 F3.5-4.5 Aspherical", [0x26, 0x48, 0x2D, 0x50, 0x24, 0x24, 0x1C] => "Sigma 18-50mm F2.8 EX DC", [0x7F, 0x48, 0x2D, 0x50, 0x24, 0x24, 0x1C] => "Sigma 18-50mm F2.8 EX DC Macro", [0x7A, 0x48, 0x2D, 0x50, 0x24, 0x24, 0x4B] => "Sigma 18-50mm F2.8 EX DC Macro", [0xF6, 0x48, 0x2D, 0x50, 0x24, 0x24, 0x4B] => "Sigma 18-50mm F2.8 EX DC Macro", [0xA4, 0x47, 0x2D, 0x50, 0x24, 0x34, 0x4B] => "Sigma 18-50mm F2.8-4.5 DC OS HSM", [0x26, 0x40, 0x2D, 0x50, 0x2C, 0x3C, 0x1C] => "Sigma 18-50mm F3.5-5.6 DC", [0x7A, 0x40, 0x2D, 0x50, 0x2C, 0x3C, 0x4B] => "Sigma 18-50mm F3.5-5.6 DC HSM", [0x26, 0x40, 0x2D, 0x70, 0x2B, 0x3C, 0x1C] => "Sigma 18-125mm F3.5-5.6 DC", [0xCD, 0x3D, 0x2D, 0x70, 0x2E, 0x3C, 0x4B] => "Sigma 18-125mm F3.8-5.6 DC OS HSM", [0x26, 0x40, 0x2D, 0x80, 0x2C, 0x40, 0x1C] => "Sigma 18-200mm F3.5-6.3 DC", [0x7A, 0x40, 0x2D, 0x80, 0x2C, 0x40, 0x4B] => "Sigma 18-200mm F3.5-6.3 DC OS HSM", [0xED, 0x40, 0x2D, 0x80, 0x2C, 0x40, 0x4B] => "Sigma 18-200mm F3.5-6.3 DC OS HSM", [0xA5, 0x40, 0x2D, 0x88, 0x2C, 0x40, 0x4B] => "Sigma 18-250mm F3.5-6.3 DC OS HSM", [0x26, 0x48, 0x31, 0x49, 0x24, 0x24, 0x1C] => "Sigma 20-40mm F2.8", [0x26, 0x48, 0x37, 0x56, 0x24, 0x24, 0x1C] => "Sigma 24-60mm F2.8 EX DG", [0xB6, 0x48, 0x37, 0x56, 0x24, 0x24, 0x1C] => "Sigma 24-60mm F2.8 EX DG", [0xA6, 0x48, 0x37, 0x5C, 0x24, 0x24, 0x4B] => "Sigma 24-70mm F2.8 IF EX DG HSM", [0x26, 0x54, 0x37, 0x5C, 0x24, 0x24, 0x1C] => "Sigma 24-70mm F2.8 EX DG Macro", [0x67, 0x54, 0x37, 0x5C, 0x24, 0x24, 0x1C] => "Sigma 24-70mm F2.8 EX DG Macro", [0xE9, 0x54, 0x37, 0x5C, 0x24, 0x24, 0x1C] => "Sigma 24-70mm F2.8 EX DG Macro", [0x26, 0x40, 0x37, 0x5C, 0x2C, 0x3C, 0x1C] => "Sigma 24-70mm F3.5-5.6 Aspherical HF", [0x26, 0x54, 0x37, 0x73, 0x24, 0x34, 0x1C] => "Sigma 24-135mm F2.8-4.5", [0x02, 0x46, 0x3C, 0x5C, 0x25, 0x25, 0x02] => "Sigma 28-70mm F2.8", [0x26, 0x54, 0x3C, 0x5C, 0x24, 0x24, 0x1C] => "Sigma 28-70mm F2.8 EX", [0x26, 0x48, 0x3C, 0x5C, 0x24, 0x24, 0x1C] => "Sigma 28-70mm F2.8 EX DG", [0x26, 0x48, 0x3C, 0x5C, 0x24, 0x30, 0x1C] => "Sigma 28-70mm F2.8-4 DG", [0x02, 0x3F, 0x3C, 0x5C, 0x2D, 0x35, 0x02] => "Sigma 28-70mm F3.5-4.5 UC", [0x26, 0x40, 0x3C, 0x60, 0x2C, 0x3C, 0x1C] => "Sigma 28-80mm F3.5-5.6 Mini Zoom Macro II Aspherical", [0x26, 0x40, 0x3C, 0x65, 0x2C, 0x3C, 0x1C] => "Sigma 28-90mm F3.5-5.6 Macro", [0x26, 0x48, 0x3C, 0x6A, 0x24, 0x30, 0x1C] => "Sigma 28-105mm F2.8-4 Aspherical", [0x26, 0x3E, 0x3C, 0x6A, 0x2E, 0x3C, 0x1C] => "Sigma 28-105mm F3.8-5.6 UC-III Aspherical IF", [0x26, 0x40, 0x3C, 0x80, 0x2C, 0x3C, 0x1C] => "Sigma 28-200mm F3.5-5.6 Compact Aspherical Hyperzoom Macro", [0x26, 0x40, 0x3C, 0x80, 0x2B, 0x3C, 0x1C] => "Sigma 28-200mm F3.5-5.6 Compact Aspherical Hyperzoom Macro", [0x26, 0x3D, 0x3C, 0x80, 0x2F, 0x3D, 0x1C] => "Sigma 28-300mm F3.8-5.6 Aspherical", [0x26, 0x41, 0x3C, 0x8E, 0x2C, 0x40, 0x1C] => "Sigma 28-300mm F3.5-6.3 DG Macro", [0xE6, 0x41, 0x3C, 0x8E, 0x2C, 0x40, 0x1C] => "Sigma 28-300mm F3.5-6.3 DG Macro", [0x26, 0x40, 0x3C, 0x8E, 0x2C, 0x40, 0x1C] => "Sigma 28-300mm F3.5-6.3 Macro", [0x02, 0x3B, 0x44, 0x61, 0x30, 0x3D, 0x02] => "Sigma 35-80mm F4-5.6", [0x02, 0x40, 0x44, 0x73, 0x2B, 0x36, 0x02] => "Sigma 35-135mm F3.5-4.5 a", [0x7A, 0x47, 0x50, 0x76, 0x24, 0x24, 0x4B] => "Sigma 50-150mm F2.8 EX APO DC HSM", [0xFD, 0x47, 0x50, 0x76, 0x24, 0x24, 0x4B] => "Sigma 50-150mm F2.8 EX APO DC HSM II", [0x48, 0x3C, 0x50, 0xA0, 0x30, 0x40, 0x4B] => "Sigma APO 50-500mm F4-6.3 EX HSM", [0x9F, 0x37, 0x50, 0xA0, 0x34, 0x40, 0x4B] => "Sigma 50-500mm F4.5-6.3 APO DG OS HSM", [0x26, 0x3C, 0x54, 0x80, 0x30, 0x3C, 0x1C] => "Sigma 55-200mm F4-5.6 DC", [0x7A, 0x3B, 0x53, 0x80, 0x30, 0x3C, 0x4B] => "Sigma 55-200mm F4-5.6 DC HSM", [0x48, 0x54, 0x5C, 0x80, 0x24, 0x24, 0x4B] => "Sigma 70-200mm F2.8 EX APO IF HSM", [0x7A, 0x48, 0x5C, 0x80, 0x24, 0x24, 0x4B] => "Sigma 70-200mm F2.8 EX APO DG Macro HSM II", [0xEE, 0x48, 0x5C, 0x80, 0x24, 0x24, 0x4B] => "Sigma 70-200mm F2.8 EX APO DG Macro HSM II", [0x9C, 0x48, 0x5C, 0x80, 0x24, 0x24, 0x4B] => "Sigma 70-200mm F2.8 EX DG OS HSM", [0x02, 0x46, 0x5C, 0x82, 0x25, 0x25, 0x02] => "Sigma 70-210mm F2.8 APO", [0x26, 0x3C, 0x5C, 0x82, 0x30, 0x3C, 0x1C] => "Sigma 70-210mm F4-5.6 UC-II", [0x26, 0x3C, 0x5C, 0x8E, 0x30, 0x3C, 0x1C] => "Sigma 70-300mm F4-5.6 DG Macro", [0x56, 0x3C, 0x5C, 0x8E, 0x30, 0x3C, 0x1C] => "Sigma 70-300mm F4-5.6 APO Macro Super II", [0xE0, 0x3C, 0x5C, 0x8E, 0x30, 0x3C, 0x4B] => "Sigma APO 70-300mm F4-5.6 DG Macro", [0xA3, 0x3C, 0x5C, 0x8E, 0x30, 0x3C, 0x4B] => "Sigma 70-300mm F4-5.6 DG OS", [0x02, 0x37, 0x5E, 0x8E, 0x35, 0x3D, 0x02] => "Sigma 75-300mm F4.5-5.6 APO", [0x02, 0x3A, 0x5E, 0x8E, 0x32, 0x3D, 0x02] => "Sigma 75-300mm F4.0-5.6", [0x77, 0x44, 0x61, 0x98, 0x34, 0x3C, 0x7B] => "Sigma 80-400mm f4.5-5.6 EX OS", [0x48, 0x48, 0x68, 0x8E, 0x30, 0x30, 0x4B] => "Sigma APO 100-300mm F4 EX IF HSM", [0xF3, 0x48, 0x68, 0x8E, 0x30, 0x30, 0x4B] => "Sigma APO 100-300mm F4 EX IF HSM", [0x48, 0x54, 0x6F, 0x8E, 0x24, 0x24, 0x4B] => "Sigma APO 120-300mm F2.8 EX DG HSM", [0x7A, 0x54, 0x6E, 0x8E, 0x24, 0x24, 0x4B] => "Sigma APO 120-300mm F2.8 EX DG HSM", [0xFA, 0x54, 0x6E, 0x8E, 0x24, 0x24, 0x4B] => "Sigma APO 120-300mm F2.8 EX DG HSM", [0xCF, 0x38, 0x6E, 0x98, 0x34, 0x3C, 0x4B] => "Sigma APO 120-400mm F4.5-5.6 DG OS HSM", [0x26, 0x44, 0x73, 0x98, 0x34, 0x3C, 0x1C] => "Sigma 135-400mm F4.5-5.6 APO Aspherical", [0xCE, 0x34, 0x76, 0xA0, 0x38, 0x40, 0x4B] => "Sigma APO 150-500mm F5-6.3 DG OS HSM", [0x26, 0x40, 0x7B, 0xA0, 0x34, 0x40, 0x1C] => "Sigma APO 170-500mm F5-6.3 Aspherical RF", [0xA7, 0x49, 0x80, 0xA0, 0x24, 0x24, 0x4B] => "Sigma APO 200-500mm F2.8 EX DG", [0x48, 0x3C, 0x8E, 0xB0, 0x3C, 0x3C, 0x4B] => "Sigma APO 300-800mm F5.6 EX DG HSM", [0x00, 0x47, 0x25, 0x25, 0x24, 0x24, 0x00] => "Tamron SP AF 14mm F/2.8 Aspherical (IF)", [0xF4, 0x54, 0x56, 0x56, 0x18, 0x18, 0x84] => "Tamron SP AF 60mm F/2 Di II LD (IF) Macro 1:1", [0x1E, 0x5D, 0x64, 0x64, 0x20, 0x20, 0x13] => "Tamron SP AF 90mm F/2.5", [0x20, 0x5A, 0x64, 0x64, 0x20, 0x20, 0x14] => "Tamron SP AF 90mm F/2.5 Macro", [0x22, 0x53, 0x64, 0x64, 0x24, 0x24, 0xE0] => "Tamron SP AF 90mm F/2.8 Macro 1:1", [0x32, 0x53, 0x64, 0x64, 0x24, 0x24, 0x35] => "Tamron SP AF 90mm F/2.8 Macro 1:1", [0x32, 0x53, 0x64, 0x64, 0x24, 0x24, 0x35] => "Tamron SP AF 90mm F/2.8 Di Macro 1:1", [0xF8, 0x55, 0x64, 0x64, 0x24, 0x24, 0x84] => "Tamron SP AF 90mm F/2.8 Di Macro 1:1", [0xF8, 0x54, 0x64, 0x64, 0x24, 0x24, 0xDF] => "Tamron SP AF 90mm F/2.8 Di Macro 1:1", [0x00, 0x4C, 0x7C, 0x7C, 0x2C, 0x2C, 0x00] => "Tamron SP AF 180mm F/3.5 Di Model", [0x21, 0x56, 0x8E, 0x8E, 0x24, 0x24, 0x14] => "Tamron SP AF 300mm F/2.8 LD-IF", [0x27, 0x54, 0x8E, 0x8E, 0x24, 0x24, 0x1D] => "Tamron SP AF 300mm F/2.8 LD-IF", [0xF6, 0x3F, 0x18, 0x37, 0x2C, 0x34, 0x84] => "Tamron SP AF 10-24mm F/3.5-4.5 Di II LD Aspherical (IF)", [0x00, 0x36, 0x1C, 0x2D, 0x34, 0x3C, 0x00] => "Tamron SP AF 11-18mm F/4.5-5.6 Di II LD Aspherical (IF)", [0x07, 0x46, 0x2B, 0x44, 0x24, 0x30, 0x03] => "Tamron SP AF 17-35mm F/2.8-4 Di LD Aspherical (IF)", [0x00, 0x53, 0x2B, 0x50, 0x24, 0x24, 0x00] => "Tamron SP AF 17-50mm F/2.8 XR Di II LD Aspherical (IF)", [0x00, 0x54, 0x2B, 0x50, 0x24, 0x24, 0x00] => "Tamron SP AF 17-50mm F/2.8 XR Di II LD Aspherical (IF)", [0xFB, 0x54, 0x2B, 0x50, 0x24, 0x24, 0x84] => "Tamron SP AF 17-50mm F/2.8 XR Di II LD Aspherical (IF)", [0xF3, 0x54, 0x2B, 0x50, 0x24, 0x24, 0x84] => "Tamron SP AF 17-50mm F/2.8 XR Di II VC LD Aspherical (IF)", [0x00, 0x3F, 0x2D, 0x80, 0x2B, 0x40, 0x00] => "Tamron AF 18-200mm F/3.5-6.3 XR Di II LD Aspherical (IF)", [0x00, 0x3F, 0x2D, 0x80, 0x2C, 0x40, 0x00] => "Tamron AF 18-200mm F/3.5-6.3 XR Di II LD Aspherical (IF) Macro", [0x00, 0x40, 0x2D, 0x80, 0x2C, 0x40, 0x00] => "Tamron AF 18-200mm F/3.5-6.3 XR Di II LD Aspherical (IF) Macro", [0xFC, 0x40, 0x2D, 0x80, 0x2C, 0x40, 0xDF] => "Tamron AF 18-200mm F/3.5-6.3 XR Di II LD Aspherical (IF) Macro", [0x00, 0x40, 0x2D, 0x88, 0x2C, 0x40, 0x62] => "Tamron AF 18-250mm F/3.5-6.3 Di II LD Aspherical (IF) Macro", [0x00, 0x40, 0x2D, 0x88, 0x2C, 0x40, 0x00] => "Tamron AF 18-250mm F/3.5-6.3 Di II LD Aspherical (IF) Macro ", [0xF5, 0x40, 0x2C, 0x8A, 0x2C, 0x40, 0x40] => "Tamron AF 18-270mm F/3.5-6.3 Di II VC LD Aspherical (IF) Macro", [0xF0, 0x3F, 0x2D, 0x8A, 0x2C, 0x40, 0xDF] => "Tamron AF 18-270mm F/3.5-6.3 Di II VC PZD", [0x07, 0x40, 0x2F, 0x44, 0x2C, 0x34, 0x03] => "Tamron AF 19-35mm F/3.5-4.5", [0x07, 0x40, 0x30, 0x45, 0x2D, 0x35, 0x03] => "Tamron AF 19-35mm F/3.5-4.5", [0x00, 0x49, 0x30, 0x48, 0x22, 0x2B, 0x00] => "Tamron SP AF 20-40mm F/2.7-3.5", [0x0E, 0x4A, 0x31, 0x48, 0x23, 0x2D, 0x0E] => "Tamron SP AF 20-40mm F/2.7-3.5", [0x45, 0x41, 0x37, 0x72, 0x2C, 0x3C, 0x48] => "Tamron SP AF 24-135mm F/3.5-5.6 AD Aspherical (IF) Macro", [0x33, 0x54, 0x3C, 0x5E, 0x24, 0x24, 0x62] => "Tamron SP AF 28-75mm F/2.8 XR Di LD Aspherical (IF) Macro", [0xFA, 0x54, 0x3C, 0x5E, 0x24, 0x24, 0x84] => "Tamron SP AF 28-75mm F/2.8 XR Di LD Aspherical (IF) Macro", [0x10, 0x3D, 0x3C, 0x60, 0x2C, 0x3C, 0xD2] => "Tamron AF 28-80mm F/3.5-5.6 Aspherical", [0x45, 0x3D, 0x3C, 0x60, 0x2C, 0x3C, 0x48] => "Tamron AF 28-80mm F/3.5-5.6 Aspherical", [0x00, 0x48, 0x3C, 0x6A, 0x24, 0x24, 0x00] => "Tamron SP AF 28-105mm F/2.8 LD Aspherical IF", [0x0B, 0x3E, 0x3D, 0x7F, 0x2F, 0x3D, 0x0E] => "Tamron AF 28-200mm F/3.8-5.6", [0x0B, 0x3E, 0x3D, 0x7F, 0x2F, 0x3D, 0x0E] => "Tamron AF 28-200mm F/3.8-5.6D", [0x12, 0x3D, 0x3C, 0x80, 0x2E, 0x3C, 0xDF] => "Tamron AF 28-200mm F/3.8-5.6 LD Aspherical (IF)", [0x4D, 0x41, 0x3C, 0x8E, 0x2B, 0x40, 0x62] => "Tamron AF 28-300mm F/3.5-6.3 XR Di LD Aspherical (IF)", [0x4D, 0x41, 0x3C, 0x8E, 0x2C, 0x40, 0x62] => "Tamron AF 28-300mm F/3.5-6.3 XR LD Aspherical (IF)", [0xF9, 0x40, 0x3C, 0x8E, 0x2C, 0x40, 0x40] => "Tamron AF 28-300mm F/3.5-6.3 XR Di VC LD Aspherical (IF) Macro", [0x00, 0x47, 0x53, 0x80, 0x30, 0x3C, 0x00] => "Tamron AF 55-200mm F/4-5.6 Di II LD", [0xF7, 0x53, 0x5C, 0x80, 0x24, 0x24, 0x84] => "Tamron SP AF 70-200mm F/2.8 Di LD (IF) Macro", [0xFE, 0x53, 0x5C, 0x80, 0x24, 0x24, 0x84] => "Tamron SP AF 70-200mm F/2.8 Di LD (IF) Macro", [0x69, 0x48, 0x5C, 0x8E, 0x30, 0x3C, 0x6F] => "Tamron AF 70-300mm F/4-5.6 LD Macro 1:2", [0x69, 0x47, 0x5C, 0x8E, 0x30, 0x3C, 0x00] => "Tamron AF 70-300mm F/4-5.6 Di LD Macro 1:2", [0x00, 0x48, 0x5C, 0x8E, 0x30, 0x3C, 0x00] => "Tamron AF 70-300mm F/4-5.6 Di LD Macro 1:2", [0xF1, 0x47, 0x5C, 0x8E, 0x30, 0x3C, 0xDF] => "Tamron SP 70-300mm F4-5.6 Di VC USD", [0x20, 0x3C, 0x80, 0x98, 0x3D, 0x3D, 0x1E] => "Tamron AF 200-400mm F/5.6 LD IF", [0x00, 0x3E, 0x80, 0xA0, 0x38, 0x3F, 0x00] => "Tamron SP AF 200-500mm F/5-6.3 Di LD (IF)", [0x00, 0x3F, 0x80, 0xA0, 0x38, 0x3F, 0x00] => "Tamron SP AF 200-500mm F/5-6.3 Di", [0x00, 0x40, 0x2B, 0x2B, 0x2C, 0x2C, 0x00] => "Tokina AT-X 17 AF PRO (AF 17mm f/3.5)", [0x00, 0x47, 0x44, 0x44, 0x24, 0x24, 0x00] => "Tokina AT-X M35 PRO DX (AF 35mm f/2.8 Macro)", [0x00, 0x54, 0x68, 0x68, 0x24, 0x24, 0x00] => "Tokina AT-X M100 PRO D (AF 100mm f/2.8 Macro)", [0x27, 0x48, 0x8E, 0x8E, 0x30, 0x30, 0x1D] => "Tokina AT-X 304 AF (AF 300mm f/4.0)", [0x00, 0x54, 0x8E, 0x8E, 0x24, 0x24, 0x00] => "Tokina AT-X 300 AF PRO (AF 300mm f/2.8)", [0x12, 0x3B, 0x98, 0x98, 0x3D, 0x3D, 0x09] => "Tokina AT-X 400 AF SD (AF 400mm f/5.6)", [0x00, 0x40, 0x18, 0x2B, 0x2C, 0x34, 0x00] => "Tokina AT-X 107 DX Fisheye (AF 10-17mm f/3.5-4.5)", [0x00, 0x48, 0x1C, 0x29, 0x24, 0x24, 0x00] => "Tokina AT-X 116 PRO DX (AF 11-16mm f/2.8)", [0x00, 0x3C, 0x1F, 0x37, 0x30, 0x30, 0x00] => "Tokina AT-X 124 AF PRO DX (AF 12-24mm f/4)", [0x7A, 0x3C, 0x1F, 0x37, 0x30, 0x30, 0x7E] => "Tokina AT-X 124 AF PRO DX II (AF 12-24mm f/4)", [0x00, 0x48, 0x29, 0x3C, 0x24, 0x24, 0x00] => "Tokina AT-X 16-28 AF PRO FX (AF 16-28mm f/2.8)", [0x00, 0x48, 0x29, 0x50, 0x24, 0x24, 0x00] => "Tokina AT-X 165 PRO DX (AF 16-50mm f/2.8)", [0x00, 0x40, 0x2A, 0x72, 0x2C, 0x3C, 0x00] => "Tokina AT-X 16.5-135 DX (AF 16.5-135mm F3.5-5.6)", [0x2F, 0x40, 0x30, 0x44, 0x2C, 0x34, 0x29] => "Tokina AF 193 (AF 19-35mm f/3.5-4.5)", [0x2F, 0x48, 0x30, 0x44, 0x24, 0x24, 0x29] => "Tokina AT-X 235 AF PRO (AF 20-35mm f/2.8)", [0x2F, 0x40, 0x30, 0x44, 0x2C, 0x34, 0x29] => "Tokina AF 235 II (AF 20-35mm f/3.5-4.5)", [0x00, 0x40, 0x37, 0x80, 0x2C, 0x3C, 0x00] => "Tokina AT-X 242 AF (AF 24-200mm f/3.5-5.6)", [0x25, 0x48, 0x3C, 0x5C, 0x24, 0x24, 0x1B] => "Tokina AT-X 270 AF PRO II (AF 28-70mm f/2.6-2.8)", [0x25, 0x48, 0x3C, 0x5C, 0x24, 0x24, 0x1B] => "Tokina AT-X 287 AF PRO SV (AF 28-70mm f/2.8)", [0x07, 0x48, 0x3C, 0x5C, 0x24, 0x24, 0x03] => "Tokina AT-X 287 AF (AF 28-70mm f/2.8)", [0x07, 0x47, 0x3C, 0x5C, 0x25, 0x35, 0x03] => "Tokina AF 287 SD (AF 28-70mm f/2.8-4.5)", [0x07, 0x40, 0x3C, 0x5C, 0x2C, 0x35, 0x03] => "Tokina AF 270 II (AF 28-70mm f/3.5-4.5)", [0x00, 0x48, 0x3C, 0x60, 0x24, 0x24, 0x00] => "Tokina AT-X 280 AF PRO (AF 28-80mm f/2.8)", [0x25, 0x44, 0x44, 0x8E, 0x34, 0x42, 0x1B] => "Tokina AF 353 (AF 35-300mm f/4.5-6.7)", [0x00, 0x48, 0x50, 0x72, 0x24, 0x24, 0x00] => "Tokina AT-X 535 PRO DX (AF 50-135mm f/2.8)", [0x12, 0x44, 0x5E, 0x8E, 0x34, 0x3C, 0x09] => "Tokina AF 730 (AF 75-300mm F4.5-5.6)", [0x14, 0x54, 0x60, 0x80, 0x24, 0x24, 0x0B] => "Tokina AT-X 828 AF (AF 80-200mm f/2.8)", [0x24, 0x54, 0x60, 0x80, 0x24, 0x24, 0x1A] => "Tokina AT-X 828 AF PRO (AF 80-200mm f/2.8)", [0x24, 0x44, 0x60, 0x98, 0x34, 0x3C, 0x1A] => "Tokina AT-X 840 AF-II (AF 80-400mm f/4.5-5.6)", [0x00, 0x44, 0x60, 0x98, 0x34, 0x3C, 0x00] => "Tokina AT-X 840 D (AF 80-400mm f/4.5-5.6)", [0x14, 0x48, 0x68, 0x8E, 0x30, 0x30, 0x0B] => "Tokina AT-X 340 AF (AF 100-300mm f/4)", [0x06, 0x3F, 0x68, 0x68, 0x2C, 0x2C, 0x06] => "Cosina AF 100mm F3.5 Macro", [0x07, 0x36, 0x3D, 0x5F, 0x2C, 0x3C, 0x03] => "Cosina AF Zoom 28-80mm F3.5-5.6 MC Macro", [0x07, 0x46, 0x3D, 0x6A, 0x25, 0x2F, 0x03] => "Cosina AF Zoom 28-105mm F2.8-3.8 MC", [0x12, 0x36, 0x5C, 0x81, 0x35, 0x3D, 0x09] => "Cosina AF Zoom 70-210mm F4.5-5.6 MC Macro", [0x12, 0x39, 0x5C, 0x8E, 0x34, 0x3D, 0x08] => "Cosina AF Zoom 70-300mm F4.5-5.6 MC Macro", [0x12, 0x3B, 0x68, 0x8D, 0x3D, 0x43, 0x09] => "Cosina AF Zoom 100-300mm F5.6-6.7 MC Macro", [0x00, 0x40, 0x31, 0x31, 0x2C, 0x2C, 0x00] => "Voigtlander Color Skopar 20mm F3.5 SLII Aspherical", [0x00, 0x54, 0x48, 0x48, 0x18, 0x18, 0x00] => "Voigtlander Ultron 40mm F2 SLII Aspherical", [0x00, 0x54, 0x55, 0x55, 0x0C, 0x0C, 0x00] => "Voigtlander Nokton 58mm F1.4 SLII", [0x00, 0x40, 0x64, 0x64, 0x2C, 0x2C, 0x00] => "Voigtlander APO-Lanthar 90mm F3.5 SLII Close Focus", [0x00, 0x40, 0x2D, 0x2D, 0x2C, 0x2C, 0x00] => "Carl Zeiss Distagon T* 3,5/18 ZF.2", [0x00, 0x48, 0x32, 0x32, 0x24, 0x24, 0x00] => "Carl Zeiss Distagon T* 2,8/21 ZF.2", [0x00, 0x54, 0x3C, 0x3C, 0x18, 0x18, 0x00] => "Carl Zeiss Distagon T* 2/28 ZF.2", [0x00, 0x54, 0x44, 0x44, 0x18, 0x18, 0x00] => "Carl Zeiss Distagon T* 2/35 ZF.2", [0x00, 0x54, 0x50, 0x50, 0x0C, 0x0C, 0x00] => "Carl Zeiss Planar T* 1,4/50 ZF.2", [0x00, 0x54, 0x50, 0x50, 0x18, 0x18, 0x00] => "Carl Zeiss Makro-Planar T* 2/50 ZF.2", [0x00, 0x54, 0x62, 0x62, 0x0C, 0x0C, 0x00] => "Carl Zeiss Planar T* 1,4/85 ZF.2", [0x00, 0x54, 0x68, 0x68, 0x18, 0x18, 0x00] => "Carl Zeiss Makro-Planar T* 2/100 ZF.2", [0x00, 0x54, 0x56, 0x56, 0x30, 0x30, 0x00] => "Coastal Optical Systems 60mm 1:4 UV-VIS-IR Macro Apo", [0x4A, 0x48, 0x24, 0x24, 0x24, 0x0C, 0x4D] => "Samyang AE 14mm f/2.8 ED AS IF UMC", [0x4A, 0x60, 0x44, 0x44, 0x0C, 0x0C, 0x4D] => "Samyang 35mm f/1.4 AS UMC", [0x4A, 0x60, 0x62, 0x62, 0x0C, 0x0C, 0x4D] => "Samyang AE 85mm f/1.4 AS IF UMC", [0x02, 0x40, 0x44, 0x5C, 0x2C, 0x34, 0x02] => "Exakta AF 35-70mm 1:3.5-4.5 MC", [0x07, 0x3E, 0x30, 0x43, 0x2D, 0x35, 0x03] => "Soligor AF Zoom 19-35mm 1:3.5-4.5 MC", [0x03, 0x43, 0x5C, 0x81, 0x35, 0x35, 0x02] => "Soligor AF C/D Zoom UMCS 70-210mm 1:4.5", [0x12, 0x4A, 0x5C, 0x81, 0x31, 0x3D, 0x09] => "Soligor AF C/D Auto Zoom+Macro 70-210mm 1:4-5.6 UMCS", [0x12, 0x36, 0x69, 0x97, 0x35, 0x42, 0x09] => "Soligor AF Zoom 100-400mm 1:4.5-6.7 MC", [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] => "Manual Lens No CPU", [0x00, 0x47, 0x10, 0x10, 0x24, 0x24, 0x00] => "Nikon Fisheye Nikkor 8mm F2.8 AiS", [0x00, 0x54, 0x44, 0x44, 0x0C, 0x0C, 0x00] => "Nikon Nikkor 35mm F1.4 AiS", [0x00, 0x48, 0x50, 0x50, 0x18, 0x18, 0x00] => "Nikon Nikkor H 50mm F2", [0x00, 0x48, 0x68, 0x68, 0x24, 0x24, 0x00] => "Nikon Series E 100mm F2.8", [0x00, 0x4C, 0x6A, 0x6A, 0x20, 0x20, 0x00] => "Nikon Nikkor 105mm F2.5 AiS", [0x00, 0x48, 0x80, 0x80, 0x30, 0x30, 0x00] => "Nikon Nikkor 200mm F4 AiS", [0x00, 0x40, 0x11, 0x11, 0x2C, 0x2C, 0x00] => "Samyang 8mm f/3.5 Fish-Eye", [0x00, 0x58, 0x64, 0x64, 0x20, 0x20, 0x00] => "Soligor C/D Macro MC 90mm f/2.5", [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] => "" } end end end tdiary-contrib-3.2.2/lib/exifparser/lib/exifparser/makernote/olympus.rb000066400000000000000000000103701213632744000263310ustar00rootroot00000000000000# # exif/makernote/olympus.rb - # # Copyright (C) Ryuichi Tamura (r-tam@fsinet.or.jp) # # $Revision: 1.1.1.1 $ # $Date: 2002/12/16 07:59:00 $ # #== Reference # #http://www.ba.wakwak.com/%7Etsuruzoh/Computer/Digicams/exif-e.html # require 'exifparser/tag' require 'exifparser/utils' module Exif # # Tags used in Olympus Makernote # module Tag module MakerNote # # 0x0200 - SpecialMode # class SpecialMode < Base def processData @formatted = [] partition_data(@count) do |data| @formatted.push _formatData(data) end end def to_s buf = "Picture taking mode: " case @formatted[0] when 0 buf << 'Normal,' when 1 buf << 'Unknown,' when 2 buf << 'Fast,' when 3 buf << 'Panorama,' else buf << 'Unknown,' end buf << " Sequence number: #{@formatted[1]}," buf << " Panorama direction: " case @formatted[2] when 1 buf << 'left to right' when 2 buf << 'right to left' when 3 buf << 'bottom to top' when 4 buf << 'top to bottom' else buf << 'unknown' end end end # # 0x0201 - JpegQual # class JpegQual < Base def to_s case @formatted when 1 "Standard Quality" when 2 "High Quality" when 3 "Super High Quality" else "Unknown" end end end # # 0x0202 - Macro # class Macro < Base def to_s case @formatted when 0 'Off' when 1 'On' else 'Unknown' end end end # # 0x0203 - Unknown # # # 0x0204 - DigiZoom # class DigiZoom < Base end # # 0x0205 - Unknown # # # 0x0206 - Unknown # # # 0x0207 - SoftwareRelease # class SoftwareRelease < Base end # # 0x0208 - PictInfo # class PictInfo < Base end # # 0x0209 - CameraID # class CameraID < Base end # # 0x0f00 # class DataDump < Base end end OlympusIFDTable = { 0x0200 => MakerNote::SpecialMode, 0x0201 => MakerNote::JpegQual, 0x0202 => MakerNote::Macro, 0x0203 => Unknown, 0x0204 => MakerNote::DigiZoom, 0x0205 => Unknown, 0x0206 => Unknown, 0x0207 => MakerNote::SoftwareRelease, 0x0208 => MakerNote::PictInfo, 0x0209 => MakerNote::CameraID, 0x0f00 => MakerNote::DataDump } end class Olympus def initialize(fin, tiff_origin, dataPos, byteOrder_module) @fin = fin @tiffHeader0 = tiff_origin @dataPos = dataPos @byteOrder_module = byteOrder_module self.extend @byteOrder_module end def scan_IFD # # Olympus MakerNote starts from 8 byte from the origin. # @fin.pos = @dataPos + 8 # # get the number of tags # num_dirs = decode_ushort(fin_read_n(2)) # # now scan them # 1.upto(num_dirs) { curpos_tag = @fin.pos tag = parseTagID(fin_read_n(2)) tagclass = Tag.find(tag.hex, Tag::OlympusIFDTable) unit, formatter = Tag::Format::Unit[decode_ushort(fin_read_n(2))] count = decode_ulong(fin_read_n(4)) tagdata = fin_read_n(4) obj = tagclass.new(tag, "MakerNote", count) obj.extend formatter, @byteOrder_module obj.pos = curpos_tag if unit * count > 4 curpos = @fin.pos begin @fin.pos = @tiffHeader0 + decode_ulong(tagdata) obj.dataPos = @fin.pos obj.data = fin_read_n(unit*count) ensure @fin.pos = curpos end else obj.dataPos = @fin.pos - 4 obj.data = tagdata end obj.processData yield obj } end private def fin_read_n(n) @fin.read(n) end end end tdiary-contrib-3.2.2/lib/exifparser/lib/exifparser/makernote/prove.rb000066400000000000000000000031441213632744000257550ustar00rootroot00000000000000# # # exifparser/makernote/prove.rb - # # Copyright (C) 2002 Ryuichi Tamura (r-tam@fsinet.or.jp) # # $Revision: 1.1.1.1 $ # $Date: 2002/12/16 07:59:00 $ # require 'exifparser/makernote/fujifilm' require 'exifparser/makernote/olympus' require 'exifparser/makernote/canon' require 'exifparser/makernote/nikon' require 'exifparser/makernote/nikon2' require 'exifparser/makernote/minolta' require 'exifparser/makernote/sigma' module Exif module MakerNote class NotSupportedError < RuntimeError; end module_function def prove(data, tag_make=nil, tag_model=nil) make = tag_make == nil ? '' : tag_make.to_s.upcase model = tag_model == nil ? '' : tag_model.to_s.upcase # # Identifier for OLYMPUS # if data[0..5] == "OLYMP\000" return Olympus # # Identifier for FUJIFILM # elsif data[0..7] == "FUJIFILM" return Fujifilm # # Identifier for Nikon # elsif make[0..4] == 'NIKON' if data[0..5] == "Nikon\000" if data[6] == 0x01 && data[7] == 0x00 return Nikon end end return Nikon2 # # Canon # elsif make[0..4] == 'CANON' return Canon # # Minolta # elsif make[0..6] == 'MINOLTA' return Minolta # # Sigma # elsif make[0..4] == 'SIGMA' return Sigma end # # If none above is applied, raises exception, # which will be caught by caller's rescue statement. # raise NotSupportedError end module_function :prove end end tdiary-contrib-3.2.2/lib/exifparser/lib/exifparser/makernote/sigma.rb000066400000000000000000000105051213632744000257210ustar00rootroot00000000000000# # exifparser/makernote/sigma.rb # # $Revision: 1.1 $ # $Date: 2010/10/23 16:41:28 $ # require 'exifparser/tag' require 'exifparser/utils' module Exif module Tag module MakerNote # # 0x0002 - SigmaSerialNo # # class SigmaSerialNo < Base # end # # 0x0003 - DriveMode # class DriveMode < Base end # # 0x0004 - ImageSize # class ImageSize < Base end # # 0x0005 - AF_Mode # class AF_Mode < Base end # # 0x0006 - AF_Setting # class AF_Setting < Base end # # 0x0007 - White_Balance # class White_Balance < Base end # # 0x0008 - ExposureMode # class ExposureMode < Base end # # 0x0009 - MeteringMode # class MeteringMode < Base end # # 0x000a - FocalLength # class FocalLength < Base end # # 0x000b - ColorSpace # class ColorSpace < Base end # # 0x000c - ExposureBias # class ExposureBias < Base end # # 0x000d - Contrast # class Contrast < Base end # # 0x000e - Shadow # class Shadow < Base end # # 0x000f - HighLight # class HighLight < Base end # # 0x0010 - Saturation # class Saturation end # # 0x0011 - SharpnessBias # class SharpnessBias < Base end # # 0x0012 - X3FillLight # class X3FillLight < Base end # # 0x0014 - ColorControl # class ColorControl < Base end # # 0x0015 - SettingMode # class SettingMode < Base end # # 0x0017 - Firmware # class Firmware < Base end # # 0x0018 - SigmaSoftware # class SigmaSoftware < Base end # # 0x0019 - AutoBracket # class AutoBracket < Base end end SigmaIFDTable = { # 0x0002 => MakerNote::SigmaSerialNo, 0x0003 => MakerNote::DriveMode, 0x0004 => MakerNote::ImageSize, 0x0005 => MakerNote::AF_Mode, 0x0006 => MakerNote::AF_Setting, 0x0007 => MakerNote::White_Balance, 0x0008 => MakerNote::ExposureMode, 0x0009 => MakerNote::MeteringMode, 0x000a => MakerNote::FocalLength, 0x000b => MakerNote::ColorSpace, 0x000c => MakerNote::ExposureBias, 0x000d => MakerNote::Contrast, 0x000e => MakerNote::Shadow, 0x000f => MakerNote::HighLight, 0x0010 => MakerNote::Saturation, 0x0011 => MakerNote::SharpnessBias, 0x0012 => MakerNote::X3FillLight, 0x0014 => MakerNote::ColorControl, 0x0015 => MakerNote::SettingMode, 0x0017 => MakerNote::Firmware, 0x0018 => MakerNote::SigmaSoftware, 0x0019 => MakerNote::AutoBracket } end class Sigma def initialize(fin, tiff_origin, dataPos, byteOrder_module) @fin = fin @tiffHeader0 = tiff_origin @dataPos = dataPos @byteOrder_module = byteOrder_module self.extend @byteOrder_module end def scan_IFD # # Sigma MakerNote starts from 10 byte from the origin # @fin.pos = @dataPos + 10 # # get the number of tags # numDirs = decode_ushort(fin_read_n(2)) # # now scan them # 1.upto(numDirs) { curpos_tag = @fin.pos tag = parseTagID(fin_read_n(2)) tagclass = Tag.find(tag.hex, Tag::SigmaIFDTable) unit, formatter = Tag::Format::Unit[decode_ushort(fin_read_n(2))] count = decode_ulong(fin_read_n(4)) tagdata = fin_read_n(4) obj = tagclass.new(tag, "MakerNote", count) obj.extend formatter, @byteOrder_module obj.pos = curpos_tag if unit * count > 4 curpos = @fin.pos begin @fin.pos = @tiffHeader0 + decode_ulong(tagdata) obj.dataPos = @fin.pos obj.data = fin_read_n(unit*count) ensure @fin.pos = curpos end else obj.dataPos = @fin.pos - 4 obj.data = tagdata end obj.processData yield obj } end private def fin_read_n(n) @fin.read(n) end end end tdiary-contrib-3.2.2/lib/exifparser/lib/exifparser/pre-setup.rb000066400000000000000000000000511213632744000245530ustar00rootroot00000000000000# pre-setup.rb - working with install.rb tdiary-contrib-3.2.2/lib/exifparser/lib/exifparser/scan.rb000066400000000000000000000160701213632744000235630ustar00rootroot00000000000000# # exifparser/scan.rb # # Copyright (C) 2002 Ryuichi Tamura (r-tam@fsinet.or.jp) # # $Revision: 1.2 $ # $Date: 2003/04/20 19:58:31 $ # # require 'exifparser/utils' require 'exifparser/tag' require 'exifparser/makernote/prove' module Exif class Scanner def initialize(fin) @fin = fin.binmode @result = {} @tiffHeader0 = nil # origin at which TIFF header begins @byteOrder_module = nil end attr_reader :result def finish @fin.close end def scan tic = Time.now if $DEBUG # # check soi (start of image) # @fin.pos = 0 if @fin.read(2) != "\xFF\xD8" raise RuntimeError, 'not JPEG format' end # # seek app1 (EXIF signature) # begin marker = get_marker break if (marker == 0xFFE1) size = get_marker_datasize @fin.seek(size - 2, IO::SEEK_CUR) end while (!@fin.eof?) if marker != 0xFFE1 raise RuntimeError, 'not EXIF format' end # # get app1 Data size # @result[:app1DataSize] = get_marker_datasize() curpos = @fin.pos @result[:app1Data] = fin_read_n(@result[:app1DataSize]) @fin.pos = curpos # # EXIF header must be exactly "Exif\000\000", but some model # does not provide correct one. So we relax the condition. # if (h = exif_identifier()) !~ /\AExif\000/ raise RuntimeError, "Invalid EXIF header: #{h}" end # # examine TIFF header # @tiffHeader0, tiff_header = get_tiff_header() # # get byte order # case tiff_header[0,2] when "MM" @byteOrder_module = Utils::Decode::Motorola when "II" @byteOrder_module = Utils::Decode::Intel else raise RuntimeError, "Unknown byte order" end self.extend @byteOrder_module @result[:offset_IFD0] = decode_ulong(tiff_header[4..-1]) # # IFD0 # @fin.pos = @tiffHeader0 + @result[:offset_IFD0] @result[:IFD0] = [] scan_IFD(Tag::IFD0Table, Tag::IFD0Table.name) do |tag| @result[:IFD0].push tag end # # IFD1 # @result[:IFD1] = [] next_ifd = decode_ulong(fin_read_n(4)) if next_ifd > 0 @fin.pos = @tiffHeader0 + next_ifd scan_IFD(Tag::IFD1Table, Tag::IFD1Table.name) do |tag| @result[:IFD1].push tag end end # # GPS IFD # @result[:GPS] = [] found = @result[:IFD0].find{ |e| e.class == Tag::GPSIFDPointer } if found @result[:offset_GPS] = found.processData @fin.pos = @tiffHeader0 + @result[:offset_GPS] scan_IFD(Tag::GPSIFDTable, Tag::GPSIFDTable.name) do |tag| @result[:GPS].push tag end end # # Exif IFD # @result[:Exif] = [] found = @result[:IFD0].find{ |e| e.class == Tag::ExifIFDPointer } if found @result[:offset_Exif] = found.processData @fin.pos = @tiffHeader0 + @result[:offset_Exif] scan_IFD(Tag::ExifIFDTable, Tag::ExifIFDTable.name) do |tag| @result[:Exif].push tag end end # # Interoperability subIFD # @result[:Interoperability] = [] found = @result[:Exif].find {|e| e.class == Tag::InteroperabilityIFDPointer } if found @result[:offset_InteroperabilityIFD] = found.processData @fin.pos = @tiffHeader0 + @result[:offset_InteroperabilityIFD] scan_IFD(Tag::InteroperabilityIFDTable, Tag::InteroperabilityIFDTable.name) do |tag| @result[:Interoperability].push tag end end # # MakerNote subIFD # @result[:MakerNote]=[] found = @result[:Exif].find {|e| e.class == Tag::Exif::MakerNote } if (found) begin # Because some vendors do not put any identifier in the header, # we try to find which model is by seeing Tag::TIFF::Make, Tag::TIFF::Model. make = @result[:IFD0].find {|e| e.class == Tag::TIFF::Make} model = @result[:IFD0].find {|e| e.class == Tag::TIFF::Model} # prove the maker makernote_class = Exif::MakerNote.prove(found.data, make, model) # set file pointer to the position where the tag was found. @fin.pos = found.pos makernote = makernote_class.new(@fin, @tiffHeader0, found.dataPos, @byteOrder_module) makernote.scan_IFD do |tag| @result[:MakerNote].push tag end rescue MakerNote::NotSupportedError rescue Exception # what to do? if $DEBUG raise $! end end end # # get thumbnail # if !@result[:IFD1].empty? format = @result[:IFD1].find do |e| e.class == Tag::TIFF::Compression end.value unless format == 6 raise NotImplementedError, "Sorry, thumbnail of other than JPEG format is not supported." end thumbStart = @result[:IFD1].find do |e| e.class == Exif::Tag::TIFF::JpegInterchangeFormat end.value thumbLen = @result[:IFD1].find do |e| e.class == Exif::Tag::TIFF::JpegInterchangeFormatLength end.value @fin.pos = @tiffHeader0 + thumbStart # check JPEG soi maker if @fin.read(2) != "\xFF\xD8" raise RuntimeError, 'not JPEG format' end @fin.pos = @fin.pos - 2 # now read thumbnail image @result[:Thumbnail] = @fin.read(thumbLen) end # turn on if $DEBUG toc = Time.now if $DEBUG puts(sprintf("scan time: %1.4f sec.", toc-tic)) if $DEBUG end private def fin_read_n(n) @fin.read(n) end def scan_IFD(tagTable, ifdname) num_dirs = decode_ushort(fin_read_n(2)) 1.upto(num_dirs) { curpos_tag = @fin.pos tag = parseTagID(fin_read_n(2)) tagclass = Tag.find(tag.hex, tagTable) unit, formatter = Tag::Format::Unit[decode_ushort(fin_read_n(2))] count = decode_ulong(fin_read_n(4)) tagdata = fin_read_n(4) next if formatter == nil obj = tagclass.new(tag, ifdname, count) obj.extend formatter, @byteOrder_module obj.pos = curpos_tag if unit * count > 4 curpos = @fin.pos begin @fin.pos = @tiffHeader0 + decode_ulong(tagdata) obj.dataPos = @fin.pos obj.data = fin_read_n(unit*count) ensure @fin.pos = curpos end else obj.dataPos = @fin.pos - 4 obj.data = tagdata end obj.processData yield obj } end def get_marker (@fin.read(1).unpack("C*")[0]) << 8 | (@fin.read(1).unpack("C*")[0]) end def get_marker_datasize (@fin.read(1).unpack("C*")[0]) << 8 | (@fin.read(1).unpack("C*")[0]) end def exif_identifier @fin.read(6) end def get_tiff_header pos = @fin.pos [pos, fin_read_n(8)] end def eoi @fin.seek(-2, IO::SEEK_END) @fin.read(2) end end end tdiary-contrib-3.2.2/lib/exifparser/lib/exifparser/tag.rb000066400000000000000000001261541213632744000234170ustar00rootroot00000000000000# # exifparser/tag.rb # # Copyright (C) 2002 Ryuichi Tamura (r-tam@fsinet.or.jp) # # $Revision: 1.3 $ # $Date: 2003/04/27 14:02:39 $ # require 'exifparser/utils' require 'rational' module Exif module Error class TagNotFound < StandardError; end end module Tag # # modules under this module provides '_formatData()' method, # which is invoked in Exif::Tag::Base#processData(). # module Formatter # # convert data to unsigned byte(1 byte) value. # module UByte def format 'Unsigned byte' end def _formatData(data) decode_ubytes(data) end end # # convert data to ASCII(1 byte) values. # module Ascii def format 'Ascii' end def _formatData(data) data.delete("\000") end end # # convert data to unsigned short(2 byte) value. # module UShort def format 'Unsigned short' end def _formatData(data) decode_ushort(data) end end # # convert data to unsigned long(4 byte) value. # module ULong def format 'Unsigned long' end def _formatData(data) decode_ulong(data) end end # # convert data to unsigned rational(4+4 byte) value, # which in turn is converted to Rational object. # module URational def format 'Unsigned rational' end def _formatData(data) a = decode_ulong(data[0,4]) b = decode_ulong(data[4,4]) return Rational(0,1) if b == 0 Rational(a, b) end end # # convert data to some value by user-supplied method. # the client code should implement 'convert(data)' method. # module Undefined def format 'Undefined' end def _formatData(data) if self.respond_to?(:_format0) _format0(data) else data.unpack("C*").collect{|e| e.to_i} end end end # # convert data to signed short value. # module SShort def format 'Signed short' end def _formatData(data) decode_sshort(data) end end # # convert data to unsigned long(4 byte) value. # module SLong def format 'Signed long' end def _formatData(data) decode_slong(data) end end # # convert data to signed rational (4+4 byte) value. # module SRational def format 'Signed rational' end def _formatData(data) a = decode_slong(data[0,4]) b = decode_slong(data[4,4]) return Rational(0,1) if b == 0 Rational(a, b) end end end # module Formatter # # maps number to size of one unit and the # corresponding formatter (defined below) module. # module Format Unit = { 1 => [1, ::Exif::Tag::Formatter::UByte], 2 => [1, ::Exif::Tag::Formatter::Ascii], 3 => [2, ::Exif::Tag::Formatter::UShort], 4 => [4, ::Exif::Tag::Formatter::ULong], 5 => [8, ::Exif::Tag::Formatter::URational], #6 => [1, ::Exif::Tag::Formatter::SByte], 7 => [1, ::Exif::Tag::Formatter::Undefined], 8 => [2, ::Exif::Tag::Formatter::SShort], 9 => [4, ::Exif::Tag::Formatter::SLong], 10 => [8, ::Exif::Tag::Formatter::SRational], #11 => [4, Exif::Formatter::SFloat], #12 => [8, Exif::Formatter::DFloat] } end # # The base class that specifies common operations for tag data. # All the tag classes are derived from this, and client code # shoude use the public methods as interface. # class Base # # the argument 'byteorder' is either :intel or :motorola. # this is used when packing @data given after initialized. # def initialize(tagID, ifdname, count) @tagID = tagID @IFD = ifdname @count = count @data = nil @formatted = nil @pos = nil @dataPos = nil end attr_writer :data attr_accessor :pos, :dataPos attr_reader :tagID, :IFD, :count def processData @formatted = _formatData(@data) end # # return tag's value: simply returns @formatted as it is. # def value @formatted end # # String representation of tag's value # this is the default method that simply # sends Object#to_s to @formatted. # Subclasses may override this so that # it returns more human-readable form. # def to_s if self.is_a? Formatter::Undefined length = @formatted.length data = length > 8 ? @formatted[0, 8] : @formatted ret = "" data.each do |dat| ret += sprintf("%02X ", dat) end ret += %Q[...(#{length} bytes)] if length > data.length return ret else @formatted.to_s end end # # return tag's name # def name self.class.to_s.split("::")[-1] end # # format focal length # def formatFocalLength(f) if (f.abs < 10.0) str = "%.1f"%[f] else str = "%.0f"%[f] end "#{str}mm" end # # format exposure time # def formatExposureTime(ss) rss = 1.0/ss if (rss >= 3.0) str = "1/%.0f"%[rss] elsif (3.0 > rss && rss > 1.0) str = "1/%.1f"%[rss] elsif (ss == 1.0) str = "1.0" elsif (3.0 > ss && ss > 1.0) str = "%.1f"%[ss] else str = "%.0f"%[ss] end "#{str}sec." end # # format f number # def formatFNumber(f) if (f.abs < 10.0) str = "%.1f"%[f] else str = "%.0f"%[f] end "F#{str}" end # # format Latitude and Longitude # def formatLatLon(f) if f[2].to_f == 0.0 sprintf("%d deg %.2f'",f[0],f[1]) else sprintf("%d deg %d' %.2f\"",f[0],f[1],f[2]) end end if not $DEBUG def inspect sprintf("#<%s ID=0x%04x, IFD=\"%s\" Name=\"%s\", Format=\"%s\", Count=\"%d\", Value=\"%s\">", self.class, @tagID, @IFD, self.name, self.format, self.count, self.value) end end private def partition_data(count) i = 0 bytes = @data.size / count while @data[i] yield @data[i..i+bytes-1] i = i + bytes end end end ## ## the class for any unknown tags in ## IFD0, IFD1, GPSIFD, ExifIFD, InteroperabilityIFD ## class Unknown < Base end ## ## tags specific to Exif IFD. ## (see Exif standard 2.2 Section 4.6.3-A ) ## # # 0x8769 - ExifIFDPointer # class ExifIFDPointer < Base end # # 0x8825 - GPSIFDPointer # class GPSIFDPointer < Base end # # 0xa005 - InteroperabilityIFDPointer # class InteroperabilityIFDPointer < Base end ## ## tags related TIFF Rev. 6.0 Attribute Information. ## (see Exif standard 2.2 Section 4.6.4 Table 3) ## module TIFF # # 0x0100 - ImageWidth # class ImageWidth < Base end # # 0x0101 - ImageLength # class ImageLength < Base end # # 0x0102 - BitsPerSample # class BitsPerSample < Base def processData @formatted = [] partition_data(@count) do |data| @formatted.push _formatData(data) end end def to_s @formatted.join(",") end end # # 0x0103 - Compression # class Compression < Base def to_s case @formatted when 1 'uncompressed' when 6 'JPEG compression' else 'Unknown' end end end # # 0x0106 - PhotometricInterpretation # class PhotometricInterpretation < Base def to_s case @formatted when 2 'RGB' when 6 'YCbCr' else 'Unknown' end end end # # 0x0111 - StripOffsets # class StripOffsets < Base end # # 0x0112 - Orientation # class Orientation < Base end # # 0x0115 - SamplePerPixel # class SamplesPerPixel < Base end # # 0x0116 - RowsPerStrip # class RowsPerStrip < Base end # # 0x0117 - StripByteCounts # class StripByteCounts < Base end # # 0x011a - XResolution # class XResolution < Base end # # 0x011b - YResolution # class YResolution < Base end # # 0x011c - PlanarConfiguration # class PlanarConfiguration < Base def to_s case @formatted when 1 'chunky format' when 2 'planar format' else 'unknown' end end end # # 0x0128 - ResolutionUnit # class ResolutionUnit < Base def to_s case @formatted when 2 'inch' when 3 'centimeter' else 'unknown' end end end # # 0x0201 - JpegInterchangeFormat # class JpegInterchangeFormat < Base end # # 0x0202 - JpegInterchangeFormatLength # class JpegInterchangeFormatLength < Base end # # 0x0211 - YCbCrCoefficients # class YCbCrCoefficients < Base def processData @formatted = [] partition_data(@count) do |data| @formatted.push _formatData(data) end end def to_s @formatted.join(",") end end # # 0x0212 - YCbCrSubSampling # class YCbCrSubSampling < Base def processData @formatted = [] partition_data(@count) do |data| @formatted.push _formatData(data) end end def to_s case @formatted when [2,1] 'YCbCr4:2:2' when [2,2] 'YCbCr4:2:0' else 'Unknown' end end end # # 0x0213 - YCbCrPositioning # class YCbCrPositioning < Base def to_s case @formatted when 1 'centered' when 2 'co-sited' else 'unknown' end end end # # 0x0214 - ReferenceBlackWhite # class ReferenceBlackWhite < Base end # # 0x010e - ImageDescription # class ImageDescription < Base end # # 0x010f - Make # class Make < Base end # # 0x0110 - Model # class Model < Base end # # 0x0112 - Orientation # class Orientation < Base def to_s case @formatted when 1 "top - left" when 2 "top - right" when 3 "bottom - right" when 4 "bottom - left" when 5 "left - top" when 6 "right - top" when 7 "right - bottom" when 8 "left - bottom" else "unknown" end end end # # 0x011a - XResolution # class XResolution < Base end # # 0x011b - YResolution # class YResolution < Base end # # 0x0128 - ResolutionUnit # class ResolutionUnit < Base def to_s case @formatted when 1 "none" when 2 "inch" when 3 "centimeter" else "unknown" end end end # # 0x012D - TransferFunction # class TransferFunction < Base end # # 0x0131 - Software # class Software < Base end # # 0x0132 - DateTime # class DateTime < Base end # # 0x013B - Artist # class Artist < Base end # # 0x013E - WhitePoint # class WhitePoint < Base def processData @formatted = [] partition_data(@count) do |data| @formatted.push _formatData(data) end end def to_s @formatted.join(",") end end # # 0x013f - PrimaryChromaticities # class PrimaryChromaticities < Base def processData @formatted = [] partition_data(@count) do |data| @formatted.push _formatData(data) end end def to_s @formatted.join(",") end end # # 0x0211 - YCbCrCoefficients # class YCbCrCoefficients < Base def processData @formatted = [] partition_data(@count) do |data| @formatted.push _formatData(data) end end def to_s @formatted.join(",") end end # # 0x0213 - YCbCrPositioning # class YCbCrPositioning < Base end # # 0x0214 - ReferenceBlackWhite # class ReferenceBlackWhite < Base def processData @formatted = [] partition_data(@count) do |data| @formatted.push _formatData(data) end end def to_s @formatted.join(",") end end # # 0x8298 - Copyright # class Copyright < Base def _format0(data) data.inspect end def to_s sep = @data.index(0) photographer = @data[0..sep-1] editor = @data[sep+1..-1] "#{photographer} (Photographer) - #{editor} (Editor)" end end end ## ## Exif IFD tags ## module Exif # # 0x829a - ExposureTime # class ExposureTime < Base def to_s formatExposureTime(@formatted.to_f) end end # # 0x829d - FNumber # class FNumber < Base def to_s formatFNumber(@formatted.to_f) end end # # 0x8822 - ExposureProgram # class ExposureProgram < Base def to_s case @formatted when 0 "Not defined" when 1 "Manual" when 2 "Normal program" when 3 "Aperture priority" when 4 "Shutter priority" when 5 "Creative program (biased toward depth of field)" when 6 "Action program (biased toward fast shutter speed)" when 7 "Portrait mode (for closeup photos with the background out of focus)" when 8 "Landscape mode (for landscape photos with the background in focus)" else "Unknown" end end end # # 0x8824 - SpectralSensitivity # class SpectralSensitivity < Base end # # 0x8828 - OECF # class OECF < Base end # # 0x8827 - ISOSpeedRatings # class ISOSpeedRatings < Base end # # 0x9000 - ExifVersion # class ExifVersion < Base def _format0(data) data end def to_s case @formatted when "0200" "Exif Version 2.0" when "0210" "Exif Version 2.1" when "0220" "Exif Version 2.2" when "0221" "Exif Version 2.21" else "Unknown Exif Version" end end end # # 0x9003 - DateTimeOriginal # class DateTimeOriginal < Base end # # 0x9004 - DateTimeDigitized # class DateTimeDigitized < Base end # # 0x9101 - ComponentsConfiguration # class ComponentsConfiguration < Base def _format0(data) data.unpack("C*").collect{|e| e.to_i} end def to_s case @formatted when [0x04,0x05,0x06,0x00] 'RGB' when [0x01,0x02,0x03,0x00] 'YCbCr' end end end # # 0x9102 - CompressedBitsPerPixel # class CompressedBitsPerPixel < Base def to_s "%.1fbits/pixel"%[@formatted.to_f] end end # # 0x9201 - ShutterSpeedValue # class ShutterSpeedValue < Base def to_s formatExposureTime(1.0/(2.0**(@formatted.to_f))) end end # # 0x9202 - ApertureValue # class ApertureValue < Base def to_s formatFNumber(Math.sqrt(2.0)**(@formatted.to_f)) end end # # 0x9203 - BrightnessValue # class BrightnessValue < Base def to_s "%+.1f"%[@formatted.to_f] end end # # 0x9204 - ExposureBiasValue # class ExposureBiasValue < Base def to_s "%+.1f"%[@formatted.to_f] end end # # 0x9205 - MaxApertureValue # class MaxApertureValue < Base def to_s "F%.01f"%[Math.sqrt(2.0)**(@formatted.to_f)] end end # # 0x9206 - SubjectDistance # class SubjectDistance < Base end # # 0x9207 - MeteringMode # class MeteringMode < Base def to_s case @formatted when 1 'Average' when 2 'CenterWeightedAverage' when 3 'Spot' when 4 'MultiSpot' when 5 'Pattern' when 6 'Partial' when 255 'other' else 'Unknown' end end end # # 0x9208 - LightSource # class LightSource < Base def to_s case @formatted when 0 'Unknown' when 1 'Daylight' when 2 'Fluorescent' when 3 'Tungsten' when 4 'Flash' when 9 'Fine weather' when 10 'Croudy weather' when 11 'Shade' when 12 'Daylight fluorescent' when 13 'Day white fluorescent' when 14 'Cool white fluorescent' when 15 'White fluorescent' when 17 'Standard light A' when 18 'Standard light B' when 19 'Standard light C' when 20 'D55' when 21 'D65' when 22 'D75' when 23 'D50' when 24 'ISO studio tungsten' when 255 'other light source' else 'reserved' end end end # # 0x9209 - Flash # class Flash < Base def to_s case @formatted when 0x0000 'Flash did not fire.' when 0x0001 'Flash fired.' when 0x0005 'Strobe return light not detected.' when 0x0007 'Strobe return light detected.' when 0x0009 'Flash fired, compulsory flash mode.' when 0x000d 'Flash fired, compulsory flash mode, return light not detected.' when 0x000f 'Flash fired, compulsory flash mode, return light detected.' when 0x0010 'Flash did not fire, compulsory flash mode.' when 0x0018 'Flash did not fire, auto mode.' when 0x0019 'Flash fired, auto mode.' when 0x001d 'Flash fired, auto mode, return light not detected.' when 0x001f 'Flash fired, auto mode, return light detected.' when 0x0020 'No flash function.' when 0x0041 'Flash fired, red-eye reduction mode.' when 0x0045 'Flash fired, red-eye reduction mode, return light not detected.' when 0x0047 'Flash fired, red-eye reduction mode, return light detected.' when 0x0049 'Flash fired, compulsory flash mode.' when 0x004d 'Flash fired, compulsory flash mode, return light not detected.' when 0x004f 'Flash fired, compulsory flash mode, return light detected.' when 0x0059 'Flash fired, auto mode, red-eye reduction mode.' when 0x005d 'Flash fired, auto mode, return light not detected, red-eye reduction mode.' when 0x005f 'Flash fired, auto mode, return light detected, red-eye reduction mode.' else "reserved" end end end # # 0x920a - FocalLength # class FocalLength < Base def to_s formatFocalLength(@formatted.to_f) end end # # 0x9214 - SubjectArea # class SubjectArea < Base def processData @formatted = [] partition_data(@count) do |data| @formatted.push _formatData(data) end end def to_s case @count when 2 "Coordinate - [%d, %d]"%[*@formatted] when 3 "Circle - Center: [%d, %d], Diameter: %d"%[*@formatted] when 4 "Rectanglar - Center: [%d, %d], Width: %d, Height: %d"%[*@formatted] else 'Unknown' end end end # # 0x927c - MakerNote # class MakerNote < Base def data @data end def _format0(data) @data end def to_s sprintf("MakerNote data (%i bytes)", data.size) end end # # 0x9286 - UserComment # class UserComment < Base def to_s case @data[0..7] # ASCII when [0x41,0x53,0x43,0x49,0x49,0x0,0x0,0x0] @data[8..-1].pack("C*") # JIS when [0x4a,0x59,0x53,0x0,0x0,0x0,0x0,0x0] @data[8..-1].pack("C*") # Unicode when [0x55,0x4e,0x49,0x43,0x4f,0x44,0x45,0x0] @data[8..-1].pack("U*") when [0x0]*8 @data[8..-1].pack("C*") else "unknown" end end end # # 0x9290 - SubsecTime < Base # class SubsecTime < Base end # # 0x9291 - SubsecTimeOriginal < Base # class SubsecTimeOriginal < Base end # # 0x9292 - SubsecTimeDigitized < Base # class SubsecTimeDigitized < Base end # # 0xa000 - FlashPixVersion # class FlashPixVersion < Base def _format0(data) data end def to_s case @formatted when "0100" "FlashPix Version 1.0" else "Unknown FlashPix Version" end end end # # 0xa001 - ColorSpace # class ColorSpace < Base def to_s case @formatted when 1 'sRGB' when 65535 'Uncalibrated' else 'Unknown: #{@formatted}' end end end # # 0xa002 - PixelXDimension # class PixelXDimension < Base def processData case self.byte_order when :intel @formatted = decode_ushort(@data[0,2]) when :motorola @formatted = decode_ushort(@data[2,2]) end end end # # 0xa003 - PixelYDimension # class PixelYDimension < Base def processData case self.byte_order when :intel @formatted = decode_ushort(@data[0,2]) when :motorola @formatted = decode_ushort(@data[2,2]) end end end # # 0xa004 - RelatedSoundFile # class RelatedSoundFile < Base end # # 0xa20b - FlashEnergy # class FlashEnergy < Base end # # 0xa20c - SpatialFrequencyResponse # class SpatialFrequencyResponse < Base end # # 0xa20e - FocalPlaneXResolution # class FocalPlaneXResolution < Base end # # 0xa20f - FocalPlaneYResolution # class FocalPlaneYResolution < Base end # # 0xa210 - FocalPlaneResolutionUnit # class FocalPlaneResolutionUnit < Base def to_s case @formatted when 1 'No unit' when 2 'Inch' when 3 'Centimeter' else 'Unknown' end end end # # 0xa214 - SubjectLocation # class SubjectLocation < Base def processData @formatted = [] partition_data(@count) do |data| @formatted.push _formatData(data) end end def to_s "[%d, %d]"%[*@formatted] end end # # 0xa215 - ExposureIndex # class ExposureIndex < Base end # # 0xa217 - SensingMethod # class SensingMethod < Base def to_s case @formatted when 2 'One-chip color area sensor' else 'Unknown' end end end # # 0xa300 - FileSource # class FileSource < Base def _format0(data) data[0] end def to_s case @formatted when 0x03 'Digital still camera' else 'Unknown' end end end # # 0xa301 - SceneType # class SceneType < Base def _format0(data) data[0] end def to_s case @formatted when 0x01 'Directory photographed' else 'Unknown' end end end # # 0xa302 - CFAPattern # class CFAPattern < Base end # # 0xa401 - CustomRendered # class CustomRendered < Base def to_s case @formatted when 0 'Normal process' when 1 'Custom process' else 'reserved' end end end # # 0xa402 - ExposureMode # class ExposureMode < Base def to_s case @formatted when 0 'Auto exposure' when 1 'Manual exposure' when 2 'Auto bracket' else 'reserved' end end end # # 0xa403 - WhiteBalance # class WhiteBalance < Base def to_s case @formatted when 0 'Auto white balance' when 1 'Manual white balance' else 'reserved' end end end # # 0xa404 - DigitalZoomRatio # class DigitalZoomRatio < Base def to_s n = @formatted.numerator d = @formatted.denominator n == 0 ? 'None' : "%.1f"%[n.to_f/d.to_f] end end # # 0xa405 - FocalLengthIn35mmFilm # class FocalLengthIn35mmFilm < Base def to_s @formatted == 0 ? 'Unknown' : formatFocalLength(@formatted) end end # # 0xa406 - SceneCaptureType # class SceneCaptureType < Base def to_s case @formatted when 0 'Standard' when 1 'Landscape' when 2 'Portrait' when 3 'Nigit scene' else 'reserved' end end end # # 0xa407 - GaincControl # class GainControl < Base def to_s case @formatted when 0 'None' when 1 'Low gain up' when 2 'High gain up' when 3 'Low gain down' when 4 'High gain down' else 'reserved' end end end # # 0xa408 - Contrast # class Contrast < Base def to_s case @formatted when 0 'Normal' when 1 'Soft' when 2 'Hard' else 'reserved' end end end # # 0xa409 - Saturation # class Saturation < Base def to_s case @formatted when 0 'Normal' when 1 'Low saturation' when 2 'High saturation' else 'reserved' end end end # # 0xa40a - Sharpness # class Sharpness < Base def to_s case @formatted when 0 'Normal' when 1 'Soft' when 2 'Hard' else 'reserved' end end end # # 0xa40b - DeviceSettingDescription # class DeviceSettingDescription < Base end # # 0xa40c - SubjectDistanceRange # class SubjectDistanceRange < Base def to_s case @formatted when 0 'Unknown' when 1 'Macro' when 2 'Close view' when 3 'Distant view' else 'reserved' end end end # # 0xa420 - ImageUniqueID # class ImageUniqueID < Base end end ## ## GPS IFD tags ## module GPS # # 0x0000 - GPSVersionID # # type : byte # count: 4 # class GPSVersionID < Base def to_s case @formatted when [2,2,0,0] "Version 2.2" else "Unknown" end end end # # 0x0001 - GPSLatitudeRef # class GPSLatitudeRef < Base def to_s case @formatted when 'N' 'North latitude' when 'S' 'South latitude' else 'Unknown' end end end # # 0x0002 - GPSLatitude # class GPSLatitude < Base def processData @formatted = [] partition_data(@count) do |data| @formatted.push _formatData(data) end end def to_s formatLatLon @formatted end end # # 0x0003 - GPSLongitudeRef # class GPSLongitudeRef < Base def to_s case @formatted when 'E' 'East longitude' when 'W' 'West longitude' else 'Unknown' end end end # # 0x0004 - GPSLongitude # class GPSLongitude < Base def processData @formatted = [] partition_data(@count) do |data| @formatted.push _formatData(data) end end def to_s formatLatLon @formatted end end # # 0x0005 - GPSAltitudeRef # class GPSAltitudeRef < Base def to_s case @formatted[0] when 0 'Sea level' when 1 'Sea level(negative value)' else 'Unknown' end end end # # 0x0006 - GPSAltitude # class GPSAltitude < Base end # # 0x0007 - GPSTimeStamp # class GPSTimeStamp < Base def processData @formatted = [] partition_data(@count) do |data| @formatted.push _formatData(data) end end def to_s @formatted.join(",") end end # # 0x0008 - GPSSatelites # class GPSSatelites < Base end # # 0x0009 - GPSStatus # class GPSStatus < Base def to_s case @formatted when 'A' 'Measurement in progress' when 'V' 'Measurement in interoperability' else 'Unknown' end end end # # 0x000A - GPSMeasureMode # class GPSMeasureMode < Base def to_s case @formatted when '2' '2-dimensional measurement' when '3' '3-dimensional measurement' else 'Unknown' end end end # # 0x000B - GPSDOP # class GPSDOP < Base end # # 0x000C - GPSSpeedRef # class GPSSpeedRef < Base def to_s case @formatted when 'K' 'Kilometers per hour' when 'M' 'Miles per hour' when 'N' 'Knots' else 'Unknown' end end end # # 0x000D - GPSSpeed # class GPSSpeed < Base end # # 0x000E - GPSTrackRef # class GPSTrackRef < Base def to_s case @formatted when 'T' 'True direction' when 'M' 'Magnetic direction' else 'Unknown' end end end # # 0x000F - GPSTrack # class GPSTrack < Base end # # 0x0010 - GPSImgDirectionRef # class GPSImgDirectionRef < Base def to_s case @formatted when 'T' 'True direction' when 'M' 'Magnetic direction' else 'Unknown' end end end # # 0x0011 - GPSImgDirection # class GPSImgDirection < Base end # # 0x0012 - GPSMapDatum # class GPSMapDatum < Base end # # 0x0013 - GPSDestLatitudeRef # class GPSDestLatitudeRef < Base def to_s case @formatted when 'N' 'North latitude' when 'S' 'South latitude' else 'Unknown' end end end # # 0x0014 - GPSDestLatitude # class GPSDestLatitude < Base def processData @formatted = [] partition_data(@count) do |data| @formatted.push _formatData(data) end end def to_s formatLatLon @formatted end end # # 0x0015 - GPSDestLongitudeRef # class GPSDestLongitudeRef < Base def to_s case @formatted when 'E' 'East longitude' when 'W' 'West longitude' else 'Unknown' end end end # # 0x0016 - GPSDestLongitude # class GPSDestLongitude < Base def processData @formatted = [] partition_data(@count) do |data| @formatted.push _formatData(data) end end def to_s formatLatLon @formatted end end # # 0x0017 - GPSDestBearingRef # class GPSDestBearingRef < Base def to_s case @formatted when 'T' 'True direction' when 'M' 'Magnetic direction' else 'Unknown' end end end # # 0x0018 - GPSDestBearing # class GPSDestBearing < Base end # # 0x0019 - GPSDestDistanceRef # class GPSDestDistanceRef < Base def to_s case @formatted when 'K' 'Kilometers' when 'M' 'Miles' when 'N' 'Knots' else 'Unknown' end end end # # 0x001A # class GPSDestDistance < Base end # # 0x001B # class GPSProcessingMethod < Base end # # 0x001C # class GPSAreaInformation < Base end # # 0x001D # class GPSDateStamp < Base end # # 0x001E # class GPSDifferential < Base def to_s case @formatted when 0 'Measurement without differential correction' when 1 'Differential correction applied' else 'Unknown' end end end end ## ## Interoperability IFD tags ## module Interoperability # # 0x0001 - InteroperabilityIndex # class InteroperabilityIndex < Base end # # 0x0002 - InteroperabilityVersion # class InteroperabilityVersion < Base end # # 0x1000 - RelatedImageFileFormat # class RelatedImageFileFormat end # # 0x1001 - RelatedImageWidth # class RelatedImageWidth < Base end # # 0x1002 - RelatedImageLength # class RelatedImageLength < Base end end # # Hash tables that maps tag ID to the corresponding class. # ExifSpecific = { 0x8769 => ExifIFDPointer, 0x8825 => GPSIFDPointer, 0xa005 => InteroperabilityIFDPointer } TIFFAttributes = { 0x0100 => TIFF::ImageWidth, 0x0101 => TIFF::ImageLength, 0x0102 => TIFF::BitsPerSample, 0x0103 => TIFF::Compression, 0x0106 => TIFF::PhotometricInterpretation, 0x010E => TIFF::ImageDescription, 0x010F => TIFF::Make, 0x0110 => TIFF::Model, 0x0111 => TIFF::StripOffsets, 0x0112 => TIFF::Orientation, 0x0115 => TIFF::SamplesPerPixel, 0x0116 => TIFF::RowsPerStrip, 0x0117 => TIFF::StripByteCounts, 0x011A => TIFF::XResolution, 0x011B => TIFF::YResolution, 0x011C => TIFF::PlanarConfiguration, 0x0128 => TIFF::ResolutionUnit, 0x012D => TIFF::TransferFunction, 0x0131 => TIFF::Software, 0x0132 => TIFF::DateTime, 0x013B => TIFF::Artist, 0x013E => TIFF::WhitePoint, 0x013F => TIFF::PrimaryChromaticities, 0x0201 => TIFF::JpegInterchangeFormat, 0x0202 => TIFF::JpegInterchangeFormatLength, 0x0211 => TIFF::YCbCrCoefficients, 0x0212 => TIFF::YCbCrSubSampling, 0x0213 => TIFF::YCbCrPositioning, 0x0214 => TIFF::ReferenceBlackWhite, 0x8298 => TIFF::Copyright, } # # ExifStandard 2.2, Section 4.6.8-A # IFD0Table = TIFFAttributes.update ExifSpecific def IFD0Table.name "IFD0" end # # ExifStandard 2.2, Section 4.6.8-B # IFD1Table = IFD0Table.dup def IFD1Table.name "IFD1" end ExifIFDTable = { 0x829a => Exif::ExposureTime, 0x829d => Exif::FNumber, 0x8822 => Exif::ExposureProgram, 0x8824 => Exif::SpectralSensitivity, 0x8827 => Exif::ISOSpeedRatings, 0x8828 => Exif::OECF, 0x9000 => Exif::ExifVersion, 0x9003 => Exif::DateTimeOriginal, 0x9004 => Exif::DateTimeDigitized, 0x9101 => Exif::ComponentsConfiguration, 0x9102 => Exif::CompressedBitsPerPixel, 0x9201 => Exif::ShutterSpeedValue, 0x9202 => Exif::ApertureValue, 0x9203 => Exif::BrightnessValue, 0x9204 => Exif::ExposureBiasValue, 0x9205 => Exif::MaxApertureValue, 0x9206 => Exif::SubjectDistance, 0x9207 => Exif::MeteringMode, 0x9208 => Exif::LightSource, 0x9209 => Exif::Flash, 0x920a => Exif::FocalLength, 0x9214 => Exif::SubjectArea, 0x927c => Exif::MakerNote, 0x9286 => Exif::UserComment, 0x9290 => Exif::SubsecTime, 0x9291 => Exif::SubsecTimeOriginal, 0x9292 => Exif::SubsecTimeDigitized, 0xa000 => Exif::FlashPixVersion, 0xa001 => Exif::ColorSpace, 0xa002 => Exif::PixelXDimension, 0xa003 => Exif::PixelYDimension, 0xa004 => Exif::RelatedSoundFile, 0xa005 => InteroperabilityIFDPointer, 0xa20b => Exif::FlashEnergy, 0xa20c => Exif::SpatialFrequencyResponse, 0xa20e => Exif::FocalPlaneXResolution, 0xa20f => Exif::FocalPlaneYResolution, 0xa210 => Exif::FocalPlaneResolutionUnit, 0xa214 => Exif::SubjectLocation, 0xa215 => Exif::ExposureIndex, 0xa217 => Exif::SensingMethod, 0xa300 => Exif::FileSource, 0xa301 => Exif::SceneType, 0xa302 => Exif::CFAPattern, 0xa401 => Exif::CustomRendered, 0xa402 => Exif::ExposureMode, 0xa403 => Exif::WhiteBalance, 0xa404 => Exif::DigitalZoomRatio, 0xa405 => Exif::FocalLengthIn35mmFilm, 0xa406 => Exif::SceneCaptureType, 0xa407 => Exif::GainControl, 0xa408 => Exif::Contrast, 0xa409 => Exif::Saturation, 0xa40a => Exif::Sharpness, 0xa40b => Exif::DeviceSettingDescription, 0xa40c => Exif::SubjectDistanceRange, 0xa420 => Exif::ImageUniqueID } def ExifIFDTable.name "Exif" end GPSIFDTable = { 0x0000 => GPS::GPSVersionID, 0x0001 => GPS::GPSLatitudeRef, 0x0002 => GPS::GPSLatitude, 0x0003 => GPS::GPSLongitudeRef, 0x0004 => GPS::GPSLongitude, 0x0005 => GPS::GPSAltitudeRef, 0x0006 => GPS::GPSAltitude, 0x0007 => GPS::GPSTimeStamp, 0x0008 => GPS::GPSSatelites, 0x000a => GPS::GPSMeasureMode, 0x000b => GPS::GPSDOP, 0x000c => GPS::GPSSpeedRef, 0x000d => GPS::GPSSpeed, 0x000e => GPS::GPSTrackRef, 0x000f => GPS::GPSTrack, 0x0010 => GPS::GPSImgDirectionRef, 0x0011 => GPS::GPSImgDirection, 0x0012 => GPS::GPSMapDatum, 0x0013 => GPS::GPSDestLatitudeRef, 0x0014 => GPS::GPSDestLatitude, 0x0015 => GPS::GPSDestLongitudeRef, 0x0016 => GPS::GPSDestLongitude, 0x0017 => GPS::GPSDestBearingRef, 0x0018 => GPS::GPSDestBearing, 0x0019 => GPS::GPSDestDistanceRef, 0x001A => GPS::GPSDestDistance, 0x001B => GPS::GPSProcessingMethod, 0x001C => GPS::GPSAreaInformation, 0x001D => GPS::GPSDateStamp, 0x001E => GPS::GPSDifferential } def GPSIFDTable.name "GPS" end InteroperabilityIFDTable = { 0x0001 => Interoperability::InteroperabilityIndex, 0x0002 => Interoperability::InteroperabilityVersion, 0x1000 => Interoperability::RelatedImageFileFormat, 0x1001 => Interoperability::RelatedImageWidth, 0x1002 => Interoperability::RelatedImageLength } def InteroperabilityIFDTable.name "Interoperability" end module_function def find(tagid, table) table[tagid] or ::Exif::Tag::Unknown end end end tdiary-contrib-3.2.2/lib/exifparser/lib/exifparser/thumbnail.rb000066400000000000000000000020521213632744000246150ustar00rootroot00000000000000# # exifparser/thumbnail.rb - # # Copyright (C) 2002 Ryuichi Tamura (r-tam@fsinet.or.jp) # # $Revision: 1.1.1.1 $ # $Date: 2002/12/16 07:59:00 $ # module Exif class Parser alias orig_thumbnail thumbnail # # redefine method. # def thumbnail Thumbnail.new(@result[:IFD1], @data) end end # # APIs are subject to change. # class Thumbnail def initialize(ifd1, data) @ifd1 = ifd1 @data = data end def size @data.size end def write(dest) dest << @data end def width search_tag('ImageWidth') end def height search_tag('ImageLength') end alias length height def bits_per_sample search_tag('BitsPerSample') end def compression search_tag('Compression') end def photometric_interpretation search_tag('PhotometricInterpretation') end def strip_offsets search_tag('StripOffsets') end private def search_tag(tag) @ifd1.find { |t| t.name == tag } end end end tdiary-contrib-3.2.2/lib/exifparser/lib/exifparser/utils.rb000066400000000000000000000027511213632744000240000ustar00rootroot00000000000000# # exifparser/utils.rb - # # Copyright (C) 2002 Ryuichi Tamura (r-tam@fsinet.or.jp) # # $Revision: 1.1.1.1 $ # $Date: 2002/12/16 07:59:00 $ # module Exif # # utility module that will be included in some classes. # module Utils module Decode module Motorola def byte_order :motorola end def decode_ubytes(str) str.unpack('C*') end def decode_ushort(str) str[0,2].unpack('n').first end def decode_ulong(str) str[0,4].unpack('N').first end def decode_sshort(str) str[0,2].unpack('n').pack('s').unpack('s').first end def decode_slong(str) str[0,4].unpack('N').pack('l').unpack('l').first end def parseTagID(str) sprintf("0x%02x%02x", *(str.unpack("C*"))) end end module Intel def byte_order :intel end def decode_ubytes(str) str.unpack('C*') end def decode_ushort(str) str[0,2].unpack('v').first end def decode_ulong(str) str[0,4].unpack('V').first end def decode_sshort(str) str[0,2].unpack('s').first end def decode_slong(str) str[0,4].unpack('l').first end def parseTagID(str) "0x" + str.unpack("C*").reverse.collect{ |e| sprintf("%02x", e) }.join("") end end end end end tdiary-contrib-3.2.2/lib/exifparser/sample/000077500000000000000000000000001213632744000206515ustar00rootroot00000000000000tdiary-contrib-3.2.2/lib/exifparser/sample/exifview.rb000066400000000000000000000134361213632744000230330ustar00rootroot00000000000000#!/usr/bin/env ruby # # exifview.rb - display EXIF information as well as EXIF image # # Copyright (C) 2002 Ryuichi Tamura (r-tam@fsinet.or.jp) # # $Revision: 1.3 $ # $Date: 2002/12/17 05:16:34 $ # # Requirements: gtk2 # require 'exifparser' require 'observer' require 'gtk2' module Exif class Parser def each_values tags.each do |tag| next if tag == Tag::Exif::MakerNote yield tag.name, tag.tagID.to_s, tag.format, tag.IFD, tag.to_s end end end end module ExifView class SelectedFile include Observable def initialize @fpath = nil end attr_reader :fpath def filename=(filename) @fpath = File.expand_path(filename) begin exif = ExifParser.new(@fpath) changed rescue changed(false) raise end notify_observers(@fpath, exif) end end DisplayImage = SelectedFile.new # # Error dialog # class ErrorDialog < ::Gtk::Dialog def initialize(msg) super() self.set_default_size(200, 100) self.set_title("ExifView: Error") button = Gtk::Button.new("dismiss") button.flags |= Gtk::Widget::CAN_DEFAULT button.signal_connect("clicked") do destroy end self.action_area.pack_start(button, 0) button.grab_default label = Gtk::Label.new(msg) vbox.pack_start(label) button.show label.show end end # # File selection # class FileSelectionWidget < ::Gtk::FileSelection def initialize super('File selection') history_pulldown self.signal_connect('destroy') { destroy } self.ok_button.signal_connect('clicked') { catch(:read_error) { begin DisplayImage.filename = self.filename rescue ErrorDialog.new($!.message).show throw :read_error end destroy } } self.cancel_button.signal_connect('clicked') { destroy } end end # # MenuItem: Open # class OpenMenuItemWidget < ::Gtk::MenuItem def initialize super('Open') @filesel = nil self.signal_connect('activate') { @filesel = FileSelectionWidget.new @filesel.show } end attr_reader :filesel end # # MenuItem: Quit # class QuitMenuItemWidget < ::Gtk::MenuItem def initialize super('Quit') self.signal_connect('activate') { Gtk.main_quit } end end # # Menu Bar # class MenuBarWidget < ::Gtk::MenuBar def initialize super() @item_open = OpenMenuItemWidget.new @item_quit = QuitMenuItemWidget.new menu = Gtk::Menu.new menu.append(@item_open) menu.append(@item_quit) filemenu = Gtk::MenuItem.new("File") filemenu.set_submenu(menu) self.append(filemenu) end end class ImageWindow < ::Gtk::ScrolledWindow def initialize super(nil, nil) DisplayImage.add_observer(self) @filename = nil @image = Gtk::Image.new @vbox = Gtk::VBox.new(false, 0) self.add_with_viewport(@vbox) self.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC) @vbox.pack_start(@image, false, false, 0) end attr_reader :filename def update(*args) @filename, = *args @image.set(filename) end end class ExifDataWindow < ::Gtk::ScrolledWindow def initialize super(nil, nil) DisplayImage.add_observer(self) @model, @treeview = setup_columns() end def setup_columns model = Gtk::ListStore.new(String, String, String, String, String) # tagname, tag_id, ifd_name, value, respectedly treeview = Gtk::TreeView.new(model) cols = []; i = 0 [["Name", 0], ["Number", 1], ["Format", 2], ["IFD", 3], ["Value", 4]].each do |e| treeview.insert_column( Gtk::TreeViewColumn.new(e[0], Gtk::CellRendererText.new, {:text => e[1]}), e[1] ) end treeview.selection.set_mode(Gtk::SELECTION_SINGLE) self.add_with_viewport(treeview) [model, treeview] end def update(*args) fpath, exif = *args @model.clear exif.each_values do |e| set_row(*e) end end private def set_row(tagname, tag_id, tag_format, ifd_name, value) iter = @model.append iter.set_value(0, tagname) iter.set_value(1, tag_id) iter.set_value(2, tag_format) iter.set_value(3, ifd_name) iter.set_value(4, value) end end class MainWindow < ::Gtk::Window def initialize(*args) super(*args) DisplayImage.add_observer(self) # Components lower: Exif data @exifdata = ExifDataWindow.new # Components middle: Image @image = ImageWindow.new # Components upper: Menu bar @menubar = MenuBarWidget.new # VBox creation @vbox = Gtk::VBox.new(false, 0) # signal connection for toplevel window self.signal_connect('destroy') { exit } self.signal_connect('delete_event') { exit } end def initialize_display set_appearance() self.show_all end def update(*args) filename, = *args self.set_title("ExifView: #{filename}") end private def set_appearance # self self.set_size_request(640,480) self.set_title("ExifView #{@image.filename}") self.add(@vbox) # menubar @vbox.pack_start(@menubar, false, false, 0) # image display @vbox.pack_start(@image, true, true, 0) # exif data display @vbox.pack_start(@exifdata, true, true, 0) end end end if $0 == __FILE__ Gtk.init # # Main # filename = ARGV.shift window = ExifView::MainWindow.new(Gtk::Window::TOPLEVEL) ExifView::DisplayImage.filename = filename if filename window.initialize_display Gtk.main end tdiary-contrib-3.2.2/lib/wgs2tky.rb000066400000000000000000000032401213632744000171560ustar00rootroot00000000000000# # wgs2tky.rb # -- GPS data converter # # kp # Destributed under the GPL class Wgs2Tky Pi = Math::PI Rd = Pi/180 # WGS84 A = 6378137.0 # 赤道半径 F = 1/298.257223563 # 扁平率 E2 = F*2 - F*F # 第一離心率 # Tokyo A_ = 6378137.0 - 739.845 # 6377397.155 F_ = 1/298.257223563 - 0.000010037483 # 1 / 299.152813 E2_ = F_*2 - F_*F_ Dx = +128 Dy = -481 Dz = -664 def Wgs2Tky.conv!(lat,lon,h = 0) b = lat[0].to_f + lat[1].to_f/60 + lat[2].to_f/3600 l = lon[0].to_f + lon[1].to_f/60 + lon[2].to_f/3600 (x,y,z) = Wgs2Tky._llh2xyz(b,l,h,A,E2) x+=Dx y+=Dy z+=Dz (b,l,h) = Wgs2Tky._xyz2llh(x,y,z,A_,E2_) lat[0..2]=Wgs2Tky._deg2gdms(b) lon[0..2]=Wgs2Tky._deg2gdms(l) end private include Math extend Math def Wgs2Tky._llh2xyz(b,l,h,a,e2) b *= Rd l *= Rd sb = sin(b) cb = cos(b) rn = a / Math.sqrt(1-e2*sb*sb) x = (rn+h)*cb*cos(l) y = (rn+h)*cb*sin(l) z = (rn*(1-e2)+h) * sb return x,y,z end def Wgs2Tky._xyz2llh(x,y,z,a,e2) bda = sqrt(1-e2) po = sqrt(x*x+y*y) t = atan2(z,po*bda) st = sin(t) ct = cos(t) b = atan2(z+e2*a/bda*st*st*st,po-e2*a*ct*ct*ct) l = atan2(y,x) sb = sin(b) rn = a / sqrt(1-e2*sb*sb) h = po / cos(b) - rn return b/Rd,l/Rd,h end def Wgs2Tky._deg2gdms(deg) sf = deg*3600 s = sf.to_i%60 m = (sf/60).to_i%60 d = (sf/3600).to_i s += sf - sf.to_i return d,m,s end end tdiary-contrib-3.2.2/misc/000077500000000000000000000000001213632744000154055ustar00rootroot00000000000000tdiary-contrib-3.2.2/misc/section_footer2/000077500000000000000000000000001213632744000205115ustar00rootroot00000000000000tdiary-contrib-3.2.2/misc/section_footer2/buzzurl.yaml000066400000000000000000000003251213632744000231120ustar00rootroot00000000000000url: http://buzzurl.jp/entry/ src: http://buzzurl.jp/static/image/api/icon/add_icon_mini_10.gif title: ja: このエントリを含む Buzzurl =: this entry on Buzzurl counter: http://buzzurl.jp/api/counter/ tdiary-contrib-3.2.2/misc/section_footer2/fc2.yaml000066400000000000000000000003511213632744000220460ustar00rootroot00000000000000url: http://bookmark.fc2.com/search/detail?url= src: http://bookmark.fc2.com/img/add-16.gif title: ja: このエントリを含む FC2ブックマーク =: this entry on FC2 Bookmark counter: http://bookmark.fc2.com/image/users/ tdiary-contrib-3.2.2/misc/section_footer2/ldc.yaml000066400000000000000000000003611213632744000221370ustar00rootroot00000000000000url: http://clip.livedoor.com/page/ src: http://parts.blog.livedoor.jp/img/cmn/clip_16_16_w.gif title: ja: このエントリを含む livedoor クリップ =: this entry on livedoor clip counter: http://image.clip.livedoor.com/counter/ tdiary-contrib-3.2.2/misc/section_footer2/retweet.yaml000066400000000000000000000003521213632744000230540ustar00rootroot00000000000000url: 'http://twitter.com/home?status=RT @your-twitter-account: %s ' src: http://kayakaya.net/parts/tdiary/retweet.gif title: ja: このエントリをRetweetする =: Retweet for this entry counter: usesubtitle: !ruby/regexp /%s/ tdiary-contrib-3.2.2/misc/section_footer2/twitter.yaml000066400000000000000000000003301213632744000230730ustar00rootroot00000000000000url: 'http://twitter.com/home?status=Reading: %s ' src: http://twitter-badges.s3.amazonaws.com/t_mini-a.png title: ja: このエントリをTweetする =: Tweet this entry counter: usesubtitle: !ruby/regexp /%s/ tdiary-contrib-3.2.2/misc/section_footer2/yahoo.yaml000066400000000000000000000003741213632744000225200ustar00rootroot00000000000000url: http://bookmarks.yahoo.co.jp/url?url= src: http://i.yimg.jp/images/sicons/ybm16.gif title: ja: このエントリを含む Yahoo!ブックマーク =: this entry on Yahoo! JAPAN Bookmarks counter: http://num.bookmarks.yahoo.co.jp/image/small/ tdiary-contrib-3.2.2/misc/tdiarygraph/000077500000000000000000000000001213632744000177235ustar00rootroot00000000000000tdiary-contrib-3.2.2/misc/tdiarygraph/tdiarygraph120x90e.swf000066400000000000000000000061431213632744000237170ustar00rootroot00000000000000CWSxW_l[?^ڱݴM0CKI\4C& i I9퐖oͤml0)  I 1ش`y`N)xi|^;L&-VΟ9= [  pD\[[;?Q!nM'"Za,_]>a@xApUĜe{_-uHIJH>6"{]]O>pյ}ݟk<<Þ)ϫ?x$Nn'G*{n/ʚz}|Ǿj$D}.x> }%Ym %kBEpOz& #h̅^,{>›Yj 7\ C dflC]Z jC5pqZFkZCHĐxV~%qOBT[mX x>dqz+F&600bsgBMC}'kK}̈́;+V9F?Ƀj4UAd8WC,|%Ov ]]U p{Q2x lf qN{ci=-*QSņE ݘ^mR^dQj&Tt8=`WeŮsS;30-.xH\Z/0aW0b_\~0f-?ca͔8>d4b],=HFd,. h頻hXը0">fKc8'bp*.6!>/W N RY}Mz0I#e7n|w)jh9Da/f msOh|SYB)"vpl~{0VltiISЄAa‘8>24B,=»Qzp '3t/h!# ;n,&7o DDlr #5b JFs mUA6T|U0h^IMxg2,FL;x 5}_J̦9j-Yҳ :Y ƌsnJXgۀul΂ ,Þp Q nh\b۷`V2?&ب c̯Wt䗱j_=#x)z19m4G6pCH /2M+BywJL(nc.S2kלC%K8 xr؀%$Xn ~5,Ŏt]^w q/Ԅpc8*=B N7%ԝ_G8j gfY_<'tz$9?X4m!ϭ+~җ+/GϳE#pZ Yw~/:iL!u8ZCȈ 1ñ[ *{1;TR,`Cb%;` j ݗ {\ 7.`74hp a~hp+A :0D n#ЍrAq;N  0p]pU` bu| 頯~#w[\HLZKW5fY/Ux{XűNkX9. UP±ln&^l:T %OsL|I=DI:9^'IBCr&8ʤ r0=f4W(" .-E0[p:OuzQl]|gWEqp1尴I<T#TRiNc2\.;ԘGxv6SHnMM` 0cŤrǻ w =5;2zLj\Lʉ-֦NeB|-q XfvT.M%z4Gg…S#f#up<&9ɩTX*ܟͲ8's$7RA&3SXGk}5e||!LA ͱ 5r2ˣ ;硐-q$oC AKhtp= #k!9N8Me1Wx#gxgu]@&FEXpNm`-R܍?b=_<ԿMs@VxMl3%2pylUͯTlh_nܯH,W ٦r&yyy˪elsld'5<\K.b.*֙B݂[6|l;:-63\4r9I㶊"i&x:MuǦ|feW 'V5gEha6-yBcB.1%Qqm j9Ɍi f @9Ȟ(]ѵ] !P*.ZQw:+52&7Lq~W056CE,e/:(>[/Nt=_Nе еX=o7- Vī!N>d́IC"p#ǏT?ZlCɊ *{7Ub[˱nx=F4} 1(4)tdiary-contrib-3.2.2/misc/tdiarygraph/tdiarygraph125x125e.swf000066400000000000000000000061431213632744000240030ustar00rootroot00000000000000CWSxW_l[?^ڱݔ&MJnm .MSԡI4 IZZv$vHpf6`Q6$lei< M}Hxi|^;L&-VΟ9= [u/qmm@DŽ`%ޟh|}x ~ 5€G9+/EKj~)]6"\\O>tյ}Eݟk<<Þik?x$Nn'G({.AY/ʚz}}-Ǿj$D}.6{JQͬ5'E= ޕLvF4 o=Jy-},.ޥ2Zp!.-|g8M5M!$[bHr<+\ո'S!6,VW4X<\d+<I>PY9"BQaD5}%͖pVxGd4\lC|Aү ])gU 7`Gnh!$ SPcy-,ѸsX~^Tğ zkO˹R6E H/ل3'aƭ^/Ӹ' `Ä#)qj}diX{bm A4OI5g_fBԵ F.<wXL)nJ?<܉L@5G0j娃9?B$;X)5m,`* [mdB ='YCvZdk2,ο$Ms՚1KT;g td$]ԕ:3kX=N'$xofŶokƼDse~L:QǘЯDQu34e/c[`{Fr6s@h.-UlPd_d WULQ7]%$nMs1,n4,bnXc1y~ʳ;A4wi݉O4NPḋb6惪߲(8Nl 8 WPw~ʆ1De}y`}5'n ~v\Y;d-\y%z-_YJjOϺ{yFO9e: _w@Fd'mb 'W)ߏ١dj+k6ϧHpVkl{`}؇zvM`7f 7-}p+8A+D pڡC:8]-(@/>8 ]0 #0 'p 4_{> _o7[.7h?|*u\K?u4ˤŻ~ZcO>)x{^Ew^O%_kj K}PIM+fϦ9M%\2da 9g ّԃIx"$4$gɉL!Lx   cFm\qE]p"*:h Rق{\A ' TǫA|u+f||n_w#̌^K{PN!_j0RO%a.5Q=&!sNiqgg3df\8VL*?ustpPޣ##MdR gRNLo6t*zkxWX23Ȧ'rqmz,18 gH%Sdh~J$Rt3@r4g8H<=l:Fd&HCeBɢ]kI FYbkוV>-BZ03_i[fzP;zҺB %v*:َRn,X-AJ|;;ӝrdw({Yk4N¦/pjv'dr3 ̢{=|ʝl褆 l[FQ췴gd5]KtIlR8:_:A[rwJ"mv]Of \rF S3v[ i^QC$ ޤ}=wSG՜Oܬld֪,(b-צ%O6Lrܱ1&$2*Nt'icͤҙթKl/ˀ[X P/:U^I6|ۡas v@_fѲxGm`Ѳ@z%q1sW'v(]{۹B) )KEz7ЊIv {ehmij !CY= Qma1XP<Èş V q q- [Isd6tXݱ`t$JޭU#̜ު "A?zf,O+Y|UjZmݡ0 (cpf7G8z/1˞;!;S]_*0r1<,.!YlXaݰ̠ߍՆ.=5@fGI{vU<'13Ӓq>-yʕkr cvz C~/5̅G/cڪ:FV[Ls)CNoKs/%e-DzL_5"`p`D'@{_edsEvcVˆkK-𶞋h_587HAf R2n5I$1BI6Z&Y #q"F%͉?֢1sMd l&^ gH Ì[:ﳽ^ q'=OBj GR *h Fi00ן jZ!Jk\,x|︱ Rܔ~)x,Ɂk8`Ԉ1 ΋+Qs~ͅ+HVSkXPU Uz%79 Ȅ"{Nx 2 JeXQ*3Hv5cfvH,d&Hp+35+aulfԍ: 6 {5D56OI"sn[m֌y[Vt`.T1_k8fi&K_ƶ2r~8)l瀶\Z"2 "'Ⱦ4N鯨 ߙ*13 o4OH_b,YihXē,&rcg)v۾`A,ORC%6Ը+VylO}ɰplp#섛 vnͰn[ V-pnV@C(tp[Q^8}p'qA`F`NNi }p?A ߀o·$5]o">?~?.U`"~0iIwi, =|R:0||oK8րi[#K> 0JI4ɬ6ρHN2GS4fh9$q<0y {Bt255Ljy;c9f3x\K͒/0'g'<-@6/Iy`ky-,e)kq 2:^㬬9,͐M Tf RlǨq\Mt?l!{Mƿg'ys<PGGCa:L6C8\፜᝹["awtIg5Mi` ?P:uODk)nQlc k d)ɸ{Wel~JfCdr~%@`Rf66\V].ee剢keȓ\\֫)رԖjml+*uy5(|nED֮+^}J`g5^vuJT;T(uȳ,X[ mG7|#LuvwP);q]&e?fQ<(hfM_&O1^fEzбbA;TI +:<ٶnGoiYK-Ol j蒤puuP6E9FK D @\gAҸHIz="h;年rS-9YU-lɬUYwQ4ZMKmP0ccLxIdT0O@_#I3S]^P B^RgCu~mC L;jebeсKb^;yhcW$="'5xsIj#OwY¢El2cn0¬nǡdjs|*NvQеs!RJS%V+n@yظAgF4*^h`?MhQ6$z~E>{<#էܩtũ8]{]{z߳6`E*RC>m! 7rHE|ъOTl?Y߻!r|Vu)6@SD4H?$)tdiary-contrib-3.2.2/misc/tdiarygraph/tdiarygraph468x60e.swf000066400000000000000000000061421213632744000237320ustar00rootroot00000000000000CWSxW[p>+iW8ĉABp`9ĎL|qlc;!%ٲT6za5LV[ax PhKR@[0MJNgj\ss~i\O\r B0ܜHEX]=a@xQpYŜ }/ڤg_JI\׽yS]uwt?~gAϰ'yI[I7-^Sy@yVrE {{>}{w f_c_5T>V<IQͬ5<'E= ޕLvF4oVbqzKF&2T'0bsgBEC܇Ox[זU-92 w :WžXcFz.$JޣU#̜ޢ "A?zf,O+Y| [XK {Bay/Q0V̬!nip, ^c=wBwX52`b~Y%yJYCXúaAQӫ _zkԁ,J1g,7Uy^b zg%\Z +C^U0j~,k Տ^lVu062BЇ,ޚ^ CִS1}͈L%!!Ͳ+F]]li gw\ NF&0$A 2˸rQpKO&M"ΰ952Qr;1E0Z,AmN7>%)b`Gy&!=' 3nuzA7Ɲ< &IScHs Ģ #k' \HiC2+]4r b2HqS|cr'2Xa4pc@0 V`JkAF7Joq; E46f1Re!˰8Tg6͑6Vk,R퐞4XɲM6fkvRW:̨gïul`kjlp;5F=Eݮ۾ ͭ1F]c~CEq̠WMFmeւqSؼmLTe< BE:N}i2(_UKƿ3UbfzGq#dwir,{0V9XӺQ' XYbS+Rx@u'~?;B7.XR|+n8-4$xS_[F݅uT+qf"N<L֜-duseZ=s<[$8(u󼍞rtRZӭ5((O>۾`A,ORC%6Ը+VlϬ}ٰup=쀝pv Mn! 8pn@+0A;(tp:[n7@/>8 0 #0 'p4 _{^ ߀o·]o">?~?.U`"~0iIwi, =|R0x7|ˀ8o,epD*(LhrН 0MgsJ@d@r΁#(I' D:IhH$L!Lx  cFmXqE]t"*:h Rق{\A ' TǫA|m+f||n_w#̌^HŸPN!_j0RO%a.5Q=&!sNiqgg3d&\8VL*?yctpPޑ]&2es3)'xZC:I =DB!>>MZ3ol|b0q~2d3񂙴<[kid)KY^c֑-ZgeaY'>_ml"_ȥ2SfsFLhy(d qk2u0-8+<ɛСCgC]w|-$g48\g 6a o vK:h"Hnҩ~"BXKwÏX.bc(.^S$LL}=\C*@`+U2Z$+˕43H\I^YYrY|.\.,Om^U.J--^MƎekl͖mbRY"ym!ha5A5"թOY\j#^]GZSȻNCV^Pn.Z^dhpKTdU|fk"*janj/7ڢ󉛕M^̭9. i!ww1w /uk`3tfu2BgP⁗P*j0ù; E᯲`Ye6`Yt Wad{b2 #eo h $?\R~#rPݖ~#̮͘0qh6#칳]Mv,PJCtʺjEh""=T0}]̟ mj: f tXa7xg~ؾ;N8ӵkk/~B{ynZWֳCʝ|݇3D?Z߽!DE|φ*W1X^7b#>uژNMC_=)tdiary-contrib-3.2.2/misc/tdiarygraph/tdiarygraph728x90e.swf000066400000000000000000000061431213632744000237350ustar00rootroot00000000000000CWSxW]p>+iW8ĉ$(r/Ʊ턄d˶RYH2v~w@3NB;L'NaS{jw%i3sw~99WY pTz ? ps"| 1 ctw"j+sė_~i&/=$=#RP䊸sͻt}kQ ??wxz=ySW=Hr*Oʏ˿&oQ*ʃ3_JYK޿{o5:Pz7hf% e=)Xd(d31=T oFf%\1-jD Avi3|ˈ34ZB%$dzQ{2ZR`!#\628Ý?b->@}[*o'͑LHKйr`5ybDh<(yQT`0s»z* j*#yͲ+F]]li g\ NF&0%A 2˸rQpIO&M"ΰ952Qr;10Z,AmN7>%)b`Gy&!=' 3nuzQ7Ɲ< &IS#Hs Ģ +ko  \HiC2+]4r b2HqS|cr'2Xa4pc@0 VocJ⫂AFJor; E4f1Rek!˰8Tg6͑6Vk,R퐞4XɲM6fkvRW:̨gïul`kjlp;5FEݮ۾ ͭ1F]c~]Ep̠ؗMFmeւqKSؼmLTe< BE:N}i2(_Qƿ3UbfzGq#dwir,{0V9XӺQ' XYbS+Rx@ܥu'~?;B7.XR|+n8-4$xC_[F݅uT+qfs"N<L֜-duseZ=s<[$8(u󼍞rtRZӭ5((O>۾`A,ORC% 6Ը+VlO}ɰp쀝p#삛v Mn[ V8pn@+0A;(tp:[n7@/>8 ]0 #0 'p 4_{> _o7[]Z.7h?|*u\K?u4ˤŻ~ZcO>)x{^Ew\_e_W骷F28"} A&a49_fϦ9M%\2da 9g ّԃIx"$4$gɉlT&U1E6,.@I4_epl=\n.y ˠUZg3>b >f/Gfh/G}{fOi(L/d5)ħ0(LLvr9Hgƴ8JƳB2w3.lj[Y+&<1|gcw_wH.ԲS[18x?ixLL||i4,1df x氬\6A~6/R)H9v]Nry4}q~<85uPB!h v;C`3.zh3T0s7rwo\%ho4^E7@5?!\GGWVi1ȊB)`mD&.!\m * -ˍ JA$T.$pYuZ>pm.m'6)]#ONNrٖr[\VcDz\f6b)۬r\^WRGvY |0ZA KlrԧDH fx&qP+mm>Y\j#^]OZ7PȻNCV^Pn.Z^dipKTdU|nk"+janj/7ڢ󉛕M^̭9. i!ww1w /uk`3tfu2BgP⁗P*j0ù; E/`Ye6`Yt Wad{b2 #eo h $?\R~#rPݖ~#̮͘0qh6#칳]Mv,PJCtʺjEh""=T0}]̟ mZ: f tXa7xg~ؾ;N8ӵkk/~B{ynZWֳC]|݇3D?Z߽!DE|φ.W1mX^7b#>uژNMC_)Vtdiary-contrib-3.2.2/misc/tdiarytimes/000077500000000000000000000000001213632744000177435ustar00rootroot00000000000000tdiary-contrib-3.2.2/misc/tdiarytimes/tdiarytimes125x125r.swf000066400000000000000000000061041213632744000240550ustar00rootroot00000000000000CWS-xWmp޻t'YRI VH0J``'q1 Xrbd"8ӁB3naL03RhNtL'?Li?f{ҝOqH ?Mwwgw_qJY!)oh2lE#K _S_^#/˿?uJrr;2s#Ͽ=k{y_/ooW={.QՃ ZvmF?Y% $HhP6ѕ#708TyM{e#l wl_}7)3?o<z f5D8D gaQw(gaԦGYH$ɆG'dmHӍ)i'4֞qkQF%%[u=6ɨ&Ǥ[%ClMAs)\6>Al|3c{FP2i']q>Y ,CSh 4[la<sri>#[uxHVye$+" L ė2!%;1qz Y;^XG dkHZp8}`ger`uR0Grr':α2 h"fݎD$0rj~@T` E2sB@$r?G=;UJ=j=x׋$ʡM=q(m I~q2@ΏXh jvA:a**Nz87tw@>֦Ǥ1m Q*_Tf9QVbF9wn,hdHx1);;*F;)boAΆÊx=Cs@0 QAUFkWbܦi b Ʃnz M~Qgi XVfq:Sz؇0`K U‘ <_nqkf>㕨yҼۏĤzST<`iFug`I q'9D .dؘbm*Q 4(;hŚ ]1*%ۉa%v7I;^5Ws7{3T]pP[M3' ~LM˘8LDƋ#y8M'pBjs&92C58V@1EöWDqIU(0E)Z'b}Zm Zm/hx>WUp5\`9\ Mp4 X `5\qXkazZ F7A ! x ۠ :] n^~؃m6vw]0I&| P 0f o2?$-S":R?{HwRKHbEp>2N0FI8f@k\ lT?sPI@!W(BqhrT:22SL Jrwf!K˦WN e@ \9^(o+tH }{3,9PN 2̤d2<og4)QhDw[*hO6?5o%>US>i~ t*}11]W{B^5oW īshAx7 SgN qcX$DȁFyys\!_HG04(lxɔV#Fi,ƃtfJ5/X}MۺsS_W_[b{rdKYJԁ EZ"0YR9}8Z gCe^P%(fC O9eD/U'ٜ<{5fs9)ܓ/ᱯ|]uBȴ<Ӽ% (l뢄MN/tv0OQ]7JgJRzkʚm%r9u`='sJv{oXb%lsӕdF`O$^sX=L~}ʔ)%]Q4]h9S+]"P \ lQQP=>Aúm4[AP-ky~7ϯ[NnA wܼ0}ܼy*5WEl< {zy T[-TϞ=+xn^}En"5]ѹ[yKh ^Ђj2+H"hҎ%G/aV]u7F2 Ѿ撉+&/WwDܞX5_#tAيȌ"~[kpf z ROі21F2eCG?ҟhX$Wy"VrgpMM_tP>2س2l3 UAE~/w9d-D|5k+1t槓g:ᾃsYVu.WU%>8V0 0ު\>J/k&Yc9Ze-8iQ3tA"nhqdv\U w}aCX䶯mb`W[*"4^1SkD3.Ҙ&v[~69'0]`7n~~޼u̾a,@ymMl^gWF nFKCz7X,k/vpjN\VM5 ъŕdCBZ`};Z!amWm}ks8^Ӥg`-s;miu}&[+Ip]qG9F2_v\X^Y.FM 1._J{`T$6*Fek]܇۬ʍjEytdiary-contrib-3.2.2/misc/tdiarytimes/tdiarytimes125x125r7.swf000066400000000000000000000062551213632744000241530ustar00rootroot00000000000000CWSxXlwgΎi2h \$MK)-b&FiL&~bRa1!LMct?)&;Bw{}{>o:+fq+qqq;n oK2%)-n S;GWV~+9"O;>q˱Ź%ߜt6b뮿$y._/[^lP甿+Jy/<O1Q7NKiΨKxKfP5#qpl"2@Q7;\* okzv-t#05sm !`z, 5"t6&I$dh'yn/4]ɏ>pR&چf`Fn\hˣ'( 𞖟 *g#M3ِp;yhI4a?ȝ[O:3-| J^Ե-N':+gԩD[ -0ìa<7r)>&G-Q͓l4sr|)Rrc46BL+j懚]HFZ€!|3+sͬ C Z'~$#φ3,V-(@cGF0A/Zy@ia8؊jl 8D :&=Ȣ؞qTp8KtI$>1*;1C QaXxzCVHh\9Av;oG i ӮCxHMLACŪ0FDa>z>z[0Չ2;Od EtH3OY^ÐJxL4ݪ ϽЌNP0JZ [‡|%àtd9m$WCjꅄ<81$R>v?؉LS@ְA\O Q r~-|1W] ۘPuAgJ7s~KWpg dC<{Zxin !nK`e64rle̙"|g7Jюe@J~!FۺI ,#רv\1n‚͎juFMT7m&4{e,+^}Ks #@x! /2 ׂ ϓt83MvVǩp҂M%Y\5XXͲby~H!,@pf3bjF2lwQƌ?(s ,NL -ޙٚc\bxAz?nZ8XC5}ekiZڜٴ}a"2X (NW>\fÐf+MyöDqrTc*87E)'bs}^i Zihx>kJ ufZ`lM0la+6 p#lnNB;o`[ 18`~ w]p7B߅ڢ& Z5?A~))bb;m[VhY"}R;O??qLn`/E5,?/p54AKdr\ cQtvJL$Ҁ:m%LS Rr\Dar*SJgYsdSp>eXFurLM沥"gjz9>Y>%xS"ۤ u,}1wLXeU_+rYN]߱u-zJNH_{<0r)ݧ8EC67=JTG&7>ObJtpTSVdJ%"K(-x==áP|PϦX7]LSr&l;[E #U2HX`Vjz|Ė$86^~qB i:8jbƧLKGM;2)j\lo:ܽj<tCETdے=b:SV/ l FJ)Fy#YTa*$*4#m<&K 9GFILpWzc 7tC| t #"M~|M,&?I/P"2Re`aNH`9f8s\- Eh_})=TI-}p(Np 28K; G(v[޺u+y=Jcx훼0 vܷ[&Sf[FS 1rz;^Vʼv ٳ`5Xi答SeUr[m策1^Fި/c=Հ1jⴠ3"#H<2ʚG/3aVYpȵ7,2Ѿe 1k*&`ӯ0 =1jӛcwyݦVoi:DVj Ka(٘@#2 eCG\6n{Iu6Xsz=&v3\W5I}6p9ɾ?uD6/_JJCg~6w8EcUgsqco(yőل!]ȅ;H2,c-WC"+[8gVMAiS"Jr]II#Zӕ(<),G2EfSǢ&G.)U!b6 玵cL3紿B9P6Hxvp(zQ@~9I OV7Hje5NqY({ķwoV-\t8Þ칳V_NQ^vnf֘!pҚsgSAzD5͉LdO{sdT`>Zv/t˄z|_}zGZr%ܽ7oq;M9}0v:.63c]fI,"B B4ȯ?r}ɦj.n+VbŠr1/l2wZ/K%Wn}IXq`3װɪ+k GZǛtdiary-contrib-3.2.2/misc/tdiarytimes/tdiarytimes125x125s.swf000066400000000000000000000057261213632744000240670ustar00rootroot00000000000000CWSkxWml[>^&u@\0ҀġI)-lvWIIl*E) 6bi&4G ď2Me5hҤ{9xיs`;` w%jR^x~/! /  NqX,*FPHJ{gJ ^ی)ǶvdK{q#8vCȝFeң<<|*ag;8pe]?spq^j9Xa%u}\T =G6nyӻBoZa1n9} ň-Hp,_&B&[)`$"KxJz6V J˂wqwgB*220⯄TvݦS.T0yׂKfn !NA国Жje6X0L 𣏕RPA˰σZXि2aӜCKEh )!x-騡]QcQNs+́-N9pb<,@\nPuȎ[N3Yִ: 5$>rѕv+/HppaׂͲ)L<)"r\X=aDӏV1pX qN\Ȣ?ynuZzؙw|.=hIp$<#P(Hd}HrCcVbˆzMZI]ñph⋒zN^"le Hk:Q-brho)3LcYB-M Op,cNǘ0~B\FӪfvnah$w8֧"!w~3!_8( -YO:䑩5;Z9{vl&ԊRgZ}ȝw&Z q^X9]FbZ;E0| _4-~uwA!-a;b,}!+\aĎ} p֛K#@X0nd /: Gׂ ;go2UR: ,3Λl_S ,%U(!aI.Fq}W 6-0@|?hnP+&ḋ!sTג8N 8 RWq\,1 3LѹxANp}~йiÉe!O6̕ih2ϕWc3$d|1]N+1! 12duGC>!$ C4>pl|5N\0e6<,CQ '%Y-]s(:@Z,A8̤YG8,PjDr a*Aޏ3$ 8}@wh@Ȯp]#\}#DDzl[Ԥjz*/Ma,]NN2 &*[Dcti2ll,m3ե\vU_Opb98a-t/6Z3pd#lrz^6wAc56~k&ACWqTnڷmm Ozc3 ؀Kyȁuzf֔Vr1* ,veQ5ƲN-:N6_]dԦd |^/`.lAfIM:ND]h~_B\ݹi5r';VcHI4cwZo%VnP(ʍMJOƶ^O;lmWpFUw΋W\Gq-ڏ|hm}G)uӳ=c͞wS7U+x"\=2ϊ䷋W#L9zp_zL脋[K+W[W&hM7)N:Lwog5ʃq#w8xڌd}QyjX871jNэLQY3 8(&@n&;|oa-~)1_NI}/Ynʮv׿ȠƅetSB=4pq$tdiary-contrib-3.2.2/misc/tdiarytimes/tdiarytimes125x30.swf000066400000000000000000000054441213632744000236140ustar00rootroot00000000000000CWS[xW}luS ᫘4CSlӖ4mӒ!Ibvc#׾1`Q6d I 1شci@`)Re=}sV=>:X5 B@PҶ xD|xRk:#D!e/9/UkoďĠtUWzPz^“AOw *|`> M3..C НCpLn㳴d*h4uWWwV϶asDD8â7a?rٝv9?fG'4x4y'D :/M"[J cy1̦T zp穰^ˆjpJǞʋ0`trP̓%y=|>β^!H#)LL;e 5Qn"a3}es*@H)!Tw^zX4hp$<Ӡ}X2ܘ蓽8Ŵ0*VHSs8!gT3p0oS|I2ΙޗhA.QƦ)=$rM DC^ic ͨ.UGDc尐* f_ Fጷe&DPK,b NrΔ CΛ't6`G=eNNx&AÆ#(>3tQ#Ԙ|5àpLyd3 뮠LѺة3aI(c&>IB9Ѐ2D8v 'jWhj9`xLMx˸wuwA+a»dv/GTv XfHj&6G,ޘ>U; ]=r2"Ѝ34vc6J5=҉mc{g["1safŋ" ^Գ-sMBhMZN^y-=CBGװi17w޷C{]켮oIDəi;0n Y2vl"5F0*I nm]]eWp \ zbpt& FMp+$ ) 6 6Hvv@?a^a ~`Fa   a G!߁ƒ!/h?|S 9J{ȊtiR)#Õ/WS_19-P`% g6ЏX~FUpRT:9: |jy}(?NyԔGD)Ϭ!|"U)5(:<U a>+P9%Q֫ @ޑaf>~C&t?'6Gֵ;J\_Xl֗F0]FGY-ۤ'ء;]5 ʕ\VC?=Jq-@Փzxv aC$do߳}؞};Go5}t`tNnpVͳmlѐ$U0Os dAgK2l|qcq 8G#z~qM?r1Tl{tjkbsBJdX* ~eay$E}c[zAVI4Ɗ٘ZV׳G ,s(6r}4jeÙes'A>֘*ehZcMmiÞA rd^JR<'ͺf}@e b_+Zě ܺv2dv Aqذdr\B\3 qVF\~ݐ ;ˠ%\~!X]sf%FiV.\͕/%c _4 s*(1;n{!:^`Pfrݨ1q3)Î c&ęG_M.yҋ8Qg׏¸2Ľ7-r햣x (Z:`$Zq4^S6-q)n|@.)MHc)J<MB$ir;=Sy{nf-)ݎVvEH`]M!.ZwQP>$7'2;Fl:z_L&-- fyrO dH~=BY.L_r[̹Ny vnR׽HlE:gT睜 V c -*v3^;| Kg8?0+tdiary-contrib-3.2.2/misc/tdiarytimes/tdiarytimes234x30.swf000066400000000000000000000054431213632744000236140ustar00rootroot00000000000000CWS[xW}luS 櫘4CSlӖ4mӒ!Ibv#׾1`Q6d I 1شci@`)Re=}sV=>:h7!(qiii[@@Gpwyʒou@!@"qјNݾOތOxXȔ h{DM ޗäO4oNj;ƂY'B3sSOFЂ'Ȃe :]@1ڙmijY,Y)ٌ#Y2b|h)Κlrs _ ٤v»VWL>0rLK0te3Sc<),0i# Z&A|5r'yճm\6Q{+tX61S.V.(٦?hW!ј"s`@IDxK)>!9Æt/W<kaZ5N@cSwSyQN&%dI^Wv!Rf1z S(qB b[z~ j/q0 E2%nuJzu1]3$4q8OLi>V nL^bF {93Y8I4)$LK\r(cSBߔlp"ѐWgژh3K'X9,d a/l*";񗂑l8m>%xSq>36Ð QOӹ!IJdLE16|D f>ld 4-NY͆@}/LE3Nj2t !%C䋳r~B pVYkm`2m[ví ʱuO bSQ5cM̿"-a}ԺKSlv^F,n$}TBw<ԋ{ (s@0 i :FqطLuǂQ]s~8Mo"`bxPceV‡HFjy@/T G6!ȮD_j9 ;gͯ*YX&7ٻO3./9I%6y(!"Xdrzc>kWZX`LLˍ?`@7^, pgHwlXj8{C72bζ@EEdg-[A禋'?+AiuZf /abo_=o32 y]ߒ3l:X (3v`>@ɳeTنDj<`6hU@E$WM<>Wp \ zpt&FMp+$!i 6 6vv@^` ~`F`  a G ߁ƒ!/h?|S 9J{ȊtiR)#Õ/WS_q9-P`% g6ЏhaFUpRT:1: sBj}0M镑Ԕ Gxp|U)5(:<U a>+P̺9%Q֫ @af>~C&t?'6Gֵ;J\_Xl֗A0]FGX-ۤ'ء;]OkP++c^>z*cZN=_UOM(bq,/5gS~oã{q;Zzz,wECZs\W6\uldh5Y(NLlI/n5NTsQ^y\O_,(5ZŚ\eb0Q,*Jprab0rFXX:IQie_(ٖЪc30vv6I9>R2Ur~UkL24G6ٌa Xy2i%wP@}f]2pX 5XH`x2D[.8F8i9 G2RfEb;h:3y@ C\ZZ<D <"㉍c)M~?W#Vŧ߈Azit[Si'3y矞A#ޗ~6}5߳7|IZ9-_ K^lP畿+KJzEc:v>~hx3>mc!S^L&1r65z_^ќNt:B  fLt M=A  .XwhgIQfI"d_g3dmhߧGO8kɡY8h$І%d}v Z]U0|@fn1NC Е҃pL.㳌d*h4uWWwV϶asdD텮XaXǰON[]Cԓjd]ɆHGćn&-c< f ^mTGeCk5Zp8}`OmOE R0:9̓%y=|>β^!HŴ#)Ll ;e 5Qn#!3Les*@H)Atw^zX4Sh1+{qBaD04>쑦pBxϨf`&8d39/тr]pM }SzIaZ DC^ic ͨ.U@Dc尐* f_ Fጷe&DPK,b NΔ CΛ't6`G=eNNx8&AÆ#(>3(lzTaP8 &8L2ie;ib4`tf /fI - 0Y-g qɜ on6(R=-]LukwrDke61fbscQ.M!<{` rwS -S/r J6t6$ jDO$|\ƱOwc2EW Du-\74AYAY] "CxxRTgP%p#N}IP8d*|5db!td>U X0$1jp0;梄`Ò{]5jc23-7!x8&!eaUAXNlou;59C 3St.^]𢞵n.:X"D emrk28]N!|-r2du}K>ΰM` $ BL|HہpA'rSeCP4٠U6MJppkt_5/\ Wp \ :n&H@ 6-V [`+ v}+w~{}0aaQ84m8.,|߇HKE\~]dO(!+ӥm|KҦ< WW |_O~q.xG:_K @-mҗ(@?}WzYAMhPLszQLi9}|1W=j7y\0FB֜FOѾ=ۇٷs]GGFkE iMMp1_Jdsձbd81%O418Qic8G#zaqM?r_Tl{tjkbsBJDX*} ˆ~aay$E}g[z@VI4Ɗ٘ZNsG'YPlhHT93 }0W1T8 ƚۄf37=`ɼܥByOQužbyJ/`"\@mOḧt,>KA5y7fv X)L t~/oܸ)MAvR.օla.l[֭.bVPHILҽwݭkn[JpEݺ]jng>#ᤵVv 3e\vETD2"udWUF}V3`7Y~kڹl5\C1a\鲹z⚭A{6w&AK2*CJ~q\R+/^TKVQA&hTPv]rBN2Ac&~SANMbI02͛]0? ϮwqW-e{ 6o웙a %Gy!fA^Q"t1,Iz9?h2"lZ(S%\k7rS񛠑$`{ oS|.L?HvzV̞[S˹항 # You can redistribute it and/or modify it under GPL2. require 'uri' def bookmark_init @conf['add.bookmark.delicious'] ||= '' @conf['add.bookmark.hatena'] ||= '' @conf['add.bookmark.livedoor'] ||= '' @conf['add.bookmark.buzzurl'] ||= '' end add_subtitle_proc do |date, index, subtitle| bookmark_init if @conf.mobile_agent? then caption = %Q|#{subtitle}| else caption = %Q|#{subtitle} | section_url = @conf.base_url + anchor(date.strftime('%Y%m%d')) + '#p' + ('%02d' % index) if @conf['add.bookmark.delicious'] == 't' then escaped_url = URI.escape(section_url, /[^-.!~*'()\w]/n) caption += %Q|
      | caption += %Q|#{@caption_delicious}| caption += %Q| | end if @conf['add.bookmark.hatena'] == 't' then caption += %Q|| caption += %Q|#{@caption_hatena}| caption += %Q| | end if @conf['add.bookmark.livedoor'] == 't' then caption += %Q|| caption += %Q|#{@caption_livedoor}| caption += %Q| | end if @conf['add.bookmark.buzzurl'] == 't' then caption += %Q|| caption += %Q|#{@caption_buzzurl}| caption += %Q| | end end <<-HTML #{caption} HTML end add_conf_proc( 'add_bookmark', @add_bookmark_label ) do add_bookmark_conf_proc end def add_bookmark_conf_proc bookmark_init saveconf_add_bookmark bookmark_categories = [ 'add.bookmark.delicious', 'add.bookmark.hatena', 'add.bookmark.livedoor', 'add.bookmark.buzzurl' ] r = '' r << %Q|

      #{@add_bookmark_label}

      #{@add_bookmark_desc}

        | bookmark_categories.each_with_index do |idx,view| checked = 't' == @conf[idx] ? ' checked' : '' label = @bookmark_label[view] r << %Q|
      • | end r << %Q|
      | end if @mode == 'saveconf' def saveconf_add_bookmark @conf['add.bookmark.delicious'] = @cgi.params['add.bookmark.delicious'][0] @conf['add.bookmark.hatena'] = @cgi.params['add.bookmark.hatena'][0] @conf['add.bookmark.livedoor'] = @cgi.params['add.bookmark.livedoor'][0] @conf['add.bookmark.buzzurl'] = @cgi.params['add.bookmark.buzzurl'][0] end end tdiary-contrib-3.2.2/plugin/apple_webclip.rb000066400000000000000000000013231213632744000211020ustar00rootroot00000000000000# # apple_webclip.rb - Add icon information for Apple WebClip. # # Copyright (C) 2008, TADA Tadashi # You can redistribute it and/or modify it under GPL. # add_header_proc do if @conf['apple_webclip.url'] and @conf['apple_webclip.url'].size > 0 %Q| \n| else '' end end add_conf_proc( 'apple_webclip', 'Apple WebClip' ) do if @mode == 'saveconf' then @conf['apple_webclip.url'] = @cgi.params['apple_webclip.url'][0] end <<-HTML

      Icon URL

      Create and cpecify PNG file 60x60 pixels.

      HTML end tdiary-contrib-3.2.2/plugin/appstore.rb000066400000000000000000000021511213632744000201310ustar00rootroot00000000000000# -*- coding: utf-8 -*- # # appstore.rb - embeded AppStore data for tDiary, # use App Store Affliate Resources Search API. # http://www.apple.com/itunes/affiliates/resources/documentation/itunes-store-web-service-search-api.html # # Copyright (C) 2011, tamoot # You can redistribute it and/or modify it under GPL2. # require 'uri' if /\A(?:latest|day|month|nyear|preview)\z/ =~ @mode enable_js('appstore.js') end def appstore_detail(url) appstore_dom = '' begin appstore_dom = appstore_common(url, {:detail => true}) rescue appstore_dom = "Error. message=#{$!.message}." end end def appstore_common(url, params) return %Q|#{url}| if feed? appstore_uri = URI::parse(url) id = appstore_uri.path.split('/').last.gsub('id', '') raise StandardError.new("AppStore ID: not found from #{url}..") if id.nil? || id == '' return %Q|| end # Local Variables: # mode: ruby # indent-tabs-mode: t # tab-width: 3 # ruby-indent-level: 3 # End: # vim: ts=3 tdiary-contrib-3.2.2/plugin/bigpresen.rb000066400000000000000000000050611213632744000202550ustar00rootroot00000000000000# bigpresen.rb $Revision: 1.03 $ # # bigpresen : åǿʹԤֹⶶ᥽åɡʸץ쥼ơ # # ѥ᥿ : # str : ʸ"|"ϥ饤ɤζڤꡢ"/"ϥ饤βԤȤʤ롣 # "|""|"ɽˤϡ"\"Ĥƥס # width : 饤ɤԥǻꡣ(ǥե : 480) # height : 饤ɤι⤵ԥǻꡣ(ǥե : 320) # # ʸˡ<%= bigpresen 'str','width','height' %> ηǵҤޤ # ʸΥϡɽƥȤȥ饤ɤΥ˹礦褦ưŪĴޤ # JavaScriptDHTMLѤưΤǡĶˤäƤɽʤȤ⤢ޤ # # Copyright (c) 2006 Maripo Goda # mailto:madin@madin.jp # Document URL http://www.madin.jp/works/plugin.html # You can redistribute it and/or modify it under GPL2. @bigPresenID = 0; def bigpresen (str='', width='480',height='320') scriptID = 'bp' + @bigPresenID.to_s @bigPresenID += 1; presen_ary = str.gsub("\\/",'⁄').gsub("\\|","&\#65073").split(/\|/); presen_ary.collect!{|s| s = '"' + s.gsub('/','
      ') + '"' } presen_str = presen_ary.join(',') return <
      START
      HTML end tdiary-contrib-3.2.2/plugin/bitly.rb000066400000000000000000000021141213632744000174160ustar00rootroot00000000000000# # bitly.rb - shorten URL by bit.ly. # # usage: shorten_url_you_got = bitly( 'long_url' ) || long_url # (because bitly returns nil sometime.) # # required some options below: # @options['biyly.login'] : your login ID of bit.ly. # @options['biyly.key'] : your API key of biy.ly. # # Copyright (C) 2010, TADA Tadashi # You can redistribute it and/or modify it under GPL. # require 'json' require 'net/http' def bitly( long_url ) return nil if !long_url or long_url.empty? @bitly_cache ||= {} # cached only on memory return @bitly_cache[long_url] if @bitly_cache[long_url] login = @conf['bitly.login'] key = @conf['bitly.key'] # proxy px_host, px_port = (@conf['proxy'] || '').split( /:/ ) px_port = 80 if px_host and !px_port query = "/v3/shorten?longUrl=#{CGI::escape long_url}&login=#{login}&apiKey=#{key}&format=json" begin Net::HTTP.version_1_2 res = Net::HTTP::Proxy(px_host, px_port).get('api.bit.ly', "#{query}") @bitly_cache[long_url] = JSON::parse(res, &:read)['data']['url'] rescue TypeError => te# biy.ly returns an error. nil end end tdiary-contrib-3.2.2/plugin/bootstrap-navi.rb000066400000000000000000000025711213632744000212520ustar00rootroot00000000000000# Show navi for twitter-bootstrap theme # # Copyright (c) KAOD Masanori # You can redistribute it and/or modify it under GPL. def bootstrap_navi(options = {}) default_options = { :navbar_class => nil, :site_name? => true, :search_form? => true } options = default_options.merge(options) body = "" if options[:site_name?] body += <<-EOS #{h @conf.html_title} EOS end body += <<-EOS EOS if options[:search_form?] body += <<-EOS EOS end <<-EOS EOS end add_header_proc do %Q|| end tdiary-contrib-3.2.2/plugin/canonical.rb000066400000000000000000000002121213632744000202170ustar00rootroot00000000000000# canonical.rb if /latest/ =~ @mode then add_header_proc do <<-HTML HTML end end tdiary-contrib-3.2.2/plugin/category_similar.rb000066400000000000000000000046221213632744000216360ustar00rootroot00000000000000# -*- coding: utf-8 -*- # category_similar.rb: # * shows similar posts under the diary # * depends on plugin/category.rb # You can redistribute it and/or modify it under the same license as tDiary. def category_similar(categories, max_item) info = Category::Info.new(@cgi, @years, @conf) months = [['01', '02', '03'], ['04', '05', '06'], ['07', '08', '09'], ['10', '11', '12']][@date.strftime("%m").to_i / (3 + 1)] # quarter years = { @date.strftime("%Y") => months } hash = @category_cache.categorize(info.category, years) items = [] hash.values_at(*categories).inject({}){|r, i| r.merge i if !r.nil? and !i.nil? }.to_a.each do |ymd_ary| ymd = ymd_ary[0] ary = ymd_ary[1] next if ymd == @date.strftime('%Y%m%d') t = Time.local(ymd[0,4], ymd[4,2], ymd[6,2]).strftime(@conf.date_format) ary.each do |idx, title, excerpt| items << %Q|#{t}#p#{'%02d' % idx} #{apply_plugin(title)}| end end unless items.empty? '
      ' + "

      #{category_similar_label}

      " + "
        " + items.sort.reverse[0, max_item].map{|i| "
      • #{i}" }.join("\n") + "
      " + "
      " end end add_conf_proc('category_similar', category_similar_label, 'basic') do if @mode == 'saveconf' @conf["category_similar.excludes"] = @cgi.params["category_similar.excludes"][0] @conf["category_similar.section_amounts"] = @cgi.params["category_similar.section_amounts"][0].to_i end <<-HTML

      #{category_similar_label}

      #{category_similar_excludes}

      #{category_similar_amounts}

      HTML end add_body_leave_proc do |date, idx| diary = @diaries[date.strftime('%Y%m%d')] if @mode =~ /day/ and diary.categorizable? categories = [] diary.each_section do |s| categories += s.categories unless s.categories.empty? end categories.delete_if do |i| @conf['category_similar.excludes'].split(/\r?\n/).include? i end category_similar(categories, @conf['category_similar.section_amounts']) end end # Local Variables: # mode: ruby # indent-tabs-mode: t # tab-width: 3 # ruby-indent-level: 3 # End: # vim: ts=3 tdiary-contrib-3.2.2/plugin/category_to_tag.rb000066400000000000000000000030541213632744000214510ustar00rootroot00000000000000# # category_to_tag.rb - show categories list in end of each section # # Copyright (C) 2005, TADA Tadashi # You can redistribute it and/or modify it under GPL2. # if respond_to?( :categorized_title_of_day ) then # BlogKit def categorized_title_of_day( date, title ) @category_to_tag_list = {} cats, stripped = title.scan( /^((?:\[[^\]]+\])+)\s*(.*)/ )[0] if cats then cats.scan( /\[([^\]]+)\]+/ ).flatten.each do |tag| @category_to_tag_list[tag] = true # true when blog end else stripped = title end stripped end add_body_leave_proc do |date| feed? ? '' : category_to_tag_list end elsif respond_to?( :category_anchor ) # diary add_section_enter_proc do |date, index| @category_to_tag_list = {} '' end alias subtitle_link_original subtitle_link def subtitle_link( date, index, subtitle ) s = '' if subtitle then s = subtitle.sub( /^(\[([^\[]+?)\])+/ ) do $&.scan( /\[(.*?)\]/ ) do |tag| @category_to_tag_list[CGI::unescapeHTML(tag[0])] = false # false when diary end '' end end subtitle_link_original( date, index, s.strip ) end add_section_leave_proc do |date, index| feed? ? '' : category_to_tag_list end end def category_to_tag_list if @category_to_tag_list and not @category_to_tag_list.empty? then r = '
      Tags: ' @category_to_tag_list.each do |tag, blog| if blog r << %Q|#{tag} | else r << category_anchor( "#{tag}" ).sub( /^\[/, '' ).sub( /\]$/, '' ) << ' ' end end r << "
      \n" end end tdiary-contrib-3.2.2/plugin/category_to_tagcloud.rb000066400000000000000000000100541213632744000224760ustar00rootroot00000000000000# # category_to_tagcloud.rb # # Usage: # <% tag_list n %> # n: 表示最大数(default: nil) # # options configurable through settings: # @options['tagcloud.hidecss'] : cssの出力 default: false # # This plugin modifes and includes tagcloud-ruby. # http://yatsu.info/articles/2005/08/05/ruby%E3%81%A7tagcloud-tagcloud-ruby require 'pstore' def category_enable? !@plugin_files.grep(/\/category\.rb$/).empty? end def add tag, url, count, elapsed_time @counts[tag] = count @urls[tag] = url @elapsed_times[tag] = elapsed_time end def print_html tags = @counts.sort_by {|a, b| b }.reverse.map {|a, b| a } return '' if tags.empty? tags = tags[0..@limit-1] if @limit if tags.size == 1 tag = tags[0] url = @urls[tag] elapsed_time = @elapsed_times[tag] return %{\n} end min = Math.sqrt(@counts[tags.last]) max = Math.sqrt(@counts[tags.first]) factor = 0 # special case all tags having the same count if max - min == 0 min = min - 24 factor = 1 else factor = 24 / (max - min) end html = %{
        } tags.sort{|a,b| a.downcase <=> b.downcase}.each do |tag| count = @counts[tag] level = ((Math.sqrt(count) - min) * factor).to_i html << %{
      • #{tag}
      • \n} end html << "
      " html end def init_category_to_tagcloud @counts = Hash.new @urls = Hash.new @elapsed_times = Hash.new @conf['category_to_tagcloud.cache'] ||= "#{@cache_path}/category2tagcloud.cache" @limit = nil end def tag_list limit = nil return '' if bot? return '' unless category_enable? init_category_to_tagcloud cache = @conf['category_to_tagcloud.cache'] @limit = limit PStore.new(cache).transaction(read_only=true) do |db| break unless db.root?('tagcloud') or db.root?('last_update') break if Time.now.strftime('%Y%m%d').to_i > db['last_update'] @counts = db['tagcloud'][0] @urls = db['tagcloud'][1] @elapsed_times = db['tagcloud'][2] end gen_tag_list if @urls.empty? print_html end def styleclass diff c = ' old' if diff > 30 c = " oldest" elsif diff > 14 c = " older" elsif diff < 7 c = " hot" end c end def gen_tag_list init_category_to_tagcloud if @mode == 'append' or @mode == 'replace' cache = @conf['category_to_tagcloud.cache'] info = Category::Tagcloud_Info.new(@cgi, @years, @conf) categorized = @category_cache.categorize(info.category, info.years) categorized.keys.each do |key| count = categorized[key].size ymd = categorized[key].keys.sort.reverse diff = (Time.now - Time.local(ymd[0][0,4], ymd[0][4,2], ymd[0][6,2])) / 86400 url = "#{@conf.index}?category=#{CGI.escape(key)}" add(key, url, count, "#{styleclass(diff.to_i)}") end PStore.new(cache).transaction do |db| db['last_update'] = Time.now.strftime('%Y%m%d').to_i db['tagcloud'] = [@counts, @urls, @elapsed_times] end end def tagcloud_css r = '' r = "\t\n" r end add_update_proc do gen_tag_list if @mode == 'append' or @mode == 'replace' end add_header_proc do tagcloud_css unless @conf['tagcloud.hidecss'] end if category_enable? module Category class Tagcloud_Info < Info def years now_year = Time.now.year now_month = Time.now.month r = Hash.new months = [ ['01'],['01','02'],['01','02','03'],['02','03','04'],['03','04','05'], ['04','05','06'],['05','06','07'],['06','07','08'],['07','08','09'], ['08','09','10'],['09','10','11'],['10','11','12'] ][now_month - 1] r[now_year.to_s] = months case now_month when 1 r["#{now_year - 1}"] = ['11','12'] when 2 r["#{now_year - 1}"] = ['12'] end r end end end end ## vim: ts=3 tdiary-contrib-3.2.2/plugin/cocomment.rb000066400000000000000000000017731213632744000202710ustar00rootroot00000000000000# cocomment.rb $Revision: 1.6 $ # # Copyright (C) 2006 by Hiroshi SHIBATA # You can redistribute it and/or modify it under GPL2. # if @mode == 'day' and not bot? and not @conf.mobile_agent? then add_body_enter_proc do |date| <<-SCRIPT SCRIPT end end # Local Variables: # mode: ruby # indent-tabs-mode: t # tab-width: 3 # ruby-indent-level: 3 # End: # vi: ts=3 sw=3 tdiary-contrib-3.2.2/plugin/code-prettify.rb000066400000000000000000000010361213632744000210530ustar00rootroot00000000000000# Source code embedded plugin for tDiary. # Copyright (C) 2012 Koichiro Ohba # License under MIT. add_header_proc do <<-EOS EOS end def code(content, lang = nil) <<-EOS
      #{content}
      EOS end tdiary-contrib-3.2.2/plugin/coderwall.rb000066400000000000000000000014531213632744000202540ustar00rootroot00000000000000require 'open-uri' require 'timeout' require 'json' def coderwall(name, size = [60, 60]) begin cache = "#{@cache_path}/coderwall.json" json = File.read(cache) File::delete(cache) if Time::now > File::mtime( cache ) + 60*60*24 rescue Errno::ENOENT begin timeout(10) do json = open( "https://coderwall.com/#{name}.json" ) {|f| f.read } end open(cache, 'wb') {|f| f.write(json) } rescue Timeout::Error return "" end end html = '
      ' JSON.parse(json)['badges'].each do |badge| html << %Q|#{badge['name']}| end html << '
      ' end # Local Variables: # mode: ruby # indent-tabs-mode: t # tab-width: 3 # ruby-indent-level: 3 # End: # vim: ts=3 tdiary-contrib-3.2.2/plugin/comment_emoji_autocomplete.rb000066400000000000000000000013511213632744000237030ustar00rootroot00000000000000# -*- coding: utf-8 -*- # # comment_emoji_autocomplete.rb : Support the automatic input of the emoji # using jQuery UI autocomplete. # # Copyright (C) 2013, tamoot # You can redistribute it and/or modify it under GPL2. # if !@cgi.mobile_agent? && /\A(?:day)\z/ =~ @mode add_header_proc do %Q|| end enable_js('http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/jquery-ui.min.js') enable_js('caretposition.js') enable_js('comment_emoji_autocomplete.js') end # Local Variables: # mode: ruby # indent-tabs-mode: t # tab-width: 3 # ruby-indent-level: 3 # End: # vim: ts=3 tdiary-contrib-3.2.2/plugin/datepicker.rb000066400000000000000000000012241213632744000204070ustar00rootroot00000000000000# -*- coding: utf-8 -*- # # datepickr.rb - show jQuery UI datepicker # # Copyright (C) 2012, tamoot # You can redistribute it and/or modify it under GPL. # # # not support # return if feed? || @conf.mobile_agent? if /\A(?:form|preview|append|edit|update)\z/ =~ @mode enable_js('http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/jquery-ui.min.js') if @conf.lang == 'ja' enable_js('http://ajax.googleapis.com/ajax/libs/jqueryui/1/i18n/jquery.ui.datepicker-ja.min.js') end enable_js('datepicker.js') end # Local Variables: # mode: ruby # indent-tabs-mode: t # tab-width: 3 # ruby-indent-level: 3 # End: # vim: ts=3 tdiary-contrib-3.2.2/plugin/day2section.rb000066400000000000000000000006171213632744000205250ustar00rootroot00000000000000# # day2section.rb - tDiary plugin # # When a visitor accesses to day page without section anchor, navigate to first section. # # Copyright (c) MATSUOKA Kohei # Distributed under the GPL # add_footer_proc do if @mode == 'day' <<-SCRIPT SCRIPT end end tdiary-contrib-3.2.2/plugin/del_footer.rb000066400000000000000000000050021213632744000204140ustar00rootroot00000000000000=begin delicious.rb Delicious から その日付分のメモを取ってきて表示するプラグイン tdiary.conf で以下を設定します。tDiaryの設定画面からも設定可能です。 @options['delicious.id'] = 'YOUR DELICIOUS ID HERE' @options['delicious.pw'] = 'YOUR DELICIOUS PW HERE' proxy は以下に設定します。 @options['amazon.proxy'] = 'PROXY_HOST:PORT' reference: * mm_footer.rb by ishinao san * rss-show.rb (in Hiki) by TAKEUCHI Hitoshi san * fujisan.rb by Michitaka Ohno. =end require 'net/https' require 'rexml/document' require 'fileutils' def delicious_save_cache cache_file, file FileUtils.mkdir_p "#{@cache_path}/delicious" File.open("#{@cache_path}/delicious/#{cache_file}", 'w') do |f| f.flock(File::LOCK_EX) f.puts file f.flock(File::LOCK_UN) end end def delicious_parse_xml(xml) posts = [] REXML::Document.new(xml).elements.each("posts/post") do |post| post = <<-EOS
    • #{post.attribute("description").to_s}
    • EOS posts << post.delete("\r\n") end return posts end def delicious_get_html(date = Date.now) req = Net::HTTP::Get.new "/v1/posts/get?dt=#{date.strftime('%Y-%m-%d')}" req.basic_auth @options['delicious.id'], @options['delicious.pw'] https = Net::HTTP.new('api.del.icio.us', 443) https.use_ssl = true parsed = https.start {|w| response = w.request(req) delicious_parse_xml(response.body) } delicious_save_cache date.strftime("%Y-%m-%d"), parsed end add_edit_proc do |date| delicious_get_html date nil end add_body_leave_proc do |date| path = "#{@cache_path}/delicious/#{date.strftime('%Y-%m-%d')}" ret = '' if File.exist? path File.open(path) do |file| ret = <<-EOS

      Delicious

        #{file.read}
      EOS end end ret end def delicious_init @conf['delicious.id'] ||= "" @conf['delicious.pw'] ||= "" @conf['delicious.title'] ||= "Todey's URL Clip" end add_conf_proc( 'delicious', @delicious_label_conf ) do delicious_conf_proc end def delicious_conf_proc if @mode == 'saveconf' then @conf['delicious.id'] = @cgi.params['delicious.id'][0] @conf['delicious.pw'] = @cgi.params['delicious.pw'][0] end delicious_init <<-HTML

      #{@delicious_label_id}

      #{@delicious_label_pw}

      HTML end tdiary-contrib-3.2.2/plugin/description_from_body.rb000066400000000000000000000011131213632744000226540ustar00rootroot00000000000000# # description_from_body.rb - set meta description by first section's body in day mode # # Copyright (C) 2011, TADA Tadashi # You can redistribute it and/or modify it under GPL. # alias description_tag_dfb_orig description_tag def description_tag if @mode == 'day' then diary = @diaries[@date.strftime '%Y%m%d'] return '' unless diary body = '' diary.each_section do |sec| body = remove_tag( apply_plugin( sec.body_to_html ) ).strip break end %Q|| else description_tag_dfb_orig end end tdiary-contrib-3.2.2/plugin/development.rb000066400000000000000000000007011213632744000206150ustar00rootroot00000000000000# development.rb - utility methods for plugin developers # # Copyright (c) 2011 MATSUOKA Kohei # You can redistribute it and/or modify it under GPL2. # # load standard version jquery.js instead of jquery.min.js alias :jquery_tag_original :jquery_tag def jquery_tag jquery_tag_original.gsub(/\.min/, '') end # js cache clear by seconds. def script_tag_query_string "?#{TDIARY_VERSION}#{Time::now.strftime('%Y%m%d%H%M%S')}" end tdiary-contrib-3.2.2/plugin/editor.rb000066400000000000000000000003761213632744000175710ustar00rootroot00000000000000# # editor.rb - support writing using wiki/gfm notation. # # Copyright (c) 2012 MATSUOKA Kohei # You can distribute it under GPL. # # load javascript if /\A(form|edit|preview|showcomment)\z/ === @mode then enable_js('editor.js') end tdiary-contrib-3.2.2/plugin/en/000077500000000000000000000000001213632744000163525ustar00rootroot00000000000000tdiary-contrib-3.2.2/plugin/en/add_bookmark.rb000066400000000000000000000007751213632744000213250ustar00rootroot00000000000000# en/add_bookmark.rb $Revision 1.3 $ # # English resource of add_bookmark.rb # You can redistribute it and/or modify it under GPL2. # @add_bookmark_label = 'add to bookmark' @add_bookmark_desc = 'Please check the link that wants to be displayed.' @caption_delicious = 'add to del.icio.us' @caption_hatena = 'add to Hatena bookmark' @caption_livedoor = 'add to livedoor clip' @caption_buzzurl = 'add to Buzzurl' @bookmark_label = [ 'del.icio.us', 'Hatena bookmark', 'livedoor Clip', 'Buzzurl' ] tdiary-contrib-3.2.2/plugin/en/del_footer.rb000066400000000000000000000004241213632744000210210ustar00rootroot00000000000000# # English resource of delicious plugin $Revision: 1.0 $ # # Copyright (C) 2006 SHIBATA Hiroshi # You can redistribute it and/or modify it under GPL2. # @delicious_label_conf = 'del.icio.us' @delicious_label_id = 'User ID' @delicious_label_pw = 'Password' tdiary-contrib-3.2.2/plugin/en/git-register.rb000066400000000000000000000002541213632744000213050ustar00rootroot00000000000000@estraier_register_conf_label = 'Git' @estraier_register_conf_header = 'commit all' @estraier_register_conf_description = 'To commit all, check the box and submit \'OK\'.' tdiary-contrib-3.2.2/plugin/en/livedoor_weather.rb000066400000000000000000000017521213632744000222460ustar00rootroot00000000000000# # English resource of livedoor_weather plugin $Revision$ # # Copyright (C) 2006 SHIBATA Hiroshi # You can redistribute it and/or modify it under GPL2. # # # setting of tdiary.conf # @options['lwws.city_id'] : City ID where weather information is specified. # @lwws_plugin_name = 'livedoor weather' @lwws_label_city_id = 'City ID' @lwws_desc_city_id = 'City ID where weather information is specified. Please select City ID from among Point definition table(RSS)' @lwws_label_disp_item = 'View items' @lwws_desc_disp_item = 'Please select the item to want to display.' @lwws_icon_label = 'Icon' @lwws_icon_desc = 'Weather information is displayed in the icon. ' @lwws_max_temp_label = 'Max Tempreture' @lwws_min_temp_label = 'Min Tempreture' @celsius_label = 'C' @lwws_label_cache = 'Auto update of cache' @lwws_desc_cache = 'Enable auto update.' @lwws_desc_cache_time = 'Please set number of update time.' tdiary-contrib-3.2.2/plugin/en/microsummary.rb000066400000000000000000000010041213632744000214210ustar00rootroot00000000000000# ja/microsummary.rb # # Japanese resources for microsummary.rb # # Copyright (c) 2006 elytsllams # Distributed under the GPL # if @mode == 'conf' || @mode == 'saveconf' add_conf_proc( 'microsummary', 'Microsummary Generator' ) do saveconf_microsummary microsummary_init <<-HTML

      URI for microsummary generator XML

      HTML end end tdiary-contrib-3.2.2/plugin/en/nicovideo.rb000066400000000000000000000030341213632744000206560ustar00rootroot00000000000000# # ja/nicovideo.rb - Japanese resource # # Copyright (C) TADA Tadashi # Distributed under GPL. # def nicovideo_player_path 'http://www.nicovideo.jp' end def nicovideo_feed( i ) <<-HTML
      #{h i[:title]} #{h i[:title]} (#{i[:length]})
      HTML end def nicovideo_html( i ) <<-HTML
      #{h i[:title]}

      #{h i[:title]} (#{i[:length].split(/:/).map{|j|'%02d' % j.to_i}.join(':')})

      #{i[:date][0,10]} Posted
      #{i[:view].scan(/\d+?(?=\d{3}*$)/).join(",")} Views
      #{i[:comment_num].scan(/\d+?(?=\d{3}*$)/).join(",")} Comments
      #{i[:mylist].scan(/\d+?(?=\d{3}*$)/).join(",")} Mylists

      HTML end tdiary-contrib-3.2.2/plugin/en/openid.rb000066400000000000000000000004041213632744000201530ustar00rootroot00000000000000# openid.rb: English resource @openid_conf_label = 'OpenID' @openid_service_label = 'OpenID Service' @openid_service_desc = 'select your OpenID service name.' @openid_id_label = 'Your ID' @openid_id_desc = 'Specify your ID of OpenID service selected above.' tdiary-contrib-3.2.2/plugin/en/section_footer.rb000066400000000000000000000005511213632744000217220ustar00rootroot00000000000000# section_footer.rb: English resource @section_footer_delicious_label = "del.icio.us history for this entry" @section_footer_hatenabm_label = "this entry on Hatena Bookmark" @section_footer_ldclip_label = "this entry on livedoor clip" @section_footer_buzzurl_label = "this entry on Buzzurl" @section_footer_yahoobm_label = "this entry on Yahoo! JAPAN Bookmark" tdiary-contrib-3.2.2/plugin/en/section_footer2.rb000066400000000000000000000002171213632744000220030ustar00rootroot00000000000000# section_footer2.rb: English resource @section_footer2_delicious_label = "Delicious history for this entry" @section_footer2_locale = 'en_US' tdiary-contrib-3.2.2/plugin/en/socialbutton.rb000066400000000000000000000003741213632744000214110ustar00rootroot00000000000000# -*- coding: utf-8 -*- # section_footer2.rb: English resource @socialbutton_label_conf = 'Social buttons' @socialbutton_label_enables = 'enable social button names' @socialbutton_label_twitter_via = 'screen name of the user to attribute the tweet to' tdiary-contrib-3.2.2/plugin/everytrail.rb000066400000000000000000000056221213632744000204700ustar00rootroot00000000000000# # everytrail.rb: plugin embedding trip map on everytrail.com. # # Copyright (C) 2010 TADA Tadashi # You can redistribute it and/or modify it under GPL2. # def everytrail_adjust_size( size ) s = size.collect {|i| i.to_i } s[0] = 400 if s[0] == 0 s[1] = 300 if s[1] == 0 if @conf.iphone? then s = [300, 300 * s[1] / s[0]] end s end def everytrail( trip_id, label = nil, size = [400, 300] ) size = everytrail_adjust_size( size ) r = %Q|
      | end def everytrail_flash( trip_id, label = nil, size = [400, 300] ) size = everytrail_adjust_size( size ) %Q|
      | end def everytrail_widget( trip_id, latitude = nil, longtitude = nil, label = nil, size = [400, 300] ) return '' if @conf.iphone? size = everytrail_adjust_size( size ) lat_param = latitude ? "&startLat=#{latitude}" : '' lon_param = longtitude ? "&startLon=#{longtitude}" : '' r = label ? %Q|

      #{h label}

      | : '' r << %Q|
      Map your trip with EveryTrail| end tdiary-contrib-3.2.2/plugin/facebook_comments.rb000066400000000000000000000040411213632744000217520ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2011, KADO Masanori # You can redistribute it and/or modify it under GPL. add_header_proc do <<-HTML HTML end def facebook_comments(href = '') <<-HTML
      HTML end add_body_leave_proc do |date| if @mode == 'day' href = @conf.base_url + anchor( @date.strftime('%Y%m%d') ) facebook_comments(href) end end add_conf_proc( 'Facebook Comments', 'Facebook Comments', 'etc' ) do if @mode == 'saveconf' then @conf['facebook_comments.YOUR_FACEBOOK_USER_ID'] = @cgi.params['facebook_comments.YOUR_FACEBOOK_USER_ID'][0] @conf['facebook_comments.YOUR_APPLICATION_ID'] = @cgi.params['facebook_comments.YOUR_APPLICATION_ID'][0] @conf['facebook_comments.num_posts'] = @cgi.params['facebook_comments.num_posts'][0] @conf['facebook_comments.width'] = @cgi.params['facebook_comments.width'][0] end <<-HTML

      YOUR_FACEBOOK_USER_ID

      YOUR_APPLICATION_ID

      num posts

      width

      HTML end # Local Variables: # mode: ruby # indent-tabs-mode: t # tab-width: 3 # ruby-indent-level: 3 # End: # vim: ts=3 tdiary-contrib-3.2.2/plugin/flickr.rb000066400000000000000000000145141213632744000175540ustar00rootroot00000000000000# show photo image on Flickr.com # # usage: # flickr(photo_id[, size[, place]]) # - photo_id: The id of the photo to show. # - size: Size of photo. (optional) # Choose from square, thumbnail, small, medium, or large. # - place: class name of img element. default is 'flickr'. # # flickr_left(photo_id[, size]) # # flickr_right(photo_id[, size]) # # options configurable through settings: # @conf['flickr.apikey'] : a key for access Flickr API # @conf['flickr.default_size'] : default image size # # Copyright (c) MATSUOKA Kohei # Distributed under the GPL # require 'net/http' require 'digest/md5' require 'rexml/document' @conf['flickr.apikey'] ||= 'f7e7fb8cc34e52db3e5af5e1727d0c0b' @conf['flickr.default_size'] ||= 'medium' if /\A(form|edit|preview|showcomment)\z/ === @mode then enable_js('flickr.js') add_js_setting('$tDiary.plugin.flickr') add_js_setting('$tDiary.plugin.flickr.apiKey', %Q|'#{@conf['flickr.apikey']}'|) add_js_setting('$tDiary.plugin.flickr.userId', %Q|'#{@conf['flickr.user_id']}'|) end def flickr(photo_id, size = nil, place = 'flickr') if @conf['flickr.apikey'] == nil || @conf['flickr.apikey'].empty? return '[ERROR] flickr.rb: API Key is not specified.' end size ||= @conf['flickr.default_size'] size = 'small' if @conf.iphone? photo = flickr_photo_info(photo_id.to_s, size) unless photo return '[ERROR] flickr.rb: failed to get photo.' end if @cgi.mobile_agent? body = %Q|#{photo[:title]}| else body = %Q|#{photo[:title]}| end body end def flickr_left(photo_id, size = nil) flickr(photo_id, size, 'left') end def flickr_right(photo_id, size = nil) flickr(photo_id, size, 'right') end def flickr_photo_info(photo_id, size) photo = {} begin flickr_open('flickr.photos.getInfo', photo_id) {|f| res = REXML::Document.new(f) photo[:page] = res.elements['//rsp/photo/urls/url'].text photo[:title] = res.elements['//rsp/photo/title'].text } flickr_open('flickr.photos.getSizes', photo_id) {|f| res = REXML::Document.new(f) res.elements.each('//rsp/sizes/size') do |s| if s.attributes['label'].downcase == size.downcase photo[:src] = s.attributes['source'] photo[:width] = s.attributes['width'] photo[:height] = s.attributes['height'] end end } rescue Exception => e return nil end photo end def flickr_open(method, photo_id) cache_dir = "#{@cache_path}/flickr" Dir::mkdir(cache_dir) unless File::directory?(cache_dir) file = "#{cache_dir}/#{photo_id}.#{method}" unless File.exist?(file) req = Flickr::Request.new(@conf['flickr.apikey']) req['method'] = method req['photo_id'] = photo_id begin timeout(5) do open(file, 'w') {|fout| fout.puts req.open } end rescue TimeoutError => e File.delete(file) raise e end end open(file) {|f| yield f } end # delete cache files def flickr_clear_cache cache_dir = "#{@cache_path}/flickr" Dir.glob("#{cache_dir}/*.flickr.photos.{getInfo,getSizes}") do |cache| # File.unlink(cache) File.rename(cache, "#{cache}.org") end end FLICKER_FORM_PID = 'plugin_flickr_pid' add_edit_proc do |date| <<-FORM
      Flickr:
      Photo size:
      FORM end def flickr_slideshow(tag, id = nil) id ||= @conf['flickr.id'] return unless id %Q|| end def flickr_slideshow_by_set(set_id) return unless set_id %Q|| end module Flickr class Request < Hash def initialize(api_key, secret = nil) self['api_key'] = api_key @secret = secret end def open Net::HTTP.version_1_2 Net::HTTP.start('www.flickr.com') {|http| response = http.get(query) response.body } end def query sign = @secret ? "&api_sig=#{signature}" : '' base_path + sort.map{|key, val| "#{key}=#{val}" }.join('&') + sign end def signature data = sort.map{|key, val| "#{key}#{val}" }.join Digest::MD5.hexdigest("#{@secret}#{data}") end def base_path '/services/rest/?' end end class RequestAuth < Request def base_path '/services/auth/?' end end end tdiary-contrib-3.2.2/plugin/gist.rb000066400000000000000000000010121213632744000172350ustar00rootroot00000000000000# show code snippet via gist.github.com # # usage: # gist(gist_id) # - gist_id: The id of the code snippet on gitst.github.com (e.g. 2056 for http://gist.github.com/2056) # # Copyright (c) KAKUTANI Shintaro # Distributed under the GPL def gist( gist_id ) gist_snippet_url = "http://gist.github.com/#{gist_id}" return (<<-EOS).chomp EOS end tdiary-contrib-3.2.2/plugin/git-register.rb000066400000000000000000000135431213632744000207100ustar00rootroot00000000000000#!/usr/bin/env ruby # -*- coding: utf-8 -*- # git-register.rb # # Copyright (C) 2011 hajime miyauchi # You can redistribute it and/or modify it under GPL2. # # tDiaryのデータを日別でGitに登録するプラグインです # # 1. プラグインディレクトリ(例: plugin)にgit-register.rbを設置。 # 2. プラグインディレクトリにja/git-register.rb、en/git-register.rbを設置。 # 3. tdiary.confにリポジトリを指定(リポジトリの場所を/var/git-respoと仮定) # @options["git.repository_dir"] = "/var/git-repos" # 4. リポジトリを作成(Apacheの起動ユーザをapacheと仮定) # $ mkdir /var/git-repos # $ cd /var/git-repos # $ git init # $ git config user.name "自分の名前" # $ git config user.email "メールアドレス" # $ chown apache.apache -R /var/git-repos # 5. リポジトリに一括commit(tDiaryのインストールディレクトリを/var/www/tdiaryと仮定) # $ cd /var/www/tdiary # $ ruby --encoding=UTF-8 git-register.rb # mode = "" if $0 == __FILE__ require 'cgi' ARGV << '' # dummy argument against cgi.rb offline mode. @cgi = CGI::new mode = "CMD" else mode = "PLUGIN" end if mode == "PLUGIN" add_body_leave_proc do |date| end end unless $tdiary_git_register_loaded $tdiary_git_register_loaded ||= true if mode == "CMD" tdiary_path = "." tdiary_conf = "." $stdout.sync = true def usage puts "git-register.rb" puts " register to git index files from tDiary's database." puts " usage: ruby --encoding=UTF-8 git-register.rb [-p ] [-c ]" exit end require 'getoptlong' parser = GetoptLong::new parser.set_options(['--path', '-p', GetoptLong::REQUIRED_ARGUMENT], ['--conf', '-c', GetoptLong::REQUIRED_ARGUMENT]) begin parser.each do |opt, arg| case opt when '--path' tdiary_path = arg when '--conf' tdiary_conf = arg end end rescue usage exit( 1 ) end tdiary_conf = tdiary_path unless tdiary_conf Dir::chdir( tdiary_conf ) begin $:.unshift tdiary_path require "#{tdiary_path}/tdiary" rescue LoadError $stderr.puts "git-register.rb: cannot load tdiary.rb. <#{tdiary_path}/tdiary>\n" $stderr.puts " usage: ruby --encoding=UTF-8 git-register.rb [-p ] [-c ]" exit( 1 ) end end module ::TDiary # # Register # class GitRegister < TDiaryBase def initialize(repository_dir, diary) @repository_dir = repository_dir @diary = diary @date = diary.date end def execute() dir = @date.strftime("#{@repository_dir}%Y%m/") Dir::mkdir( dir ) unless FileTest::directory?( dir ) td2_file = @date.strftime("#{dir}%Y%m%d.td2") fh = File::open(td2_file, 'w') fh.puts( "Date: #{@date}" ) fh.puts( "Title: #{@diary.title}" ) fh.puts( "Last-Modified: #{@diary.last_modified.to_i}" ) fh.puts( "Visible: #{@diary.visible? ? 'true' : 'false'}" ) fh.puts( "Format: #{@diary.style}" ) fh.puts fh.puts( @diary.to_src.gsub( /\r/, '' ).gsub( /\n\./, "\n.." ) ) fh.close # commit require 'shellwords' msg = "#{ENV['REMOTE_ADDR']} - #{ENV['REMOTE_HOST']}" Dir.chdir("#{@repository_dir}") do td2_file2 = @date.strftime("%Y%m/%Y%m%d.td2") system("git add -- #{Shellwords.shellescape(td2_file2)}".untaint) system("git commit -q -m \"#{msg}\" -- #{Shellwords.shellescape(td2_file2)}".untaint) end end protected def mode; 'day'; end def cookie_name; ''; end def cookie_mail; ''; end def convert(str) str end end # # Main # class GitRegisterMain < TDiaryBase def initialize(conf) super(CGI::new, 'day.rhtml', conf) end def execute(out = $stdout) require 'fileutils' repository_dir = @conf['git.repository_dir'] calendar @years.keys.sort.reverse_each do |year| out << "(#{year.to_s}/) " @years[year.to_s].sort.reverse_each do |month| @io.transaction(Time::local(year.to_i, month.to_i)) do |diaries| diaries.sort.reverse_each do |day, diary| out << diary.date.strftime('%m%d ') GitRegister.new(repository_dir, diary).execute end false end end end end end end if mode == "CMD" begin require 'cgi' if TDiary::Config.instance_method(:initialize).arity != 0 # for tDiary 2.1 or later cgi = CGI.new conf = TDiary::Config::new(cgi) else # for tDiary 2.0 or earlier conf = TDiary::Config::new end conf.header = '' conf.footer = '' conf.show_comment = true conf.hide_comment_form = true conf.show_nyear = false def conf.bot?; true; end TDiary::GitRegisterMain.new(conf).execute rescue print $!, "\n" $@.each do |v| print v, "\n" end exit( 1 ) end puts else add_update_proc do conf = @conf.clone conf.header = '' conf.footer = '' conf.show_comment = true conf.hide_comment_form = true conf.show_nyear = false def conf.bot?; true; end repository_dir = @conf['git.repository_dir'] diary = @diaries[@date.strftime('%Y%m%d')] TDiary::GitRegister.new(repository_dir, diary).execute end if !@conf['git.hideconf'] && (@mode == 'conf' || @mode == 'saveconf') args = ['git_register', @git_register_conf_label] args << 'update' if TDIARY_VERSION > '2.1.3' add_conf_proc(*args) do str = <<-HTML

      #{@git_register_conf_header}

      HTML if @mode == 'saveconf' if @cgi.valid?( 'git_register_rebuild' ) str << '

      The following diaries were registered.

      ' out = '' TDiary::GitRegisterMain.new(@conf).execute(out) str << "

      #{out}

      " end end str end end end end # $tdiary_git_register_loaded # Local Variables: # mode: ruby # indent-tabs-mode: t # tab-width: 3 # ruby-indent-level: 3 # End: tdiary-contrib-3.2.2/plugin/github_badge.rb000066400000000000000000000020231213632744000206760ustar00rootroot00000000000000# Github Badge, by drnic plugin. # http://drnicjavascript.rubyforge.org/github_badge/ # # usage: # github_badge(username, list_length, head, theme, title, show_all) # - username: user name on github.com # - list_length: project list length # - theme: specify theme for badge. "white" or "black". # - title: top text display on the badge. # - show_all: 'Show All' message. # # Copyright (c) 2008 KAKUTANI Shintaro # Distributed under the GPL def github_badge( username, list_length = 10, head = "div", theme = "white", title = "My Projects", show_all = "Show all" ) return (<<-EOS).chomp
      EOS end tdiary-contrib-3.2.2/plugin/github_link.rb000066400000000000000000000004061213632744000205740ustar00rootroot00000000000000def gh_link(gh_identifier, text=nil) text = gh_identifier.split('/').last if text.nil? id_and_name, number = gh_identifier.split('#') url = "https://github.com/#{id_and_name}" url = url + "/issues/#{number}" if number "#{h text}" end tdiary-contrib-3.2.2/plugin/goo_gl.rb000066400000000000000000000021161213632744000175430ustar00rootroot00000000000000# # goo_gl.rb - shorten URL by goo.gl # # usage: shorten_url_you_got = goo_gl( 'long_url' ) || long_url # # Copyright (C) 2011, tamoot # You can redistribute it and/or modify it under GPL. # require 'json' require 'net/https' def goo_gl( long_url ) return nil if !long_url or long_url.empty? # on memory @goo_gl_cache ||= {} # cached only on memory return @goo_gl_cache[long_url] if @goo_gl_cache[long_url] # proxy px_host, px_port = (@conf['proxy'] || '').split( /:/ ) px_port = 80 if px_host and !px_port # params params = {'longUrl' => long_url}.to_json https = nil begin https = Net::HTTP::Proxy(px_host, px_port).new('www.googleapis.com', 443) https.use_ssl = true res, body = https.post("/urlshortener/v1/url", params, {'Content-Type' => 'application/json'}) @goo_gl_cache[long_url] = JSON::parse(body)["id"] if res.code == '200' rescue Exception => e # do nothing.. ensure https.finish if https && https.started? end return @goo_gl_cache[long_url] end tdiary-contrib-3.2.2/plugin/google_adsense.rb000066400000000000000000000143131213632744000212550ustar00rootroot00000000000000# # Google AdSense plugin for tDiary # # Copyright (C) 2004 Kazuhiko # You can redistribute it and/or modify it under GPL2. # # modified by TADA Tadashi # def google_adsense( layout = nil, slot = nil ) google_adsense_init( layout ) google_ad_client = "pub-3317603667498586" google_ad_size = [ [468, 60], # 0 [120, 600], # 1 [728, 90], # 2 [300, 250], # 3 [125, 125], # 4 [160, 600], # 5 [120, 240], # 6 [180, 150], # 7 [250, 250], # 8 [336, 280], # 9 [200, 200], # 10 [234, 60] # 11 ] result = <<-EOF EOF result.gsub( /^\t+/, '' ) end def google_adsense_init( layout ) if layout != nil then @conf['google_adsense.layout'] = layout.to_i else @conf['google_adsense.layout'] = 0 unless @conf['google_adsense.layout'] end @conf['google_adsense.layout'] = @conf['google_adsense.layout'].to_i if @conf['google_adsense.layout'] < 0 or @conf['google_adsense.layout'] > 11 then @conf['google_adsense.layout'] = 0 end @conf['google_adsense.color.border'] = 'CCCCCC' unless @conf['google_adsense.color.border'] @conf['google_adsense.color.bg'] = 'FFFFFF' unless @conf['google_adsense.color.bg'] @conf['google_adsense.color.link'] = '000000' unless @conf['google_adsense.color.link'] @conf['google_adsense.color.url'] = '666666' unless @conf['google_adsense.color.url'] @conf['google_adsense.color.text'] = '333333' unless @conf['google_adsense.color.text'] end add_section_leave_proc do |date,index| if @mode == 'day' and !@conf.iphone? and index == 1 and @conf['google_adsense.slot'] then %Q|
      #{google_adsense( 0, @conf['google_adsense.slot'] )}
      | else '' end end # insert section target tags add_body_enter_proc do |date| "\n" end add_body_leave_proc do |date| "\n" end add_conf_proc( 'google_adsense', 'Google AdSense' ) do if @mode == 'saveconf' then @conf['google_adsense.layout'] = @cgi.params['google_adsense.layout'][0].to_i @conf['google_adsense.color.border'] = @cgi.params['google_adsense.color.border'][0] @conf['google_adsense.color.bg'] = @cgi.params['google_adsense.color.bg'][0] @conf['google_adsense.color.link'] = @cgi.params['google_adsense.color.link'][0] @conf['google_adsense.color.url'] = @cgi.params['google_adsense.color.url'][0] @conf['google_adsense.color.text'] = @cgi.params['google_adsense.color.text'][0] else google_adsense_init( nil ) end <<-HTML

      バナーのサイズ(#{@conf['google_adsense.layout']})

      広告バナーのサイズは全部で12種類あります。お好きなサイズを選んでください。

      バナーの色

      バナーの各パーツの色を指定できます。HTMLやCSSと同じ、6桁の16進数で指定します。

        
      背景  
      リンク  
      URL  
      テキスト  
      HTML end tdiary-contrib-3.2.2/plugin/google_analytics.rb000066400000000000000000000022771213632744000216300ustar00rootroot00000000000000# # Google Analytics plugin for tDiary # # Copyright (C) 2005 TADA Tadashi # You can redistribute it and/or modify it under GPL2. # if /^(?:latest|day|month|nyear|search)$/ =~ @mode then add_footer_proc do google_analytics_insert_code end end def google_analytics_insert_code return '' unless @conf['google_analytics.profile'] <<-HTML HTML end # UA-53836-1 add_conf_proc( 'google_analytics', 'Google Analytics' ) do if @mode == 'saveconf' then @conf['google_analytics.profile'] = @cgi.params['google_analytics.profile'][0] end <<-HTML

      Google Analytics Profile

      set your Profile ID (NNNNN-N)

      HTML end tdiary-contrib-3.2.2/plugin/google_map.rb000066400000000000000000000131271213632744000204120ustar00rootroot00000000000000# -*- coding: utf-8 -*- # # google_map.rb - embeded Google Map for tDiary, use Google Maps JavaScript API V3. # http://code.google.com/intl/ja/apis/maps/documentation/v3/services.html # # Copyright (C) 2010, tamoot # You can redistribute it and/or modify it under GPL2. # def google_map(lat, lon, params = {}) params.merge!(:lat => lat, :lon => lon) google_map_common(params) end def google_geomap(address, params = {}) params.merge!(:address => address) google_map_common(params) end def google_map_common(params) init_gmap_data if feed? require 'cgi' query = params[:lat] && params[:lon] ? "#{params[:lat]},#{params[:lon]}" : params[:address] url = %Q|http://maps.google.com/maps?q=#{CGI::escape(query)}| return %Q|#{url}| end return 'not support this environment.' if @conf.mobile_agent? params[:zoom] ||= 10 params[:html] ||= nil params[:title] ||= nil params[:width] ||= 320 params[:height] ||= 240 params[:address] ||= nil params[:type] ||= :ROADMAP params[:overview]||= false dom_id = "#{@date.strftime("%Y%m")}_#{@gmap_count}" params.merge!(:id => dom_id) params.merge!(:width => 240, :height => 180) if @conf.iphone? @gmap_data << params @gmap_count += 1 %Q|
      | end add_header_proc do if /\A(?:latest|day|month|nyear|preview)\z/ =~ @mode %Q|\n| end end add_body_leave_proc do |date| init_gmap_data gmap_scripts = '' if !feed? && @gmap_data.any? gmap_scripts = %Q|\n| end gmap_scripts end def init_gmap_data @gmap_data ||= [] @gmap_count ||= 0 end def google_map_script(hash) str = '' str << %Q|google.maps.event.addDomListener(window, 'load', function() {\n| str << %Q| var mapdiv = document.getElementById("#{hash[:id]}");\n| str << %Q| var myOptions = {\n| str << %Q| zoom: #{hash[:zoom]},\n| str << %Q| overviewMapControl: #{hash[:overview]},\n| str << %Q| overviewMapControlOptions: {\n| str << %Q| opened: #{hash[:overview]}\n| str << %Q| },\n| str << %Q| center: new google.maps.LatLng(#{hash[:lat]}, #{hash[:lon]}),\n| str << %Q| mapTypeId: google.maps.MapTypeId.#{hash[:type]},\n| str << %Q| scaleControl: true\n| str << %Q| };\n| str << %Q| var gMap = new google.maps.Map(mapdiv, myOptions);\n| # set Marker if hash[:title] str << %Q| var marker = new google.maps.Marker({\n| str << %Q| position: new google.maps.LatLng(#{hash[:lat]}, #{hash[:lon]}),\n| str << %Q| map: gMap,\n| str << %Q| title: '#{hash[:title]}'\n| str << %Q| });\n| # set InfoWindow if hash[:html] str << %Q| var infowindow = new google.maps.InfoWindow({\n| str << %Q| content: '#{hash[:html]}',\n| str << %Q| size: new google.maps.Size(350, 200)\n| str << %Q| });\n| str << %Q| infowindow.open(gMap, marker);\n| end # :html end # :title str << %Q|});\n| str end def google_geomap_script(hash) str = '' str << %Q|google.maps.event.addDomListener(window, 'load', function() {\n| str << %Q| var geocoder = new google.maps.Geocoder();\n| str << %Q| if(geocoder) {\n| str << %Q| geocoder.geocode( { 'address': '#{hash[:address]}'}, function(results, status) {\n| str << %Q| if (status == google.maps.GeocoderStatus.OK) {\n| str << %Q| var geoLat = results[0].geometry.location;\n| str << %Q| var mapdiv = document.getElementById("#{hash[:id]}");\n| str << %Q| var myOptions = {\n| str << %Q| zoom: #{hash[:zoom]},\n| str << %Q| overviewMapControl: #{hash[:overview]},\n| str << %Q| overviewMapControlOptions: {\n| str << %Q| opened: #{hash[:overview]}\n| str << %Q| },\n| str << %Q| center: geoLat,\n| str << %Q| mapTypeId: google.maps.MapTypeId.#{hash[:type]},\n| str << %Q| scaleControl: true\n| str << %Q| };\n| str << %Q| var gMap = new google.maps.Map(mapdiv, myOptions);\n| # set Marker if hash[:title] str << %Q| var marker = new google.maps.Marker({\n| str << %Q| position: geoLat,\n| str << %Q| map: gMap,\n| str << %Q| title: '#{hash[:title]}'\n| str << %Q| });\n| # set InfoWindow if hash[:html] str << %Q| var infowindow = new google.maps.InfoWindow({\n| str << %Q| content: '#{hash[:html]}',\n| str << %Q| size: new google.maps.Size(350, 200)\n| str << %Q| });\n| str << %Q| infowindow.open(gMap, marker);\n| end # :html end # :title str << %Q| }else{\n| str << %Q| alert("Geocode was not successful for the following reason: " + status)\n| str << %Q| }\n| str << %Q| });\n| str << %Q| }\n| str << %Q|});\n| str end # Local Variables: # mode: ruby # indent-tabs-mode: t # tab-width: 3 # ruby-indent-level: 3 # End: # vim: ts=3 tdiary-contrib-3.2.2/plugin/google_sitemaps.rb000066400000000000000000000034611213632744000214620ustar00rootroot00000000000000# google_sitemap.rb # Copyright (c) 2006 http://d.bulkitem.com/ # Distributed under the GPL add_update_proc do require 'time' headers = Array.new header = Hash.new Dir.glob(@conf.data_path + '/????/*.td2') { |data_file| File.open(data_file) { |buffer| buffer.each { |line| line.strip! if line == "." then if header['visible'] then headers.push(header.clone) end header.clear end if %r|^Date: ([0-9]+)$|i =~ line then header['loc'] = sprintf(@conf['google_sitemaps.uri_format'], $1) end if %r|^Last-Modified: ([0-9]+)$|i =~ line then header['lastmod'] = Time.at($1.to_i).iso8601 end if %r|^Visible: (.+)$|i =~ line then if $1.upcase == "TRUE" then header['visible'] = true else header['visible'] = false end end } } } headers.sort! { |a, b| b['loc'] <=> a['loc']} top_page_uri = File::dirname(@conf['google_sitemaps.uri_format']) + '/' now_datetime = Time.now.iso8601 File.open(@conf['google_sitemaps.output_file'], 'w') do |fp| fp.write %Q[\n] fp.write %Q[\n] fp.write %Q[ #{CGI::escapeHTML(top_page_uri)}#{now_datetime}\n] headers.each { |entry| fp.write %Q[ #{CGI::escapeHTML(entry['loc'])}#{entry['lastmod']}\n] } fp.write %Q[\n] end end def saveconf_google_sitemaps if @mode == 'saveconf' then @conf['google_sitemaps.uri_format'] = @cgi.params['google_sitemaps.uri_format'][0] @conf['google_sitemaps.output_file'] = @cgi.params['google_sitemaps.output_file'][0] end end tdiary-contrib-3.2.2/plugin/google_webmaster.rb000066400000000000000000000013261213632744000216240ustar00rootroot00000000000000# encoding: utf-8 # google-webmaster.rb - embed a meta tag to let Google Webmaster tool know your verification code. # # Copyright (C) 2012, Tatsuya Sato # You can redistribute it and/or modify it under GPL2. # add_header_proc do "" end add_conf_proc('Google Webmaster', 'Google ウェブマスターツール', 'etc') do if @mode == 'saveconf' @conf['google_webmaster.verification'] = @cgi.params['google_webmaster.verification'][0] end <<-HTML

      Google ウェブマスターツールの検証コード

      HTML end tdiary-contrib-3.2.2/plugin/hatena_bookmark_nocomment.rb000066400000000000000000000003071213632744000235010ustar00rootroot00000000000000# hatena_bookmark_nocomment.rb # # Copyright (c) 2008 SHIBATA Hiroshi # Distributed under the GPL2 # add_header_proc do %Q|| end tdiary-contrib-3.2.2/plugin/hatena_star.rb000066400000000000000000000044221213632744000205700ustar00rootroot00000000000000# hatena_star.rb # Itoshi Nikaido # Distributed under the GPL @hatena_star_options = { 'token' => 'Token', 'star.image' => '.hatena-star-star-image', 'star.add' => '.hatena-star-add-button-image', 'comment.image' => '.hatena-star-comment-button-image' } add_header_proc do hatena_star = %Q|\t\n| hatena_star << %Q|\t\n| hatena_star << %Q|\t\n| end add_conf_proc( 'hatena_star', 'Hatena::Star' ) do if( @mode == 'saveconf' ) then @hatena_star_options.keys.each do |o| @conf["hatena_star.#{o}"] = @cgi.params["hatena_star.#{o}"][0].strip if @conf["hatena_star.#{o}"].length == 0 then @conf["hatena_star.#{o}"] = nil end end end <<-HTML

      Token

      Star Image (URL)

      Add Star Image (URL)

      Comment Image (URL)

      HTML end tdiary-contrib-3.2.2/plugin/hb_footer.rb000066400000000000000000000147111213632744000202500ustar00rootroot00000000000000# # hb_footer.rb # # はてなブックマーク (http://b.hatena.ne.jp/) のコメントを該当日付に貼り付けるtDiaryプラグイン # 改造版rss_recent Version 0.0.5i2と共に使用する # # Licence: GPL # Author: ishinao # add_body_leave_proc(Proc.new do |date| if @mode == 'day' or @mode == 'latest' diary = @diaries[date.strftime('%Y%m%d')] pnum = 1 hbsrc = '' diary.each_section do |para| td_url = "http://tdiary.ishinao.net/#{date.strftime('%Y%m%d')}.html%23p#{'%02d' % pnum}" hb_url = "http://b.hatena.ne.jp/entry/#{td_url}" rss_url = "http://b.hatena.ne.jp/entry/rss/#{td_url}" template_head = %Q[
      \n

      はてなブックマークの反応

      \n\n
      \n" cache_time = 3600; if date.strftime('%Y-%m-%d') != Time.now.strftime('%Y-%m-%d') cache_time = 3600 * 12; end hbsrc << hb_footer(rss_url, 50, cache_time, template_head, template_list, template_foot) pnum+=1 end hbsrc else '' end end) # rss-recent.rb: RSS recent plugin # # rss_recnet: show recnet list from RSS # parameters (default): # url: URL of RSS # max: max of list itmes(5) # cache_time: cache time(second) of RSS(60*60) # template_head: rendering header part # template_list: rendering RSS item part(with loop) # template_foot: rendering footer part # # Copyright (c) 2003-2004 Kouhei Sutou # Distributed under the GPL # # Modified using template string and content:encoded # Version 0.0.5i2 by ishinao # require "rss/rss" RSS_RECENT_FIELD_SEPARATOR = "\0" RSS_RECENT_ENTRY_SEPARATOR = "\1" RSS_RECENT_VERSION = "0.0.5i2" RSS_RECENT_HTTP_HEADER = { "User-Agent" => "tDiary RSS recent plugin version #{RSS_RECENT_VERSION}. " << "Using RSS parser version is #{::RSS::VERSION}.", } def hb_footer(url, max = 5, cache_time = 3600, \ template_head = "\n") url.untaint cache_file = "#{@cache_path}/rss-recent.#{CGI.escape(url)}" hb_footer_cache_rss(url, cache_file, cache_time.to_i) return '' unless test(?r, cache_file) rv = template_head i = 0 hb_footer_read_from_cache(cache_file).each do |title, url, time, content, description| break if i >= max next if (url.nil? or title.nil?) rv << eval('%Q[' + template_list + ']') i += 1 end rv << template_foot if i > 0 rv else '' end end class InvalidResourceError < StandardError; end def hb_footer_cache_rss(url, cache_file, cache_time) cached_time = nil cached_time = File.mtime(cache_file) if File.exist?(cache_file) if cached_time.nil? or Time.now > cached_time + cache_time require 'time' require 'open-uri' require 'net/http' require 'uri/generic' require 'rss/parser' require 'rss/1.0' require 'rss/2.0' require 'rss/dublincore' require 'rss/content' begin uri = URI.parse(url) raise URI::InvalidURIError if uri.scheme != "http" rss_source = hb_footer_fetch_rss(uri, cached_time) raise InvalidResourceError if rss_source.nil? # parse RSS rss = ::RSS::Parser.parse(rss_source, false) raise ::RSS::Error if rss.nil? # pre processing begin rss.output_encoding = @conf.charset || charset rescue ::RSS::UnknownConversionMethodError end rss_infos = rss.items.collect do |item| hb_footer_pubDate_to_dc_date(item) [item.title, item.link, item.dc_date, item.content_encoded, item.description] end hb_footer_write_to_cache(cache_file, rss_infos) rescue URI::InvalidURIError hb_footer_write_to_cache(cache_file, [['Invalid URI', url]]) rescue InvalidResourceError, ::RSS::Error # hb_footer_write_to_cache(cache_file, [['Invalid Resource', url]]) # when cannot get valid RSS, use old cache end end end def hb_footer_fetch_rss(uri, cache_time) rss = nil begin uri.open(hb_footer_http_header(cache_time)) do |f| case f.status.first when "200" rss = f.read # STDERR.puts "Got RSS of #{uri}" when "304" # not modified # STDERR.puts "#{uri} does not modified" else raise InvalidResourceError end end rescue TimeoutError, SocketError, StandardError, SecurityError # occured in redirect raise InvalidResourceError end rss end def hb_footer_http_header(cache_time) header = RSS_RECENT_HTTP_HEADER.dup if cache_time.respond_to?(:rfc2822) header["If-Modified-Since"] = cache_time.rfc2822 end header end def hb_footer_write_to_cache(cache_file, rss_infos) File.open(cache_file, 'w') do |f| f.flock(File::LOCK_EX) rss_infos.each do |info| f << info.join(RSS_RECENT_FIELD_SEPARATOR) f << RSS_RECENT_ENTRY_SEPARATOR end f.flock(File::LOCK_UN) end end def hb_footer_read_from_cache(cache_file) require 'time' infos = [] File.open(cache_file) do |f| while info = f.gets(RSS_RECENT_ENTRY_SEPARATOR) info = info.chomp(RSS_RECENT_ENTRY_SEPARATOR) infos << info.split(RSS_RECENT_FIELD_SEPARATOR) end end infos.collect do |title, url, time, content, description| [ hb_footer_convert(title), hb_footer_convert(url), hb_footer_convert(time) {|time| Time.parse(time)}, hb_footer_convert(content), hb_footer_convert(description), ] end end def hb_footer_convert(str) if str.nil? or str.empty? nil else if block_given? yield str else str end end end # from RWiki def hb_footer_modified(t) return '-' unless t dif = (Time.now - t).to_i dif = dif / 60 return "#{dif}m" if dif <= 60 dif = dif / 60 return "#{dif}h" if dif <= 24 dif = dif / 24 return "#{dif}d" end # from RWiki def hb_footer_modified_class(t) return 'dangling' unless t dif = (Time.now - t).to_i dif = dif / 60 return "modified-hour" if dif <= 60 dif = dif / 60 return "modified-today" if dif <= 24 dif = dif / 24 return "modified-month" if dif <= 30 return "modified-year" if dif <= 365 return "modified-old" end def hb_footer_pubDate_to_dc_date(target) if target.respond_to?(:pubDate) class << target alias_method(:dc_date, :pubDate) end end end tdiary-contrib-3.2.2/plugin/hb_footer4sec.rb000066400000000000000000000145001213632744000210230ustar00rootroot00000000000000# # hb_footer.rb # # はてなブックマーク (http://b.hatena.ne.jp/) のコメントを該当セクションに貼り付けるtDiaryプラグイン # 改造版rss_recent Version 0.0.5i2と共に使用する # # Licence: GPL # Author: ishinao # add_section_leave_proc do |date, index| td_url = "http://tdiary.ishinao.net/#{date.strftime('%Y%m%d')}.html%23p#{'%02d' % index}" hb_url = "http://b.hatena.ne.jp/entry/#{td_url}" rss_url = "http://b.hatena.ne.jp/entry/rss/#{td_url}" template_head = %Q[
      \n

      このセクションに対するはてブ

      \n\n
      \n" cache_time = 3600; if date.strftime('%Y-%m-%d') != Time.now.strftime('%Y-%m-%d') cache_time = 3600 * 12; end hb_footer4sec(rss_url, 50, cache_time, template_head, template_list, template_foot) end # rss-recent.rb: RSS recent plugin # # rss_recnet: show recnet list from RSS # parameters (default): # url: URL of RSS # max: max of list itmes(5) # cache_time: cache time(second) of RSS(60*60) # template_head: rendering header part # template_list: rendering RSS item part(with loop) # template_foot: rendering footer part # # Copyright (c) 2003-2004 Kouhei Sutou # Distributed under the GPL # # Modified using template string and content:encoded # Version 0.0.5i2 by ishinao # require "rss/rss" RSS_RECENT_FIELD_SEPARATOR = "\0" RSS_RECENT_ENTRY_SEPARATOR = "\1" RSS_RECENT_VERSION = "0.0.5i2" RSS_RECENT_HTTP_HEADER = { "User-Agent" => "tDiary RSS recent plugin version #{RSS_RECENT_VERSION}. " << "Using RSS parser version is #{::RSS::VERSION}.", } def hb_footer4sec(url, max = 5, cache_time = 3600, \ template_head = "\n") url.untaint cache_file = "#{@cache_path}/rss-recent.#{CGI.escape(url)}" hb_footer4sec_cache_rss(url, cache_file, cache_time.to_i) return '' unless test(?r, cache_file) rv = template_head i = 0 hb_footer4sec_read_from_cache(cache_file).each do |title, url, time, content, description| break if i >= max next if (url.nil? or title.nil?) rv << eval('%Q[' + template_list + ']') i += 1 end rv << template_foot if i > 0 rv else '' end end class InvalidResourceError < StandardError; end def hb_footer4sec_cache_rss(url, cache_file, cache_time) cached_time = nil cached_time = File.mtime(cache_file) if File.exist?(cache_file) if cached_time.nil? or Time.now > cached_time + cache_time require 'time' require 'open-uri' require 'net/http' require 'uri/generic' require 'rss/parser' require 'rss/1.0' require 'rss/2.0' require 'rss/dublincore' require 'rss/content' begin uri = URI.parse(url) raise URI::InvalidURIError if uri.scheme != "http" rss_source = hb_footer4sec_fetch_rss(uri, cached_time) raise InvalidResourceError if rss_source.nil? # parse RSS rss = ::RSS::Parser.parse(rss_source, false) raise ::RSS::Error if rss.nil? # pre processing begin rss.output_encoding = @conf.charset || charset rescue ::RSS::UnknownConversionMethodError end rss_infos = rss.items.collect do |item| hb_footer4sec_pubDate_to_dc_date(item) [item.title, item.link, item.dc_date, item.content_encoded, item.description] end hb_footer4sec_write_to_cache(cache_file, rss_infos) rescue URI::InvalidURIError hb_footer4sec_write_to_cache(cache_file, [['Invalid URI', url]]) rescue InvalidResourceError, ::RSS::Error # hb_footer4sec_write_to_cache(cache_file, [['Invalid Resource', url]]) # when cannot get valid RSS, use old cache end end end def hb_footer4sec_fetch_rss(uri, cache_time) rss = nil begin uri.open(hb_footer4sec_http_header(cache_time)) do |f| case f.status.first when "200" rss = f.read # STDERR.puts "Got RSS of #{uri}" when "304" # not modified # STDERR.puts "#{uri} does not modified" else raise InvalidResourceError end end rescue TimeoutError, SocketError, StandardError, SecurityError # occured in redirect raise InvalidResourceError end rss end def hb_footer4sec_http_header(cache_time) header = RSS_RECENT_HTTP_HEADER.dup if cache_time.respond_to?(:rfc2822) header["If-Modified-Since"] = cache_time.rfc2822 end header end def hb_footer4sec_write_to_cache(cache_file, rss_infos) File.open(cache_file, 'w') do |f| f.flock(File::LOCK_EX) rss_infos.each do |info| f << info.join(RSS_RECENT_FIELD_SEPARATOR) f << RSS_RECENT_ENTRY_SEPARATOR end f.flock(File::LOCK_UN) end end def hb_footer4sec_read_from_cache(cache_file) require 'time' infos = [] File.open(cache_file) do |f| while info = f.gets(RSS_RECENT_ENTRY_SEPARATOR) info = info.chomp(RSS_RECENT_ENTRY_SEPARATOR) infos << info.split(RSS_RECENT_FIELD_SEPARATOR) end end infos.collect do |title, url, time, content, description| [ hb_footer4sec_convert(title), hb_footer4sec_convert(url), hb_footer4sec_convert(time) {|time| Time.parse(time)}, hb_footer4sec_convert(content), hb_footer4sec_convert(description), ] end end def hb_footer4sec_convert(str) if str.nil? or str.empty? nil else if block_given? yield str else str end end end # from RWiki def hb_footer4sec_modified(t) return '-' unless t dif = (Time.now - t).to_i dif = dif / 60 return "#{dif}m" if dif <= 60 dif = dif / 60 return "#{dif}h" if dif <= 24 dif = dif / 24 return "#{dif}d" end # from RWiki def hb_footer4sec_modified_class(t) return 'dangling' unless t dif = (Time.now - t).to_i dif = dif / 60 return "modified-hour" if dif <= 60 dif = dif / 60 return "modified-today" if dif <= 24 dif = dif / 24 return "modified-month" if dif <= 30 return "modified-year" if dif <= 365 return "modified-old" end def hb_footer4sec_pubDate_to_dc_date(target) if target.respond_to?(:pubDate) class << target alias_method(:dc_date, :pubDate) end end end tdiary-contrib-3.2.2/plugin/hb_footer4sec_js.rb000066400000000000000000000017321213632744000215220ustar00rootroot00000000000000# hb_footer4sec_js.rb $Revision 1.0 $ # # Copyright (c) 2008 SHIBATA Hiroshi # You can redistribute it and/or modify it under GPL2. # def permalink( date, index, escape = true ) ymd = date.strftime( "%Y%m%d" ) uri = @conf.index.dup uri.sub!( %r|\A(?!https?://)|i, @conf.base_url ) uri.gsub!( %r|/\.(?=/)|, "" ) # /././ -> / link = uri + anchor( "#{ymd}p%02d" % index ) link.sub!( "#", "%23" ) if escape link end add_section_leave_proc do |date, index| if @mode == 'day' and not bot? and not @conf.mobile_agent? then <<-SCRIPT
      SCRIPT end end tdiary-contrib-3.2.2/plugin/hide_comment_form.rb000066400000000000000000000001051213632744000217470ustar00rootroot00000000000000def hide_comment_form @conf.hide_comment_form = true return '' end tdiary-contrib-3.2.2/plugin/hide_sidebar_iphone.rb000066400000000000000000000005341213632744000222430ustar00rootroot00000000000000# hide_sidebar_iphone.rb # # Copyright (C) 2008 SHIBATA Hiroshi # You can redistribute it and/or modify it under GPL2. # add_header_proc do if @conf.iphone? then <<-CSS CSS end end tdiary-contrib-3.2.2/plugin/iddy.rb000066400000000000000000000045601213632744000172330ustar00rootroot00000000000000# # iddy.rb: iddy.jp plugin for tDiary # # Copyright (C) 2007 by TADA Tadashi # Distributed under GPL. # ###################################################################### # If you will modify or release another version of this code, # please get your own application key from iddy.jp and replace below. ###################################################################### @iddy_key = 'f93d2f38442fae3a1f08e82f84d335112cca0855' require 'open-uri' require 'timeout' require 'rexml/document' def iddy( id ) begin cache = "#{@cache_path}/iddy.xml" xml = open( cache ) {|f| f.read } if Time::now > File::mtime( cache ) + 60*60 then File::delete( cache ) # clear cache 1 hour later end rescue Errno::ENOENT begin xml = iddy_call_api( id, @iddy_key ) open( cache, 'wb' ) {|f| f.write( xml ) } rescue Timeout::Error return '
      No data.
      ' end end doc = REXML::Document::new( xml ) if doc.elements[1].attribute( 'status' ).to_s == 'fail' then return '
      iddy.jp returns fail.
      ' end user = doc.elements.to_a( '*/*/user' )[0].elements profileurl = user.to_a( 'profileurl' )[0] unless profileurl then return '
      No profile URL on iddy.jp.
      ' end imageurl = user.to_a( 'imageurl' )[0] name = user.to_a( 'name' )[0] nameroma = user.to_a( 'nameroma' )[0] mail = user.to_a( 'mail' )[0] submail = user.to_a( 'submail' )[0] html = '' @conf.to_native( html ) end def iddy_call_api( id, key ) request = "http://iddy.jp/api/user/?apikey=#{key}" request << "&accountname=#{id}" proxy = @conf['proxy'] proxy = 'http://' + proxy if proxy timeout( 3 ) do open( request, :proxy => proxy ) {|f| f.read } end end tdiary-contrib-3.2.2/plugin/image_detail.rb000066400000000000000000000107411213632744000207040ustar00rootroot00000000000000# -*- coding: utf-8 -*- # image_gps.rb $Revision: 1.1 $ # # 概要: # # # 使い方: # 絵日記Plugin(image.rb)とおなじ # # Copyright (c) 2009,2010 kp # Distributed under the GPL # =begin ChangeLog 2010-04-21 kp * スマートフォン対応 * Google Maps API Keyが設定されていない場合はStaticMAPを生成しない * リンク先をGoogle Mapsに統一 2009-06-03 kp * first version * fork from image_gps2.rb =end require 'exifparser' def tky2wgs lat,lon lat_w = lat - lat*0.00010695 + lon*0.000017464 + 0.0046017 lon_w = lon - lat*0.000046038 - lon*0.000083043 + 0.010040 lat = lat_w lon = lon_w return lat,lon end def image( id, alt = 'image', thumbnail = nil, size = nil, place = 'photo' ) if @conf.secure then image = "#{@image_date}_#{id}.jpg" image_t = "#{@image_date}_#{thumbnail}.jpg" if thumbnail else image = image_list( @image_date )[id.to_i] image_t = image_list( @image_date )[thumbnail.to_i] if thumbnail end if size then if size.kind_of?(Array) size = %Q[ width="#{size[0]}" height="#{size[1]}"] else size = %Q[ width="#{size.to_i}"] end else size = "" end exif = ExifParser.new("#{@image_dir}/#{image}".untaint) rescue nil google = "http://maps.google.co.jp" if exif #GPS Info begin lat = exif['GPSLatitude'].value lat = lat[0].to_f + lat[1].to_f/60 + lat[2].to_f/3600 lat = -lat if exif['GPSLatitudeRef'].value == 'S' lon = exif['GPSLongitude'].value lon = lon[0].to_f + lon[1].to_f/60 + lon[2].to_f/3600 lon = -lon if exif['GPSLongitudeRef'].value == 'W' datum = exif['GPSMapDatum'].value if exif.tag?('GPSMapDatum') lat,lon = tky2wgs(lat,lon) if datum == 'TOKYO' rescue lat = nil end detail = "" end img = %Q[#{alt}] img_t = %Q[#{alt}] url = '' if @conf.mobile_agent? url += %Q[] unless lat.nil? url += thumbnail ? img_t : img url += %Q[] unless lat.nil? else url += %Q[

      #{alt}

      ] if detail url += %Q[] url += thumbnail ? img_t : img url +=%Q[] url += %Q[#{detail}
      ] if detail end url end add_header_proc do if @mode !~ /conf$/ and not bot? then <<-HTML HTML else '' end end add_conf_proc('image_gps','image_gpsの設定','etc') do if @mode == 'saveconf' then @conf['image_gps.add_info'] = @cgi.params['image_gps.add_info'][0] @conf['image_gps.google_maps_api_key'] = @cgi.params['image_gps.google_maps_api_key'][0] end <<-HTML

      撮影条件の表示

      タイトルに撮影条件を追加する

      Google Maps API Key

      HTML end tdiary-contrib-3.2.2/plugin/image_ex.rb000066400000000000000000000354741213632744000200700ustar00rootroot00000000000000# image_plugin_ex.rb # version 0.3 # -pv- # # 名称: # 絵日記Plugin機能追加版 # # 概要: # 日記更新画面からの画像アップロード、サムネイル作成、本文への表示 # # 使う場所: # 本文 # # 使い方: # image( number, 'altword', thumbnail ) - 画像を表示します。 # number - 画像の番号0、1、2等 # altword - imgタグの altに入れる文字列 # thumbnail - サムネイル(小さな画像)を指定する(省略可) # # image_left( number, 'altword', thumbnail ) - imageにclass=leftを追加します。 # image_right( number, 'altword', thumbnail ) - imageにclass=rightを追加します。 # # image_link( number, 'desc' ) - 画像へのリンクを生成します。 # number - 画像の番号0、1、2等 # desc - 画像の説明 # # その他: # tDiary version 1.5.4以降で動作します。 # tdiary.confで、 # 画像ファイルを保存するディレクトリ # @options['image.dir'] # 画像ファイルのURL # @options['image.url'] # 縮小画像の生成方法 # @options['image.url'] # 0 - 縮小画像を生成しない # 1 - ImageMagickのconvertで縮小画王を生成 # 2 - netpbm群で縮小画王を生成 # を設定してください。 # また、@secure = trueな環境では動作しません。 # # 詳しくは、 # http://shimoi.s26.xrea.com/hiki/hiki.xcg?TdiaryEnikkiEx # をご覧下さい。 # # ライセンスについて: # Copyright (c) 2002 Daisuke Kato # Copyright (c) 2002 Toshi Okada # Copyright (c) 2003 Yoshimi KURUMA # # You can redistribute it and/or modify it under GPL2. # =begin Changelog 2003-05-16 Yoshimi KURUMA * method 'image' is extended to show a thumbnail. * new method: 'image_link'. * version 0.3 2003-05-16 Yoshimi KURUMA * modify illegal option names. * version 0.2. 2003-05-16 Yoshimi KURUMA * support manual upload of thumbnail when useresize == 0 2003-04-27 Yoshimi KURUMA * link element is removed when no thumbnail. 2003-04-25 Yoshimi KURUMA * add JavaScript for insert plugin tag into diary. * upload/delete form style changed. 2003-04-24 Yoshimi KURUMA * upload/delete form style changed. 2003-04-22 Yoshimi KURUMA * version 0.1 first form_proc version. =end @image_dir = @options && @options['image.dir'] || './images/' @image_dir.chop! if /\/$/ =~ @image_dir @image_url = @options && @options['image.url'] || './images/' @image_url.chop! if /\/$/ =~ @image_url @imageex_thumbnailsize = @options && @options['image_ex.previewsize'] || 120 @imageex_yearlydir = @options && @options['image_ex.yearlydir'] || 0 if @conf.smartphone? enable_js("image_ex.js") end add_body_enter_proc(Proc.new do |date| @image_date = date.strftime("%Y%m%d") @image_year = date.strftime("%Y") "" end) def image( id, alt = "image", id2 = nil, width = nil, place="none" ) @image_date ||= @date.strftime("%Y%m%d") @image_year ||= @date.strftime("%Y") if @imageex_yearlydir == 1 image_url = %Q[#{@image_url}/#{@image_year}/] image_dir = %Q[#{@image_dir}/#{@image_year}/] else image_url = %Q[#{@image_url}/] image_dir = %Q[#{@image_dir}/] end image_dir.untaint Dir.mkdir(image_dir) unless File.directory?(image_dir) list = imageList(@image_date, image_dir).untaint slist = imageList(@image_date, image_dir, "s").untaint if width width_tag = %Q[width="#{h width}"] else width_tag = "" end if id2 %Q[#{h alt}] else if slist[id.to_i] %Q[#{h alt}] else if list[id.to_i] # %Q[#{h alt}] %Q[#{h alt}] end end end end def image_left( id, alt = "image", id2 = nil, width=nil ) image( id, alt, id2, width, "left" ) end def image_right( id, alt = "image", id2 = nil, width=nil ) image( id, alt, id2, width, "right" ) end def image_link( id, str ) @image_date ||= @date.strftime("%Y%m%d") @image_year ||= @date.strftime("%Y") if @imageex_yearlydir == 1 image_url = %Q[#{@image_url}/#{@image_year}/] image_dir = %Q[#{@image_dir}/#{@image_year}/] else image_url = %Q[#{@image_url}/] image_dir = %Q[#{@image_dir}/] end list = imageList(@image_date, image_dir).untaint %Q[#{str}] end ### def imageList(date, image_dir='@image_dir', prefix="") date = "#{prefix}"+date image_path = [] Dir.foreach(image_dir){ |file| if file =~ /(.*)\_(.*)\.(.*)/ if $1 == date image_path[$2.to_i] = file end end } image_path end add_form_proc do |date| begin # ENV['PATH'] = nil imageex_useresize = @options && @options['image_ex.useresize'] || 0 imageex_converttype = @options && @options['image_ex.converttype'] || 0 imageex_thresholdsize = @options && @options['image_ex.thresholdsize'] || 160 imageex_convertedwidth = @options && @options['image_ex.convertedwidth'] || 160 imageex_convertedheight = @options && @options['image_ex.convertedheight'] || 120 if imageex_useresize == 1 || imageex_useresize ==2 begin require 'image_size.rb' rescue LoadError imageex_useresize = 0 end end if imageex_useresize == 1 def resize_image(orig, new, width, height, imageex_convertedwidth, imageex_convertedheight, orig_type, new_type) imageex_convertpath = @options && @options['image_ex.convertpath'] || "convert" imageex_convertpath if width > height imageex_convertedsize = %Q[#{imageex_convertedwidth}x#{imageex_convertedheight}] imageex_convertedsize else imageex_convertedsize = %Q[#{imageex_convertedheight}x#{imageex_convertedwidth}] imageex_convertedsize end system(imageex_convertpath , "-geometry", imageex_convertedsize , orig, new) if FileTest::size?( new ) == 0 File::delete( new ) end end elsif imageex_useresize == 2 def resize_image(orig, new, width, height, imageex_convertedwidth, imageex_convertedheight, orig_type, new_type) pnmscale = @options && @options['image_ex.pnmscalepath'] || "pnmscale" jpegtopnm = @options && @options['image_ex.jpegtopnmpath'] || "jpegtopnm" pnmtojpeg = @options && @options['image_ex.pnmtojpegpath'] || "pnmtojpeg" pngtopnm = @options && @options['image_ex.pngtopnmpath'] || "pngtopnm" pnmtopng = @options && @options['image_ex.pnmtopngpath'] || "pnmtopng" giftopnm = @options && @options['image_ex.giftopnmpath'] || "giftopnm" tifftopnm = @options && @options['image_ex.tifftopnmpath'] || "tifftopnm" bmptopnm = @options && @options['image_ex.bmptopnmpath'] || "bmptopnm" downtype = orig_type.downcase topnm = eval("#{downtype}topnm") if new_type == "jpg" pnmto = pnmtojpeg elsif new_type == "png" pnmto = pnmtopng end if width > height imageex_convertedsize ="#{imageex_convertedwidth}" else imageex_convertedsize ="#{imageex_convertedheight}" end com_line =%Q[#{topnm} #{orig} | #{pnmscale} --width #{imageex_convertedsize} | #{pnmto} > #{new}] system( com_line ) if FileTest::size?( new ) == 0 File::delete( new ) end end end def dayimagelist( image_dir, image_date, prefix="") image_path = [] image_dir.untaint Dir.foreach(image_dir){ |file| if file=~ /(.*)\_(.*)\.(.*)/ if $1 == "#{prefix}" + image_date.to_s image_path[$2.to_i] = file end end } return image_path end if @cgi.params['plugin_image_add'][0] && @cgi.params['plugin_image_file'][0].original_filename != '' image_dir = @cgi.params['plugin_image_dir'][0].read.untaint image_filename = '' image_extension = '' image_date = date.strftime("%Y%m%d") image_filename = @cgi.params['plugin_image_file'][0].original_filename if image_filename =~ /(\.jpg|\.jpeg|\.gif|\.png)\z/i image_extension = $1 image_name = dayimagelist(image_dir, image_date) image_file = image_dir+image_date+"_"+image_name.length.to_s+image_extension.downcase image_file.untaint File::umask( 022 ) File::open( image_file, "wb" ) {|f| f.print @cgi.params['plugin_image_file'][0].read } end if imageex_useresize == 1 or imageex_useresize == 2 open(image_file,"rb") do |fh| img = ImageSize.new(fh.read) width = img.get_width height = img.get_height orig_type = img.get_type if imageex_converttype == 0 new_type = "jpg" elsif imageex_converttype == 1 new_type = "png" end if width if width > imageex_thresholdsize or height > imageex_thresholdsize small_image_file = %Q[#{image_dir}s#{image_date}_#{image_name.length.to_s}.#{new_type}] resize_image(image_file, small_image_file, width, height, imageex_convertedwidth, imageex_convertedheight, orig_type, new_type) end end end end elsif @cgi.params['plugin_image_thumbnail'][0] && @cgi.params['plugin_image_file'][0].original_filename != '' image_dir = @cgi.params['plugin_image_dir'][0].read.untaint image_filename = '' image_extension = '' image_date = date.strftime("%Y%m%d") image_filename = @cgi.params['plugin_image_file'][0].original_filename if image_filename =~ /(\.jpg|\.jpeg|\.gif|\.png)\z/i image_extension = $1 image_name = @cgi.params['plugin_image_name'][0].read.untaint image_file=image_dir+"s"+image_name+image_extension.downcase image_file.untaint File::umask( 022 ) File::open( image_file, "wb" ) {|f| f.print @cgi.params['plugin_image_file'][0].read } end elsif @cgi.params['plugin_image_del'][0] image_dir = @cgi.params['plugin_image_dir'][0] image_date = date.strftime("%Y%m%d") image_name = dayimagelist( image_dir, image_date) image_name2= dayimagelist( image_dir, image_date, "s") @cgi.params['plugin_image_id'].untaint.each do |id| if image_name[id.to_i] image_file=image_dir+image_name[id.to_i] image_file.untaint if File::exist?(image_file) File::delete(image_file) end end if image_name2[id.to_i] image_file2=image_dir+image_name2[id.to_i] image_file2.untaint if File::exist?(image_file2) File::delete(image_file2) end end end end rescue Exception puts "Content-Type: text/plain\n\n" puts "#$! (#{$!.type})" puts "" puts $@.join( "\n" ) end if @imageex_yearlydir == 1 image_dir = %Q[#{@image_dir}/#{@date.year}/] else image_dir = %Q[#{@image_dir}/] end if @imageex_yearlydir == 1 image_url = %Q[#{@image_url}/#{@date.year}/] else image_url = %Q[#{@image_url}/] end Dir.mkdir(image_dir) unless File.directory?(image_dir) n_image = imageList(@date.strftime("%Y%m%d"), image_dir).length list = imageList(@date.strftime("%Y%m%d"), image_dir) slist = imageList(@date.strftime("%Y%m%d"), image_dir, "s") pretable="" posttable="" if n_image > 0 pretable<< %Q[] posttable << %Q[
      ] end if @conf.respond_to?(:style) and @conf.style =~ /Wiki$/i image_plugin_tag1 = "{{" image_plugin_tag2 = "}}" elsif @conf.respond_to?(:style) and @conf.style =~ /RD$/i image_plugin_tag1 = "((%" image_plugin_tag2 = "%))" else image_plugin_tag1 = "<%=" image_plugin_tag2 = "%>" end r = '' r << %Q[ ] i = '' i << "" nt=0 id=0 while id < n_image do thumbnail_tag = '' if slist[id.to_i] src_tag = %Q[src="#{h image_url}#{h slist[id.to_i]}"] alt_tag = %Q[alt="#{h slist[id.to_i]}"] else src_tag = %Q[src="#{h image_url}#{h list[id.to_i]}"] alt_tag = %Q[alt="#{h list[id.to_i]}"] thumbnail_tag = %Q[
      #{csrf_protection}
      ] if imageex_useresize == 0 end ptag = "#{image_plugin_tag1}image #{id}, '画像の説明'#{image_plugin_tag2}" i<< %Q[
      #{image_plugin_tag1}image #{h id},'title#{h id}'#{image_plugin_tag2}
      #{thumbnail_tag}
      #{csrf_protection}
      ] if slist[id.to_i] || list[id.to_i] nt += 1 if slist[id.to_i] || list[id.to_i] if nt > 0 and nt%2 == 0 i<< %Q[
      ] end id +=1 end if n_image > 0 r << %Q[
      絵日記(一覧・削除)
      #{pretable} #{i} #{posttable}
      ] end r << %Q[
      絵日記(追加)
      #{csrf_protection}
      ] end # vim: set ts=3 sw=3 noexpandtab : tdiary-contrib-3.2.2/plugin/image_gps.rb000066400000000000000000000072001213632744000202270ustar00rootroot00000000000000# -*- coding: utf-8 -*- # image_gps.rb $Revision: 1.7 $ # # 概要: # 画像にGPSによる位置情報が含まれている場合は、対応する地図へのリンクを生成する。 # # 使い方: # 絵日記Plugin(image.rb)とおなじ # # Copyright (c) 2004,2010 kp # Distributed under the GPL # =begin ChangeLog 2010-04-21 kp * リンク先をGoogleに統一 2009-06-01 kp * モバイルモード時も世界測地系とする 2009-05-26 kp * walk.eznavi.jpの場合のクエリを修正 * リンク先をGoogle Mapsに * wgs2tkyを使用しない 2008-05-22 kp * MapDatumがTOKYO以外の場合、WGS-84と類推する 2008-01-17 kp * いろいろ変更 2006-03-28 kp * cooperation with ALPSLAB clip! 2006-03-27 kp * use exifparser 2005-07-25 kp * correct link URL when access with mobile. 2005-07-19 kp * MapDatum macth to WGS84 2005-05-25 kp * correct URL link to Mapion. 2005-05-24 kp * create link to http://walk.eznavi.jp when access with mobile. 2004-11-30 kp * first version =end require 'exifparser' def tky2wgs lat,lon lat_w = lat - lat*0.00010695 + lon*0.000017464 + 0.0046017 lon_w = lon - lat*0.000046038 - lon*0.000083043 + 0.010040 lat = lat_w lon = lon_w return lat,lon end def image( id, alt = 'image', thumbnail = nil, size = nil, place = 'photo' ) if @conf.secure then image = "#{@image_date}_#{id}.jpg" image_t = "#{@image_date}_#{thumbnail}.jpg" if thumbnail else image = image_list( @image_date )[id.to_i] image_t = image_list( @image_date )[thumbnail.to_i] if thumbnail end if size then if size.kind_of?(Array) size = %Q[ width="#{size[0]}" height="#{size[1]}"] else size = %Q[ width="#{size.to_i}"] end else size = "" end #m_map = 'http://m.google.com/maps' map = 'http://maps.google.co.jp' exif = ExifParser.new("#{@image_dir}/#{image}".untaint) rescue nil datum = nil if exif if @conf['image_gps.add_info'] alt += ' '+exif['Model'].to_s if exif.tag?('Model') alt += ' '+exif['FocalLength'].to_s if exif.tag?('FocalLength') alt += ' '+exif['ExposureTime'].to_s if exif.tag?('ExposureTime') alt += ' '+exif['FNumber'].to_s if exif.tag?('FNumber') end begin lat = exif['GPSLatitude'].value lat = lat[0].to_f + lat[1].to_f/60 + lat[2].to_f/3600 lat = -lat if exif['GPSLatitudeRef'].value == 'S' lon = exif['GPSLongitude'].value lon = lon[0].to_f + lon[1].to_f/60 + lon[2].to_f/3600 lon = -lon if exif['GPSLongitudeRef'].value == 'W' datum = exif['GPSMapDatum'].value if exif.tag?('GPSMapDatum') rescue lat = nil end end unless lat.nil? lat,lon = tky2wgs(lat,lon) if datum == 'TOKYO' end if thumbnail url = %Q[#{alt}] elsif lat.nil? url = %Q[#{alt}] else if @conf.mobile_agent? url = %Q[] else url = %Q[] end url += %Q[#{alt}] end url end add_conf_proc('image_gps','image_gpsの設定','etc') do if @mode == 'saveconf' then @conf['image_gps.add_info'] = @cgi.params['image_gps.add_info'][0] end <<-HTML

      撮影条件の表示

      タイトルに撮影条件を追加する

      HTML end tdiary-contrib-3.2.2/plugin/inline_wiki.rb000066400000000000000000000001771213632744000206030ustar00rootroot00000000000000# Copyright (C) 2009 Hideki Sakamoto require 'hikidoc' def inline_wiki(buf) HikiDoc::to_html(buf) end tdiary-contrib-3.2.2/plugin/instagr.rb000066400000000000000000000034561213632744000177540ustar00rootroot00000000000000# -*- coding: utf-8 -*- # # instagr.rb - plugin to insert images on instagr.am # # Copyright (C) 2011, tamoot # You can redistribute it and/or modify it under GPL2. # # usage: # <%= instagr 'short URL instag.ram' => # <%= instagr 'short URL instag.ram', size} => # # available size option: # :small => 150x150 pixel # :medium => 306x306 pixel (default) # :large => 612x612 pixel require 'cgi' require 'json' require 'net/http' def instagr( short_url, size = :medium) return %Q|

      Argument is empty.. #{short_url}

      | if !short_url or short_url.empty? option = option.nil? ? {} : option # img size maxwidth_data = {:small => 150, :medium => 306, :large => 612} maxwidth = maxwidth_data[ size ] ? maxwidth_data[ size ] : maxwidth_data[:medium] # proxy px_host, px_port = (@conf['proxy'] || '').split( /:/ ) px_port = 80 if px_host and !px_port # query query = "?url=#{CGI::escape(short_url)}&maxwidth=#{maxwidth}" begin Net::HTTP.version_1_2 res = Net::HTTP::Proxy(px_host, px_port).get('instagram.com', "/api/v1/oembed/#{query}") json_data = JSON::parse( res, &:read ) width = option[:width] ? option[:width] : json_data["width"] height = option[:height] ? option[:height] : json_data["height"] return <<-INSTAGR_DOM
      #{h @conf.to_native(json_data[

      #{h json_data["author_name"]}'s photo.

      INSTAGR_DOM rescue return %Q|

      Failed Open URL.. #{short_url}
      #{h $!}

      | end end alias :instagram :instagr # Local Variables: # mode: ruby # indent-tabs-mode: t # tab-width: 3 # ruby-indent-level: 3 # End: # vim: ts=3 tdiary-contrib-3.2.2/plugin/ja/000077500000000000000000000000001213632744000163425ustar00rootroot00000000000000tdiary-contrib-3.2.2/plugin/ja/add_bookmark.rb000066400000000000000000000011221213632744000213000ustar00rootroot00000000000000# ja/add_bookmark.rb $Revision 1.3 $ # # Japanese resource of add_bookmark.rb # You can redistribute it and/or modify it under GPL2. # @add_bookmark_label = 'ブックマーク追加' @add_bookmark_desc = 'ページに埋め込みたいリンクをチェックしてください。' @caption_delicious = 'del.icio.usに追加' @caption_hatena = 'はてなブックマークに追加' @caption_livedoor = 'livedoor クリップに追加' @caption_buzzurl = 'Buzzurl に追加' @bookmark_label = [ 'del.icio.us', 'はてなブックマーク', 'livedoor クリップ', 'Buzzurl' ] tdiary-contrib-3.2.2/plugin/ja/del_footer.rb000066400000000000000000000004761213632744000210200ustar00rootroot00000000000000# # English resource of delicious plugin $Revision: 1.0 $ # # Copyright (C) 2006 SHIBATA Hiroshi # You can redistribute it and/or modify it under GPL2. # @delicious_label_conf = 'del.icio.us' @delicious_label_id = 'del.icio.usのユーザーID' @delicious_label_pw = 'del.icio.usのパスワード' tdiary-contrib-3.2.2/plugin/ja/flickr.rb000066400000000000000000000064561213632744000201540ustar00rootroot00000000000000# flickr.rb Japanese resources add_conf_proc('flickr', 'Flickr プラグイン') do if @mode == 'saveconf' @conf['flickr.default_size'] = @cgi.params['flickr.default_size'][0] @conf['flickr.user_id'] = @cgi.params['flickr.user_id'][0] if @cgi.params['flickr.clear'][0] == "true" flickr_clear_cache end end flickr_bookmarklet = CGI.escapeHTML %Q{javascript:(function(){var w=window;w.page_photo_id||/^\/photos\/[^/]+\/(\d+)\//.test(w.location.pathname)?w.location.href="#{@conf.base_url}#{@update}?#{FLICKER_FORM_PID}="+w.page_photo_id||RegExp.$1:void(0);})()} r = <<-_HTML

      Flickr に登録した画像を日記に表示するプラグインです。日記の本文中で下記のように呼び出します。

      <%=flickr 画像ID, 画像サイズ%>
      画像ID
      それぞれの写真に一意に付けられる番号です。
      画像IDは Flickr で画像を表示したときの URL に含まれています。
      画像サイズ
      表示する画像の大きさを square, thumbnail, small, medium, large から指定します。
      この値は省略できます。省略すると、画像は設定画面(この画面)で指定したサイズで表示されます。

      標準の画像サイズ

      画像サイズを省略してプラグインを呼び出した場合のサイズを指定します。

      FlickrのユーザID

      Flickr上でのあなたのユーザIDを入力してください。

      ※ Flickr ID は「19594487@N00」のような文字列です。分からないときは idgettr.com で調べることができます。

      Bookmarklet

      写真をかんたんに tDiary の日記へ載せるための Bookmarklet です。Bookmarklet を登録しなくても Flickr プラグインは使えますが、登録すればより便利になります。

      Flickr to tDiary (このリンクをブラウザのお気に入り・ブックマークに登録してください)

      使い方

      1. Flickr にアクセスし、日記に載せたい写真のページを開いて、この Bookmarklet を実行してください。
      2. 日記の編集フォームの下に先ほどの写真が表示されます。
      3. 「本文に追加」ボタンを押すと、日記中にこの写真を表示するための記述(プラグイン)が追記されます。

      キャッシュファイルの削除

      Flickrプラグインが使用しているキャッシュを削除します。

      _HTML end tdiary-contrib-3.2.2/plugin/ja/git-register.rb000066400000000000000000000002531213632744000212740ustar00rootroot00000000000000@git_register_conf_label = 'Git' @git_register_conf_header = 'Gitへ再登録' @git_register_conf_description = 'Gitへ再登録する場合はOKを押してください' tdiary-contrib-3.2.2/plugin/ja/google_sitemaps.rb000066400000000000000000000033231213632744000220510ustar00rootroot00000000000000# google_sitemap.rb # Copyright (c) 2006 http://d.bulkitem.com/ # Distributed under the GPL add_conf_proc('google_sitemaps', 'Google sitemap') do saveconf_google_sitemaps request_uri = File::dirname(@cgi.request_uri) if request_uri == "/" @conf['google_sitemaps.uri_format'] ||= 'http://' + @cgi.server_name + '/index.cgi?date=%s' else @conf['google_sitemaps.uri_format'] ||= 'http://' + @cgi.server_name + request_uri + '/index.cgi?date=%s' end @conf['google_sitemaps.output_file'] ||= File::dirname(ENV['SCRIPT_FILENAME']) + '/sitemap.xml' if File.writable_real?(@conf['google_sitemaps.output_file']) == false msg = "[NG] 指定されているファイルの書き込み権限がありません。" else msg = "[OK] 指定されているファイルの書き込み権限があります。" end <<-HTML

      Google ウェブマスターツール用のSitemap XMLを出力する設定を行います。

      アドレスフォーマット

      日付別表示時のURLフォーマットを指定します。日付文字列の部分は%sにしてください。

      eg.
      http://www.example.com/inex.cgi?date=%s
      http://www.example.com/%s.html

      XMLファイルの出力先

      出力するファイルを絶対パスで指定します。

      #{msg}

      HTML end tdiary-contrib-3.2.2/plugin/ja/livedoor_weather.rb000066400000000000000000000024241213632744000222330ustar00rootroot00000000000000# # Japanese resource of livedoor_weather plugin $Revision$ # # Copyright (C) 2006 SHIBATA Hiroshi # You can redistribute it and/or modify it under GPL2. # # # tdiary.confにおける設定: # @options['lwws.city_id'] : 天気情報を取得したい都市のIDを指定(設定画面から編集可能) # @lwws_plugin_name = 'livedoor 天気情報' @lwws_label_city_id = '都市IDの設定' @lwws_desc_city_id = '天気情報を取得する都市IDを指定します。全国の地点定義表(RSS)内の「1次細分区(cityタグ)」のidから選択してください。(初期設定は東京)' @lwws_label_disp_item = '表示項目の設定' @lwws_desc_disp_item = '表示させたい項目を選択してください。' @lwws_icon_label = 'アイコン表示の設定' @lwws_icon_desc = '天気情報をアイコン表示にする(詳細へのリンクは画像に設定)' @lwws_max_temp_label = '最高気温' @lwws_min_temp_label = '最低気温' @celsius_label = '℃' @lwws_label_cache = 'キャッシュの自動更新' @lwws_desc_cache = '自動更新を有効にする。' @lwws_desc_cache_time = 'キャッシュの更新間隔を時間で指定します。(初期設定は6時間)' tdiary-contrib-3.2.2/plugin/ja/microsummary.rb000066400000000000000000000010041213632744000214110ustar00rootroot00000000000000# ja/microsummary.rb # # Japanese resources for microsummary.rb # # Copyright (c) 2006 elytsllams # Distributed under the GPL # if @mode == 'conf' || @mode == 'saveconf' add_conf_proc( 'microsummary', 'Microsummary Generator' ) do saveconf_microsummary microsummary_init <<-HTML

      URI for microsummary generator XML

      HTML end end tdiary-contrib-3.2.2/plugin/ja/nicovideo.rb000066400000000000000000000033121213632744000206450ustar00rootroot00000000000000# # ja/nicovideo.rb - Japanese resource # # Copyright (C) TADA Tadashi # Distributed under GPL. # def nicovideo_player_path 'http://www.nicovideo.jp' end def nicovideo_feed( i ) <<-HTML
      #{h i[:title]} #{h i[:title]} (#{i[:length]})
      #{i[:desc]}
      HTML end def nicovideo_html( i ) <<-HTML
      #{h i[:title]}

      #{i[:date][0,10]}
      再生: #{i[:view].scan(/\d+?(?=\d{3}*$)/).join(",")}
      コメント: #{i[:comment_num].scan(/\d+?(?=\d{3}*$)/).join(",")}
      マイリスト: #{i[:mylist].scan(/\d+?(?=\d{3}*$)/).join(",")}

      #{h i[:title]} (#{i[:length].split(/:/).map{|j|'%02d' % j.to_i}.join(':')})
      #{i[:desc]}

      #{i[:comment]}

      HTML end tdiary-contrib-3.2.2/plugin/ja/openid.rb000066400000000000000000000005751213632744000201540ustar00rootroot00000000000000# openid.rb: Japanese resource @openid_conf_label = 'OpenID' @openid_service_label = 'OpenID認証サービス名' @openid_service_desc = 'あなたが使っているOpenIDの認証サービス名を選んでください' @openid_id_label = 'あなたのID' @openid_id_desc = '上で選択した認証サービスに登録してある、あなたのIDを入力してください' tdiary-contrib-3.2.2/plugin/ja/section_footer.rb000066400000000000000000000006771213632744000217230ustar00rootroot00000000000000# section_footer.rb: Japanese resource @section_footer_delicious_label = "このエントリの del.icio.us history" @section_footer_hatenabm_label = "このエントリを含むはてなブックマーク" @section_footer_ldclip_label = "このエントリを含む livedoor クリップ" @section_footer_buzzurl_label = "このエントリを含む Buzzurl" @section_footer_yahoobm_label = "このエントリを含む Yahoo!ブックマーク" tdiary-contrib-3.2.2/plugin/ja/section_footer2.rb000066400000000000000000000002571213632744000217770ustar00rootroot00000000000000# -*- coding: utf-8 -*- # section_footer2.rb: Japanese resource @section_footer2_delicious_label = "このエントリの Delicious history" @section_footer2_locale = 'ja_JP' tdiary-contrib-3.2.2/plugin/ja/socialbutton.rb000066400000000000000000000004661213632744000214030ustar00rootroot00000000000000# -*- coding: utf-8 -*- # section_footer2.rb: Japanese resource @socialbutton_label_conf = 'ソーシャルボタン' @socialbutton_label_enables = 'ボタンを表示するサービス' @socialbutton_label_twitter_via = 'ツイート時に表示するユーザ名(あなたのTwitterアカウント名)' tdiary-contrib-3.2.2/plugin/jdate.rb000066400000000000000000000012211213632744000173600ustar00rootroot00000000000000# jdate.rb $Revision: 1.1 $ # #「%J」で日本語の曜日名を出す # pluginに入れるだけで動作する。 # 日付フォーマットなどで「%J」を指定するとそこが日本語の曜日になる # # Copyright (c) 2003 TADA Tadashi # You can distribute this file under the GPL. # unless Time::new.respond_to?( :strftime_jdate_backup ) then eval( <<-MODIFY_CLASS, TOPLEVEL_BINDING ) class Time alias strftime_jdate_backup strftime JWDAY = %w(日 月 火 水 木 金 土) def strftime( format ) strftime_jdate_backup( format.gsub( /%J/, JWDAY[self.wday] ) ) end end MODIFY_CLASS end tdiary-contrib-3.2.2/plugin/jholiday.rb000066400000000000000000000006701213632744000201030ustar00rootroot00000000000000require 'Calendar.rb' require 'date' unless Time::new.respond_to?( :strftime_holiday_backup ) then eval( <<-MODIFY_CLASS, TOPLEVEL_BINDING ) class Time alias strftime_holiday_backup strftime def strftime( format ) holiday = "" day = Day.new(self.day,self.month,self.year,self.wday) holiday = day.holiday_name_jp if day.holiday? strftime_holiday_backup( format.gsub( /%K/, holiday ) ) end end MODIFY_CLASS end tdiary-contrib-3.2.2/plugin/jmonth.rb000066400000000000000000000013541213632744000175770ustar00rootroot00000000000000# jmonth.rb $Revision: 1.1 $ # #「%i」で日本語の陰暦月名を出す # pluginに入れるだけで動作する。 # 日付フォーマットなどで「%i」を指定するとそこが陰暦月名になる # # Copyright (c) 2005 sasasin/SuzukiShinnosuke # You can distribute this file under the GPL. # unless Time::new.respond_to?( :strftime_jmonth_backup ) then eval( <<-MODIFY_CLASS, TOPLEVEL_BINDING ) class Time alias strftime_jmonth_backup strftime JMONTH = %w(睦月 如月 弥生 卯月 皐月 水無月 文月 葉月 長月 神無月 霜月 師走) def strftime( format ) strftime_jmonth_backup( format.gsub( /%i/, JMONTH[self.month-1] ) ) end end MODIFY_CLASS end tdiary-contrib-3.2.2/plugin/jquery_ui_theme.rb000066400000000000000000000023271213632744000214770ustar00rootroot00000000000000# -*- coding: utf-8 -*- # # jquery_ui.rb - use jQuery UI # # Copyright (C) 2012, tamoot # You can redistribute it and/or modify it under GPL. # # # not support # return if feed? || @conf.mobile_agent? add_header_proc do if /\A(?:form|preview|append|edit|update)\z/ =~ @mode themes = @conf['jquery_ui.theme'] if themes.nil? || theme == '' themes = 'base' end jquery_ui = '' jquery_ui << %Q|\n| jquery_ui else '' end end add_conf_proc( 'jquery_ui_theme', 'jQuery UI Theme' ) do if @mode == 'saveconf' then @conf['jquery_ui.theme'] = @cgi.params['jquery_ui.theme'][0] end <<-HTML

      Theme name

      sample) blitzer, flick .. See JQuery UI Theme.

      default is base.

      HTML end # Local Variables: # mode: ruby # indent-tabs-mode: t # tab-width: 3 # ruby-indent-level: 3 # End: # vim: ts=3 tdiary-contrib-3.2.2/plugin/jroku.rb000066400000000000000000000016761213632744000174410ustar00rootroot00000000000000# jroku.rb $Revision: 1.1 $ # #「%R」で六曜を出す # 動かすためには # http://www.funaba.org/calendar.html#calendar # で配布されているClendarモジュールと付属しているcalclass.rbが必要 # 日付フォーマットなどで「%R」を指定するとそこが六曜になる # # Copyright (c) 2005 SHIBATA Hiroshi # You can distribute this file under the GPL. # require 'calclass.rb' unless Time::new.respond_to?( :strftime_jroku_backup ) then eval( <<-MODIFY_CLASS, TOPLEVEL_BINDING ) class Time alias strftime_jroku_backup strftime JROKU = %w(大安 赤口 先勝 友引 先負 仏滅) def strftime( format ) d=Gregorian.new(self.month, self.day, self.year) q_d = Calendar.kyureki_from_absolute(d.abs) index = (q_d[0] + q_d[2]) % 6 strftime_jroku_backup( format.gsub( /%R/, JROKU[index] ) ) end end MODIFY_CLASS end tdiary-contrib-3.2.2/plugin/jyear.rb000066400000000000000000000021351213632744000174100ustar00rootroot00000000000000# jyear.rb $Revision: 1.1 $ # # 西暦を和暦に変換するプラグイン。 # 日記やツッコミの日付フォーマットで使う。 # 「%Y」で「2005」のところを、「%K」で「平成17」と表示。 # pluginに入れるだけで動作する。 # # Copyright (c) 2005 sasasin/SuzukiShinnosuke # You can distribute this file under the GPL. # unless Time::new.respond_to?( :strftime_jyear_backup ) then eval( <<-MODIFY_CLASS, TOPLEVEL_BINDING ) class Time alias strftime_jyear_backup strftime def strftime( format ) case self.year when 0 .. 1926 gengo = "昔々" if self.year == 1926 && self.month == 12 && self.day >=25 then gengo = "昭和元年" end when 1927 .. 1989 jyear = self.year - 1925 gengo = "昭和" + jyear.to_s if self.year == 1989 && self.month == 1 && self.day >= 8 then gengo = "平成元年" end else jyear = self.year - 1988 gengo = "平成" + jyear.to_s end strftime_jyear_backup( format.gsub( /%K/, gengo ) ) end end MODIFY_CLASS end tdiary-contrib-3.2.2/plugin/latlonglab_route.rb000066400000000000000000000012601213632744000216310ustar00rootroot00000000000000# # latlonglab_route.rb - tDiary plugin for LatLongLab Route # # Copyright (C) 2009, Michitaka Ohno # Copyright (C) 2010, KAYA Satoshi # You can redistribute it and/or modify it under GPL2. # def route( id, w = 480, h = 480 ) if feed? or @conf.mobile_agent? return %Q|

      Link to LatLongLab Route

      | end if @conf.iphone? w = 240 h = 380 end <<-HTML
      HTML end tdiary-contrib-3.2.2/plugin/lazy_referer.rb000066400000000000000000000017621213632744000207740ustar00rootroot00000000000000# -*- coding: utf-8; -*- # # lazy_referer.rb: lazy loading referer # # Copyright (C) 2013 by MATSUOKA Kohei # You can distribute it under GPL. # if /^(day|form|edit)$/ =~ @mode and not bot? then enable_js('referer.js') # # overwrite method: draw only referer area (content will feach with ajax) # def referer_of_today_long( diary, limit ) return if limit == 0 return unless diary date = diary.date.strftime('%Y%m%d') # FIXME: endpoint is should created by TDiary::Plugin, because easy customize routing endpoint = "#{@conf.index}?plugin=referer&date=#{date}" %Q[\n] end end # # return referer of date as is (html) # add_content_proc('referer') do |date| diary = @diaries[date] referer_load_current( diary ) referer_of_today_long( diary, 100 ) end # Local Variables: # mode: ruby # indent-tabs-mode: t # tab-width: 3 # ruby-indent-level: 3 # End: tdiary-contrib-3.2.2/plugin/livedoor_weather.rb000066400000000000000000000132461213632744000216450ustar00rootroot00000000000000# -*- coding: utf-8 -*- # livedoor_weather.rb # # insert weather information using livedoor weather web service. # # Copyright (C) 2007 SHIBATA Hiroshi # You can redistribute it and/or modify it under GPL2. # require 'open-uri' require 'timeout' require 'time' @lwws_rest_url = 'http://weather.livedoor.com/forecast/webservice/json/v1' def lwws_init @conf['lwws.city_id'] ||= 130010 @conf['lwws.icon.disp'] ||= "" @conf['lwws.max_temp.disp'] ||= "" @conf['lwws.min_temp.disp'] ||= "" @conf['lwws.cache'] ||= "" @conf['lwws.cache_time'] ||= 6 end def lwws_request( city_id ) url = @lwws_rest_url.dup url << "?city=#{city_id}" proxy = @conf['proxy'] proxy = 'http://' + proxy if proxy timeout( 10 ) do open( url, :proxy => proxy ) {|f| f.read } end end def lwws_get lwws_init city_id = @conf['lwws.city_id'] cache_time = @conf['lwws.cache_time'] * 60 * 60 file_name = "#{@cache_path}/lwws/#{Time.now.strftime("%Y%m%d")}.json" begin Dir.mkdir("#{@cache_path}/lwws") unless File.directory?("#{@cache_path}/lwws") cached_time = if File.exist?( file_name ) File.mtime( file_name ) else nil end update = true if @conf['lwws.cache'] == "t" && cached_time && Time.now > cached_time + cache_time if cached_time.nil? || update json = lwws_request(city_id) File.open(file_name, 'wb') {|f| f.write(json)} end rescue => e @logger.error( e ) end end def lwws_to_html(date) lwws_init file_name = "#{@cache_path}/lwws/#{date.strftime("%Y%m%d")}.xml" begin # http://weather.livedoor.com/help/restapi_close if Time.parse('20130331') < date file_name.sub!(/xml/, 'json') require 'json' doc = JSON.parse(File.read(file_name)) telop = @conf.to_native( doc["forecasts"][0]["telop"], 'utf-8' ) # 「今日」のデータに気温は含まれない場合がある max_temp = doc["forecasts"][0]["temperature"]["max"]["celsius"] rescue nil min_temp = doc["forecasts"][0]["temperature"]["min"]["celsius"] rescue nil detail_url = doc["link"] title = @conf.to_native( doc["forecasts"][0]["image"]["title"], 'utf-8' ) url = doc["forecasts"][0]["image"]["url"] width = doc["forecasts"][0]["image"]["width"] height = doc["forecasts"][0]["image"]["height"] else require 'rexml/document' doc = REXML::Document.new(File.read(file_name)).root telop = @conf.to_native( doc.elements["telop"].text, 'utf-8' ) max_temp = doc.elements["temperature/max/celsius"].text min_temp = doc.elements["temperature/min/celsius"].text detail_url = doc.elements["link"].text title = @conf.to_native( doc.elements["image/title"].text, 'utf-8' ) url = doc.elements["image/url"].text width = doc.elements["image/width"].text height = doc.elements["image/height"].text end result = "" result << %Q|
      | if @conf['lwws.icon.disp'] != "t" or @conf.mobile_agent? then result << %Q|#{telop}| else result << %Q|#{title}| end if @conf['lwws.max_temp.disp'] == "t" and not max_temp.nil? then result << %Q| #{@lwws_max_temp_label}:#{h(max_temp)}#{@celsius_label}| end if @conf['lwws.min_temp.disp'] == "t" and not min_temp.nil? then result << %Q| #{@lwws_min_temp_label}:#{h(min_temp)}#{@celsius_label}| end result << %Q|
      | result rescue StandardError, Errno::ENOENT => e @logger.error( e ) '' end end def lwws_conf_proc lwws_init if @mode == 'saveconf' then @conf['lwws.city_id'] = @cgi.params['lwws.city_id'][0].to_i @conf['lwws.icon.disp'] = @cgi.params['lwws.icon.disp'][0] @conf['lwws.max_temp.disp'] = @cgi.params['lwws.max_temp.disp'][0] @conf['lwws.min_temp.disp'] = @cgi.params['lwws.min_temp.disp'][0] @conf['lwws.cache'] = @cgi.params['lwws.cache'][0] @conf['lwws.cache_time'] = @cgi.params['lwws.cache_time'][0].to_i end result = '' result << <<-HTML

      #{@lwws_label_city_id}

      #{@lwws_desc_city_id}

      HTML result << %Q|

      #{@lwws_icon_label}

      | checked = "t" == @conf['lwws.icon.disp'] ? ' checked' : '' result << %Q|

      | result << %Q|

      #{@lwws_label_disp_item}

      | result << %Q|

      #{@lwws_desc_disp_item}

      | result << %Q|
        | checked = "t" == @conf['lwws.max_temp.disp'] ? ' checked' : '' result << %Q|
      • | checked = "t" == @conf['lwws.min_temp.disp'] ? ' checked' : '' result << %Q|
      • | result << %Q|
      | result << %Q|

      #{@lwws_label_cache}

      | checked = "t" == @conf['lwws.cache'] ? ' checked' : '' result << %Q|

      | result << %Q|

      #{@lwws_desc_cache_time}

      | result << %Q|

      | result end add_body_enter_proc do |date| unless @conf.mobile_agent? or @conf.iphone? or feed? or bot? lwws_to_html(date) end end add_update_proc do lwws_get end add_conf_proc( 'lwws', @lwws_plugin_name ) do lwws_conf_proc end # Local Variables: # mode: ruby # indent-tabs-mode: t # tab-width: 3 # ruby-indent-level: 3 # End: # vim: ts=3 tdiary-contrib-3.2.2/plugin/make_link.rb000066400000000000000000000020431213632744000202260ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2011, KADO Masanori # You can redistribute it and/or modify it under GPL. # needs category.rb plugin add_edit_proc do <<-HTML HTML end tdiary-contrib-3.2.2/plugin/makerss_category.rb000066400000000000000000000016121213632744000216370ustar00rootroot00000000000000# # makerss_category.rb: extension for makerss plugin. # # Copyright (C) 2007 by SHIBATA Hiroshi # Distributed under GPL2. # # Usage: # @conf['makerss.category'] = ["mixi", "sns"] # class MakeRssCategory < MakeRssFull def title '(category only)' end def item( seq, body, rdfsec ) return unless rdfsec.section.respond_to?( :body_to_html ) return if rdfsec.section.categories.length == 0 rdfsec.section.categories.each do |category| if @conf['makerss.category'].include?(category) super end end end def file f = @conf['makerss.category.file'] || 'category.rdf' f = 'category.rdf' if f.length == 0 f end def write( encoder ) super( encoder ) end def url u = @conf['makerss.category.url'] || "#{@conf.base_url}category.rdf" u = "#{@conf.base_url}category.rdf" if u.length == 0 u end end @makerss_rsses << MakeRssCategory::new( @conf ) tdiary-contrib-3.2.2/plugin/makerss_comment.rb000066400000000000000000000012541213632744000214660ustar00rootroot00000000000000# # makerss_comment.rb: extension for makerss plugin. # # Copyright (C) 2007 by SHIBATA Hiroshi # Distributed under GPL2. # class MakeRssComments < MakeRssFull def title '(comments only)' end def item( seq, body, rdfsec ) return if rdfsec.section.respond_to?( :body_to_html ) super end def file f = @conf['makerss.no_comments.file'] || 'comments.rdf' f = 'comments.rdf' if f.length == 0 f end def write( encoder ) super( encoder ) end def url u = @conf['makerss.no_comments.url'] || "#{@conf.base_url}comments.rdf" u = "#{@conf.base_url}comments.rdf" if u.length == 0 u end end @makerss_rsses << MakeRssComments::new( @conf ) tdiary-contrib-3.2.2/plugin/microsummary.rb000066400000000000000000000033541213632744000210310ustar00rootroot00000000000000# microsummary.rb # # Copyright (c) 2006 elytsllams # Distributed under the GPL # add_header_proc do generator_xml = @conf['generator.xml'] if generator_xml != nil and @mode == 'latest' and !@cgi.valid?( 'date' ) %Q|\t\n| end end def create_xml file_name xml = <<-XML ^#{@conf.base_url.gsub(/\./, '\\.')}$ XML begin File::open( file_name, 'w' ) do |f| f.print to_utf8( xml ) end rescue end end def microsummary_init @conf['generator.xml'] ||= "" create_xml( @conf['generator.xml'] ) unless File::exists? @conf['generator.xml'] end if @mode == 'saveconf' def saveconf_microsummary @conf['generator.xml'] = @cgi.params['generator.xml'][0] end end tdiary-contrib-3.2.2/plugin/mm_footer.rb000066400000000000000000000124151213632744000202670ustar00rootroot00000000000000# # mm_footer.rb # # MM ( http://1470.net/mm/) のmylistを各日付に貼り付けるtDiaryプラグイン # # Licence: GPL # Author: ishinao # require 'nkf' add_body_leave_proc(Proc.new do |date| oldest_date = Time.local(2005, 1, 11) if date > oldest_date if @mode == 'day' or @mode == 'latest' if date < Time.local(2006, 7, 6) mm_user = 82 # your MM id url = "http://1470.net/mm/mylist.html/#{mm_user}?date=#{date.strftime('%Y-%m-%d')}" rssurl = "http://1470.net/mm/mylist.html/#{mm_user}?date=#{date.strftime('%Y-%m-%d')}&mode=rss" template_list = '
    • #{content}
    • ' else userName = 'hsbt' # your 1470.net id url = "http://1470.net/user/#{userName}/#{date.strftime('%Y/%m/%d')}" rssurl = "http://1470.net/user/#{userName}/#{date.strftime('%Y/%m/%d')}/feed" template_list = '
    • #{content.gsub(/href="\//, "href=\"http://1470.net\/")}
    • ' end template_head = %Q[\n" cache_time = 3600; if date.strftime('%Y-%m-%d') != Time.now.strftime('%Y-%m-%d') cache_time = 3600 * 12; end NKF.nkf('-e', mm_footer(rssurl, 50, cache_time, template_head, template_list, template_foot)) else '' end end end) require "rss/rss" MM_FOOTER_FIELD_SEPARATOR = "\0" MM_FOOTER_ENTRY_SEPARATOR = "\1" MM_FOOTER_VERSION = "0.0.5i" MM_FOOTER_HTTP_HEADER = { "User-Agent" => "tDiary RSS recent plugin version #{MM_FOOTER_VERSION}. " << "Using RSS parser version is #{::RSS::VERSION}.", } def mm_footer(url, max = 5, cache_time = 3600, \ template_head = "\n") url.untaint cache_file = "#{@cache_path}/rss-recent/rss-recent.#{CGI.escape(url)}" mm_footer_cache_rss(url, cache_file, cache_time.to_i) return '' unless test(?r, cache_file) rv = template_head i = 0 mm_footer_read_from_cache(cache_file).each do |title, url, time, content| break if i >= max next if (url.nil? or title.nil?) rv << eval('%Q[' + template_list + ']') i += 1 end rv << template_foot if i > 0 rv else '' end end class InvalidResourceError < StandardError; end def mm_footer_cache_rss(url, cache_file, cache_time) cached_time = nil cached_time = File.mtime(cache_file) if File.exist?(cache_file) if cached_time.nil? or Time.now > cached_time + cache_time require 'time' require 'open-uri' require 'net/http' require 'uri/generic' require 'rss/parser' require 'rss/1.0' require 'rss/2.0' require 'rss/dublincore' require 'rss/content' begin uri = URI.parse(url) raise URI::InvalidURIError if uri.scheme != "http" rss_source = mm_footer_fetch_rss(uri, cached_time) raise InvalidResourceError if rss_source.nil? # parse RSS rss = ::RSS::Parser.parse(rss_source, false) raise ::RSS::Error if rss.nil? # pre processing begin rss.output_encoding = @conf.charset || charset rescue ::RSS::UnknownConversionMethodError end rss_infos = rss.items.collect do |item| mm_footer_pubDate_to_dc_date(item) [item.title, item.link, item.dc_date, item.content_encoded] end mm_footer_write_to_cache(cache_file, rss_infos) rescue URI::InvalidURIError mm_footer_write_to_cache(cache_file, [['Invalid URI', url]]) rescue InvalidResourceError, ::RSS::Error # mm_footer_write_to_cache(cache_file, [['Invalid Resource', url]]) # when cannot get valid RSS, use old cache end end end def mm_footer_fetch_rss(uri, cache_time) rss = nil begin uri.open(mm_footer_http_header(cache_time)) do |f| case f.status.first when "200" rss = f.read # STDERR.puts "Got RSS of #{uri}" when "304" # not modified # STDERR.puts "#{uri} does not modified" else raise InvalidResourceError end end rescue TimeoutError, SocketError, StandardError, SecurityError # occured in redirect raise InvalidResourceError end rss end def mm_footer_http_header(cache_time) header = MM_FOOTER_HTTP_HEADER.dup if cache_time.respond_to?(:rfc2822) header["If-Modified-Since"] = cache_time.rfc2822 end header end def mm_footer_write_to_cache(cache_file, rss_infos) File.open(cache_file, 'w') do |f| f.flock(File::LOCK_EX) rss_infos.each do |info| f << info.join(MM_FOOTER_FIELD_SEPARATOR) f << MM_FOOTER_ENTRY_SEPARATOR end f.flock(File::LOCK_UN) end end def mm_footer_read_from_cache(cache_file) require 'time' infos = [] File.open(cache_file) do |f| while info = f.gets(MM_FOOTER_ENTRY_SEPARATOR) info = info.chomp(MM_FOOTER_ENTRY_SEPARATOR) infos << info.split(MM_FOOTER_FIELD_SEPARATOR) end end infos.collect do |title, url, time, content| [ mm_footer_convert(title), mm_footer_convert(url), mm_footer_convert(time) {|time| Time.parse(time)}, mm_footer_convert(content) ] end end def mm_footer_convert(str) if str.nil? or str.empty? nil else if block_given? yield str else str end end end def mm_footer_pubDate_to_dc_date(target) if target.respond_to?(:pubDate) class << target alias_method(:dc_date, :pubDate) end end end tdiary-contrib-3.2.2/plugin/monthly_autopagerize.rb000066400000000000000000000034151213632744000225510ustar00rootroot00000000000000# # monthly_autopagerize.rb - tDiary plugin # # add and tags for AutoPagerize at monthly mode # # Copyright (C) 2009 MATSUI Shinsuke # You can redistribute it and/or modify it under GPL2. # if @mode == 'month' then add_header_proc do stream = @conf['monthly_autopagerize.stream'] || 0 result = String.new ym = [] @years.keys.each do |y| ym += @years[y].collect {|m| y + m} end ym.sort! now = @date.strftime( '%Y%m' ) return '' unless ym.index( now ) prev_month = ym.index( now ) == 0 ? nil : ym[ym.index( now )-1] next_month = ym[ym.index( now )+1] case stream #when 0 # rel_prev_month = 'next' # rel_next_month = 'prev' when 1 rel_prev_month = 'prev' rel_next_month = 'next' else rel_prev_month = 'next' rel_next_month = 'prev' end if prev_month then result << %Q[\n\t] end if next_month then result << %Q[\n\t] end result.chop.chop end end add_conf_proc( 'monthly_autopagerize', 'Monthly AutoPagerize' ) do if @mode == 'saveconf' then @conf['monthly_autopagerize.stream'] = @cgi.params['monthly_autopagerize.stream'][0].to_i end <<-HTML

      Stream of Monthly AutoPagerize

      HTML end # Local Variables: # mode: ruby # indent-tabs-mode: t # tab-width: 3 # ruby-indent-level: 3 # End: # vi: ts=3 sw=3 tdiary-contrib-3.2.2/plugin/my_hotentry.rb000066400000000000000000000077341213632744000206710ustar00rootroot00000000000000# show my hot-entry in Hatena::Bookmark # # usage: # <%= my_hotentry %> # # Copyright (c) MATSUOKA Kohei # Distributed under the GPL # require 'uri' require 'open-uri' require 'rexml/document' require 'pstore' require 'timeout' # 人気の日記のソート順(新着順: eid, 注目順: hot, 人気順: count) @conf ||= {} @conf['my_hotentry.sort'] ||= 'hot' class MyHotEntry def initialize(dbfile) @dbfile = dbfile end # 人気の日記の一覧を返す def entries r = nil PStore.new(@dbfile).transaction(true) do |db| r = db[:entries] end r || [] end # 人気の日記一覧を取得する def update(base_url, options = {}) options[:title] ||= '' options[:sort] ||= 'eid' options[:threshold] ||= 3 # RSSを取得 rss = nil rss_url = 'http://b.hatena.ne.jp/entrylist?mode=rss&url=' rss_url << URI.escape(base_url, /[^-.!~*'()\w]/n) rss_url << "&sort=#{options[:sort]}&threshold=#{options[:threshold]}" begin timeout(5) do # convert Tempfile to String because REXML can't accept Tempfile open(rss_url) do |f| rss = REXML::Document.new(f.readlines.join("\n")) end end rescue TimeoutError => e return end # RDF/itemが空ならDBを更新しない (たまにitemが空のデータが返るため) return if rss.elements['rdf:RDF/item'].nil? # キャッシュに格納する PStore.new(@dbfile).transaction do |db| db[:entries] = [] rss.elements.each('rdf:RDF/item') do |item| url = item.elements['link'].text title = item.elements['title'].text # リンク先のタイトルからサイト名と日付を取り除く title.sub!(/(?: - )?#{options[:html_title]}(?: - )?/, '') title.sub!(/\(\d{4}-\d{2}-\d{2}\)/, '') db[:entries].push({ :url => url, :title => title }) end end end end # キャッシュファイルのパスを取得する def my_hotentry_dbfile cache_dir = "#{@cache_path}/hatena" Dir::mkdir(cache_dir) unless File::directory?(cache_dir) "#{cache_dir}/my_hotentry.dat" end # 人気の日記一覧を表示する def my_hotentry(count = 5) dbfile = my_hotentry_dbfile hotentry = MyHotEntry.new(dbfile) r = %Q|
        \n| hotentry.entries[0...count].each do |entry| entry_link = %Q|#{CGI::escapeHTML(entry[:title])}| escape_url = entry[:url].gsub(/#/, '%23') b_image = "http://b.hatena.ne.jp/entry/image/#{escape_url}" b_link = "http://b.hatena.ne.jp/entry/#{escape_url}" b_title = "このエントリを含むはてなブックマーク" bookmark_link = %Q|| r << "\t\t
      • #{entry_link} #{bookmark_link}
      • " end r << %Q|
      | r << %Q|
      \tPowered by Hatena Bookmark
      \n| end # 人気の日記一覧を更新する def my_hotentry_update dbfile = my_hotentry_dbfile hotentry = MyHotEntry.new(dbfile) hotentry.update(@conf.base_url, :html_title => @conf.html_title, :sort => @conf['my_hotentry.sort']) end if __FILE__ == $0 # コマンドラインから実行した場合 # tdiary.conf に base_url を設定しないと動作しない begin require 'tdiary' rescue LoadError STDERR.puts "tdiary.rb not found." STDERR.puts "please execute in tdiary base directory" exit 1 end cgi = CGI::new @conf = TDiary::Config::new(cgi) @cache_path = @conf.cache_path || "#{@conf.data_path}cache" my_hotentry_update puts my_hotentry else # 人気の日記一覧を取得する (日記更新時) add_update_proc do # ツッコミ時は実行しない if @mode == 'append' or @mode == 'replace' begin my_hotentry_update rescue end end end end tdiary-contrib-3.2.2/plugin/navi_day.rb000066400000000000000000000070471213632744000200770ustar00rootroot00000000000000# # navi_day.rb # # navi_day: 「前の日記」や「次の日記」を“月またぎ”に対応させる。 # # 日単位での表示の時の「前の日記」や「次の日記」のリンクが、 # 異なる月の日記を正しく指せない場合があるという tDiary の制限を # 解消するプラグインです。以前よりある navi_user.rb と機能的には # 同じですが、navi_user.rb よりは処理がずっと軽くなっています。 # また、日記の表示状態(非表示の日記)に対する考慮もなされています。 # # tDiary 2.0 以降で使えると思います。セキュアモードでも使えますが、 # セキュアモードの場合は、モバイル端末からのアクセスに対しては # このプラグインは効力を持ちません(tDiary セキュア環境の制限: # モバイル端末の場合は本文を出力するときに calc_links が呼ばれる # ため)。 # # navi_user.rb と併用すると navi_user.rb の方が優先されますので、 # このプラグインを使うときには必ず navi_user.rb を外してください。 # # Copyright (C) 2007, MIYASAKA Masaru # You can redistribute it and/or modify it under GPL2. # # Last Modified : May 27, 2007 # # for tDiary 2.0.X if not TDiaryMonth.method_defined?(:diaries) then eval( <<-MODIFY_CLASS, TOPLEVEL_BINDING ) module TDiary class TDiaryMonth attr_reader :diaries end end MODIFY_CLASS end class NaviDayCGI attr_reader :params def referer; nil; end def initialize @params = Hash.new([]) end end alias :calc_links_navi_day_backup :calc_links def calc_links if not (@conf.secure and @conf.mobile_agent?) and \ (/day|edit/ =~ @mode or \ (@conf.mobile_agent? and /latest|month|nyear/ =~ @mode)) then if /(latest|month|nyear)/ === @mode today = @diaries.keys.sort[-1] else today = @date.strftime('%Y%m%d') end days = @diaries.keys days |= [today] days.sort! days.unshift(nil).push(nil) today_index = days.index(today) days[0 .. today_index - 1].reverse_each do |prev_day| @prev_day = prev_day break unless @prev_day break if (@mode == 'edit') or @diaries[@prev_day].visible? end days[today_index + 1 .. -1].each do |next_day| @next_day = next_day break unless @next_day break if (@mode == 'edit') or @diaries[@next_day].visible? end if not @prev_day or not @next_day then cgi = NaviDayCGI.new years = [] @years.each do |k, v| v.each do |m| years << k + m end end this_month = @date.strftime('%Y%m') years |= [this_month] years.sort! years.unshift(nil).push(nil) this_month_index = years.index(this_month) years[0 .. this_month_index - 1].reverse_each do |prev_month| break unless not @prev_day and prev_month cgi.params['date'] = [prev_month] diaries = TDiaryMonth.new(cgi, '', @conf).diaries days = diaries.keys.sort days.unshift(nil) days.reverse_each do |prev_day| @prev_day = prev_day break unless @prev_day break if (@mode == 'edit') or diaries[@prev_day].visible? end end years[this_month_index + 1 .. -1].each do |next_month| break unless not @next_day and next_month cgi.params['date'] = [next_month] diaries = TDiaryMonth.new(cgi, '', @conf).diaries days = diaries.keys.sort days.push(nil) days.each do |next_day| @next_day = next_day break unless @next_day break if (@mode == 'edit') or diaries[@next_day].visible? end end end else calc_links_navi_day_backup end end tdiary-contrib-3.2.2/plugin/navi_this_month.rb000066400000000000000000000006301213632744000214650ustar00rootroot00000000000000# navi-this-month.rb # ref. http://www.tom.sfc.keio.ac.jp/~sakai/d/?date=20080628#p01 # alias navi_this_month__orig__navi_user_day navi_user_day def navi_user_day result = navi_this_month__orig__navi_user_day if @mode=='day' this_month = @date.strftime( '%Y%m' ) result << navi_item( "#{@index}#{anchor this_month}", "#{navi_this_month}" ) end result end def navi_this_month; "月表示"; end tdiary-contrib-3.2.2/plugin/nicovideo.rb000066400000000000000000000102031213632744000202500ustar00rootroot00000000000000# # nicovideo.rb - tDiary plugin for Nico Nico Video # # Copyright (C) 2012 TADA Tadashi # You can modify and/or distribute it under GPL. # # usage: # Link to the movie and show thumbnail, description...: # <%= nicovideo 'sm99999999' %> # # Link to the movie with original label: # <%= nicovideo 'sm99999999', 'movie title' %> # # Link to the movie with original label and link: # <%= nicovideo 'sm99999999', 'movie title', 'http://example.com/video' %> # # Show Inline player: # <%= nicovideo_player 'sm99999999' %> # # Show Inline player with size: # <%= nicovideo_player 'sm99999999', [400,300] %> # require 'net/http' require 'timeout' require 'rexml/document' enable_js( 'nicovideo.js' ) def nicovideo_call_api( video_id ) uri = "http://ext.nicovideo.jp/api/getthumbinfo/#{video_id}" proxy = @conf['proxy'] proxy = 'http://' + proxy if proxy xml = timeout( feed? ? 10 : 2 ) { px_host, px_port = (@conf['proxy'] || '').split( /:/ ) px_port = 80 if px_host and !px_port Net::HTTP::Proxy( px_host, px_port ).get_response( URI::parse( uri ) ).body } doc = REXML::Document::new( xml ).root res = doc.elements.to_a( '/nicovideo_thumb_response' )[0] if res.attributes['status'] == 'ok' then res.elements.to_a( 'thumb' )[0] else raise ::Errno::ENOENT::new end end def nicovideo_inline( video_id, elem, label = nil, link = nil ) i = {} i[:id] = video_id i[:url] = link || elem.to_a( 'watch_url' )[0].text i[:thumb] = elem.to_a( 'thumbnail_url' )[0].text i[:title] = label || elem.to_a( 'title' )[0].text i[:desc] = elem.to_a( 'description' )[0].text i[:comment] = @conf.mobile_agent? ? '' : elem.to_a( 'last_res_body' )[0].text i[:date] = elem.to_a( 'first_retrieve' )[0].text i[:length] = elem.to_a( 'length' )[0].text i[:view] = elem.to_a( 'view_counter' )[0].text i[:comment_num] = elem.to_a( 'comment_num' )[0].text i[:mylist] = elem.to_a( 'mylist_counter' )[0].text if feed? then result = nicovideo_feed( i ) else result = nicovideo_html( i ) end result.gsub( /^\t+/, '' ) end def nicovideo_iframe( video_id ) %Q|\n| end def nicovideo_player( video_id, size = [544,384] ) if feed? or @conf.mobile_agent? or @conf.iphone? then nicovideo( video_id ) else q = '' if size then q = "?w=#{h size[0]}&h=#{h size[1]}" end %Q|| end end def nicovideo( video_id, label = nil, link = nil ) begin r = '' r << %Q|
      | api = nicovideo_call_api( video_id ).elements thumb = @conf.to_native( nicovideo_inline( video_id, api, label, link ), 'UTF-8' ) thumb.gsub!( /"INLINE_PLAYER"/, %Q|"#" onclick="return nicovideoPlayer( '#{video_id}' );"| ) r << thumb r << '
      ' if feed? or @conf.mobile_agent? or @conf.iphone? then r.gsub!( /]*)?>/, '' ) r.gsub!( %r{}, '' ) else r << %Q|| end r rescue ::Errno::ENOENT "Sorry, #{video_id} was deleted." rescue Timeout::Error, NoMethodError, SecurityError, StandardError nicovideo_iframe( video_id ) end end tdiary-contrib-3.2.2/plugin/notify_miniblog.rb000066400000000000000000000072201213632744000214660ustar00rootroot00000000000000# # Copyright (C) 2007 peo # You can redistribute it and/or modify it under GPL2. # # modified hsbt. require 'net/http' @miniblog_config = (Struct.const_defined?("MiniBlogConfig") ? Struct::MiniBlogConfig : Struct.new("MiniBlogConfig", :host, :path)) @miniblog_list = { 'HatenaHaiku' => @miniblog_config.new('h.hatena.ne.jp', '/api/statuses/update.json'), } module Miniblog class Updater def initialize( user, pass, config ) @user = user @pass = pass @config = config end # this code is based on http://la.ma.la/blog/diary_200704111918.htm def update( status ) Net::HTTP.version_1_2 req = Net::HTTP::Post.new(@config.path) req.basic_auth(@user, @pass) req.body = status Net::HTTP.start( @config.host, 80 ) do |http| response = http.request(req) if response.body =~ /error/ raise 'update failed.' end end end end end def notify_miniblog notify_miniblog_init date = @date.strftime('%Y%m%d') diary = @diaries[date] sectitle = '' index = 0 diary.each_section do |sec| index += 1 sectitle = sec.subtitle end # strip category sectitle.gsub!(/\[[^\]]+\] */, '') url = URI.encode(@conf.base_url + anchor("#{date}p%02d" % index), /[^-.!~*'()\w]/n) prefix = @conf['miniblog.notify.prefix'] format = @conf['miniblog.notify.format'] source = 'tdiary/notify_miniblog.rb' status = 'status=' + format % [prefix, sectitle, url] + '&source=' + source if @conf['miniblog.service'] == "HatenaHaiku" then status += '&keyword=id:' + @conf['miniblog.user'] end config = @miniblog_list[@conf['miniblog.service']] begin miniblog_updater = Miniblog::Updater.new(@conf['miniblog.user'], @conf['miniblog.pass'], config) miniblog_updater.update( status ) rescue => e @logger.debug( e ) end end def notify_miniblog_init @conf['miniblog.notify.prefix'] ||= '[blog update]' @conf['miniblog.notify.format'] ||= '%s %s %s' @conf['miniblog.service'] ||= 'Twitter' end add_update_proc do if @mode == 'append' then notify_miniblog if @cgi.params['miniblog.notify'][0] == 'true' end end add_edit_proc do checked = '' if @mode == 'preview' then checked = @cgi.params['miniblog.notify'][0] == 'true' ? ' checked' : '' end <<-HTML
      HTML end add_conf_proc( 'notify_miniblog', 'MiniBlog' ) do notify_miniblog_init if @mode == 'saveconf' then @conf['miniblog.service'] = @cgi.params['miniblog.service'][0] @conf['miniblog.user'] = @cgi.params['miniblog.user'][0] @conf['miniblog.pass'] = @cgi.params['miniblog.pass'][0] @conf['miniblog.notify.prefix'] = @cgi.params['miniblog.notify.prefix'][0] @conf['miniblog.notify.format'] = @cgi.params['miniblog.notify.format'][0] end options = '' @miniblog_list.each_key do |key| options << %Q|\n| end <<-HTML

      MiniBlog Service

      Account Name

      Account Password

      Notify prefix

      Notify status format

      HTML end # vim:ts=3 tdiary-contrib-3.2.2/plugin/ogp.rb000066400000000000000000000032331213632744000170630ustar00rootroot00000000000000# ogp.rb - add Open Graph Protocol tags to header # # Copyright (c) 2011 MATSUOKA Kohei # You can redistribute it and/or modify it under GPL2. # # @conf['ogp.facebook.app_id'] - your facebook application ID. # @conf['ogp.facebook.admins'] - your facebook ID. def ogp_description section_index = @cgi.params['p'][0] # section_index = "1" if @mode == 'day' and section_index diary = @diaries[@date.strftime('%Y%m%d')] sections = diary.instance_variable_get(:@sections) section = sections[section_index.to_i - 1].body_to_html @conf.shorten(apply_plugin(section, true), 200) else @conf.description end end add_header_proc do headers = { # TODO: og:urlへ対応 'og:title' => title_tag.match(/>([^<]+) @conf.html_title, 'og:description' => ogp_description, 'og:image' => @conf.banner, 'og:type' => (@mode == 'day') ? 'article' : 'blog', 'og:author' => @conf.author_name, 'fb:app_id' => @conf['ogp.facebook.app_id'], 'fb:admins' => @conf['ogp.facebook.admins'] } headers.select {|key, val| val && !val.empty? }.map {|key, val| %Q|| }.join("\n") end add_conf_proc('Open Graph Protocol', 'Open Graph Protocol') do if @mode == 'saveconf' @conf['ogp.facebook.app_id'] = @cgi.params['ogp.facebook.app_id'][0] @conf['ogp.facebook.admins'] = @cgi.params['ogp.facebook.admins'][0] end <<-HTML

      Facebook Application ID

      Facebook User ID

      HTML end tdiary-contrib-3.2.2/plugin/ohmsha_estore.rb000066400000000000000000000034471213632744000211450ustar00rootroot00000000000000# -*- coding: utf-8 -*- # You can redistribute it and/or modify it under the same license as tDiary. # # display book info in http://estore.ohmsha.co.jp/ like amazon.rb # USAGE: {{ohmsha_estore '978427406694P'}} def ohmsha_estore_cache_dir cache = "#{@cache_path}/ohmsha-estore" Dir.mkdir( cache ) unless File.directory?( cache ) cache end def ohmsha_estore_cache_set( id, result ) File.open( "#{ohmsha_estore_cache_dir}/#{id}", "w" ) do |f| f.write result end end def ohmsha_estore_cache_get( id ) File.open( "#{ohmsha_estore_cache_dir}/#{id}", "r" ) do |f| f.read end rescue nil end def ohmsha_estore( id, doc = nil ) if !@conf.secure and !(result = ohmsha_estore_cache_get(id)).nil? return result end domain = "http://estore.ohmsha.co.jp" image = "#{domain}/images/covers/#{id}.gif" link = "#{domain}/titles/#{id}" require 'open-uri' doc ||= open(link) require 'rexml/document' xml = REXML::Document.new( doc ) biblio = "//html/body/div/div[2]/div/div/div/div[2]" title = REXML::XPath.match( xml, "#{biblio}/h2").first.text author = REXML::XPath.match( xml, "#{biblio}/div" ).first.text description = REXML::XPath.match( xml, '//html/body/div/div[2]/div/div/div[2]' ). first.text result = <<-EOS
      #{h title}
      #{h title}
      #{h author}
      #{h description}

      EOS ohmsha_estore_cache_set( id, result ) unless @conf.secure result end # Local Variables: # mode: ruby # indent-tabs-mode: t # tab-width: 3 # ruby-indent-level: 3 # End: tdiary-contrib-3.2.2/plugin/openid.rb000066400000000000000000000077121213632744000175620ustar00rootroot00000000000000# # openid.rb: Insert OpenID delegation information. $Revision: 1.10 $ # # Copyright (C) 2005, TADA Tadashi # You can redistribute it and/or modify it under GPL2. # @openid_config = (Struct.const_defined?("OpenIdConfig") ? Struct::OpenIdConfig : Struct.new("OpenIdConfig", :openid, :openid2, :x_xrds_location)) if /^(?:latest|conf|saveconf)$/ =~ @mode then @openid_list = { # service => @openid_config.new( # [openid.server, openid.delegate(replace as account name)], # openid # [openid2.provider, openid2.local_id(replace as account name)], # openid2 # 'X-XRDS-Location(replace as account name)'), 'Hatena' => @openid_config.new(['https://www.hatena.ne.jp/openid/server', 'http://www.hatena.ne.jp//']), 'livedoor' => @openid_config.new(['http://auth.livedoor.com/openid/server', 'http://profile.livedoor.com/']), 'LiveJournal' => @openid_config.new(['http://www.livejournal.com/openid/server.bml', 'http://.livejournal.com/']), 'OpenID.ne.jp' => @openid_config.new( ['http://www.openid.ne.jp/user/auth', 'http://.openid.ne.jp'], nil, 'http://.openid.ne.jp/user/xrds'), 'TypeKey' => @openid_config.new(['http://www.typekey.com/t/openid/', 'http://profile.typekey.com//']), 'Vox' => @openid_config.new(['http://www.vox.com/services/openid/server', 'http://.vox.com/']), 'myopenid.com' => @openid_config.new( ['http://www.myopenid.com/server', 'http://.myopenid.com'], # openid ['http://www.myopenid.com/server', 'http://.myopenid.com'], # openid2 "http://www.myopenid.com/xrds?username="), 'claimID.com' => @openid_config.new( ['http://openid.claimid.com/server', 'http://openid.claimid.com/'], nil, #['http://openid.claimid.com/server', 'http://openid.claimid.com/'], 'http://claimid.com//xrds'), 'Personal Identity Provider (PIP)' => @openid_config.new( ['http://pip.verisignlabs.com/server', 'http://.pip.verisignlabs.com/'], ['http://pip.verisignlabs.com/server', 'http://.pip.verisignlabs.com/'], 'http://pip.verisignlabs.com/user//yadisxrds'), 'Yahoo! Japan' => @openid_config.new( nil, ['https://open.login.yahooapis.jp/openid/op/auth', 'https://me.yahoo.co.jp/a/'], 'http://open.login.yahoo.co.jp/openid20/www.yahoo.co.jp/xrds'), 'Yahoo!' => @openid_config.new( nil, ['https://open.login.yahooapis.com/openid/op/auth', 'https://me.yahoo.com/a/'], 'http://open.login.yahooapis.com/openid20/www.yahoo.com/xrds'), } if @conf['openid.service'] and @conf['openid.id'] then openid_service = @openid_list[@conf['openid.service']] openid_id = @conf['openid.id'] result = '' add_header_proc do result = <<-HTML if openid_service.openid HTML result << <<-HTML if openid_service.openid2 HTML result << <<-HTML if openid_service.x_xrds_location HTML result.gsub( /^\t{2}/, '' ) end if openid_service end end add_conf_proc( 'openid', @openid_conf_label ) do if @mode == 'saveconf' then @conf['openid.service'] = @cgi.params['openid.service'][0] @conf['openid.id'] = @cgi.params['openid.id'][0] end options = '' @openid_list.each_key do |key| options << %Q|\n| end <<-HTML

      #{@openid_service_label}

      #{@openid_service_desc}

      #{@openid_id_label}

      #{@openid_id_desc}

      HTML end tdiary-contrib-3.2.2/plugin/opensearch_ad.rb000066400000000000000000000020501213632744000210650ustar00rootroot00000000000000# opensearch_ad.rb $Revision: 1.1 $ # # Copyright (c) 2008 SHIBATA Hiroshi # Distributed under the GPL # if /\A(?:latest|day)\z/ =~ @mode then if @conf['opensearch.xml'] and @conf['opensearch.title'] then opensearch_xml = @conf['opensearch.xml'] opensearch_title = @conf['opensearch.title'] add_header_proc do result = <<-HTML HTML result.gsub( /^\t\t/, '' ) end end end add_conf_proc( 'opensearch_ad', 'OpenSearch Auto-Discovery' ) do if @mode == 'saveconf' @conf['opensearch.xml'] = @cgi.params['opensearch.xml'][0] @conf['opensearch.title'] = @cgi.params['opensearch.title'][0] end <<-HTML

      Tilte for OpenSearch

      URI for OpenSearch description XML

      HTML end tdiary-contrib-3.2.2/plugin/picasa.rb000066400000000000000000000027301213632744000175370ustar00rootroot00000000000000# show photo image on Picasa Web Album # # usage: # picasa( src[, title[, place]] ) # - src: The url of the photo to show. # - title: title of photo. (optional) # - place: class name of img element. default is 'photo'. # # picasa_left( src[, title] ) # # picasa_right( src[, title] ) # # options configurable through settings: # @conf['picasa.user'] : picasa username # @conf['picasa.default_size'] : default image size # # Copyright (c) hb # Distributed under the GPL. # def picasa( src, alt = "photo", place = 'photo' ) src.sub!( %r|/s\d+/|, "/s200/" ) if @conf.iphone? if @cgi.mobile_agent? body = %Q|#{alt}| else body = %Q|#{alt}| end body end def picasa_left( src, alt = "photo" ) picasa( src, alt, 'left' ) end def picasa_right( src, alt = "photo" ) picasa( src, alt, 'right' ) end if /\A(form|edit|preview|showcomment)\z/ === @mode then enable_js( 'picasa.js' ) add_js_setting( '$tDiary.plugin.picasa' ) add_js_setting( '$tDiary.plugin.picasa.userId', %Q|'#{@conf['picasa.user']}'| ) add_js_setting( '$tDiary.plugin.picasa.imgMax', %Q|'#{@conf[ 'picasa.default_size'] || 400}'| ) end add_edit_proc do |date| unless @conf['picasa.user'] '

      [ERROR] picasa.rb: Picasa username is not specified.

      ' else <<-HTML

      Picasa Web Album

      HTML end end tdiary-contrib-3.2.2/plugin/plugin_checker.rb000066400000000000000000000027701213632744000212650ustar00rootroot00000000000000# plugin_checker.rb # # Copyright (c) 2012 MATSUOKA Kohei # You can redistribute it and/or modify it under GPL2. # def plugin_checker_js_settings enable_js('plugin_checker.js') add_js_setting('$tDiary.plugins', plugins.to_json) add_js_setting('$tDiary.mode', @mode.to_json) end if /\A(form|edit|preview|showcomment)\z/ === @mode add_header_proc do <<-STYLE STYLE end plugin_checker_js_settings end tdiary-contrib-3.2.2/plugin/popit.rb000066400000000000000000000016601213632744000174330ustar00rootroot00000000000000# popit.rb:plugin embedding POP on POPit(http://pop-it.jp) # # usage: # popit(pop_id) - pop_id: The id of the POP on POPit (e.g. 2000 http://pop-it.jp/item/amazon/1989/pop/2000 ) # # Copyright (c) KAYA Satoshi # You can redistributed it and/or modify if under GPL2. # def popit(pop_id, size = "large") return unless pop_id width_size = {"large" => "260", "small" => "180" } height_size = {"large" => "380", "small" => "220" } width_style = {"large" => "220px", "small" => "160px" } sizequery = size == "large" ? "?size=large" : '' r = "" r << %Q|| r << %Q|
      Powered by POPit
      | return r end tdiary-contrib-3.2.2/plugin/prettify.rb000066400000000000000000000011531213632744000201430ustar00rootroot00000000000000# prettify.rb if /\A(?:latest|day|month|nyear)\z/ =~ @mode then add_header_proc do <<-HTML HTML end end tdiary-contrib-3.2.2/plugin/prezi.rb000066400000000000000000000021551213632744000174310ustar00rootroot00000000000000# # prezi.rb: plugin embedding presentation on prezi.com # # Copyright (C) 2010 TADA Tadashi # You can redistribute it and/or modify it under GPL2. # def prezi( prezi_id, label = 'Link to presentation', size = [512,384] ) %Q|| end tdiary-contrib-3.2.2/plugin/profile.rb000066400000000000000000000143141213632744000177400ustar00rootroot00000000000000# # profile.rb: profile plugin for tDiary # # usage: # profile(id[, service = :twitter]) # - id: user ID for profile service # - service: profile service (default is :twitter) # Choose from :github, :twitter, :friendfeed, :iddy # # Copyright (C) 2009 by MATSUOKA Kohei < http://www.machu.jp/ > # Distributed under the GPL. # require 'timeout' require 'rexml/document' require 'open-uri' require 'digest/md5' require 'pstore' module ::Profile module Service # base class for profile services class Base # default attributes attr_reader :id attr_reader :image attr_reader :name attr_reader :mail attr_reader :description attr_reader :link # class instance variables class << self attr_reader :properties attr_reader :endpoint_proc end # set property and xpath pair for parse XML document def self.property(property, path) @properties ||= {} @properties[property] = path end # set endpoint proc (this proc is called by initialize method with id) def self.endpoint(&block) @endpoint_proc = block end def initialize(id, options = {}) @id = id @options = options if self.class.endpoint_proc endpoint = self.class.endpoint_proc.call(id) doc = fetch(endpoint) parse(doc) end end # get a XML document from endpoint and create REXML::Document instance def fetch(endpoint) timeout(5) do open(endpoint) do |f| doc = REXML::Document.new(f) end end end # parse XML document with properties def parse(doc) self.class.properties.each do |property, path| if doc.elements[path] value = doc.elements[path].text instance_variable_set("@#{property}", value) end end end end # github.com class GitHub < Base property :name, 'name' property :mail, 'email' endpoint {|id| "https://api.github.com/users/#{id}" } def image # "http://www.gravatar.com/avatar/#{Digest::MD5.hexdigest(@mail)}.jpg" Gravatar.new(@mail, @options).image end def link "http://github.com/#{@id}" end def fetch(endpoint) require 'json' timeout(5) do doc = open(endpoint) {|f| JSON.parse(f.read) } end end def parse(doc) self.class.properties.each do |property, key| instance_variable_set("@#{property}", doc[key]) if doc[key] end end end # twitter.com class Twitter < Base property :name, '//user/name' property :image, '//user/profile_image_url' property :description, '//user/description' endpoint {|id| "http://twitter.com/users/show/#{id}.xml" } def link "http://twitter.com/#{@id}" end end # friendfeed.com class FriendFeed < Base property :name, '//feed/name' property :description, '//feed/description' endpoint {|id| "http://friendfeed-api.com/v2/feed/#{id}?format=xml&num=0" } def image "http://friendfeed-api.com/v2/picture/#{id}" end def link "http://friendfeed.com/#{@id}" end end # iddy.jp # this class is based on iddy.rb class Iddy < Base ###################################################################### # If you will modify or release another version of this code, # please get your own application key from iddy.jp and replace below. ###################################################################### API_KEY = '9262ea8ffba962aabb4f1a1d3f1cfa953b11aa23' unless defined? API_KEY property :name, '//response/users/user/accountname' property :image, '//response/users/user/imageurl' property :description, '/response/users/user/profile' endpoint {|id| "http://iddy.jp/api/user/?apikey=#{API_KEY}&accountname=#{id}" } def link "http://iddy.jp/profile/#{@id}/" end end # gravatar.com class Gravatar < Base def image size = @options[:size] ? "?s=#{@options[:size]}" : "" "http://www.gravatar.com/avatar/#{Digest::MD5.hexdigest(@id.downcase)}.jpg#{size}" end end class Hatena < Base def image prefix = id[0..1] "http://www.hatena.ne.jp/users/#{prefix}/#{id}/profile.gif" end def link "http://www.hatena.ne.jp/#{id}/" end end end end PROFILE_VERSION = '20090909' def profile(id, service = :twitter, options = {}) html = '' service_class = { :twitter => Profile::Service::Twitter, :github => Profile::Service::GitHub, :friendfeed => Profile::Service::FriendFeed, :iddy => Profile::Service::Iddy, :gravatar => Profile::Service::Gravatar, :hatena => Profile::Service::Hatena, }[service.to_s.downcase.to_sym] # TODO: create cache manager class # cache = "#{@cache_path}/profile.yaml" cache = "#{@cache_path}/profile.pstore" profile = nil # db = YAML::Store.new(cache) db = PStore.new(cache) db.transaction do key = service_class.name db[key] ||= {} # initialize db updated = db[key][:updated] if updated && (Time::now < updated + 60 * 60) && db[key][:version] == PROFILE_VERSION # use cache profile = db[key][:profile] else # get latest date and update cache begin profile = service_class.new(id, options) rescue Timeout::Error, StandardError return html << %Q{
      no profile
      } end db[key][:updated] = Time::now db[key][:profile] = profile db[key][:version] = PROFILE_VERSION end end html << %Q{
      } end tdiary-contrib-3.2.2/plugin/pygments_css.rb000066400000000000000000000103421213632744000210130ustar00rootroot00000000000000# # pygments.rb: insert CSS for html formatted code with Pygments. # # Copyright (C) 2012 SHIBATA Hiroshi # You can redistribute it and/or modify it under GPL2. # require 'pygments' add_header_proc do <<-STYLE STYLE end tdiary-contrib-3.2.2/plugin/rating.rb000066400000000000000000000300321213632744000175570ustar00rootroot00000000000000# $Revision:0.1$ # rating.rb: ʣˤ뵭ɾȥɽ # for tDiary # # Ȥ # Τޤ plugin ǥ쥯ȥ֤ޤ # '' -> 'rating.rb Configuration' ǡɾ # ɽƤꡣ # 路 # http://www.maripo.jp/diary/?date=20071019 # # Copyright (c) 2007 Mariko/Maripo GODA # http://www.maripo.jp/ # You can redistribute it and/or modify it under GPL. require 'pstore' require 'cgi' @dbase = "#{@cache_path}/rating.db" ######################################### # Config (Form) ######################################### add_conf_proc('rating', 'rating.rb Configuration') do rating_config = RatingConfig.new(@dbase) form_string = "" if @mode == 'saveconf' # save conf index = 0 # edit axes rating_config.each { |axis_config| #check values if (@cgi.params["label" + index.to_s][0] != "" && (@cgi.params["range" + index.to_s][0]).to_i > 0) axis_config.edit(@cgi.params["label" + index.to_s][0], @cgi.params["label_max" + index.to_s][0],@cgi.params["label_min" + index.to_s][0],@cgi.params["range" + index.to_s][0].to_i,@cgi.params["order" + index.to_s][0].to_i,@cgi.params["display" + index.to_s][0]!=nil) index += 1 end } if (@cgi.params["label_new"][0] != "" && @cgi.params["range_new"][0].to_i > 0) # add new axis rating_config.add_axis(@cgi.params["label_new"][0], @cgi.params["label_max_new"][0], @cgi.params["label_min_new"][0], @cgi.params["range_new"][0].to_i) end rating_config.save_to_db end # print conf form form_string += < եɥХåե򤷤ޤϤĤǤ뤳ȤǤޤ

      blog ɲþ󤬽񤤤Ƥ뤫⤷ޤ

      ˡ

      • ɽ֤Ǥۤ¤Ӥޤֹ椬ǤOK
      • ɽ ʤϥå򳰤ƤޤäƤ
      • ̾ () "εϻͤˤʤޤ"
      • ٥ "ޤäͤˤʤʤ"
      • ǹ٥ "ȤƤ⻲ͤˤʤä"
      • : 155ʳʤ "5"
      • HTML index = 0; rating_config.each { |axis_config| form_string += < HTML index += 1 } form_string += <
        : ̾: ٥: ǹ٥: : ɽ:
        ɲ ̾: ٥: ǹ٥: :
        HTML form_string += '
        ' form_string #evaluate end ######################################### # Entry of the day ######################################### add_body_leave_proc do |date| graph_string = "" form_string = "" contentString = "" #initialize DateEval object todays_eval = DateEval.new(date.strftime('%Y%m%d'), @dbase) #initialize RatingConfig object @rating_config = RatingConfig.new(@dbase) graph_string += <
        [ʬۤߤ]
        HTML form_string += '' + "\n" form_string += ('
        ') @rating_config.each{|axis_config| if !axis_config.display next end # add axis info form_string += ('
        ' + axis_config.label + '') # add radio buttons form_string += ('' + axis_config.label_min + '') # append graph string current_rank = 0 graph_string += '
        ' #begin "graphBox" graph_string += 'average : ' + sprintf("%10.2f", todays_eval.get_average(axis_config.id)) +'
        ' while current_rank < axis_config.range graph_string += ('
        ' + (current_rank + 1).to_s + '
        (' + todays_eval.get_value(axis_config.id, current_rank).to_s + 'ɼ)
        ') current_rank += 1 end graph_string += '
        ' #end "graphBox" for current_rank in 0..axis_config.range - 1 form_string += " " + '' + (current_rank + 1).to_s end form_string += ('' + axis_config.label_max + '
        ') form_string += '
        ' } graph_string += <
        HTML form_string += '' form_string += '
        '+"\n" (form_string + graph_string) end ######################################### # class RatingConfig ######################################### class RatingConfig @axes @max_axis_id= 0 @dbase def initialize (dbase) @dbase = dbase db = PStore.new(@dbase) db.transaction do #begin transaction if db.root?("config") @axes = Hash.new obj = db["config"] @max_axis_id = obj[0] obj.each{|ary| id = ary[4] @axes[id] = AxisConfig.new(ary[0],ary[1],ary[2],ary[3],ary[4],ary[5],ary[6]) } else @axes = Hash.new @max_axis_id = 0 end end #end transaction end #end initialize def save_to_db save_array = Array.new db = PStore.new(@dbase) save_array.push(@max_axis_id) each {|axis_config| save_array.push(axis_config.to_array) } db.transaction do #begin transaction db["config"] = save_array end #end transaction end #end save_to_db def add_axis (label, label_max, label_min, range) @max_axis_id += 1 new_axis = AxisConfig.new(label, label_max, label_min, range, @max_axis_id, 0, true) @axes[@max_axis_id] = new_axis end #end add_axis def edit_axis (axis_id, label, label_max, label_min, range, order,display) target_axis = @axes[axis_id] target_axis.edit(label, label_max, label_min, range, order,display) end def length return @axes.size end #end length def each @axes.to_a.sort {|a, b| a[1].order <=> b[1].order}.each {|key ,axis_conf| yield axis_conf } end #end each end ######################################### # class AxisConfig ######################################### class AxisConfig @label @label_max @label_min @range @id @order @display = true #accessors attr_reader :label, :label_max, :label_min, :range, :id, :order, :display def initialize (label, label_max, label_min, range, id,order,display) @label = label @label_max = label_max @label_min = label_min @range = range @id = id @order = order @display = display end #end initialize def edit (label, label_max, label_min, range, order, display) @label = label @label_max = label_max @label_min = label_min @range = range @order = order @display = display end #end initialize def to_array return [@label, @label_max, @label_min, @range, @id, @order,@display] end def disable @hidden = true end #end disable def enable @hidden = false end #end disable def check_label return @display? "checked":"" end #end check_label end ######################################### # class DateEval ######################################### class DateEval @axes #axes[id][rank] @date_string = "" @dbase @average #average[id] @total #total[id] GRAPH_PIXEL_LENGTH = 300 attr_reader :axes, :average, :total # constructor def initialize (date_string, dbase) @dbase = dbase @date_string = date_string db = PStore.new(@dbase) db.transaction do #begin transaction if db.root?(date_string) #read @axes = db[date_string] else #initialize @axes = Hash.new end end #end transaction end #end constructor def get_value(id, rank) if @axes.key?(id) && @axes[id][rank] != nil return @axes[id][rank] else return 0 end end def get_average(id) sum = 0 vote = 0 unless @axes.key?(id) return 0 end for index in 0..@axes[id].length - 1 if @axes.key?(id) && @axes[id][index] != nil vote += @axes[id][index] sum += @axes[id][index] * index end end if @axes[id].length == 0 return 0 else return sum.to_f/vote + 1 end end def vote(id, rank) unless @axes.key?(id) @axes[id] = Array.new end if @axes[id][rank] != nil @axes[id][rank] += 1 else @axes[id][rank] = 1 end end def save_to_db db = PStore.new(@dbase) db.transaction do #begin transaction #save db[@date_string] = @axes end #end transaction end #end save_to_db def get_graph_length (id, rank) unless @axes.key?(id) return 0 end if @axes[id][rank] != nil total = 0 @axes[id].each {|val| unless val == nil total += val end } return (@axes[id][rank] * GRAPH_PIXEL_LENGTH / total).to_i else return 0 end end #end end # class dateEval end ######################################### # Comment (vote) ######################################### if (@mode == 'comment') if @cgi.params["body"][0] != 'rating' return end @dbase = "#{@cache_path}/rating.db" #initialize RatingConfig object rating_config = RatingConfig.new(@dbase) #initialize DateEval object todays_eval = DateEval.new(@cgi.params['date'][0], @dbase) rating_config.each { |axis_config| if @cgi.params["axis" + axis_config.id.to_s][0]!= nil todays_eval.vote(axis_config.id, @cgi.params["axis" + axis_config.id.to_s][0].to_i) end } todays_eval.save_to_db end tdiary-contrib-3.2.2/plugin/recent_estraier.rb000066400000000000000000000026221213632744000214550ustar00rootroot00000000000000# recent_estraier.rb $Revision 1.1 $ # # recent_estraier: Estraier検索語新しい順 # estsearch.cgiが作成する検索キーワードログから # 最新xx件分の検索語を表示します。 # パラメタ: # file: 検索キーワードログファイル名(絶対パス表記) # estraier: estseach.cgiのパス # limit: 表示件数(未指定時:5) # make_link: を生成するか?(未指定時:生成する) # # # Copyright (c) 2005 SHIBATA Hiroshi # Distributed under the GPL2. # require 'nkf' def recent_estraier(file, estraier, limit = 5, make_link = true) begin lines = [] log = open(file) if log.stat.size > 300 * limit then log.seek(-300 * limit,IO::SEEK_END) end log.each_line do |line| lines << line end result = "
          " lines.reverse.each_with_index do |line,idx| break if idx >= limit word = NKF::nkf('-We -m0', line.split(/\t/)[2]) if word.empty? then limit += 1 else if make_link result << %Q|
        1. #{h word}
        2. | else result << %Q|#{h word}| end end end result << %Q[
        ] rescue %Q[

        #$! (#{$!.class})
        cannot read #{file}.

        ] end end tdiary-contrib-3.2.2/plugin/recent_tweet.rb000066400000000000000000000041161213632744000207670ustar00rootroot00000000000000# # recemt_tweet.rb: Twitter status plugin for tDiary # # Copyright (C) 2007 by Nishimoto Masaki # Distributed under GPL. # require 'open-uri' require 'timeout' require 'rexml/document' def recent_tweet( id, count ) begin cache = "#{@cache_path}/recent_tweet.xml" xml = open( cache ) {|f| f.read } if Time::now > File::mtime( cache ) + 10*60 then File::delete( cache ) # clear cache 10 minutes later end rescue Errno::ENOENT begin xml = recent_tweet_call_api( id ) open( cache, 'wb' ) {|f| f.write( xml ) } rescue Timeout::Error, StandardError return %Q|
        recent_tweet: #{$!}
        | end end begin doc = REXML::Document::new( xml ) if doc then html = '
        ' html << '

        ' html << 'What am I doing...' html << '

        ' html << '
          ' i = 0 doc.elements.each( 'statuses/status' ) do |status| created_at = Time.parse( status.elements.to_a( 'created_at' )[0].text ) text = status.elements.to_a( 'text' )[0].text if /^@/.match( text ) == nil and i < count then html << '
        • ' if Time.now > created_at + 60*60*23 then time = created_at.localtime.strftime( '%b %d %H:%M' ) else time = created_at.localtime.strftime( '%H:%M' ) end html << '' << %Q|#{text}| << ' ' html << '(' << %Q|#{time}| << ')' html << '
        • ' i += 1 end end html << '
        ' @conf.to_native( html ) else return '
        recent_tweet: Failed to open file
        ' end rescue REXML::ParseException return '
        recent_tweet: Failed to parse XML
        ' end end def recent_tweet_call_api( id ) request = "http://twitter.com/statuses/user_timeline/#{id}.xml" proxy = @conf['proxy'] proxy = 'http://' + proxy if proxy timeout( 10 ) do open( request, :proxy => proxy ) {|f| f.read } end end tdiary-contrib-3.2.2/plugin/retweet.rb000066400000000000000000000052361213632744000177620ustar00rootroot00000000000000# # retweet.rb - show retweet count in each section # This plugin uses a Topsy Retweet Button for Web Sites powered by Topsy.com # # Copyright (C) 2010, MATSUOKA Kohei # You can redistribute it and/or modify it under GPL2. # # # settings for Topsy Retweet Button. # see: http://labs.topsy.com/button/retweet-button/#global_settings # # your Twitter username @topsy_nick = "your_twitter_account" # retweet button color #@topsy_theme = "blue" # retweet button text #@topsy_retweet_text = "retweet" unless defined?(permalink) def permalink( date, index, escape = true ) ymd = date.strftime( "%Y%m%d" ) uri = @conf.index.dup uri.sub!( %r|\A(?!https?://)|i, @conf.base_url ) uri.gsub!( %r|/\.(?=/)|, "" ) # /././ -> / link = uri + anchor( "#{ymd}p%02d" % index ) link.sub!( "#", "%23" ) if escape link end end unless defined?(subtitle) def subtitle( date, index, escape = true ) diary = @diaries[date.strftime( "%Y%m%d" )] return "" unless diary sn = 1 diary.each_section do |section| if sn == index old_apply_plugin = @options["apply_plugin"] @options["apply_plugin"] = true title = apply_plugin( section.subtitle_to_html, true ) @options["apply_plugin"] = old_apply_plugin title.gsub!( /(?=")/, "\\" ) if escape return title end sn += 1 end end end # load Tospy's script and initialize add_header_proc do r = "" r << %Q|\n| return r unless @topsy_theme or @topsy_nick or @topsy_retweet_text r << %Q|\n| end # show retweet button in top of section add_section_enter_proc do |date, index| <<-"EOS"
        EOS end # show retweet button in end of section add_section_leave_proc do |date, index| <<-"EOS"
        Twitter:
        EOS end tdiary-contrib-3.2.2/plugin/rubykaigi.rb000066400000000000000000000100751213632744000202660ustar00rootroot00000000000000# # rubykaigi.rb: make badges of RubyKaigi. # # usage: <%= rubykaigi 'role', 'size' %> # role: attendee (default), speaker, sponsor, staff, committer, individual sponsor, away # size: large(160x160), small(160x90) # # Copyright (C) TADA Tadashi # Distributed under GPL. # def rubykaigi2013( role = 'attendee', size = nil ) r = role.split(/[ _]+/).map{|s| s.capitalize}.join s = "@#{h size}" unless size.nil? %Q|RubyKaigi 2013 #{h r}| end def sappororubykaigi2012( role = 'attendee' ) r = role.split(/[ _]+/).map{|s| s.capitalize}.join %Q|SapporoRubyKaigi 2012 #{h r}| end def kansairubykaigi04( role = 'attendee' ) badges = { 'attendee' => "attendee_taiyou", 'speaker' => "speaker_shika", 'staff' => "staff_daibutsu" } %Q|KansaiRubyKaigi04 #{h role.capitalize}| end def rubykaigi2011( role = 'attendee', size = 'large' ) badges = Hash::new( 'attendee' ).update({ 'committer' => 'committer', 'individual sponsor' => 'individualSponsor', 'sponsor' => 'sponsor', 'staff' => 'staff', 'speaker' => 'speaker', 'attendee' => 'attendee', 'away' => 'attendeeAway' }) width, height = size == 'large' ? ['160','160'] : ['160', '90'] %Q|RubyKaigi2010 #{h role.capitalize}| end alias :rubykaigi :rubykaigi2011 #----- OLD EDITIONS -----# def sappororubykaigi03( role = 'attendee' ) %Q|badge_#{h role}.gif| end def rubykaigi2010( role = 'attendee' ) badges = Hash::new( 'attendee' ).update({ 'committer' => 'committer', 'individual sponsor' => 'individual_sponsor', 'sponsor' => 'sponsor', 'staff' => 'staff', 'speaker' => 'speaker', 'attendee' => 'attendee', 'away' => 'away' }) %Q|RubyKaigi2010 #{h role.capitalize}| end def rubykaigi2009( role = 'attendee' ) %Q|
        RubyKaigi2009#{h role.capitalize}
        | end def rubykaigi2008( role = 'attendee' ) img = case role when 'speaker' 1 when 'sponsor' 2 when 'staff' 3 else role = 'attendee' 0 end %Q|
        RubyKaigi2008#{h role.capitalize}
        | end def sappororubykaigi02( role = 'attendee' ) %Q|
        SapporoRubyKaigi02#{h role.capitalize}
        | end # Local Variables: # mode: ruby # indent-tabs-mode: t # tab-width: 3 # ruby-indent-level: 3 # End: # vim: ts=3 tdiary-contrib-3.2.2/plugin/search-bing.rb000066400000000000000000000046101213632744000204600ustar00rootroot00000000000000# -*- coding: utf-8 -*- # # search-bing.rb - site search plugin sample using Bing API. # # Copyright (C) 2011, TADA Tadashi # You can redistribute it and/or modify it under GPL. # # Needed these options below: # # @options['search-bing.appid'] : Your Bing AppId # @options['search.result_filter'] : your dialy's URL format of DAY mode into Regexp. # require 'timeout' require 'json' require 'open-uri' def search_title '全文検索 by Bing' end def search_input_form( q ) r = <<-HTML
        検索キーワード:
        HTML end def search_bing_api( q, start = 0 ) appid = @conf['search-bing.appid'] u = 'https://api.datamarket.azure.com/Data.ashx/Bing/SearchWeb/v1/Web' u << "?Query=%27#{q}%27&Options=%27EnableHighlighting%27&$top=50&$skip=#{start}&$format=Json" uri = URI( u ) open( uri, {:http_basic_authentication => [appid, appid]} ).read ### FIX ME: this code failed on Timeout error, temporary using open-uri above. # px_host, px_port = (@conf['proxy'] || '').split( /:/ ) # px_port = 8080 if px_host and !px_port # res = Net::HTTP::Proxy( px_host, px_port ).start( uri.host, uri.port ) do |http| # req = Net::HTTP::Get.new( uri.request_uri ) # req.basic_auth( appid, appid ) # res = http.request( req ) # end # res.body end def search_to_html( str ) (str || '').gsub( /\uE000/, '' ).gsub( /\uE001/, '' ) end def search_result query = CGI::unescape( @cgi.params['q'][0] ) start = CGI::unescape( @cgi.params['start'][0] || '0' ).to_i begin uri = URI::parse( @conf.base_url ) #uri = URI::parse( 'http://sho.tdiary.net/' ) ### FOR DEBUGGING ### q = "#{query} site:#{uri.host}" q << %Q| inurl:"#{uri.path}"| unless uri.path == '/' xml = search_bing_api( u( q.untaint ), start ) json = JSON::parse( xml ) rescue Net::HTTPError return %Q|

        #$!

        | end r = search_input_form( query ) r << '
        ' json['d']['results'].each do |entry| url = entry['Url'] title = entry['Title'] desc = entry['Description'] r << %Q|
        #{search_to_html title}
        | r << %Q|
        #{search_to_html desc}
        | end r << '
        ' r << '
        ' # no search navi on Bing search because no total result not supported r << '
        ' r end tdiary-contrib-3.2.2/plugin/search-default.rb000066400000000000000000000135331213632744000211710ustar00rootroot00000000000000# -*- coding: utf-8 -*- # # search-default.rb - site search plugin sample using DefaultIO. # # Copyright (C) 2003-2005 Minero Aoki # Copyright (C) 2012, TADA Tadashi # You can redistribute it and/or modify it under GPL2. # # def search_title '全文検索' end class WrongQuery < StandardError; end module DefaultIOSearch module_function def setup_patterns(query) patterns = split_string(query).map {|pat| check_pattern pat Regexp.new( Regexp.quote(pat), Regexp::IGNORECASE ) } raise WrongQuery, 'no pattern' if patterns.empty? raise WrongQuery, 'too many sub patterns' if patterns.length > 8 patterns end def check_pattern(pat) raise WrongQuery, 'no pattern' unless pat raise WrongQuery, 'empty pattern' if pat.empty? raise WrongQuery, "pattern too short: #{pat}" if pat.length < 2 raise WrongQuery, 'pattern too long' if pat.length > 128 end def split_string(str) str.split(/[\s ]+/ou).reject {|w| w.empty? } end INF = 1 / 0.0 def match_components(patterns, data_path) foreach_diary_from_latest(data_path) do |diary| next unless diary.visible? num = 1 diary.each_section do |sec| if patterns.all? {|re| re =~ sec.to_src } yield diary, fragment('p', num), sec end num += 1 end diary.each_visible_comment(INF) do |cmt, num| if patterns.all? {|re| re =~ cmt.body } yield diary, fragment('c', num), cmt end end end end def fragment(type, num) sprintf('%s%02d', type, num) end # # tDiary Implementation Dependent # def foreach_diary_from_latest(data_path, &block) foreach_data_file(data_path.sub(%r, '')) do |path| read_diaries(path).sort_by {|diary| diary.date }.reverse_each(&block) end end def foreach_data_file(data_path, &block) Dir.glob("#{data_path}/[0-9]*/*.td2").sort.reverse_each do |path| yield path.untaint end end def read_diaries(path) d = nil diaries = {} load_tdiary_textdb(path) do |header, body| begin d = diary_class(header['Format']).new(header['Date'], '', body) rescue ArgumentError next end d.show(header['Visible'] != 'false') diaries[d.ymd] = d end (Years[d.y] ||= []).push(d.m) if d load_comments diaries, path diaries.values end DIARY_CLASS_CACHE = {} def diary_class(style) c = DIARY_CLASS_CACHE[style] return c if c require "tdiary/style/#{style.downcase}_style.rb" c = eval("TDiary::#{style.capitalize}Diary") c.__send__(:include, DiaryClassDelta) DIARY_CLASS_CACHE[style] = c c end module DiaryClassDelta def ymd date().strftime('%Y%m%d') end def y_m_d date().strftime('%Y-%m-%d') end def y '%04d' % date().year end def m '%02d' % date().month end end def load_comments(diaries, path) cmtfile = path.sub(/2\z/, 'c') return unless File.file?(cmtfile) load_tdiary_textdb(cmtfile) do |header, body| c = TDiary::Comment.new(header['Name'], header['Mail'], body, Time.at(header['Last-Modified'].to_i)) c.show = (header['Visible'] != 'false') d = diaries[header['Date']] d.add_comment c if d end end def load_tdiary_textdb(path) File.open(path) {|f| ver = f.gets.strip raise "unkwnown format: #{ver}" unless ver == 'TDIARY2.00.00' or ver == 'TDIARY2.01.00' f.each('') do |header| h = {} header.untaint.strip.each_line do |line| begin n, v = *line.split(':', 2) rescue ArgumentError next end h[n.strip] = v.strip end body = f.gets("\n.\n").chomp(".\n").untaint yield h, body end } end def short_html(component) # Section classes do not have common superclass, we can't use class here. case component.class.name when /Section/ section = component if section.subtitle sprintf('%s
        %s', tdiary2text(section.subtitle_to_html), tdiary2text(section.body_to_html)) else tdiary2text(section.body_to_html) end when /Comment/ cmt = component shorten(escape((cmt.name + ': ' + cmt.body))) else raise "must not happen: #{component.class}" end end def tdiary2text(html) re = Regexp.new('<[^>]*>', Regexp::EXTENDED) shorten(apply_tdiary_plugins(html).gsub(re, '')) end Years = {} TDiary::Plugin.__send__(:public, :apply_plugin) def apply_tdiary_plugins(html) #@plugin.apply_plugin(html, false) html end @plugin = nil # # Utils # HTML_ESCAPE_TABLE = { '&' => '&', '<' => '<', '>' => '>', '"' => '"' } def escape(str) tbl = HTML_ESCAPE_TABLE str.gsub(/[&"<>]/) {|ch| tbl[ch] } end def shorten(str, len = 200) matched = str.gsub( /\n/, ' ' ).scan( /^.{0,#{len - 3}}/u )[0] if $'.nil? || $'.empty? matched else matched + '...' end end end def search_input_form( q ) r = <<-HTML
        検索キーワード:
        HTML end def search_result unless @conf.io_class == TDiary::DefaultIO return %Q|

        could not use this plugin under #{@conf.io_class}.

        | end query = CGI::unescape( @cgi.params['q'][0] ) start = CGI::unescape( @cgi.params['start'][0] || '0' ).to_i begin patterns = DefaultIOSearch::setup_patterns(query) r = search_input_form( query ) r << '
        ' count = 0 too_many = false DefaultIOSearch::match_components(patterns, @conf.data_path) do |diary, fragment, component| count += 1 if count > 50 # TO MANY HITS too_many = true break end href = @conf.index + anchor( "#{diary.ymd}#{fragment}" ) r << %Q|
        #{h diary.y_m_d}
        | r << %Q|
        #{DefaultIOSearch::short_html(component)}
        | end r << '
        ' r << '
        ' r << "

        #{too_many ? 'too many' : count} hits.

        " r << '
        ' r rescue WrongQuery search_input_form( query ) + %Q|

        #{$!.message}

        | end end tdiary-contrib-3.2.2/plugin/search-google-custom.rb000066400000000000000000000043021213632744000223230ustar00rootroot00000000000000# -*- coding: utf-8 -*- # # search-google-custom.rb - site search plugin using Goole Custom Search. # # Copyright (C) 2011, hb # You can redistribute it and/or modify it under GPL. # # Needed these options below: # # @options["search-google-custom.id"] : Your Google Custome Search ID # @options["search-google-custom.cof"] : 広告の表示場所(9:右,10:一番上と右,11:一番上と下) # @options["search-google-custom.width"] : 検索結果のフレームの幅 # @options["search-google-custom.height"] : 検索結果のフレームの高さ # @options["search-google-custom.search_label"] : 検索テキストボックス左のラベル # @options["search-google-custom.button_text"] : 検索ボタンに書かれる文字列 # def search_title '全文検索 by Google カスタム検索' end add_footer_proc do %Q|| end def search_input_form(q='') cof = @conf["search-google-custom.cof"] || 9 search_label = @conf["search-google-custom.search_label"] || '検索キーワード:' button_text = @conf["search-google-custom.button_text"] || '検索' r = <<-HTML HTML end def search_result w = @conf["search-google-custom.width"] || 600 h = @conf["search-google-custom.height"] || 1300 r = <<-HTML
        HTML end tdiary-contrib-3.2.2/plugin/search-yahoo-websearch.rb000066400000000000000000000072411213632744000226240ustar00rootroot00000000000000# -*- coding: utf-8 -*- # # search-yahoo-websearch.rb - Yahoo!デベロッパーネットワークのWeb検索APIを利用した検索プラグイン. # # Copyright (C) 2011, hb # You can redistribute it and/or modify it under GPL. # # オプション # # @options['search-yahoo-websearch.appid'] : アプリケーションID(必須) # @options['search-yahoo-websearch.premium'] : アップグレード版利用時はtrueを指定する(任意) # def search_title '全文検索 by Yahoo! ウェブ検索' end def search_input_form( q ) r = <<-HTML
        検索キーワード:
        HTML end def request_url if @conf['search-yahoo-websearch.premium'] 'http://search.yahooapis.jp/PremiumWebSearchService/V1/webSearch' else 'http://search.yahooapis.jp/WebSearchService/V2/webSearch' end end def search_to_html( str ) (str || '').gsub( /(?:]*)?>)+/, '' ).gsub( %r{<(/?)b[ \t\n\r]*>}, '<\\1strong>' ) end def yahoo_websearch_api( q, start = 1 ) url = request_url appid = @conf['search-yahoo-websearch.appid'] uri = URI::parse( @conf.base_url ) url << "?appid=#{appid}&query=#{q}&results=20&start=#{start}&format=html&site=#{uri.host}" proxy = @conf['proxy'] proxy = 'http://' + proxy if proxy proxy_host, proxy_port = nil if proxy proxy_host = proxy_uri.host proxy_port = proxy_uri.port end proxy_class = Net::HTTP::Proxy(proxy_host, proxy_port) query = URI.parse(url) req = Net::HTTP::Get.new(query.request_uri) http = proxy_class.new(query.host, query.port) http.open_timeout = 20 http.read_timeout = 20 res = http.start do http.request(req) end res.body end def yahoo_websearch_attribution <<-EOF Web Services by Yahoo! JAPAN EOF end def search_result query = CGI::unescape( @cgi.params['q'][0] ) start = CGI::unescape( @cgi.params['start'][0] || '1' ).to_i begin uri = URI::parse( @conf.base_url ) xml = yahoo_websearch_api( u( query.untaint ), start ) doc = REXML::Document::new( REXML::Source.new( xml ) ).root err = doc.elements.to_a( '/Error/Message' )[0] if err return %Q|

        ERROR - #{err.text}

        | end rescue OpenURI::HTTPError return %Q|

        #$!

        | end r = '
        ' doc.elements.to_a( 'Result' ).each do |elem| url = elem.elements.to_a( 'Url' )[0].text next unless url =~ @conf['search.result_filter'] title = elem.elements.to_a( 'Title' )[0].text summary = elem.elements.to_a( 'Summary' )[0].text r << %Q|
        #{search_to_html title}
        | r << %Q|
        #{search_to_html summary}
        | end r << '
        ' r << '
        ' pos = doc.elements["/ResultSet"].attributes["firstResultPosition"] unless pos == '1' r << %Q| | end total = doc.elements["/ResultSet"].attributes["totalResultsAvailable"] ret = doc.elements["/ResultSet"].attributes["totalResultsReturned"] if ret.to_i == 20 and pos.to_i + 19 < 1000 r << %Q|| end r << '
        ' r << yahoo_websearch_attribution r end tdiary-contrib-3.2.2/plugin/search-yahoo.rb000066400000000000000000000057551213632744000206730ustar00rootroot00000000000000# -*- coding: utf-8 -*- # # search-yahoo.rb - site search plugin sample using Yahoo! Search BOSS API. # # Copyright (C) 2009, TADA Tadashi # You can redistribute it and/or modify it under GPL. # # Needed these options below: # # @options['search-yahoo.appid'] : Your BOSS APPID # @options['search-yahoo.result_filter'] : your dialy's URL format of DAY mode into Regexp. # require 'timeout' require 'rexml/document' require 'net/http' Net::HTTP.version_1_2 def search_title '全文検索 by Yahoo! Search BOSS' end def search_input_form( q ) r = <<-HTML
        検索キーワード:
        HTML end def search_boss_api( q, start = 0 ) url = 'http://boss.yahooapis.com/ysearch/web/v1/' appid = @conf['search-yahoo.appid'] url << "#{q}?appid=#{appid}&format=xml&count=20&start=#{start}" proxy = @conf['proxy'] proxy = 'http://' + proxy if proxy proxy_host, proxy_port = nil if proxy proxy_host = proxy_uri.host proxy_port = proxy_uri.port end proxy_class = Net::HTTP::Proxy(proxy_host, proxy_port) query = URI.parse(url) req = Net::HTTP::Get.new(query.request_uri) http = proxy_class.new(query.host, query.port) http.open_timeout = 20 http.read_timeout = 20 res = http.start do http.request(req) end res.body end def search_to_html( str ) (str || '').gsub( /(?:]*)?>)+/, '' ).gsub( %r{<(/?)b[ \t\n\r]*>}, '<\\1strong>' ) end def search_result query = CGI::unescape( @cgi.params['q'][0] ) start = CGI::unescape( @cgi.params['start'][0] || '0' ).to_i begin uri = URI::parse( @conf.base_url ) q = "#{query} site:#{uri.host}" q << %Q| inurl:"#{uri.path}"| unless uri.path == '/' xml = search_boss_api( u( q.untaint ), start ) doc = REXML::Document::new( REXML::Source.new( xml ) ).root res = doc.elements.to_a( '/ysearchresponse' )[0] unless res.attribute( 'responsecode' ).value == '200' then return '

        ERROR

        ' end rescue OpenURI::HTTPError return %Q|

        #$!

        | end r = search_input_form( query ) r << '
        ' doc.elements.to_a( '*/result' ).each do |elem| url = elem.elements.to_a( 'url' )[0].text next unless url =~ @conf['search-yahoo.result_filter'] title = elem.elements.to_a( 'title' )[0].text abstract = elem.elements.to_a( 'abstract' )[0].text r << %Q|
        #{search_to_html title}
        | r << %Q|
        #{search_to_html abstract}
        | end r << '
        ' r << '
        ' doc.elements.to_a( '/ysearchresponse/prevpage' ).each do |p| if /start=\d+/ =~ p.text then r << %Q| | end end doc.elements.to_a( '/ysearchresponse/nextpage' ).each do |n| if /start=\d+/ =~ n.text then r << %Q|| end end r << '
        ' r end tdiary-contrib-3.2.2/plugin/section_footer.rb000066400000000000000000000147241213632744000213270ustar00rootroot00000000000000# -*- coding: utf-8 -*- # section_footer.rb # # Copyright (c) 2005 SHIBATA Hiroshi # You can redistribute it and/or modify it under GPL2. # require 'digest/md5' require 'open-uri' require 'timeout' def permalink( date, index, escape = true ) ymd = date.strftime( "%Y%m%d" ) uri = @conf.index.dup uri.sub!( %r|\A(?!https?://)|i, @conf.base_url ) uri.gsub!( %r|/\.(?=/)|, "" ) # /././ -> / link = uri + anchor( "#{ymd}p%02d" % index ) link.sub!( "#", "%23" ) if escape link end add_header_proc do <<-SCRIPT SCRIPT end add_section_enter_proc do |date, index| @category_to_tag_list = {} end alias subtitle_link_original subtitle_link def subtitle_link( date, index, subtitle ) s = '' if subtitle then s = subtitle.sub( /^(\[([^\[]+?)\])+/ ) do $&.scan( /\[(.*?)\]/ ) do |tag| @category_to_tag_list[tag] = false # false when diary end '' end end subtitle_link_original( date, index, s.strip ) end add_section_leave_proc do |date, index| r = '
        ' unless @conf.mobile_agent? then # カテゴリタグの追加 if @category_to_tag_list and not @category_to_tag_list.empty? then r << "Tags: " @category_to_tag_list.each do |tag, blog| if blog r << %Q|#{tag} | else r << category_anchor( "#{tag}" ).sub( /^\[/, '' ).sub( /\]$/, '' ) << ' ' end end end # 「このエントリの Delicious history (JSON)」 r << add_delicious_json(date, index) # 「このエントリを含む Delicious (画像API)」 # r << add_delicious(date, index) # 「このエントリを含むはてなブックーク」 r << add_hatenabm(date, index) # 「このエントリを含む livedoor クリップ」 r << add_ldclip(date, index) # 「このエントリを含む Buzzurl」 r << add_buzzurl(date, index) # 「このエントリを含む Yahoo!ブックマーク」 r << add_yahoobm(date, index) # Permalinkの追加 r << add_permalink(date, index) end r << "
        \n" end def add_permalink(date, index) r = " | " r << %Q|Permalink | return r end def add_hatenabm(date, index) r = " | " r << %Q|#{@section_footer_hatenabm_label} | return r end def add_ldclip(date, index) r = " | " r << %Q|#{@section_footer_ldclip_label} | return r end def add_buzzurl(date, index) r = " | " r << %Q|#{@section_footer_buzzurl_label} | return r end def add_delicious(date, index) url_md5 = Digest::MD5.hexdigest(permalink(date, index, false)) r = " | " r << %Q|#{@section_footer_delicious_label} | return r end def add_delicious_json(date, index) require 'fileutils' begin require 'json' rescue retry if require 'rubygems' end url_md5 = Digest::MD5.hexdigest(permalink(date, index, false)) cache_dir = "#{@cache_path}/delicious/#{date.strftime( "%Y%m" )}/" file_name = "#{cache_dir}/#{url_md5}.json" cache_time = 8 * 60 * 60 # 8 hour update = false count = 0 r = " | " r << %Q|#{@section_footer_delicious_label}| begin FileUtils.mkdir_p( cache_dir ) unless File::directory?( cache_dir ) cached_time = nil cached_time = File::mtime( file_name ) if File::exist?( file_name ) unless cached_time.nil? if Time.now > cached_time + cache_time update = true end end if cached_time.nil? or update begin timeout(10) do open( "http://feeds.delicious.com/v2/json/urlinfo/#{url_md5}") do |file| File::open( file_name, 'wb' ) do |f| f.write( file.read ) end end end rescue => e @logger.debug( e ) end end rescue end begin File::open( file_name ) do |f| data = JSON.parse(@conf.to_native( f.read, 'utf-8' )) unless data[0].nil? count = data[0]["total_posts"].to_i end end rescue end if count > 0 r << %Q| #{count} users| else r << %Q|| end return r end def add_yahoobm(date, index) r = " | " r << %Q|#{@section_footer_yahoobm_label}| return r end tdiary-contrib-3.2.2/plugin/section_footer2.rb000066400000000000000000000170551213632744000214110ustar00rootroot00000000000000# section_footer2.rb # # Copyright (c) 2008 SHIBATA Hiroshi # You can redistribute it and/or modify it under GPL2. # require 'digest/md5' require 'timeout' require 'open-uri' require 'yaml' require 'pathname' begin require 'json' rescue LoadError retry if require 'rubygems' end def permalink( date, index, escape = true ) ymd = date.strftime( "%Y%m%d" ) uri = @conf.index.dup uri.sub!( %r|\A(?!https?://)|i, @conf.base_url ) uri.gsub!( %r|/\.(?=/)|, "" ) # /././ -> / link = uri + anchor( "#{ymd}p%02d" % index ) link.sub!( "#", "%23" ) if escape link end unless defined?(subtitle) def subtitle( date, index, escape = true ) diary = @diaries[date.strftime( "%Y%m%d" )] return "" unless diary sn = 1 diary.each_section do |section| if sn == index old_apply_plugin = @options["apply_plugin"] @options["apply_plugin"] = true title = apply_plugin( section.subtitle_to_html, true ) @options["apply_plugin"] = old_apply_plugin title.gsub!( /(?=")/, "\\" ) if escape return title end sn += 1 end '' end end def init_buttons_status @installed_buttons = ['yaml', 'delicious', 'hatena', 'facebook', 'twitter', 'plusone'] if @conf['section_footer2.isDisplay'].nil? @conf['section_footer2.isDisplay'] = '' end end add_header_proc do <<-"EOS" EOS end add_section_enter_proc do |date, index| @category_to_tag_list = {} init_buttons_status '' end alias section_footer2_subtitle_link_original subtitle_link unless defined?( section_footer2_subtitle_link_original ) def subtitle_link( date, index, subtitle ) s = '' @subtitle = subtitle if subtitle then s = subtitle.sub( /^(?:\[[^\[]+?\])+/ ) do $&.scan( /\[(.*?)\]/ ) do |tag| @category_to_tag_list[tag.shift] = false # false when diary end '' end end section_footer2_subtitle_link_original( date, index, s.strip ) end add_section_leave_proc do |date, index| unless @conf.mobile_agent? or @conf.iphone? or feed? or bot? r = '
        ' # add category_tag if @category_to_tag_list and not @category_to_tag_list.empty? then r << "Tags: " @category_to_tag_list.each do |tag, blog| r << category_anchor( "#{tag}" ).sub( /^\[/, '' ).sub( /\]$/, '' ) << ' ' end r << ' | ' end # add button r << add_button_by_service(date, index) # add Permalink r << %Q|Permalink | r << "
        \n" end end def call_delicious_json( url_md5 ) json = nil begin timeout(10) do open( "http://feeds.delicious.com/v2/json/urlinfo/#{url_md5}" ) do |f| json = JSON.parse( f.read ) end end rescue => e @logger.debug( e ) end return json end def add_delicious( date, index ) url_md5 = Digest::MD5.hexdigest(permalink(date, index, false)) db_file = "#{@cache_path}/delicious.cache" r = '' r << %Q|#{@section_footer2_delicious_label}| begin cache_time = 8 * 60 * 60 # 12 hour PStore.new(db_file).transaction do |db| entry = db[url_md5] entry = { :count => 0, :update=> Time.at(0) } if entry.nil? if Time.now > entry[:update] + cache_time json = call_delicious_json( url_md5 ) entry[:count] = json[0]["total_posts"].to_i unless json[0].nil? entry[:update] = Time.now db[url_md5] = entry end if entry[:count] > 0 r << %Q| #{entry[:count]} user| r << 's' if entry[:count] > 1 end end rescue => e @logger.debug( e ) end r << '' r << ' | ' return r end def add_hatena( date, index ) %Q! | ! end def add_facebook(date, index) # add Facebook Like! r = '' r << %Q! | ! end def add_twitter(date, index) r = <<-"EOS" | EOS end def add_plusone(date, index) %Q! | ! end def add_yaml(date, index) r = '' yaml_dir = "#{@cache_path}/yaml/" Dir.glob( yaml_dir + "*.yaml" ) do |file| r << parse_sbm_yaml(file, date, index) end return r end def add_button_by_service(date, index) r = '' @installed_buttons.each do |button| if @conf['section_footer2.isDisplay'].include?(button) then method = "add_" + button + "(date, index)" unless method.nil? then r << instance_eval(method) end end end return r end def parse_sbm_yaml(file, date, index) config = YAML.load( Pathname.new( file ).expand_path.read ) r = "" unless config.nil? url = config["url"] unless config['usesubtitle'].nil? sub = (@subtitle || '').sub( /\A(?:\[[^\]]*\])+ */, '' ) sub = apply_plugin( sub, true ).strip regexp = config["usesubtitle"] url.gsub!(regexp, sub) char_space = ' ' end title = config["title"][@conf.lang] r << %Q|| r << %Q|| r << %Q| | unless config["counter"].nil? r << '' r << ' | ' end return r end add_conf_proc('section_footer2', 'Section Footer Button') do if @mode == 'saveconf' then @conf['section_footer2.isDisplay'] = '' @cgi.params['section_footer2.isDisplay'].each do |item| @conf['section_footer2.isDisplay'] << item + '\n' end end r = '

        表示するボタンをチェックしてください(YAMLをチェックすると各自でインストールしたYAMLのボタンをすべて表示します)

        ' r << '

        ' init_buttons_status @installed_buttons.each do |button| if @conf['section_footer2.isDisplay'].include?(button) then item_checked = "checked" else item_checked = '' end r << %Q|#{button}| end r << '

        ' end # Local Variables: # mode: ruby # indent-tabs-mode: t # tab-width: 3 # ruby-indent-level: 3 # End: # vim: ts=3 tdiary-contrib-3.2.2/plugin/section_permalink.rb000066400000000000000000000030341213632744000220030ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2011, KADO Masanori # You can redistribute it and/or modify it under GPL. # # section_permalink.rb # - enables section permalink and shows section title def section_mode? @mode == 'day' and @cgi.params['p'][0].to_s != "" end # Change permalink def anchor( s ) if /^([\-\d]+)#?([pct]\d*)?$/ =~ s then if $2 then s1 = $1 s2 = $2 if $2 =~ /^p/ "?date=#{s1}&p=#{s2.gsub(/p/, '')}" else "?date=#{s1}.html##{s2}" end else "?date=#$1" end else "" end end # Change HTML title to section name alias :_orig_title_tag :title_tag def title_tag if section_mode? and diary = @diaries[@date.strftime('%Y%m%d')] sections = diary.instance_variable_get(:@sections) title = "" section = sections[@cgi.params['p'][0].to_i - 1].stripped_subtitle_to_html title << apply_plugin(section, true).chomp title << " - #{h @html_title}" title << "(#{@date.strftime( '%Y-%m-%d' )})" if @date title << "" return title else _orig_title_tag end rescue _orig_title_tag end add_header_proc do if section_mode? and diary = @diaries[@date.strftime('%Y%m%d')] index = @cgi.params['p'][0] <<-EOS EOS end end # Local Variables: # mode: ruby # indent-tabs-mode: t # tab-width: 3 # ruby-indent-level: 3 # End: # vim: ts=3 tdiary-contrib-3.2.2/plugin/section_permalink_anchor.rb000066400000000000000000000013261213632744000233370ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2011, KADO Masanori # You can redistribute it and/or modify it under GPL. # # section_permalink_anchor.rb # - enables section permalink with mod_rewrite # - depends on section_permalink.rb # # sample .htaccess: # # RewriteEngine on # RewriteRule ^([0-9\-]+)p?([0-9]*)\.html$ ?date=$1&p=$2 [L] # def anchor( s ) if /^([\-\d]+)#?([pct]\d*)?$/ =~ s then if $2 then s1 = $1 s2 = $2 if $2 =~ /^p/ "#{s1}#{s2}.html" else "#{s1}.html##{s2}" end else "#$1.html" end else "" end end # Local Variables: # mode: ruby # indent-tabs-mode: t # tab-width: 3 # ruby-indent-level: 3 # End: # vim: ts=3 tdiary-contrib-3.2.2/plugin/select_style.rb000066400000000000000000000024151213632744000207760ustar00rootroot00000000000000# -*- coding: utf-8 -*- # # select_style.rb: a plugin for selecting styles # Distributed under the GPL # # [CAUTION] You need to insert a line to tdiary.conf after "load_cgi_conf" # @style = @options2['style'] if @options2['style'] # # styles def saveconf_style if @mode == 'saveconf' then @conf['style'] = @cgi.params['style'][0] end end if @mode =~ /^(conf|saveconf)$/ then @conf_style_list = [] Dir::glob( "#{::TDiary::PATH}/tdiary/{style/,}*_style.rb" ) do |style_file| style = File::basename( style_file ).sub( /_style\.rb$/, '' ) @conf_style_list << style end end add_conf_proc( 'style', 'スタイル' ) do saveconf_style r = <<-HTML

        スタイルの指定

        #{"

        スタイル (日記の文法) を指定します。

        " unless @conf.mobile_agent?}

        #{"

        スタイルについての詳細はスタイル - tDiary の記法をごらんください。

        " unless @conf.mobile_agent?} HTML end tdiary-contrib-3.2.2/plugin/select_theme.rb000066400000000000000000000043321213632744000207400ustar00rootroot00000000000000# Copyright (C) 2005 akira yamada # You can redistribute it and/or modify it under GPL2. THEME_BASE = File.join(::TDiary::PATH, 'theme') CACHE_FILE = File.join(@cache_path, 'theme_list') def get_theme_list if FileTest.exist?(CACHE_FILE) && File.mtime(CACHE_FILE) >= File.mtime(THEME_BASE) File.open(CACHE_FILE, 'r') do |i| i.flock(File::LOCK_EX) return Marshal.load(i.read) end end list = [] Dir.glob(File.join(THEME_BASE, '*')).sort.each do |dir| theme = dir.sub(%r[.*/theme/], '') next unless FileTest::file?("#{dir}/#{theme}.css".untaint) name = theme.split(/_/).collect{|s| s.capitalize}.join(' ') list << [theme, name] end File.open(CACHE_FILE, 'w') do |o| o.flock(File::LOCK_EX) o.puts Marshal.dump(list) end return list end def select_theme_form options = '' get_theme_list.each do |theme, name| options << %Q!\t\n! if theme == DEFAULT_THEME options = %Q!\t\n! + options end end < HTML end def label 'use' end def check_theme(name) return false if name.nil? || name.empty? FileTest.file?(File.join(THEME_BASE, name, name + '.css')) end with_cgiparam = false theme = nil if @cgi.params['select_theme'] && @cgi.params['select_theme'][0] tmp = @cgi.params['select_theme'][0].gsub(/[^-.\w]/, '') tmp.untaint if check_theme(tmp) theme = tmp with_cgiparam = true end end if theme.nil? && @cgi.cookies && @cgi.cookies.include?('tdiary_select_theme') tmp = @cgi.cookies['tdiary_select_theme'][0].gsub(/[^-.\w]/, '') tmp.untaint theme = tmp if check_theme(tmp) end if theme.nil? theme = @conf.theme end cookie_path = File::dirname( @cgi.script_name ) cookie_path += '/' if cookie_path !~ /\/$/ cookie = CGI::Cookie::new( 'name' => 'tdiary_select_theme', 'value' => theme, 'path' => cookie_path, 'expires' => Time::now.gmtime + 90*24*60*60) # 90days add_cookie(cookie) # XXX: OK? DEFAULT_THEME = @conf.theme @conf.theme = theme tdiary-contrib-3.2.2/plugin/show_and_hide.rb000066400000000000000000000033701213632744000210730ustar00rootroot00000000000000# -*- coding: utf-8 -*- # # show_and_hide.rb - Show or hide the elements with a sliding motion using jQuery. # # Copyright (C) 2011, tamoot # You can redistribute it and/or modify it under GPL2. # require 'digest/md5' if /\A(?:latest|day|month|nyear|preview)\z/ =~ @mode enable_js('show_and_hide.js') end def show_and_hide(contents, title = 'Show contents', type = :link, rss_title = '(Hide contents on RSS. See my page...)') data_id = show_and_hide_id(contents) toggle_attr = {:class => 'show_and_hide_toggle', :"data-showandhideid" => data_id} dom_contents = '' if feed? # RSS dom_contents = h(rss_title) elsif type.to_s == 'button' toggle_attr.merge!(:value => title, :type => "button") dom_contents = %Q|| + show_and_hide_contents(contents, data_id) else toggle_attr.merge!(:href => 'javascript:void(0)') dom_contents = %Q|#{h(title)}| + show_and_hide_contents(contents, data_id) end dom_contents end def show_and_hide_id(contents) @@show_and_hide_counter ||= 0 @@show_and_hide_counter += 1 "#{Time::now.strftime("%s")}_#{@@show_and_hide_counter}_#{ Digest::MD5.hexdigest(contents)}" end def show_and_hide_contents(contents, id) %Q|
        #{h(contents)}
        | end def hash2attr(hash) attrs = [] hash.keys.each do |k| attrs << %Q|#{k}="#{hash[k]}"| end attrs.join(" ") end # Local Variables: # mode: ruby # indent-tabs-mode: t # tab-width: 3 # ruby-indent-level: 3 # End: # vim: ts=3 tdiary-contrib-3.2.2/plugin/slideshare.rb000066400000000000000000000006051213632744000204210ustar00rootroot00000000000000# # slideshare.rb - insert some services of slideshare.net # # Copyright (C) 2011, Kiwamu Okabe . # You can redistribute it and/or modify it under GPL2. # def slideshare( embed_code ) %Q|| end tdiary-contrib-3.2.2/plugin/socialbutton.rb000066400000000000000000000037151213632744000210110ustar00rootroot00000000000000# socialbutton.rb # # Copyright (c) 2011 MATSUOKA Kohei # You can redistribute it and/or modify it under GPL2. # # enable social button names @conf['socialbutton.enables'] ||= 'twitter,hatena,facebook_like' # screen name of the user to attribute the tweet to @conf['socialbutton.twitter.via'] ||= '' def socialbutton_js_settings enable_js('jquery.socialbutton.js') enable_js('socialbutton.js') add_js_setting('$tDiary.plugin.socialbutton') # convert array to json add_js_setting('$tDiary.plugin.socialbutton.enables', %Q|["#{@conf['socialbutton.enables'].split(',').join('", "')}"]|) if @conf['socialbutton.twitter.via'] != '' options = "{ twitter: { via: '#{@conf['socialbutton.twitter.via']}' } }" else options = "{}" end add_js_setting('$tDiary.plugin.socialbutton.options', options) end socialbutton_footer = Proc.new { %Q|| } if blogkit? add_body_leave_proc(socialbutton_footer) else add_section_leave_proc(socialbutton_footer) end add_conf_proc('socialbutton', @socialbutton_label_conf) do @conf['socialbutton.enables'] ||= [] if @mode == 'saveconf' @conf['socialbutton.enables'] = @cgi.params['socialbutton.enables'].join(",") @conf['socialbutton.twitter.via'] = @cgi.params['socialbutton.twitter.via'][0] end result = <<-HTML

        #{@socialbutton_label_enables}

          HTML ['twitter', 'hatena', 'evernote', 'facebook_like', 'google_plusone', 'pinterest'].each do |service| checked = @conf['socialbutton.enables'].index(service) ? 'checked' : '' id = "socialbutton.enables.#{service}" result << %Q|
        • | result << %Q|
        • | end result << <<-HTML

        #{@socialbutton_label_twitter_via}

        HTML end # load javascript socialbutton_js_settings() tdiary-contrib-3.2.2/plugin/tatsu_zine.rb000066400000000000000000000047321213632744000204700ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2011, KADO Masanori # You can redistribute it and/or modify it under GPL. # # display book info in http://tatsu-zine.com/ like amazon.rb # USAGE: {{tatsu_zine 1}} require 'open-uri' def tatsu_zine_cache_dir cache = "#{@cache_path}/tatsu-zine" Dir.mkdir( cache ) unless File.directory?( cache ) cache end def tatsu_zine_cache_set( id, result ) File.open( "#{tatsu_zine_cache_dir}/#{id}", "w" ) do |f| f.write result end end def tatsu_zine_cache_get( id ) File.open( "#{tatsu_zine_cache_dir}/#{id}", "r" ) do |f| f.read end rescue nil end def tatsu_zine( id, doc = nil ) if !@conf.secure and !(result = tatsu_zine_cache_get(id)).nil? return result end link = "http://tatsu-zine.com/books/#{id}" doc ||= open( link ).read title = doc.match(%r||).to_a[1] image = doc.match(%r||).to_a[1] price = doc.match(%r|

        [\r\n]?(.*?)[\r\n]?

        |m).to_a[1]. gsub(/\s/, '') author = doc.match(%r|

        (.*)

        |).to_a[1] result = <<-EOS #{h title} #{h title}
        #{h author}
        #{h price}

        EOS tatsu_zine_cache_set( id, result ) unless @conf.secure result rescue link end if __FILE__ == $0 require 'test/unit' class TestTatsuZine < Test::Unit::TestCase def setup @conf = Struct.new("Conf", :secure).new(true) def h(str); str; end end def test_tatsu_zine expect = <<-EOS Ruby環境構築講座 Windows編 Ruby環境構築講座 Windows編
        arton
        1,000円(税込)

        EOS assert_equal expect, tatsu_zine('winrubybuild') end end end # Local Variables: # mode: ruby # indent-tabs-mode: t # tab-width: 3 # ruby-indent-level: 3 # End: tdiary-contrib-3.2.2/plugin/tdiarygraph_flashstyle.rb000066400000000000000000000411061213632744000230530ustar00rootroot00000000000000# tdiarygraph_flashstyle.rb $Revision: 1.3 $ # # Copyright (c) 2004 phonondrive # Distributed under the GPL # # プラグイン配布ページ: # http://phonondrive.com/trd/ # -------------------------------------------------------------------- # # # # Abstract: # -------------------------------------------------------------------- # counter.rb のカウンタログ (counter.log) をグラフ化した # Flash アプレットを表示します。 # # # Usage: # -------------------------------------------------------------------- # プラグインは、プラグインフォルダに入れてください。 # tdiarygraph*.swf を tdiary.rb と同じフォルダにアップロードします。 # ヘッダ、フッタ部に記述した <%= tdiarygraph_flashstyle %> の部分に、 # Flash アプレットが表示されます。 # counter.log は日記登録時に .swf と同じフォルダにコピーされます。 # # ※ counter.rb を使用しており、かつカウンタログ (counter.log) の出力を # オンにしている必要があります。 # # # Options: # -------------------------------------------------------------------- # グラフの色、透明度、サイズなどは、プリファレンス画面で設定できます。 # # # In secure mode: # -------------------------------------------------------------------- # たぶん動作しません。 # # # Acknowledgements: # -------------------------------------------------------------------- # counter.rb (counter.log) # # Copyright (c) 2002 MUTOH Masao # Distributed under the GPL2. # http://ponx.s5.xrea.com/hiki/ja/counter.rb.html # # =begin ChangeLog 2004.04.27 phonondrive * version 1.3.0 キャッシュ対策としてユニークIDを付加してファイル取得するオプションを追加 対応 Flash ファイルを e 系列に変更 フォントを _sans から 04b03b に変更 04b03b.ttf, copyright (c) 1998-2001 YUJI OSHIMOTO http://www.04.jp.org/ 2004.04.10 phonondrive * version 1.2.1 レポート書式で改行タグが機能しない不具合を修正 背景の枠線を表示しないオプションを追加 対応 Flash ファイルを d 系列に変更 2004.04.09 phonondrive * version 1.2.0 ログファイルが転送されない不具合を修正 作成するログのデフォルト名を変更 (tdiarygraph.log → counter.log) 線幅を絶対値で指定出来るオプションを追加 レポート書式のカスタマイズオプションを追加 対応 Flash ファイルを c 系列に変更 2004.04.05 phonondrive * version 1.1.1 線の太さを変更するオプションを追加 対応 Flash ファイルに b 系列を追加 2004.04.05 phonondrive * version 1.1.0 Ruby 1.6.x に対応 (1.6.7 で動作確認) 作成するログのデフォルト名を変更 (counter.log → tdiarygraph.log) 2004.04.04 phonondrive * version 1.0.0 =end # -------------------------------------------------------------------- # プラグインの表示 # -------------------------------------------------------------------- def tdiarygraph_flashstyle if @conf['tdiarygraph_f.templete'] == nil or @conf['tdiarygraph_f.templete'] == "" %Q|使用を開始するには、プリファレンス画面にて一度設定を完了して下さい。(tdiarygraph-flashstyle)| else logname = ((@conf['tdiarygraph_f.log_path'] != "" and @conf['tdiarygraph_f.log_path'] != nil) ? @conf['tdiarygraph_f.log_path'] : "counter.log") @conf['tdiarygraph_f.templete'].sub(/&uid/, "\\&=#{File.mtime(logname.untaint).to_i}") end end # -------------------------------------------------------------------- # 日記登録時の処理 (counter.log のコピー) # -------------------------------------------------------------------- if /\A(?:append|replace)\z/ =~ @mode and @cgi.params['hide'][0] != 'true' then logname = ((@conf['tdiarygraph_f.log_path'] != "" and @conf['tdiarygraph_f.log_path'] != nil) ? @conf['tdiarygraph_f.log_path'] : "counter.log") open("#{@cache_path}/counter/counter.log"){|input| open(logname, "w"){|output| output.write(input.read) } } end # -------------------------------------------------------------------- # プリファレンス画面での設定 # -------------------------------------------------------------------- add_conf_proc( 'tdiarygraph_f', 'tdiarygraph-flashstyle の設定' ) do if @mode == 'saveconf' then filename = "tdiarygraph468x60e.swf" width = "468" height = "60" argvs = "" argv = Array.new @conf['tdiarygraph_f.uid'] = @cgi.params['uid'][0] argv << "#{Time.now.to_i}&uid" if @conf['tdiarygraph_f.uid'] == "1" @conf['tdiarygraph_f.type'] = @cgi.params['type'][0] @conf['tdiarygraph_f.filename'] = @cgi.params['filename'][0] @conf['tdiarygraph_f.width'] = @cgi.params['width'][0] @conf['tdiarygraph_f.height'] = @cgi.params['height'][0] @conf['tdiarygraph_f.log_path'] = @cgi.params['log_path'][0] argv << "log_path=#{@cgi.params['log_path'][0]}" if @cgi.params['log_path'][0] != "" @conf['tdiarygraph_f.init_num'] = @cgi.params['init_num'][0] argv << "init_num=#{@cgi.params['init_num'][0]}" if @cgi.params['init_num'][0] != "" @conf['tdiarygraph_f.text_text'] = @cgi.params['text_text'][0].upcase argv << "text_text=#{h NKF::nkf('-s', @cgi.params['text_text'][0].upcase)}" if @cgi.params['text_text'][0] != "" @conf['tdiarygraph_f.text_rgb'] = @cgi.params['text_rgb'][0] argv << "text_rgb=0x#{@cgi.params['text_rgb'][0]}" if @cgi.params['text_rgb'][0] != "" @conf['tdiarygraph_f.text_report'] = @cgi.params['text_report'][0] argv << "text_report=#{@cgi.params['text_report'][0]}" if @cgi.params['text_report'][0] == "0" @conf['tdiarygraph_f.text_report_format'] = @cgi.params['text_report_format'][0] argv << "text_report_format=#{tdiarygraph_flashstyle_text_report_format(@cgi.params['text_report_format'][0])}" if @cgi.params['text_report_format'][0] != "" @conf['tdiarygraph_f.text_report_rgb'] = @cgi.params['text_report_rgb'][0] argv << "text_report_rgb=0x#{@cgi.params['text_report_rgb'][0]}" if @cgi.params['text_report_rgb'][0] != "" @conf['tdiarygraph_f.bg_rgb'] = @cgi.params['bg_rgb'][0] argv << "bg_rgb=0x#{@cgi.params['bg_rgb'][0]}" if @cgi.params['bg_rgb'][0] != "" @conf['tdiarygraph_f.bg_alpha'] = @cgi.params['bg_alpha'][0] argv << "bg_alpha=#{@cgi.params['bg_alpha'][0]}" if @cgi.params['bg_alpha'][0] != "" @conf['tdiarygraph_f.bg_frame'] = @cgi.params['bg_frame'][0] argv << "bg_frame=#{@cgi.params['bg_frame'][0]}" if @cgi.params['bg_frame'][0] == "1" @conf['tdiarygraph_f.bar_rgb'] = @cgi.params['bar_rgb'][0] argv << "bar_rgb=0x#{@cgi.params['bar_rgb'][0]}" if @cgi.params['bar_rgb'][0] != "" @conf['tdiarygraph_f.bar_alpha'] = @cgi.params['bar_alpha'][0] argv << "bar_alpha=#{@cgi.params['bar_alpha'][0]}" if @cgi.params['bar_alpha'][0] != "" @conf['tdiarygraph_f.line_rgb'] = @cgi.params['line_rgb'][0] argv << "line_rgb=0x#{@cgi.params['line_rgb'][0]}" if @cgi.params['line_rgb'][0] != "" @conf['tdiarygraph_f.line_alpha'] = @cgi.params['line_alpha'][0] argv << "line_alpha=#{@cgi.params['line_alpha'][0]}" if @cgi.params['line_alpha'][0] != "" @conf['tdiarygraph_f.bar_width'] = @cgi.params['bar_width'][0] argv << "bar_width=#{@cgi.params['bar_width'][0]}" if @cgi.params['bar_width'][0] != "" @conf['tdiarygraph_f.line_width'] = @cgi.params['line_width'][0] argv << "line_width=#{@cgi.params['line_width'][0]}" if @cgi.params['line_width'][0] != "" @conf['tdiarygraph_f.bold'] = @cgi.params['bold'][0] argv << "bold=#{@cgi.params['bold'][0]}" if @cgi.params['bold'][0] != "" @conf['tdiarygraph_f.preview'] = @cgi.params['preview'][0] if @cgi.params['type'][0] == "0" filename = @cgi.params['filename'][0] width = @cgi.params['width'][0] height = @cgi.params['height'][0] elsif @cgi.params['type'][0] filename = "tdiarygraph#{@cgi.params['type'][0].delete('-')}.swf" width = @cgi.params['type'][0].split('-').first.split('x')[0] height = @cgi.params['type'][0].split('-').first.split('x')[1] end if argv.size > 0 then argvs = "?#{argv.join('&')}" end @conf['tdiarygraph_f.templete'] = tdiarygraph_flashstyle_templete(filename, argvs, width, height) end <<-HTML

        設定の概要

        () 内は初期値です。初期値を使用する場合は、空欄のままで構いません。色は RRGGBB 形式で指定して下さい。不透明度は 0 (透明) 〜 100 (不透明) です。線幅はピクセルで指定します。


        プレビュー

        #{tdiarygraph_flashstyle_preview}

        表示する Flash アプレットの選択

        プリセットを使用しない場合は、以下で指定して下さい。

        Flash のファイル名

        Flash の表示幅

        Flash の表示高さ


        アクセスログデータ

        本プラグインが作成する counter.log の複製のファイル名 (counter.log)

        累計アクセス数の初期値。(0) counter.rb で init_num を指定している場合は、同じ値 (#{@conf['counter.init_num']}) を設定してください。


        タイトルテキスト

        タイトルテキスト (TDIARYGRAPH-FLASHSTYLE)
        使用出来る文字は、英大文字 (A-Z) と数字 (0-9)、および記号のみです。

        タイトルテキストの色 (FFFFFF)

        レポートテキスト

        レポートの表示有無 (表示)

        レポートテキストの色 (CCCCCC)

        レポート書式のカスタマイズ

        タグを埋め込んだ位置にデータが展開されます。
        使用出来る文字 (タグを除く) は、英大文字 (A-Z) と数字 (0-9)、および記号のみです。

        [ 使用出来るタグ ] <firstday> : ログ初日, <lastday> : ログ最終日, <days> : ログ日数, <total> : 累計アクセス数, <peak> : 日別最大アクセス数, <br> : 改行


        背景や棒グラフの色

        背景の色 (333333)

        背景の不透明度 (100)

        背景の枠線 (非表示)

        日別アクセス数棒グラフの色 (CCCCCC)

        日別アクセス数棒グラフの不透明度 (100)

        累計アクセス数棒グラフの色 (666666)

        累計アクセス数棒グラフの不透明度 (100)


        棒グラフの線幅

        日別アクセス数棒グラフの線幅を絶対値で指定します。

        累計アクセス数棒グラフの線幅を絶対値で指定します。


        モアレ対策

        棒グラフの線幅を相対的に微調整します。(0) 設定した値に対して線幅がリニアに変更されるわけではありません。


        ユニークID を使用したファイル取得

        ファイル取得のリクエストにユニークID (例えば ?#{Time.now.to_i}) を含めることにより、古いファイルがブラウザにキャッシュされたままになるのを防ぎます。Flash のユニークID はプリファレンス設定時に、ログファイルのユニークID はエントリ登録時に更新されます。

        ユニークID の付加 (付加する)


        プレビュー

        表示したい SWF ファイル (.swf) が tdiary.rb と同じフォルダにアップロードされている必要があります。また、カウンタログファイルが SWF ファイルと同じフォルダに転送されていない場合にはグラフが表示されません。

        プレビュー (非表示)

        HTML end def tdiarygraph_flashstyle_preview unless @conf.mobile_agent? <<-r

        #{if @conf['tdiarygraph_f.preview'] == "1" then "#{tdiarygraph_flashstyle}" else "プレビュー表示を有効にすると、ここに Flash が表示されます。" end}

        r end end def tdiarygraph_flashstyle_templete( filename="tdiarygraph468x60e.swf", argvs="", width="468", height="60" ) <<-r r end def tdiarygraph_flashstyle_text_report_format( format="" ) if format != "" r = format.gsub('<', '<').gsub('>', '>').gsub(' ', '+') end end tdiary-contrib-3.2.2/plugin/tdiarytimes.rb000066400000000000000000000117271213632744000206430ustar00rootroot00000000000000# tdiarytimes.rb $Revision: 1.2 $ # # Copyright (c) 2003 neuichi # Distributed under the GPL # # プラグイン配布ページ # http://nmnl.jp/hiki/software/?tDiary+%3A%3A+Plugin # # 動作条件: # ruby-gdが使える環境が必要です。 # # 使い方: # このプラグインをプラグインディレクトリに入れ、 # index.rbと同じディレクトリに、tdiarytimes.pngという名前の # サーバが書き込み権限を持っているファイルを作ります。 # これで日記に書き込みするごとに、tdiarytimes.pngに # 画像を書き込みます。 # # 日記上からこのpngファイルを呼び出すには、 # tDiray上からプラグインとして # <%=tdiarytimes%> # として呼び出します。 # 引数としてimgタグのaltの文字列を指定することも出来ます。 # <%=tdiarytimes '文字列'%> # # また、tdiary.confに以下のオプションを書き込むことにより、 # カスタマイズをすることが出来ます。 # # @options['tdiarytimes.width'] = 400 # 四角の横幅。デフォルト値400。 # 実際に出力される画像サイズは、これに+10したサイズ。 # # @options['tdiarytimes.height'] = 20 # 四角の縦幅。デフォルト値20。 # 実際に出力される画像サイズは、これに+16したサイズ。 # # @options['tdiarytimes.file'] = 'tdiarytimes.png' # 出力する画像ファイル名。デフォルトは'tdiarytimes.png' # # @options['tdiarytimes.fillcolor'] = '#444444' # 四角の色。デフォルトは'#444444' # # @options['tdiarytimes.linecolor'] = '#ffffff' # 縦棒の色。デフォルトは'#ffffff' # # @options['tdiarytimes.textcolor'] = '#444444' # 文字色。デフォルトは'#444444' # # @options['tdiarytimes.text'] = 'T D I A R Y T I M E S' # 出力する文字。デフォルトは'T D I A R Y T I M E S'。なお半角英数字のみ対応。 # # @options['tdiarytimes.day'] = 30 # ログを保存する最大日数。デフォルトは30。 # この場合、30日以上経ったデータは消去され、縦棒として描画されなくなる。 # require 'GD' if /^(append|replace)$/ =~ @mode then #初期設定 width = @options['tdiarytimes.width'] || 400 height = @options['tdiarytimes.height'] || 20 file = @options['tdiarytimes.file'] || 'tdiarytimes.png' fillcolor = @options['tdiarytimes.fillcolor'] || '#444444' linecolor = @options['tdiarytimes.linecolor'] || '#ffffff' textcolor = @options['tdiarytimes.textcolor'] || '#444444' text = @options['tdiarytimes.text'] || 'T D I A R Y T I M E S' day = @options['tdiarytimes.day'] || 30 cache = "#{@cache_path}/tdiarytimes" Dir::mkdir( cache ) unless File::directory?( cache ) image = GD::Image.new(width + 10,height + 16) transcolor = image.colorAllocate("#fffffe") image.transparent(transcolor) image.interlace = TRUE fillcolor = image.colorAllocate(fillcolor) linecolor = image.colorAllocate(linecolor) textcolor = image.colorAllocate(textcolor) #帯の描画 image.filledRectangle(5,8,width + 4,height + 7,fillcolor) #時間挿入 if width >= 160 hour = 2 hour_w = width / 12.0 image.string(GD::Font::TinyFont, 2, height + 8, "0", textcolor) 11.times { image.string(GD::Font::TinyFont, (hour_w * hour/2).to_i , height + 8, hour.to_s, textcolor) hour += 2 } image.string(GD::Font::TinyFont, width + 2, height + 8, "0", textcolor) else hour = 0 hour_w = width / 6.0 6.times { image.string(GD::Font::TinyFont, (hour_w * hour/4).to_i + 4, height + 8, hour.to_s, textcolor) hour += 4 } image.string(GD::Font::TinyFont, width + 2, height + 8, "0", textcolor) end #現在時刻の保存,読み込み begin io = open("#{cache}/tdiarytimes.dat","r") ary_times = Marshal.load(io) io.close rescue ary_times = [] end ary_times << Time.now.to_f ary_times_new = [] while ary_times.size != 0 time = ary_times.shift time_now = Time.now.to_f.to_i ary_times_new << time.to_i if (86400 * day) > (time_now - time).to_i end ary_times = ary_times_new io = open("#{cache}/tdiarytimes.dat","w") Marshal.dump(ary_times,io) io.close #時間軸の挿入 while ary_times.size != 0 time = Time.at(ary_times.shift) time_w = ((time.to_a[2] * 60 + time.to_a[1]) / 1440.0 * width).to_i image.line(time_w + 5, 8 ,time_w + 5,height + 7, linecolor) end #文字の挿入 image.string(GD::Font::TinyFont, 5, 0, text, textcolor) pngfile = open(file, 'w') image.png(pngfile) pngfile.close end def tdiarytimes(alt = nil) width = @options['tdiarytimes.width'].to_i || 400 width += 10 height = @options['tdiarytimes.height'].to_i || 20 height += 16 file = @options['tdiarytimes.file'] || 'tdiarytimes.png' text = @options['tdiarytimes.text'] || 'T D I A R Y T I M E S' result = "" if alt result << %Q|#{h alt}| else result << %Q|#{h text}| end result end tdiary-contrib-3.2.2/plugin/tdiarytimes2.rb000066400000000000000000000265301213632744000207230ustar00rootroot00000000000000# tdiarytimes.rb $originalRevision: 1.1 $ # # Copyright (c) 2003 neuichi # Distributed under the GPL # # 2003-12-01 circle extention added by Minero Aoki # $Id: tdiarytimes2.rb,v 1.2 2007/01/11 02:55:26 tadatadashi Exp $ # # プラグイン配布ページ # http://i.loveruby.net/w/tdiarytimes.html # # 動作条件: # ruby-gdが使える環境が必要です。 # # 使い方: # このプラグインをプラグインディレクトリに入れ、 # index.rbと同じディレクトリに、tdiarytimes.pngという名前の # サーバが書き込み権限を持っているファイルを作ります。 # これで日記に書き込みするごとに、tdiarytimes.pngに # 画像を書き込みます。 # # 日記上からこのpngファイルを呼び出すには、 # tDiray上からプラグインとして # <%=tdiarytimes%> # として呼び出します。 # 引数としてimgタグのaltの文字列を指定することも出来ます。 # <%=tdiarytimes '文字列'%> # # また、tdiary.confに以下のオプションを書き込むことにより、 # カスタマイズをすることが出来ます。 # # @options['tdiarytimes.width'] = 400 # 四角の横幅。デフォルト値400。 # 実際に出力される画像サイズは、これに+10したサイズ。 # # @options['tdiarytimes.height'] = 20 # 四角の縦幅。デフォルト値20。 # 実際に出力される画像サイズは、これに+16したサイズ。 # # @options['tdiarytimes.file'] = 'tdiarytimes.png' # 出力する画像ファイル名。デフォルトは'tdiarytimes.png' # # @options['tdiarytimes.fillcolor'] = '#444444' # 四角の色。デフォルトは'#444444' # # @options['tdiarytimes.linecolor'] = '#ffffff' # 縦棒の色。デフォルトは'#ffffff' # # @options['tdiarytimes.textcolor'] = '#444444' # 文字色。デフォルトは'#444444' # # @options['tdiarytimes.fadeout'] = false # フェードアウトするか。デフォルトはfalse。 # フェードアウトしたいときには true にすればよい。 # # @options['tdiarytimes.fadeoutcolor'] = '#ffffff' # フェードアウトするとき、 # デフォルトではfillcolorへとフェードアウトしていく。 # ここで色を指定するとその色へとフェードアウトしていく。 # デフォルトは false # # @options['tdiarytimes.text'] = 'T D I A R Y T I M E S' # 出力する文字。デフォルトは'T D I A R Y T I M E S'。なお半角英数字のみ対応。 # # @options['tdiarytimes.day'] = 30 # ログを保存する最大日数。デフォルトは30。 # この場合、30日以上経ったデータは消去され、縦棒として描画されなくなる。 # require 'GD' ::GD::Image.module_eval { def tiny_string(text, x, y, color) string(GD::Font::TinyFont, x, y, text, color) end def small_string(text, x, y, color) string(GD::Font::SmallFont, x, y, text, color) end } # Ruby 1.6 missing File.read unless ::File.respond_to?(:read) def (::File).read(fname) File.open(fname) {|f| return f.read } end end # Ruby 1.6 missing MatchData#captures unless ::MatchData.method_defined?(:captures) ::MatchData.module_eval { def captures a = to_a() a.shift a end } end class TDiaryTimes class << TDiaryTimes alias newobj new end def TDiaryTimes.new(datadir, options) case options['tdiarytimes.shape'] when 'bar', nil c = TDiaryTimesBar when 'circle' c = TDiaryTimesCircle else raise ArgumentError, "unknown tdiarytimes.shape: #{options['tdiarytimes.shape']}" end c.newobj("#{datadir}/tdiarytimes", options) end def initialize(dbfile, options) @dbfile = dbfile @image_file = options['tdiarytimes.file'] || 'tdiarytimes.png' @day = options['tdiarytimes.day'] || 30 @keepdb = options['tdiarytimes.keepdb'] end attr_reader :image_file def update_image now = Time.now mtimes = (load_database() + [now]).reject {|tm| (now - tm) > (60 * 60 * 24 * @day) } image = create_image(mtimes) File.open(@image_file, 'w') {|png| image.png(png) } save_database(mtimes) unless @keepdb end private # # database # def load_database begin return Marshal.load(File.read(@dbfile)) rescue Errno::ENOENT return [] end end def save_database(content) File.open(@dbfile, 'w') {|f| Marshal.dump(content, f) } end # # common paint methods # def fadeout_color(srccolor, destcolor, time) par = (Time.now - time).to_f / (60 * 60 * 24 * @day) r, g, b = *zip(parse_rgb(srccolor), parse_rgb(destcolor))\ .map {|src, dest| src - (src - dest) * par }.map {|c| c.to_i } sprintf('#%02x%02x%02x', r, g, b) end def parse_rgb(str) hex = '[\da-f]' m = /\A\#(#{hex}{2})(#{hex}{2})(#{hex}{2})\z/io.match(str) or raise ArgumentError, "tdiarytimes: not color: #{str.inspect}" m.captures.map {|c| c.hex } end def zip(*lists) result = [] lists[0].each_index do |idx| result.push lists.map {|lst| lst[idx] } end result end end class TDiaryTimesBar < TDiaryTimes def initialize(dbfile, options) super @text = options['tdiarytimes.text'] || 'T D I A R Y T I M E S' @width = options['tdiarytimes.width'].to_i || 400 @height = options['tdiarytimes.height'].to_i || 20 @textcolor = options['tdiarytimes.textcolor'] || '#444444' @fillcolor = options['tdiarytimes.fillcolor'] || '#444444' @linecolor = options['tdiarytimes.linecolor'] || '#ffffff' @fadeoutcolor = options['tdiarytimes.fadeoutcolor'] || @fillcolor @fadeoutp = options['tdiarytimes.fadeout'] end def html(alt) %Q[#{h( alt || @text )}].gsub(/\s+/, ' ') end private GAP_W = 16 GAP_H = 16 def create_image(mtimes) image = GD::Image.new(@width + GAP_W, @height + GAP_H) image.transparent(image.colorAllocate('#fffffe')) image.interlace = true image.tiny_string @text, (GAP_W / 2), 0, image.colorAllocate(@textcolor) image.filledRectangle 0 + GAP_W / 2, 0 + GAP_H / 2, image.width - GAP_W / 2, image.height - GAP_H / 2, image.colorAllocate(@fillcolor) if @fadeoutp paint_lines_fadeout image, mtimes, @linecolor, @fadeoutcolor else paint_lines image, mtimes, @linecolor end paint_hours image, image.colorAllocate(@textcolor), (image.width - GAP_W > 160 ? 2 : 4) image end def paint_lines(image, mtimes, color) gdcolor = image.colorAllocate(color) mtimes.each do |time| line image, time, gdcolor end end def paint_lines_fadeout(image, mtimes, linecolor, destcolor) mtimes.each do |time| line image, time, image.colorAllocate(fadeout_color(linecolor, destcolor, time)) end end def line(image, time, color) x0 = (image.width - GAP_W).to_f * (time.hour * 60 + time.min) / (60 * 24) x = (x0 + (GAP_W / 1.25)).to_i image.line x, 0 + (GAP_H / 2), x, image.height - (GAP_H / 2), color end def paint_hours(image, color, stepping) 0.step(24, stepping) do |hour| image.tiny_string hour.to_s, (image.width - GAP_W) * (hour.to_f / 24) + (GAP_W / 2) - 4, image.height - (GAP_H / 2), color end end end class TDiaryTimesCircle < TDiaryTimes def initialize(dbfile, options) super #@text # cannot change now @width = options['tdiarytimes.width'].to_i || 80 @height = options['tdiarytimes.height'].to_i || 80 @textcolor = options['tdiarytimes.textcolor'] || '#444444' @fillcolor = options['tdiarytimes.fillcolor'] || '#444444' @linecolor = options['tdiarytimes.linecolor'] || '#ffffff' @fadeoutcolor = options['tdiarytimes.fadeoutcolor'] || @fillcolor @fadeoutp = options['tdiarytimes.fadeout'] end def html(alt) %Q[#{h( alt || '' )}].gsub(/\s+/, ' ') end private MIN_DEGREE = 0 MAX_DEGREE = 250 BAR_WIDTH = 24 TRANSCOLOR = '#ffffff' def create_image(mtimes) image = GD::Image.new(@width, @height) trans = image.colorAllocate(TRANSCOLOR) image.transparent trans image.interlace = true paint_outer_circle image, trans if @fadeoutp paint_lines_fadeout image, mtimes, @linecolor, @fadeoutcolor else paint_lines image, mtimes, @linecolor end paint_inner_circle image, trans textcolor = image.colorAllocate(@textcolor) image.small_string 'tdiary', @width / 2 + 1, 11, textcolor image.small_string 'times', @width / 2 + 4, 21, textcolor image end def paint_outer_circle(image, trans) image.filledArc @width / 2, @height / 2, @width, @height, MIN_DEGREE, MAX_DEGREE, if @fillcolor == TRANSCOLOR then trans else image.colorAllocate(@fillcolor) end, 0 end def paint_inner_circle(image, trans) image.filledArc @width / 2, @height / 2, @width - BAR_WIDTH * 2, (@width - BAR_WIDTH * 2) * (@height.to_f / @width), 0, 360, trans, 0 end def paint_lines(image, mtimes, color) gdcolor = image.colorAllocate(color) mtimes.each do |time| line image, time, gdcolor end end def paint_lines_fadeout(image, mtimes, linecolor, destcolor) mtimes.each do |time| line image, time, image.colorAllocate(fadeout_color(linecolor, destcolor, time)) end end def line(image, time, color) d0 = (time.hour * 60 + time.min).to_f / (60 * 24) d = MIN_DEGREE + (MAX_DEGREE - MIN_DEGREE) * d0 image.line @width / 2, @height / 2, @width / 2 + degcos(d) * (@width / 2) * 0.95, @height / 2 + degsin(d) * (@height / 2) * 0.95, color end include Math def degsin(d) sin(d / (180 / Math::PI)) end def degcos(d) cos(d / (180 / Math::PI)) end end def tdiarytimes(alt = nil) TDiaryTimes.new(@conf.data_path, @options).html(alt) end if $0 == __FILE__ # debugging tmp_options_bar = { 'tdiarytimes.shape' => 'bar', 'tdiarytimes.textcolor' => '#666666', 'tdiarytimes.linecolor' => '#df0000', 'tdiarytimes.fillcolor' => '#0f5f0f', 'tdiarytimes.fadeout' => true, 'tdiarytimes.keepdb' => false # for debug } tmp_options_circle = { 'tdiarytimes.shape' => 'circle', 'tdiarytimes.textcolor' => '#000000', 'tdiarytimes.linecolor' => '#bfbfbf', 'tdiarytimes.fillcolor' => '#2f2f7f', 'tdiarytimes.fadeout' => true, 'tdiarytimes.keepdb' => false # for debug } @mode = 'latest' @conf = Object.new def @conf.data_path '.' end case ARGV[0] when 'bar' @options = tmp_options_bar else @options = tmp_options_circle end TDiaryTimes.new(@conf.data_path, @options).update_image puts tdiarytimes() exit 0 end if /append|replace/ =~ @mode TDiaryTimes.new(@conf.data_path, @options).update_image end tdiary-contrib-3.2.2/plugin/tdiarytimes_flashstyle.rb000066400000000000000000000356051213632744000231020ustar00rootroot00000000000000# tdiarytimes_flashstyle.rb $Revision: 1.2 $ # # Copyright (c) 2004 phonondrive # Distributed under the GPL # # プラグイン配布ページ: # http://phonondrive.com/trd/ # -------------------------------------------------------------------- # # # # Abstract: # -------------------------------------------------------------------- # 日記を登録した時間帯をタイムライン上に記録します。記録されたエントリは # 日時の経過と共にフェードアウトしていきます。このような MTBlogTimes や # tdiarytimes.rb と同等の機能を Flash で実現します。 # ruby-gd のインストール作業も必要ないため、すぐに使用出来ます。 # # # Usage: # -------------------------------------------------------------------- # プラグインは、プラグインフォルダに入れて下さい。 # # プラグインは、プラグインフォルダに入れてください。 # tdiarytimes*.swf を tdiary.rb と同じフォルダにアップロードします。 # ヘッダ、フッタ部に記述した <%= tdiarytimes_flashstyle %> の部分に、 # Flash アプレットが表示されます。 # tdiarytimes.log は日記登録時に .swf と同じフォルダに作成されます。 # # ※ tdiarytimes_textstyle.rb との互換性はありません。 # # # Options: # -------------------------------------------------------------------- # タイムラインの色、透明度、サイズなどは、プリファレンス画面で設定できます。 # # # In secure mode: # -------------------------------------------------------------------- # たぶん動作しません。 # # =begin ChangeLog 2004.05.02 phonondrive * version 1.1.2 タイムラインが曜日別の Flash を追加 2004.05.02 phonondrive * version 1.1.1 タイムラインが円形で、時刻盤が曜日表示の Flash を追加 ログファイルが存在しない時にエラーが出る不具合を修正 2004.04.28 phonondrive * version 1.1.0 タイムラインが円形の Flash を追加 2004.04.27 phonondrive * version 1.0.1 時刻目盛テキストの色が変更されない不具合を修正 2004.04.25 phonondrive * version 1.0.0 =end # -------------------------------------------------------------------- # プラグインの動作 # -------------------------------------------------------------------- def tdiarytimes_flashstyle if @conf['tdiarytimes_f.templete'] == nil or @conf['tdiarytimes_f.templete'] == "" %Q|使用を開始するには、プリファレンス画面にて一度設定を完了して下さい。(tdiarytimes-flashstyle)| else logname = ((@conf['tdiarytimes_f.log_path'] != "" and @conf['tdiarytimes_f.log_path'] != nil) ? @conf['tdiarytimes_f.log_path'] : "tdiarytimes.log") @conf['tdiarygraph_f.templete'].sub(/&uid/, "\\&=#{File.mtime(logname.untaint).to_i}") end end # -------------------------------------------------------------------- # 日記登録時の処理 # -------------------------------------------------------------------- if /\A(?:append|replace)\z/ =~ @mode and @cgi.params['hide'][0] != 'true' then logname = ((@conf['tdiarytimes_f.log_path'] != "" and @conf['tdiarytimes_f.log_path'] != nil) ? @conf['tdiarytimes_f.log_path'] : "tdiarytimes.log") entr_lifetime = ((@conf['tdiarytimes_f.entr_lifetime'] != "" and @conf['tdiarytimes_f.entr_lifetime'] != nil) ? @conf['tdiarytimes_f.entr_lifetime'].to_i * 60 * 60 * 24 : 30 * 24 * 60 * 60) entr_interval = ((@conf['tdiarytimes_f.entr_interval'] != "" and @conf['tdiarytimes_f.entr_interval'] != nil) ? @conf['tdiarytimes_f.entr_interval'] : 2 * 60 * 60) begin logs = open(logname){|io| io.read }.chomp.split(',') rescue logs = "" end if (Time.now.to_i - logs.max.to_i) > entr_interval.to_i logs << "#{Time.now.to_i}" open(logname, "w"){|io| io.write(logs.find_all{|item| (Time.now.to_i - item.to_i) < entr_lifetime.to_i }.join(',')) } end end # -------------------------------------------------------------------- # プリファレンス画面での設定 # -------------------------------------------------------------------- add_conf_proc( 'tdiarytimes_f', 'tdiarytimes-flashstyle の設定' ) do if @mode == 'saveconf' then filename = "tdiarytimes234x30.swf" width = "234" height = "30" argvs = "" argv = Array.new @conf['tdiarytimes_f.uid'] = @cgi.params['uid'][0] argv << "#{Time.now.to_i}&uid" if @conf['tdiarytimes_f.uid'] == "1" @conf['tdiarytimes_f.type'] = @cgi.params['type'][0] @conf['tdiarytimes_f.filename'] = @cgi.params['filename'][0] @conf['tdiarytimes_f.width'] = @cgi.params['width'][0] @conf['tdiarytimes_f.height'] = @cgi.params['height'][0] @conf['tdiarytimes_f.log_path'] = @cgi.params['log_path'][0] argv << "log_path=#{@cgi.params['log_path'][0]}" if @cgi.params['log_path'][0] != "" @conf['tdiarytimes_f.text_visible'] = @cgi.params['text_visible'][0] argv << "text_visible=#{@cgi.params['text_visible'][0]}" if @cgi.params['text_visible'][0] == "0" @conf['tdiarytimes_f.text_text'] = @cgi.params['text_text'][0] argv << "text_text=#{CGI::escape @cgi.params['text_text'][0].upcase}" if @cgi.params['text_text'][0] != "" @conf['tdiarytimes_f.text_rgb'] = @cgi.params['text_rgb'][0] argv << "text_rgb=0x#{@cgi.params['text_rgb'][0]}" if @cgi.params['text_rgb'][0] != "" @conf['tdiarytimes_f.face_visible'] = @cgi.params['face_visible'][0] argv << "face_visible=#{@cgi.params['face_visible'][0]}" if @cgi.params['face_visible'][0] == "0" @conf['tdiarytimes_f.face_rgb'] = @cgi.params['face_rgb'][0] argv << "face_rgb=0x#{@cgi.params['face_rgb'][0]}" if @cgi.params['face_rgb'][0] != "" @conf['tdiarytimes_f.stage_rgb'] = @cgi.params['stage_rgb'][0] argv << "stage_rgb=0x#{@cgi.params['stage_rgb'][0]}" if @cgi.params['stage_rgb'][0] != "" @conf['tdiarytimes_f.stage_alpha'] = @cgi.params['stage_alpha'][0] argv << "stage_alpha=#{@cgi.params['stage_alpha'][0]}" if @cgi.params['stage_alpha'][0] != "" @conf['tdiarytimes_f.bg_rgb'] = @cgi.params['bg_rgb'][0] argv << "bg_rgb=0x#{@cgi.params['bg_rgb'][0]}" if @cgi.params['bg_rgb'][0] != "" @conf['tdiarytimes_f.bg_alpha'] = @cgi.params['bg_alpha'][0] argv << "bg_alpha=#{@cgi.params['bg_alpha'][0]}" if @cgi.params['bg_alpha'][0] != "" @conf['tdiarytimes_f.bar_rgb'] = @cgi.params['bar_rgb'][0] argv << "bar_rgb=0x#{@cgi.params['bar_rgb'][0]}" if @cgi.params['bar_rgb'][0] != "" @conf['tdiarytimes_f.bar_width'] = @cgi.params['bar_width'][0] argv << "bar_width=#{@cgi.params['bar_width'][0]}" if @cgi.params['bar_width'][0] != "" @conf['tdiarytimes_f.entr_interval'] = @cgi.params['entr_interval'][0] @conf['tdiarytimes_f.entr_lifetime'] = @cgi.params['entr_lifetime'][0] @conf['tdiarytimes_f.fade_time'] = @cgi.params['fade_time'][0] argv << "fade_time=#{@cgi.params['fade_time'][0]}" if @cgi.params['fade_time'][0] != "" @conf['tdiarytimes_f.preview'] = @cgi.params['preview'][0] if @cgi.params['type'][0] == "0" filename = @cgi.params['filename'][0] width = @cgi.params['width'][0] height = @cgi.params['height'][0] elsif @cgi.params['type'][0] filename = "tdiarytimes#{@cgi.params['type'][0].delete('-')}.swf" width = @cgi.params['type'][0].split('-').first.split('x')[0] height = @cgi.params['type'][0].split('-').first.split('x')[1] end if argv.size > 0 then argvs = "?#{argv.join('&')}" end @conf['tdiarytimes_f.templete'] = tdiarytimes_flashstyle_templete(filename, argvs, width, height) end <<-HTML

        設定の概要

        () 内は初期値です。初期値を使用する場合は、空欄のままで構いません。色は RRGGBB 形式で指定して下さい。不透明度は 0 (透明) 〜 100 (不透明) です。線幅はピクセルで指定します。


        プレビュー

        #{tdiarytimes_flashstyle_preview}

        表示する Flash アプレットの選択

        プリセットを使用しない場合は、以下で指定して下さい。

        Flash のファイル名

        Flash の表示幅

        Flash の表示高さ


        タイトルテキスト

        タイトルテキストの表示有無 (表示)

        タイトルテキスト (TDIARYTIMES-FLASHSTYLE)
        使用出来る文字は、英大文字 (A-Z) と数字 (0-9)、および記号のみです。

        タイトルテキストの色 (333333)

        時刻目盛テキスト

        時刻目盛テキストの表示有無 (表示)

        時刻目盛テキストの色 (333333)


        背景や棒グラフの色

        背景の色 (FFFFFF)

        背景の不透明度 (0)

        タイムラインの背景の色 (333333)

        タイムラインの背景の不透明度 (100)

        タイムラインに記録される棒グラフの色 (EEEEEE)

        タイムラインに記録される棒グラフの線幅 (1)

        タイムラインに記録される棒グラフの寿命日数 (30)


        ログ管理

        前回の日記登録から設定時間内はエントリを新規登録しない (2)

        設定日数後にログファイルからエントリを削除する (30)

        本プラグインが作成するログファイル名 (tdiarytimes.log)


        ユニークID を使用したファイル取得

        ファイル取得のリクエストにユニークID (例えば ?#{Time.now.to_i}) を含めることにより、古いファイルがブラウザにキャッシュされたままになるのを防ぎます。Flash のユニークID はプリファレンス設定時に、ログファイルのユニークID はエントリ登録時に更新されます。

        ユニークID の付加 (付加する)


        プレビュー

        表示したい SWF ファイル (.swf) が tdiary.rb と同じフォルダにアップロードされている必要があります。また、ログファイルが SWF ファイルと同じフォルダに作成されていない場合にはグラフが表示されません。

        プレビュー (非表示)

        HTML end def tdiarytimes_flashstyle_preview unless @conf.mobile_agent? <<-r

        #{if @conf['tdiarytimes_f.preview'] == "1" then "#{tdiarytimes_flashstyle}" else "プレビュー表示を有効にすると、ここに Flash が表示されます。" end}

        r end end def tdiarytimes_flashstyle_templete( filename="tdiarytimes234x30.swf", argvs="", width="234", height="30" ) <<-r r end tdiary-contrib-3.2.2/plugin/tdiarytimes_textstyle.rb000066400000000000000000000272111213632744000227630ustar00rootroot00000000000000# tdiarytimes_textstyle.rb $Revision: 1.3 $ # # Copyright (c) 2004 phonondrive # Distributed under the GPL # # プラグイン配布ページ: # http://phonondrive.com/trd/ # -------------------------------------------------------------------- # # # # Abstract: # -------------------------------------------------------------------- # 日記を登録した時間帯をタイムライン上に記録します。 # 記録されたエントリは日時の経過と共にフェードアウトしていきます。 # このような MTBlogTimes や tdiarytimes と同等の機能をテキストで実現します。 # また、テキストベースであることを生かした柔軟なサイトデザインが可能です。 # ruby-gd のインストール作業も必要ないため、すぐに使用出来ます。 # # # Usage: # -------------------------------------------------------------------- # プラグインは、プラグインフォルダに入れてください。 # ヘッダ、あるいはフッタ部に入力した <%= tdiarytimes_textstyle %> # の位置にタイムライン文字列が展開されます。 # 新しいエントリの記録や保持期間の過ぎた古いエントリの削除は、 # 日記の追加および登録時に行われます。 # ただし、エントリのフェードアウト効果はリアルタイムに計算されます。 # エントリの表示分解能は10分ごとです。 # # # Options: # -------------------------------------------------------------------- # # 現在、次の9つのオプションが用意されています。 # # init_text 日記の登録されていない時間帯の文字列 (任意の文字列) # entr_text 日記が登録された時間帯の文字列 (任意の文字列) # init_color 日記の登録されていない時間帯の文字列の色 (RRBBGG形式で指定) # entr_color 日記が登録された時間帯の文字列の色 (RRBBGG形式で指定) # fade_color 日記が登録された時間帯の文字列のフェードアウト先の色 (RRBBGG形式で指定) # init_css タイムライン文字列全体のCSS設定 (CSSの書式に準拠) # entr_css 日記が登録された時間帯の文字列のCSS設定 (CSSの書式に準拠) # title_text オブジェクト上にマウスをポイントした時のTIPS文字列 (任意の文字列) # fade_time ログとして保存しておく(フェードアウトに要する)日数 (任意の数値) # entr_interval 前回のエントリ登録から指定時間以内は新規登録しない (任意の数値) # # オプション値の設定方法には3つの方法があり、その優先順位は次の通りです。 # <%= tdiarytimes_textstyle %> 引数指定 > tdiary.conf設定値 > デフォルト値 # # entr_intervalを除いた全てのオプション値は <%= %> への引数指定により設定出来るため、 # ページにごとに意匠を変更するなど自由度の高いサイトデザインが可能です。 # 一方で、全てのオプションにデフォルト値が用意されているため、 # 全く設定を行わなくても動作します。 # デフォルト値の具体的な値については、tdiary.confへの記述方法の項を参照して下さい。 # # # <%= tdiarytimes_textstyle %>への引数指定によるオプション設定方法 # -------------------------------------------------------------------- #【書式】 # <%= tdiarytimes_textstyle init_text, entr_text, init_color, entr_color, fade_color, init_css, entr_css, title_text, fade_time %> # #【記述例】 # <%=tdiarytimes_textstyle "●","●","004400","66ff66","004400","background-color:#002200;font-size:9px",nil,"TEXTSTYLE!!",15 %> # # ※ tdiary.conf指定値、またはデフォルト値を使用したい場合は、引数に nil を指定してください。 # # # tdiary.confへの記述によるオプション設定方法 # -------------------------------------------------------------------- #【記述例】 (例として指定されている値は、プラグイン本体の持つデフォルト値です) # @options['tdiarytimes_textstyle.init_text'] = "|" # @options['tdiarytimes_textstyle.entr_text'] = "|" # @options['tdiarytimes_textstyle.init_color'] = "444444" # @options['tdiarytimes_textstyle.entr_color'] = "eeeeee" # @options['tdiarytimes_textstyle.fade_color'] = "444444" # @options['tdiarytimes_textstyle.init_css'] = "background-color:#444444;" # @options['tdiarytimes_textstyle.entr_css'] = "" # @options['tdiarytimes_textstyle.title_text'] = "TDIARYTIMES-TEXTSTYLE" # @options['tdiarytimes_textstyle.fade_time'] = 30 # @options['tdiarytimes_textstyle.entr_interval'] = 1 # # ※ fade_time の単位は日、entr_interval の単位は時間です。 # ※ ログとして保存しておく期間(フェードアウト期間)を過ぎたデータエントリは、 # 指定期間経過後の次回日記追加時にログファイルから削除されます。 # この期間を決定する fade_time 値は、<%= %> 引数からは指定出来ません。 # デフォルト値(30日)以外の値を用いたい場合は、必ず tdiary.conf にて指定して下さい。 # 同様に、entr_interval もデフォルト値(1時間)以外に設定したい場合は、 # tdiary.conf にて指定して下さい。ちなみに0.5だと30分間隔になります。 # # # In secure mode: # -------------------------------------------------------------------- # 現在のところ動作しません。(ログファイルを読み込めない為) # # # Acknowledgements: # -------------------------------------------------------------------- # This plugin is based on tdiarytimes.rb $Revision: 1.3 $ # Copyright (c) 2003 neuichi # Distributed under the GPL # http://nmnl.jp/hiki/software/?tDiary+%3A%3A+Plugin # # =begin ChangeLog 2004.03.04 phonondrive * version 1.0.4 非応答USER-AGENTリストを更新しました。 2004.02.05 phonondrive * version 1.0.3 フェードアウト効果の計算結果が正しく出力されない点を修正しました。 2004.01.30 phonondrive * version 1.0.2 最低登録間隔のオプション (entr_interval) を追加。 前回のエントリ登録から指定時間以内は新規登録しないようにしました。 2004.01.29 phonondrive * version 1.0.1 replace(登録)時もエントリを記録するようにしました。 次のUSER-AGENTからの呼び出しには結果を出力しないようにしました。 モバイル端末 (tDiary準拠) テキストブラウザ (w3m, Lynx, links) CSS非対応ブラウザ (Mosaic, Lite, iCab, JustView, WebExplorer) 検索ボット (bot, crawler, Spider, Slurp, inktomi, Sidewinder, naver) その他 (libwww, antenna) 2004.01.28 phonondrive * version 1.0.0 =end # tDiarytimes_textstyle の結果を出力しない USER-AGENT リスト # モバイル端末、テキストブラウザ、CSS非対応ブラウザ、検索ボット、アンテナなど # 大文字・小文字は区別しません。 def tdiarytimes_textstyle_ignore_user_agent; "w3m|Lynx|links|Mosaic|Lite|iCab|JustView|WebExplorer|bot|crawler|Spider|Slurp|inktomi|Sidewinder|naver|libwww|archiver|http|check|WDB|WWWC|WWWD|samidare|tamatebako|NATSU-MICAN|hina|antenna"; end # -------------------------------------------------------------------- # 日記登録時の処理 # -------------------------------------------------------------------- if /^(append|replace)$/ =~ @mode then # オプション値(エントリ保持期間)の読み込みと設定 fade_time = @options['tdiarytimes_textstyle.fade_time'] || 30 fade_time = 24 * 60 * 60 * fade_time.to_f entr_interval = @options['tdiarytimes_textstyle.entr_interval'] || 1 entr_interval = 60 * 60 * entr_interval.to_f # ログデータの読み込み cache = "#{@cache_path}/tdiarytimes_textstyle" Dir::mkdir( cache ) unless File::directory?( cache ) begin io = open("#{cache}/tdiarytimes_textstyle.dat","r") ary_data = Marshal.load(io) io.close # 1.0.1 >> 1.0.2 ログデータ移行用 if ary_data.size == 144 ary_data.push(Time.now.to_i - entr_interval - 1) end rescue # ログがない場合は仮データを用意 ary_data = Array.new(145) {|i| 0 } end # 不良データや寿命が来たエントリを削除する (0..143).each {|i| delta = (Time.now.to_i - ary_data[i])/fade_time.to_f if delta < 0 || delta > 1 ary_data[i] = 0 end } # 最低登録間隔を経過していたら、日記が登録された時間帯に新しいエントリをセットする if (Time.now.to_i - ary_data[144]) > entr_interval.to_f ary_data[(Time.now.strftime('%H').to_i*6 + Time.now.strftime('%M').to_f/10).to_i] = Time.now.to_i # 最終登録時間の記録 ary_data[144] = Time.now.to_i end # ログデータの書き込み io = open("#{cache}/tdiarytimes_textstyle.dat","w") Marshal.dump(ary_data,io) io.close end # -------------------------------------------------------------------- # プラグイン表示時の動作 # -------------------------------------------------------------------- def tdiarytimes_textstyle(init_text = nil, entr_text = nil, init_color = nil, entr_color = nil, fade_color = nil, init_css = nil, entr_css = nil, title_text = nil, fade_time = nil) # モバイル端末、テキストブラウザ、CSS非対応ブラウザ、検索ボットなどには結果を出力しない unless @cgi.mobile_agent? || @cgi.user_agent =~ %r[(#{tdiarytimes_textstyle_ignore_user_agent})]i r = "" # オプション値の読み込みと設定 init_text = @options['tdiarytimes_textstyle.init_text'] || "|" unless init_text entr_text = @options['tdiarytimes_textstyle.entr_text'] || "|" unless entr_text init_color = @options['tdiarytimes_textstyle.init_color'] || "444444" unless init_color entr_color = @options['tdiarytimes_textstyle.entr_color'] || "eeeeee" unless entr_color fade_color = @options['tdiarytimes_textstyle.fade_color'] || "444444" unless fade_color init_css = @options['tdiarytimes_textstyle.init_css'] || "background-color:#444444;" unless init_css entr_css = @options['tdiarytimes_textstyle.entr_css'] || "" unless entr_css title_text = @options['tdiarytimes_textstyle.title_text'] || "TDIARYTIMES-TEXTSTYLE" unless title_text fade_time = @options['tdiarytimes_textstyle.fade_time'] || 30 unless fade_time entr_color_rgb = entr_color.unpack("a2a2a2") fade_color_rgb = fade_color.unpack("a2a2a2") fade_time = 24 * 60 * 60 * fade_time.to_f # ログデータの読み込み cache = "#{@cache_path}/tdiarytimes_textstyle" begin io = open("#{cache}/tdiarytimes_textstyle.dat","r") ary_data = Marshal.load(io) io.close rescue # ログファイルが見つからない場合はエラーとダミーデータを表示 r << %Q|Error! cannot open log file.| ary_data = Array.new(145) {|i| 0 } end # htmlデータの出力 r << %Q|| (0..143).each {|i| data = ary_data[i] if data != 0 delta = (Time.now.to_i - data)/fade_time.to_f if delta < 0 # 不良エントリ対策 now_color = init_color elsif delta > 1 # フェードアウト期間超過エントリ対策 now_color = fade_color else # 正常なエントリの処理 now_color = "" (0..2).each{|i| now_color << format("%02x", entr_color_rgb[i].hex + ((fade_color_rgb[i].hex - entr_color_rgb[i].hex)*delta).to_i) } end r << %Q|#{entr_text}| else r << %Q|#{init_text}| end } r << %Q|| end end tdiary-contrib-3.2.2/plugin/title_anchor.rb000066400000000000000000000004441213632744000207520ustar00rootroot00000000000000# # title_anchor.rb: # # Copyright (C) 2007 by SHIBATA Hiroshi # Distributed under GPL2. # def title_anchor r = '' if /^latest$/ =~ @mode r << %Q|

        #{h @conf.html_title}

        | else r << %Q|

        #{h @conf.html_title}

        | end r end tdiary-contrib-3.2.2/plugin/tweet_quote.rb000066400000000000000000000064621213632744000206520ustar00rootroot00000000000000# -*- coding: utf-8 -*- # # tweet_quote.rb - tDiary plugin to quote tweet on twitter.com, # formaly known as blackbird-pie.rb # # Copyright (C) 2010, hb # # usage: # <%= tweet_quote "id|url" %> # or # <%= twitter_quote "id|url" %> # or # <%= blackbird_pie "id|url" %> # or # <%= bbp "id|url" %> # require 'pstore' require 'open-uri' require 'timeout' require 'rexml/document' require 'time' require 'uri' def twitter_statuses_show_api( tweet_id ) url = "http://api.twitter.com/1/statuses/show/#{tweet_id}.xml" proxy = @conf['proxy'] proxy = 'http://' + proxy if proxy timeout( 20 ) do open( url, :proxy => proxy ) {|f| f.read } end end def tweet_quote( src ) if %r|http(?:s)?://twitter.com/(?:#!/)?[^/]{1,15}/status(?:es)?/([0-9]+)| =~ src.to_s.downcase src = $1 end return unless /\A[0-9]+\z/ =~ src.to_s cache = "#{@cache_path}/blackbird.pstore" xml = nil db = PStore.new( cache ) db.transaction do key = src db[key] ||= {} if db[key][:xml] xml = db[key][:xml] else begin xml = twitter_statuses_show_api( src ) rescue OpenURI::HTTPError return %Q|

        #$!

        | end db[key][:xml] = xml end end doc = REXML::Document::new( REXML::Source.new( xml ) ).root tweet_id = doc.elements['//id'].text screen_name = doc.elements['//user/screen_name'].text name = doc.elements['//user/name'].text background_url = doc.elements['//user/profile_background_image_url'].text profile_background_color = '#' + doc.elements['//user/profile_background_color'].text avatar = doc.elements['//user/profile_image_url'].text source = doc.elements['//source'].text timestamp = Time.parse( doc.elements['//created_at'].text ).to_s content = doc.elements['//text'].text content.gsub!( URI.regexp( %w|http https| ) ){ %Q|#{$&}| } content = content.split( /(<[^>]*>)/ ).map do |s| next s if s[/\A([a-zA-Z0-9_]{1,15}))(?![a-zA-Z0-9_])/ ){ %Q|#{$&}| } s.gsub( /#([a-zA-Z0-9]{1,16})/ ){ %Q|#{$&}| } end.join r = <<-HTML

        #{content} #{timestamp} via #{source}

        HTML end alias :blackbird_pie :tweet_quote alias :bbp :tweet_quote alias :twitter_quote :tweet_quote tdiary-contrib-3.2.2/plugin/twitpic.rb000066400000000000000000000006741213632744000177670ustar00rootroot00000000000000# # twitpic.rb: plugin to insert images on twitpic.com. # # Copyright (C) 2010 TADA Tadashi # You can redistribute it and/or modify it under GPL2. # def twitpic( image_id, label = 'image on Twitpic', place = 'photo' ) %Q|#{h label}| end tdiary-contrib-3.2.2/plugin/twitter.rb000066400000000000000000000023161213632744000200010ustar00rootroot00000000000000# twitter.rb $Revision: 1.1 $ # Copyright (C) 2007 Michitaka Ohno # You can redistribute it and/or modify it under GPL2. require 'timeout' require 'time' require 'open-uri' require 'rexml/document' @twitter_statuses = [] if /^(latest|day)$/ =~ @mode then add_header_proc do xml = nil timeout( 5 ) do begin xml = open( "http://twitter.com/statuses/user_timeline/#{@conf['twitter.user']}.xml" ){|f| f.read} rescue Exception end end doc = REXML::Document.new( xml ).root if xml if doc then doc.elements.each( 'status' ) do |e| @twitter_statuses << [@conf.to_native( e.elements['text'].text ), Time.parse( e.elements['created_at'].text ).localtime] end end '' end end add_body_leave_proc do |date| today_statuses = [] @twitter_statuses.each do |t, d| today_statuses << [t, d] if d.to_a[3,3] == date.to_a[3,3] end if !today_statuses.empty? r = %Q[
        ] r << %Q[

        Twitter statuses

        ] today_statuses.sort{|a, b| b.last<=>a.last}.each do |t, d| r << %Q[

        #{CGI::escapeHTML( t )} (#{d.strftime( '%H:%M:%S' )})

        ] end r << %Q[
        ] else '' end end tdiary-contrib-3.2.2/plugin/twitter_anywhere.rb000066400000000000000000000127251213632744000217100ustar00rootroot00000000000000# -*- coding: utf-8 -*- # # twitter_anywhere.rb - bringing the Twitter communication platform to tDiary # refer to the URL below. # https://dev.twitter.com/docs/anywhere/welcome # # Copyright (C) 2010-2012, tamoot # You can redistribute it and/or modify it under GPL2. # def follow_button(account) return not_support_anywhere unless support_anywhere? return not_ready_anywhere unless ready_anywhere? if account.nil? || account == '' return anywhere_plugin_error("Account name is not specified.") end <<-FOLLOW_API FOLLOW_API end def tweet_box(label = nil, content = nil, option = {}) return not_support_anywhere unless support_anywhere? return not_ready_anywhere unless ready_anywhere? init_tweetbox @tweetbox_opt.merge!(option) @tweetbox_opt.merge!(:height => 120) unless option[:height].to_i > 0 @tweetbox_opt.merge!(:width => 480) unless option[:width].to_i > 0 @tweetbox_opt.merge!(:label => label) if label @tweetbox_opt.merge!(:defaultContent => content) if content %Q|| end def twitter_anywhere_settings enable_js('twitter_anywhere.js') add_js_setting('$tDiary.plugin.twitter_anywhere') selectors = @conf['twitter_anywhere.hovercards.selectors'].split(',').collect do |selector| %Q|"#{selector.strip}"| end add_js_setting('$tDiary.plugin.twitter_anywhere.selectors', "[#{selectors.join(',')}]" ) expanded = '{}' if @conf['twitter_anywhere.hovercards.expand_default'] == 'true' expanded = '{"expanded":true}' end add_js_setting('$tDiary.plugin.twitter_anywhere.hovercards') add_js_setting('$tDiary.plugin.twitter_anywhere.hovercards.expand_default', expanded) end add_header_proc do if /\A(?:latest|day|month|nyear|preview)\z/ =~ @mode if ready_anywhere? %Q|| else '' end end end def init_tweetbox @tweetbox_json_opt ||= [] @tweetbox_opt ||= {} end add_footer_proc do |date| if /\A(?:latest|day|month|nyear|preview)\z/ =~ @mode if ready_anywhere? init_tweetbox @tweetbox_opt.each_pair do |k, v| @tweetbox_json_opt << "\"#{k}\":\"#{v}\"" end tweet_box_call = %Q|\n| else '' end else '' end end add_conf_proc( 'twitter_anywhere', 'Twitter Anywhere' ) do if @mode == 'saveconf' then @conf['twitter_anywhere.id'] = @cgi.params['twitter_anywhere.id'][0] @conf['twitter_anywhere.hovercards.selectors'] = @cgi.params['twitter_anywhere.hovercards.selectors'][0] @conf['twitter_anywhere.hovercards.expand_default'] = @cgi.params['twitter_anywhere.hovercards.expand_default'][0] end expand_true = "" expand_false = "selected" if @conf['twitter_anywhere.hovercards.expand_default'] == "true" expand_true = "selected" expand_false = "" end <<-HTML

        Consumer key

        Register your tDiary and get Consumer key. Go Twitter OAuth settings.

        Rending Hovercards

        CSS Selector To limit the scope of where Hovercards appear

        example) div.section p, div.commentshort p, div.commentbody p

        Expanded by Default

        HTML end def support_anywhere? return false if @conf.mobile_agent? || feed? return true end def ready_anywhere? if @conf['twitter_anywhere.id'] && @conf['twitter_anywhere.id'].size > 0 return true end return false end def not_support_anywhere '[Twitter@Anywhere] not support this environment.' end def not_ready_anywhere anywhere_plugin_error( "Twitter consumer Key not specified.", %Q|Go Twitter OAuth settings.|) end def anywhere_plugin_error(message, detail= '') <<-PLUGIN_ERROR

        [ERROR] twitter_anywhere.rb: #{message}


        #{detail}

        PLUGIN_ERROR end if /\A(?:latest|day|month|nyear|preview)\z/ =~ @mode twitter_anywhere_settings end # Local Variables: # mode: ruby # indent-tabs-mode: t # tab-width: 3 # ruby-indent-level: 3 # End: # vim: ts=3 tdiary-contrib-3.2.2/plugin/twitter_badge.rb000066400000000000000000000021041213632744000211160ustar00rootroot00000000000000# # twitter_badge.rb: insert 'Follow me' badge of Twitter. # # Copyright (C) 2010 TADA Tadashi # You can redistribute it and/or modify it under GPL2. # def twitter_badge( account, opt = {} ) return '' unless account @twitter_badge_setting = { :account => account, :label => (opt[:label] || 'follow-me'), :color => (opt[:color] || '#35ccff'), :side => (opt[:side] || 'right')[0,1], :top => (opt[:top] || 136).to_i, :delay => (opt[:delay] || 5).to_i * 1000, } '' # do nothing in this method. end add_footer_proc do if @twitter_badge_setting then t = @twitter_badge_setting <<-TEXT TEXT else '' end end tdiary-contrib-3.2.2/plugin/twitter_js.rb000066400000000000000000000035601213632744000204770ustar00rootroot00000000000000# twitter_js.rb $Revision: 1.1 $ # Copyright (C) 2007 Michitaka Ohno # You can redistribute it and/or modify it under GPL2. if /\A(?:latest|day)\z/ =~ @mode then if @conf['twitter.user'] then twitter_user = @conf['twitter.user'] add_header_proc do result = <<-HTML HTML result.gsub( /^\t\t/, '' ) end add_body_leave_proc do |date| result = <<-HTML
        HTML result.gsub( /^\t\t/, '' ) end end end add_conf_proc( 'twitter_js', 'Twitter' ) do if @mode == 'saveconf' then @conf['twitter.user'] = @cgi.params['twitter.user'][0] end <<-HTML

        Account Name

        HTML end tdiary-contrib-3.2.2/plugin/ustream.rb000066400000000000000000000011611213632744000177540ustar00rootroot00000000000000# # ustream.rb - insert some services of Ustream.tv # # Copyright (C) 2010, TADA Tadashi . # You can redistribute it and/or modify it under GPL2. # def ustream( id, type = :recorded ) if type == :live then return '' end # insert recorded video if @conf.mobile_agent? or @conf.iphone? or feed? then return %Q|Link to Ustream ##{id}

        | end %Q|| end tdiary-contrib-3.2.2/plugin/vimeo.rb000066400000000000000000000007721213632744000174220ustar00rootroot00000000000000# # vimeo.rb - insert some services of vimeo.com # # Copyright (C) 2011, Kiwamu Okabe . # You can redistribute it and/or modify it under GPL2. # def vimeo( id ) if @conf.mobile_agent? or @conf.iphone? or feed? then return %Q|Link to vimeo ##{id}

        | end %Q|| end tdiary-contrib-3.2.2/plugin/volatile.rb000066400000000000000000000046471213632744000201270ustar00rootroot00000000000000# hide old diaries # # options configurable through settings: # @conf['volatile.limit'] : number of diaries to show # # Copyright (c) MATSUOKA Kohei # Distributed under the GPL # module ::TDiary # 複数の日記を一括して更新するためのクラス class TDiaryBulkUpdate < TDiaryUpdate def initialize( cgi, rhtm, conf ) super date = Time::local( *cgi.params['date'][0].scan( /^(\d{4})(\d\d)$/ )[0] ) @io.transaction( date ) do |diaries| yield(diaries) # DIRTY_DIARYは@ioへ日記を更新することを伝えるフラグ DIRTY_DIARY end end end end # 古い日記を非表示にするプラグイン class VolatileDiaryPlugin def initialize(conf) @conf = conf @limit = conf['volatile.limit'] || 10 end # all を true にすると全ての日記を対象とする def update(years, all = false) each_recent_diary(years) do |date, diary, count| diary.show(count <= @limit) all || count <= @limit end end def each_recent_diary(years) cgi = CGI.new count = 1 break_flag = false years.keys.sort.reverse_each do |year| years[year].sort.reverse_each do |month| cgi.params['date'] = ["#{year}#{month}"] cgi.params['year'] = [year] cgi.params['month'] = [month] cgi.params['day'] = ["1"] m = TDiaryBulkUpdate::new(cgi, '', @conf) {|diaries| # diaries.class is Hash (date => diary) diaries.sort.reverse_each do |date, diary| unless yield(date, diary, count) break_flag = true break end count += 1 end } break if break_flag end break if break_flag end end end add_update_proc do # 古い日記を非表示にする plugin = VolatileDiaryPlugin.new(@conf) plugin.update(@years) end add_conf_proc('volatile', "揮発性日記", 'update') do if @mode == 'saveconf' then @conf['volatile.limit'] = @cgi.params['volatile.limit'][0].to_i p = VolatileDiaryPlugin.new(@conf) p.update(@years, true) end r = <<-HTML

        日記の更新時に古い日記を非表示にします。

        公開する日記の件数

        公開したい日記の件数を入力してください。
        HTML r end tdiary-contrib-3.2.2/plugin/vote.rb000066400000000000000000000056121213632744000172560ustar00rootroot00000000000000# tdiary_vote.rb $Revision: 2 $ # Copyright (C) 2006 Michitaka Ohno # You can redistribute it and/or modify it under GPL2. # # ref. http://elpeo.jp/diary/20060622.html#p01 # # .tdiary-vote { # float: left; # background-color: aqua; # } require 'digest/md5' require 'pstore' @tdiary_vote_db = "#{@cache_path}/tdiary_vote" @tdiary_vote_label = "投票" @tdiary_vote_date = nil def vote( *items ) return '' unless @tdiary_vote_date h, voted = get_vote( @tdiary_vote_date, @cgi.cookies['tdiary_vote'][0] ) max = h.empty? ? 1 : h.values.max r = %Q[] items.sort{|a, b| h[b] <=> h[a]}.each do |item| num = h[item] r << %Q[] r << %Q[] r << %Q[] unless voted then r << %Q[] end r << %Q[] end r << %Q[
        #{CGI.escapeHTML( item )}#{num}] r << %Q[
        ] r << %Q[#{csrf_protection}] r << %Q[] r << %Q[] r << %Q[] r << %Q[] r << %Q[] r << %Q[
        ] r << %Q[
        ] end def get_vote( date, uid ) h = Hash.new(0) voted = false file = "#{@tdiary_vote_db}/#{date.strftime( "%Y%m%d" )}.db" if File.exist?( file ) then PStore.new( file ).transaction do |db| h.update( db['vote'] ) if db.root?( 'vote' ) voted = db['voter'].include?( uid ) if db.root?( 'voter' ) db.abort end end [h, voted] end def add_vote( date, item, uid ) Dir::mkdir( @tdiary_vote_db ) unless File::directory?( @tdiary_vote_db ) file = "#{@tdiary_vote_db}/#{date.strftime( "%Y%m%d" )}.db" PStore.new( file ).transaction do |db| db['voter'] = Hash.new unless db.root?( 'voter' ) db.abort if db['voter'].include?( uid ) db['voter'][uid] = @cgi.remote_addr db['vote'] = Hash.new(0) unless db.root?( 'vote' ) db['vote'][item] += 1 end end add_body_enter_proc do |date| @tdiary_vote_date = date '' end add_body_leave_proc do |date| @tdiary_vote_date = nil '' end unless bot? then if @mode == 'comment' && @cgi.valid?( 'vote' ) && @cgi.cookies['tdiary_vote'][0] then add_vote( @date, @cgi.params['vote'][0], @cgi.cookies['tdiary_vote'][0] ) end add_footer_proc do uid = @cgi.cookies['tdiary_vote'][0] || Digest::MD5.hexdigest( @cgi.remote_addr + Time.now.to_s + rand.to_s ) cookie_path = File::dirname( @cgi.script_name ) cookie_path += '/' if cookie_path !~ /\/$/ cookie = CGI::Cookie::new( 'name' => 'tdiary_vote', 'value' => uid, 'path' => cookie_path, 'expires' => Time.now.gmtime + 30*24*60*60 ) add_cookie( cookie ) '' end end tdiary-contrib-3.2.2/plugin/wikiloc.rb000066400000000000000000000017331213632744000177420ustar00rootroot00000000000000# # wikiloc.rb: plugin embedding trip map on wikiloc. # # Copyright (C) 2008 MUNEDA Takahiro # You can redistribute it and/or modify it under GPL2. # # derived from everytrail.rb, Copyright (C) 2008 TADA Tadashi # # Parameters: # @trip_id : your trip id # @measures : on/off # @maptype : M/S/H/T # @size : [width,height] # # Please see the following address about the details: # http://www.wikiloc.com/forum/posts/list/14.page # # ChangeLog: # 20080706: Initial release # 20080713: Change default parameters # def wikiloc( trip_id, measures = "off", maptype = "M", size = [500,400] ) size.collect! {|i| i.to_i } size[0] = 500 if size[0] == 0 size[1] = 400 if size[1] == 0 %Q|| end tdiary-contrib-3.2.2/plugin/windex.rb000066400000000000000000000327111213632744000175770ustar00rootroot00000000000000#!/usr/bin/env ruby # windex.rb $Revision: 1.2 $ # # windex: 索引を生成する # パラメタ: # str: キーワード文字列 # readname: 読み仮名 # # wikw: 索引からアンカーを生成する # パラメタ: # str: キーワード文字列 # # このファイルをtDiaryのトップディレクトリにも配置し、CGIとして # 実行することで索引ページを出力できます。 # # CGI動作時の引数 # http://(日記URL)/windex.rb?kw=(キーワード文字列) # とキーワードを指定してアクセスすることでそのキーワードに関係する日記の # 日付一覧を出力できます。一つだけの場合にはその日付の日記への # リダイレクトを出力します。 # # tdiary.confによる設定 # @options['windex.generate_all'] = true # 全ての日記から索引を生成します。これは時間がかかるので、索引の全生成を # 行いたいときだけtrueに設定して更新を行うような使い方を想定しています。 # # Copyright (c) 2003 Gony # Distributed under the GPL # mode = "" if $0 == __FILE__ mode = "CGI" if FileTest.symlink?(__FILE__) == true org_path = File.dirname(File.readlink(__FILE__)) else org_path = File.dirname(__FILE__) end $:.unshift(org_path) require "pstore" require "tdiary" tdiarybase = TDiary::TDiaryBase else tdiarybase = TDiaryBase end class WITDiary < tdiarybase def load_plugins super end def generate_wordindex(date,plugin,index) wordindex = WIWordIndex.new @io.transaction(date) do |diaries| wordindex.generate(diaries,plugin,index) end return wordindex end end class WIWordIndex def initialize @windex = {} @dates = [] end def generate(diaries,plugin,index) diaries.each_value do |diary| num_section = 1 diary.each_section do |section| anchor = index \ + plugin.anchor(diary.date.strftime("%Y%m%d")) \ + "#p%02d" % num_section if section.subtitle != nil scan(section.subtitle,anchor) end scan(section.body,anchor) num_section = num_section + 1 end end end def load(dir) @windex = {} Dir.mkdir(dir) unless File.directory?(dir) PStore.new(dir + "/windex").transaction do |pstore| @dates = pstore.roots @dates.each do |key| windex_tmp = pstore[key] windex_tmp.each_key do |key_windex| if @windex.has_key?(key_windex) == false @windex[key_windex] = {"readname" => nil, "anchor" => []} end if @windex[key_windex]["readname"] == nil \ && windex_tmp[key_windex].has_key?("readname") == true @windex[key_windex]["readname"] = windex_tmp[key_windex]["readname"] end @windex[key_windex]["anchor"].concat(windex_tmp[key_windex]["anchor"]) end end end end def save(dir,keyname) if File.directory?(dir) == false Dir.mkdir(dir,0755) end PStore.new(dir + "/windex").transaction do |pstore| pstore[keyname] = @windex end end def generate_html(page) return page.generate_html(@windex) end def has_key?(key) return @windex.has_key?(key) end def [](key) return @windex[key] end private def scan(body,anchor) to_delimiter_end = { "(" => ")","[" => "]","{" => "}","<" => ">", } wistrs = body.scan(%r[<%\s*=\s*windex\s*[^(<%)]*\s*%>]) wistrs.each do |wistr| # 引数抽出 argstr = wistr.gsub(%r[<%\s*=\s*windex\s*],"") argstr = argstr.gsub(%r[\s*%>],"") args = [] flag_done = false while flag_done == false pos_delimiter = argstr.index(%r['|"|%[Qq].]) #"' if pos_delimiter != nil # デリミタ文字取得 delimiter = argstr.scan(%r['|"|%[Qq].])[0] #"' if delimiter.length == 3 delimiter_end = delimiter[2].chr if to_delimiter_end.has_key?(delimiter_end) delimiter_end = to_delimiter_end[delimiter_end] end else delimiter_end = delimiter end # デリミタまでの文字列を削除 argstr = argstr[(pos_delimiter + delimiter.length)..-1] pos_delimiter = argstr.index(delimiter_end) if pos_delimiter != nil if pos_delimiter > 0 # 引数として取得 args << argstr[0..(pos_delimiter - 1)] else args << "" end # デリミタまでの文字列を削除 argstr = argstr[(pos_delimiter + delimiter_end.length)..-1] else flag_done = true end else flag_done = true end end if args.length > 0 if @windex.has_key?(args[0]) == false # ハッシュを生成 @windex[args[0]] = {"readname" => nil,"anchor" => []} end if args.length > 1 && @windex[args[0]]["readname"] == nil && args[1] != "" @windex[args[0]]["readname"] = args[1] end @windex[args[0]]["anchor"] << anchor end end end end class WIIndexPage def initialize(title,css) @title = title @css = css end def generate_html(windex) body = "" # 大項目名 => 名前の配列 のハッシュを生成 subindex_to_name = {} windex.keys.each do |key| subindex = "" if windex[key]["readname"] != nil subindex = get_subindex(windex[key]["readname"]) else subindex = get_subindex(key) end if subindex_to_name.has_key?(subindex) == false subindex_to_name[subindex] = [] end subindex_to_name[subindex] << key end # 大項目名ごとにHTMLを生成 if subindex_to_name.has_key?("記号") == true body << generate_html_subindex(windex,subindex_to_name,"記号") end subindex_to_name.keys.sort.each do |key| if key != "記号" body << generate_html_subindex(windex,subindex_to_name,key) end end body = <<-BODY #{h @title}(索引) #{@css}

        #{@title} [索引]

        #{body}
        BODY return body end private def generate_html_subindex(windex,subindex_to_name,key) readname_to_name = {} subindex_to_name[key].each do |name| key_new = "" if windex[name]["readname"] != nil key_new = windex[name]["readname"] else key_new = name end if readname_to_name.has_key?(key_new) == false readname_to_name[key_new] = [] end readname_to_name[key_new] << name end body = %Q[

        #{key}

        \n] # 読み仮名のソートでループ -> 名前のソートでループ keys = readname_to_name.keys if keys.empty? == false keys.sort.each do |readname| readname_to_name[readname].sort.each do |name| body << "

        #{name} ... " num_anchor = 1 windex[name]["anchor"].sort.each do |anchor| body = body + %Q[#{num_anchor}] if num_anchor < windex[name]["anchor"].length body = body + "," end num_anchor = num_anchor + 1 end body << "

        " end end end body << "\n
        \n" return body end def get_subindex(name) to_plainhiragana = { "ぁ" => "あ","ぃ" => "い","ぅ" => "う","ぇ" => "え","ぉ" => "お", "が" => "か","ぎ" => "き","ぐ" => "く","げ" => "け","ご" => "こ", "ざ" => "さ","じ" => "し","ず" => "す","ぜ" => "せ","ぞ" => "そ", "だ" => "た","ぢ" => "ち","っ" => "つ","づ" => "つ","で" => "て","ど" => "と", "ば" => "は","ぱ" => "は","び" => "ひ","ぴ" => "ひ","ぶ" => "ふ","ぷ" => "ふ","べ" => "へ","ぺ" => "へ","ぼ" => "ほ","ぽ" => "ほ", "ゃ" => "や","ゅ" => "ゆ","ょ" => "よ", "ゎ" => "わ","ヴ" => "う","ヵ" => "か","ヶ" => "け", } to_1byte = { "!" => "!",'”' => '"',"#" => "#","$" => "$","%" => "%","&" => "&","’" => "'","(" => "(",")" => ")","*" => "*","+" => "+","," => ",","−" => "-","." => ".","/" => "/", "0" => "0","1" => "1","2" => "2","3" => "3","4" => "4","5" => "5","6" => "6","7" => "7","8" => "8","9" => "9",":" => ":",";" => ";","<" => "<","=" => "=",">" => ">","?" => "?", "@" => "@","A" => "A","B" => "B","C" => "C","D" => "D","E" => "E","F" => "F","G" => "G","H" => "H","I" => "I","J" => "J","K" => "K","L" => "L","M" => "M","N" => "N","O" => "O", "P" => "P","Q" => "Q","R" => "R","S" => "S","T" => "T","U" => "U","V" => "V","W" => "W","X" => "X","Y" => "Y","Z" => "Z","[" => "[","¥" => "\\","]" => "]","^" => "^","_" => "_", "a" => "a","b" => "b","c" => "c","d" => "d","e" => "e","f" => "f","g" => "g","h" => "h","i" => "i","j" => "j","k" => "k","l" => "l","m" => "m","n" => "n","o" => "o", "p" => "p","q" => "q","r" => "r","s" => "s","t" => "t","u" => "u","v" => "v","w" => "w","x" => "x","y" => "y","z" => "z","{" => "{","|" => "|","}" => "}","‾" => "~", } topchr = name[0,1] if topchr.count("\xA1-\xFE") == 1 # マルチバイト文字 topchr = name[0,2] end if to_1byte.has_key?(topchr) == true topchr = to_1byte[topchr] end if topchr.length == 1 # シングルバイト文字の処理 topchr = topchr.upcase if (0x21 <= topchr[0] && topchr[0] <= 0x2F) \ || (0x3A <= topchr[0] && topchr[0] <= 0x40) \ || (0x5B <= topchr[0] && topchr[0] <= 0x60) \ || (0x7B <= topchr[0] && topchr[0] <= 0x7B) topchr = "記号" end else # マルチバイト文字の処理 # カタカナ->ひらがな変換 code = topchr[0] * 0x100 + topchr[1] if 0xA5A1 <= code && code <= 0xA5F3 topchr = 0xA4.chr + topchr[1].chr end # 濁点 / 半濁点 撥音など変換 if to_plainhiragana.has_key?(topchr) == true topchr = to_plainhiragana[topchr] end end return topchr end end class WIRedirectPage def initialize(key) @key = key end def generate_html(windex) anchor = windex[@key]["anchor"][0] body = <<-BODY moving... Wait or Click here! BODY return body end end class WISinglePage def initialize(title,date_format,css,key) @title = title @date_format = date_format @css = css @key = key end def generate_html(windex) anchors = windex[@key]["anchor"] body = %Q[

        #{@key}

        \n] anchors.sort.each do |anchor| str_date = anchor.scan(/\d{8}/)[0] date = Time.local(str_date[0..3].to_i,str_date[4..5].to_i,str_date[6..7].to_i) body << %Q[

        #{date.strftime(@date_format)}

        \n] end body << "\n
        \n" body = <<-BODY #{h @title}(索引) #{@css}

        #{@title} [索引]

        #{body}
        BODY return body end end class WIErrorPage def initialize(title,css,key) @title = title @css = css @key = key end def generate_html(windex) body = <<-BODY #{h @title}(索引) #{@css}

        #{@title} [索引]

        キーワード「#{h @key}」は登録されていません。
        BODY return body end end def windex(str,readname = "") return str end def wikw(str) if @wordindex.has_key?(str) == true anchors = @wordindex[str]["anchor"] if anchors.length == 1 return %Q[#{str}] else body = "#{str}(" num_anchor = 1 anchors.sort.each do |anchor| body << %Q[#{num_anchor}] if num_anchor < anchors.length body << "," end num_anchor = num_anchor + 1 end body << ")" return body end end return str end if mode != "CGI" @wordindex = WIWordIndex.new @wordindex.load(@cache_path + "/windex") add_update_proc do if @conf.options["windex.generate_all"] == true tdiary = WITDiary.new(@cgi,"day.rhtml",@conf) @years.each_key do |year| @years[year.to_s].each do |month| date = Time::local(year,month) wordindex = tdiary.generate_wordindex(date,self,@conf.index) wordindex.save(@cache_path + "/windex",date.strftime('%Y%m')) end end else wordindex = WIWordIndex.new wordindex.generate(@diaries,self,@conf.index) wordindex.save(@cache_path + "/windex",@date.strftime('%Y%m')) end end else cgi = CGI.new conf = TDiary::Config.new(cgi) cache_path = conf.data_path + "cache" plugin = WITDiary.new(cgi,"day.rhtml",conf).load_plugins wordindex = WIWordIndex.new wordindex.load(cache_path + "/windex") if cgi.valid?('kw') == true key = cgi.params['kw'][0] if wordindex.has_key?(key) == true num_anchor = wordindex[key]["anchor"].length if num_anchor == 0 page = WIErrorPage.new(conf.html_title,plugin.css_tag,key) elsif num_anchor == 1 page = WIRedirectPage.new(key) else page = WISinglePage.new(conf.html_title,conf.date_format,plugin.css_tag,key) end else page = WIErrorPage.new(conf.html_title,plugin.css_tag,key) end else page = WIIndexPage.new(conf.html_title,plugin.css_tag) end body = wordindex.generate_html(page) header = { "type" => "text/html", "charset" => "UTF-8", "Content-Length" => body.size.to_s, "Pragma" => "no-cache", "Cache-Control" => "no-cache", "Vary" => "User-Agent", } head = cgi.header(header) print head print body end tdiary-contrib-3.2.2/plugin/yahoo_kousei.rb000066400000000000000000000054361213632744000210030ustar00rootroot00000000000000# # yahoo_kousei.rb - # Yahoo!JAPANデベロッパーネットワークの校正支援APIを利用して、 # 日本語文の校正作業を支援します。文字の入力ミスや言葉の誤用がないか、 # わかりにくい表記や不適切な表現が使われていないかなどをチェックします。 # # Copyright (c) 2010, hb # You can redistribute it and/or modify it under GPL. # # 設定: # # @options['yahoo_kousei.appid'] : アプリケーションID(必須) # @options['yahoo_kousei.filter_group'] : # 指摘グループの番号をコンマで区切って指定します。 # @options['yahoo_kousei.no_filter'] : # filter_groupで指定した指摘グループから除外する指摘を指定します。 # # 設定値は http://developer.yahoo.co.jp/webapi/jlp/kousei/v1/kousei.html を参照 # require 'timeout' require 'rexml/document' require 'net/http' Net::HTTP.version_1_2 def kousei_api( sentence ) appid = @conf['yahoo_kousei.appid'] query = "appid=#{appid}&sentence=#{URI.encode( sentence.gsub( /\n/, '' ) )}" query << "&filter_group=" + @conf['yahoo_kousei.filter_group'] if @conf['yahoo_kousei.filter_group'] query << "&no_filter=" + @conf['yahoo_kousei.no_filter'] if @conf['yahoo_kousei.no_filter'] px_host, px_port = (@conf['proxy'] || '').split( /:/ ) px_port = 80 if px_host and !px_port xml = '' Net::HTTP::Proxy( px_host, px_port ).start( 'jlp.yahooapis.jp' ) do |http| xml = http.post( '/KouseiService/V1/kousei', query ).body end xml end def kousei_result( result_set ) html = <<-HTML

        文章校正結果

        HTML doc = REXML::Document::new( result_set ) results = REXML::XPath.match( doc, "//Result" ) if results.empty? html << "

        指摘項目は見つかりませんでした。

        " else html << '' html << '' doc.elements.each( '//ResultSet/Result' ) do |r| html << %Q|| end html << '
        対象表記候補文字詳細情報場所
        #{r.elements['Surface'].text}#{r.elements['ShitekiWord'].text}#{r.elements['ShitekiInfo'].text}#{r.elements['StartPos'].text},#{r.elements['Length'].text}
        ' end html end add_edit_proc do if @mode == 'preview' && @conf['yahoo_kousei.appid'] then xml = kousei_api( @cgi.params['body'][0] ) <<-HTML
        #{kousei_result( xml )} Webサービス by Yahoo! JAPAN
        HTML end end if /\A(form|edit|preview|showcomment)\z/ === @mode then enable_js( 'yahoo_kousei.js' ) end tdiary-contrib-3.2.2/plugin/yahoo_map.rb000066400000000000000000000071171213632744000202570ustar00rootroot00000000000000# -*- coding: utf-8 -*- # # yahoo_map.rb - embeded Yahoo! JAPAN Map for tDiary # # Copyright (C) 2010, KAYA Satoshi # You can redistribute it and/or modify it under GPL2. # add_header_proc do init_ymap r = '' if @conf['yahoo_jp.appid'] and @conf['yahoo_jp.appid'].size > 0 r << %Q|| end end add_conf_proc( 'yahoo_jp_appid', 'Yahoo! JAPAN Application ID' ) do if @mode == 'saveconf' then @conf['yahoo_jp.appid'] = @cgi.params['yahoo_jp.appid'][0] end <<-HTML

        Yahoo! JAPAN Application ID

        Get Application id

        HTML end add_footer_proc do |date| insert_ymap_js end def init_ymap @ymap_container = Array.new end def generate_ymapid(lat, lon, layer, size) ymapid = 'ymapid' << lat.to_s << lon.to_s << layer.to_s << size ymapid.delete('.') end def yahoo_map(lat, lon, options = {}) options[:layer] ||= 17 options[:size] ||= 'medium' if feed? or @conf.mobile_agent? then return %Q|

        Link to Yahoo! JAPAN Map

        | end # define map size height = {'iphone' => '240px', 'small'=> '240px', 'medium' => '360px', 'large' => '480px'} width = {'iphone' => '240px', 'small' => '320px', 'medium' => '480px', 'large' => '640px'} if @conf.iphone? then size = 'iphone' else size = options[:size] end ymapid = generate_ymapid(lat, lon, options[:layer], options[:size]) ymap_info = {:ymapid => ymapid, :lat => lat, :lon => lon, :layer => options[:layer]} @ymap_container << ymap_info %Q|
        | end def insert_ymap_js r = '' if @ymap_container.size > 0 and not feed? then r << %Q|| end end # Local Variables: # mode: ruby # indent-tabs-mode: t # tab-width: 3 # ruby-indent-level: 3 # End: # vim: ts=3 tdiary-contrib-3.2.2/plugin/youtube.rb000066400000000000000000000023141213632744000177710ustar00rootroot00000000000000# # youtube.rb: YouTube plugin for tDiary # # Copyright (C) 2010 by TADA Tadashi # # usage: <%= youtube 'VIDEO_ID' %> # def youtube( video_id, size = [425,350] ) if @conf.mobile_agent? or feed? then %Q|| elsif defined?( :smartphone? ) and @conf.smartphone? size = [240, 194] <<-TAG TAG else <<-TAG TAG end end def youtube_custom( video_id, size = [416,337] ) <<-TAG TAG end tdiary-contrib-3.2.2/plugin/yshop.rb000066400000000000000000000140671213632744000174470ustar00rootroot00000000000000# yshop.rb $Revision: 3 $ # Copyright (C) 2008 Michitaka Ohno # You can redistribute it and/or modify it under GPL2. # ja/yshop.rb @yshop_label_conf ='Yahoo!ショッピング' @yshop_label_appid = 'アプリケーションID' @yshop_label_affiliate_type = 'アフィリエイトの種類' @yshop_label_yid = 'Yahoo! JAPANアフィリエイト' @yshop_label_vc = 'バリューコマースアフィリエイト' @yshop_label_affiliate_id = 'アフィリエイトID' @yshop_label_imgsize = '表示するイメージのサイズ' @yshop_label_medium = '普通' @yshop_label_small = '小さい' @yshop_label_clearcache = 'キャッシュの削除' @yshop_label_clearcache_desc = 'イメージ関連情報のキャッシュを削除する(Yahoo!ショッピング上の表示と矛盾がある場合に試して下さい)' require 'rexml/document' require 'open-uri' require 'kconv' eval( <<-TOPLEVEL_CLASS, TOPLEVEL_BINDING ) require 'erb' include ERB::Util TOPLEVEL_CLASS def yshop_get( param, store ) if Hash === param then param = param.dup elsif /^(\d{8}|\d{13})$/ === param then param = {:jan => $1} else param = {:query => param.to_s} end param[:store_id] = store if store cache = "#{@cache_path}/yshop" Dir::mkdir( cache ) unless File::directory?( cache ) file = "#{cache}/#{u( param.to_s )}.xml" begin xml = File::read( file ) rescue qs = [] qs << 'appid='+u( @conf['yshop.appid']||'YahooDemo' ) qs << 'affiliate_type='+u( @conf['yshop.affiliate_type'] ) if @conf['yshop.affiliate_type'] qs << 'affiliate_id='+u( @conf['yshop.affiliate_id'] ) if @conf['yshop.affiliate_id'] [:query, :jan, :isbn, :store_id].each do |item| qs << "#{item}="+u( param[item].toutf8 ) if param.include?( item ) end qs << 'hits=1' xml = open( 'http://shopping.yahooapis.jp/ShoppingWebService/V1/itemSearch?'+(qs*'&') ){|f| f.read} open( file, 'wb' ) {|f| f.write( xml )} if xml end REXML::Document.new( xml ).root if xml end def yshop_get_image( doc ) img = Struct.new( :size, :src, :width, :height ).new if @conf['yshop.imgsize'] == 1 then img.size = 'Small' img.width = img.height = 76 else img.size = 'Medium' img.width = img.height = 146 end begin img.src = doc.elements["Result/Hit/Image/#{img.size}"].text rescue img.src = "http://i.yimg.jp/images/sh/noimage/#{img.width}x#{img.height}.gif" end img end def yshop_get_brands( doc ) begin @conf.to_native( doc.elements['Result/Hit/Brands/Name'].text ) rescue '-' end end def yshop_get_price( doc ) begin r = doc.elements['Result/Hit/Price'].text nil while r.gsub!(/(.*\d)(\d\d\d)/, '\1,\2') "\\"+r rescue '(no price)' end end def yshop_get_shop( doc ) begin @conf.to_native( doc.elements['Result/Hit/Store/Name'].text ) rescue '-' end end def yshop_get_html( param, store, pos ) doc = yshop_get( param, store ) return unless doc && doc.attributes['totalResultsReturned'].to_i > 0 name = @conf.to_native( doc.elements["Result/Hit/Name"].text ) link = doc.elements["Result/Hit/Url"].text img = yshop_get_image( doc ) r = %Q[] r << %Q[#{h( name )}] if img.src r << h( name ) r << %Q[] end def yshop_image( param, store = nil ) yshop_get_html( param, store, 'amazon' ) end def yshop_image_left( param, store = nil ) yshop_get_html( param, store, 'left' ) end def yshop_image_right( param, store = nil ) yshop_get_html( param, store, 'right' ) end def yshop_detail( param, store = nil ) doc = yshop_get( param, store ) return unless doc && doc.attributes['totalResultsReturned'].to_i > 0 name = @conf.to_native( doc.elements["Result/Hit/Name"].text ) link = doc.elements["Result/Hit/Url"].text img = yshop_get_image( doc ) brands = yshop_get_brands( doc ) price = yshop_get_price( doc ) shop = yshop_get_shop( doc ) <<-HTML #{h( name )} #{h( name )}
        #{h( brands )}
        #{h( shop )}
        #{h( price )}
        HTML end add_conf_proc( 'yshop', @yshop_label_conf ) do yshop_conf_proc end def yshop_conf_proc if @mode == 'saveconf' then @conf['yshop.imgsize'] = @cgi.params['yshop.imgsize'][0].to_i if @cgi.params['yshop.clearcache'][0] == 'true' then Dir["#{@cache_path}/yshop/*"].each do |cache| File::delete( cache.untaint ) end end if @cgi.params['yshop.appid'][0].empty? then @conf['yshop.appid'] = nil else @conf['yshop.appid'] = @cgi.params['yshop.appid'][0] end if @cgi.params['yshop.affiliate_id'][0].empty? then @conf['yshop.affiliate_type'] = nil @conf['yshop.affiliate_id'] = nil else @conf['yshop.affiliate_type'] = @cgi.params['yshop.affiliate_type'][0] @conf['yshop.affiliate_id'] = @cgi.params['yshop.affiliate_id'][0] end end <<-HTML

        #{@yshop_label_appid}

        #{@yshop_label_affiliate_type}

        #{@yshop_label_affiliate_id}

        #{@yshop_label_imgsize}

        #{@yshop_label_clearcache}

        HTML end tdiary-contrib-3.2.2/plugin/zenback.rb000066400000000000000000000020441213632744000177120ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (C) 2011, KADO Masanori # You can redistribute it and/or modify it under GPL. def insert_zenback return if feed? @conf['zenback.script'] || '' end if @mode == 'day' and (respond_to?(:section_mode?) ? section_mode? : true) add_title_proc do |date, title| "#{title}" end add_body_enter_proc do "" end if defined? add_comment_leave_proc add_comment_leave_proc do "" + insert_zenback end else add_body_leave_proc do "" + insert_zenback end end end add_conf_proc( 'zenback', 'zenback', 'etc' ) do if @mode == 'saveconf' then @conf['zenback.script'] = @cgi.params['zenback.script'][0] end <<-HTML

        Script Code

        HTML end # Local Variables: # mode: ruby # indent-tabs-mode: t # tab-width: 3 # ruby-indent-level: 3 # End: # vim: ts=3 tdiary-contrib-3.2.2/spec/000077500000000000000000000000001213632744000154045ustar00rootroot00000000000000tdiary-contrib-3.2.2/spec/apple_webclip_spec.rb000066400000000000000000000017561213632744000215620ustar00rootroot00000000000000$:.unshift(File.dirname(__FILE__)) require 'spec_helper' describe "apple_webclip plugin" do def setup_apple_webclip_plugin( url ) fake_plugin(:apple_webclip) { |plugin| plugin.conf['apple_webclip.url'] = url } end describe "url is enabled" do before do plugin = setup_apple_webclip_plugin('http://example.com/example.png') @header_snippet = plugin.header_proc end it "header include url" do @header_snippet.should == %Q|\t| end end describe "url is disabled" do describe "url is empty" do before do plugin = setup_apple_webclip_plugin('') @header_snippet = plugin.header_proc end it "header is empty" do @header_snippet.should be_empty end end describe "url is nil" do before do plugin = setup_apple_webclip_plugin(nil) @header_snippet = plugin.header_proc end it "header is empty" do @header_snippet.should be_empty end end end end tdiary-contrib-3.2.2/spec/fixtures/000077500000000000000000000000001213632744000172555ustar00rootroot00000000000000tdiary-contrib-3.2.2/spec/fixtures/friendfeed.xml000066400000000000000000000741611213632744000221030ustar00rootroot00000000000000 44123b23Ex-CTO of Facebook. Previously co-founder and CEO of FriendFeed. Programmer, food lover.userbretBret TaylorFriendFeed Blog: Ben Darnell joins FriendFeed: Ben++! - <a rel="nofollow" href="http://blog.friendfeed.com/2009/07/ben-darnell-joins-friendfeed-ben.html" title="http://blog.friendfeed.com/2009/07/ben-darnell-joins-friendfeed-ben.html">http://blog.friendfeed.com/2009...</a>http://friendfeed.com/share/bookmarkletBookmarkletuserBret Taylorbrethttp://m.friendfeed-media.com/d8a3d0cffc2d534fb6c7e87912928dd4ee8695b1109http://blog.friendfeed.com/2009/07/ben-darnell-joins-friendfeed-ben.html175http://friendfeed.com/friendfeed-news/c970e279/friendfeed-blog-ben-darnell-joins2009-07-27T22:52:09ZWelcome, Ben!userkfuryKevin Foxe/c970e27954f349869b58d30a2b75631a/c/affd43519b134e2f8b0175f97267affd2009-07-27T22:52:53ZRight on! Congrats, Ben.usermicahwittmanMicahe/c970e27954f349869b58d30a2b75631a/c/3ae682d1abd74d9cbec58d8614d34c9f2009-07-27T22:54:13ZCongrats Ben! Also, congrats to FF you are lucky to have him!usershellenJason Shellene/c970e27954f349869b58d30a2b75631a/c/a297cd5ec49d4196855bd042dbb8ae982009-07-27T23:14:34ZData storage and scalability rock. :)userlouisgrayLouis Graye/c970e27954f349869b58d30a2b75631a/c/0c562741868248cd80fe1b70c041fe642009-07-27T23:42:50ZBen's feed is here: <a href="http://friendfeed.com/bdarnell">http://friendfeed.com/bdarnell</a>userBret Taylorbrete/c970e27954f349869b58d30a2b75631a/c/31a62c1498c446c090ed63594205c2262009-07-27T23:51:54ZCongrats, Ben! :-)userkoltregaskesKol Tregaskese/c970e27954f349869b58d30a2b75631a/c/e79d0783d7b347a88f3905b722f5d7762009-07-28T00:17:50ZYeah Ben!!!userphoenixRachel Lea Foxe/c970e27954f349869b58d30a2b75631a/c/28ca4607a72c4289ab196230d03e6f742009-07-28T00:41:58Zso i finally get my answer to this :) <a href="http://friendfeed.com/chris/3870e6df/v-excited-about-my-friend-new-job-his" title="http://friendfeed.com/chris/3870e6df/v-excited-about-my-friend-new-job-his">http://friendfeed.com/chris...</a>userparislemonMG Sieglere/c970e27954f349869b58d30a2b75631a/c/0dce0a67de704224b0215da71a2ba4082009-07-28T00:44:52ZYeah, sorry I couldn't respond to that one before. :-)userkfuryKevin Foxe/c970e27954f349869b58d30a2b75631a/c/2d9ae52ed9d942f988a18a028d4dc2152009-07-28T01:01:55Zwell i be darned .... we now can rejoice, since fast paced additions to already good product are surely fastly coming about off the feedpipe ... it'l be a hectic season of finest upgrades ... I'm sure they'l start with keyboard shortcutze. ... I mean Google Reader rules on that. Intelligent to the extreme. ..Google.com, on the other hand - are we sleeping? .. not even &quot;/&quot; ??.. and that is the first page on the planet! .. i'l be darned. ..... then, lets boost them blogging facilities ! ... i mean, how hard internet programming could be ???userpetrbubenpb:e/c970e27954f349869b58d30a2b75631a/c/c17c8d9235a34d238c3ab4376f1b84ab2009-07-28T01:21:05ZCongrats Ben! Totally agree with Jason. Our latest project wouldn't have become feasible without Ben -- I'm just so glad we managed to get a fraction of his time before he left! :)userstongSimone/c970e27954f349869b58d30a2b75631a/c/e7e1b7c2bcbc4c3cb9c112238fb411082009-07-28T02:40:46ZCongratulations, Ben! You're joining an awesome team.useraboueyAnne Boueye/c970e27954f349869b58d30a2b75631a/c/c0428e7432994c73b40365644bf22f7e2009-07-28T03:31:25ZWoohoo! Another Googler :)usertimhoeckTim Hoecke/c970e27954f349869b58d30a2b75631a/c/14daa1eeb6f043b1b58f2213e75971f62009-07-28T03:59:39ZCongrats, you are now a &quot;big company&quot;! ;))))useryogarK.D.e/c970e27954f349869b58d30a2b75631a/c/9d52f70158314758a604daad757326572009-07-28T06:44:21ZThat's not my picture! They got the picture wrong! In fact, I didn't get the letter of hire either. :( Oh, Hi there, Ben...if that's your real name. ;)userjoshhaleyTrueJosh Haleye/c970e27954f349869b58d30a2b75631a/c/531163c5e9e34b9f92c0db5f9d3888c62009-07-28T07:03:07ZGood luck Ben! With you our preferred service will go more interestinghttp://www.fftogo.com/fftogouserpostoditaccoTrueRobertoe/c970e27954f349869b58d30a2b75631a/c/d2aeb1623ed14f089dc567f50f2c418c2009-07-28T10:13:27Zyou're building a friendfeed army there :-)userdobataDobromir Hadzhieve/c970e27954f349869b58d30a2b75631a/c/81b72085bac844868ac7321a6d6ebf072009-07-28T10:50:24ZCongratsuserportakalÖzkan Altunere/c970e27954f349869b58d30a2b75631a/c/c04066a9eec842508018999185260fd42009-07-28T12:42:29ZNice, any former Google Reader-er is a friend of mine.usermikereynoldsMike Reynoldse/c970e27954f349869b58d30a2b75631a/c/833416de1ee14f3a88eb25b3a7ec21cc2009-07-28T13:35:08Zgratz Ben!usertimepilottimepilote/c970e27954f349869b58d30a2b75631a/c/b9d20666d611497abf9be5213eb15b162009-07-28T18:09:12ZWelcome Bret!userjamessmith24Michael_techiee/c970e27954f349869b58d30a2b75631a/c/04cdf733ae664d1f853698aa70090a422009-08-10T20:14:31ZSo, Facebook...?userdpritchettTrueDaniel J. Pritchette/c970e27954f349869b58d30a2b75631a/c/4c811104219a47d0be72b60a464933362009-08-10T21:16:06ZPoor Ben Darnell. The last to enter are always the first to leave in mergers.userbeersagebeersagee/c970e27954f349869b58d30a2b75631a/c/d6c86c49e7a84536821f3627f3debd072009-08-11T06:49:41ZHiring new staff while in secret acquisition talks, not exactly classy guys. I hope Ben knew what he was getting intouserdalzielGlenn Slavene/c970e27954f349869b58d30a2b75631a/c/7858bb2711894dc7ba792ac22a369c4b2009-08-14T05:21:51ZWhy on earth does he use the Duck Hunt theme?uservzxVezquexe/c970e27954f349869b58d30a2b75631a/c/99acd29f314b4d9d821866b5d85770bc2009-08-14T05:23:45ZI don't know.. but it is awesome! :)usertimhoeckTim Hoecke/c970e27954f349869b58d30a2b75631a/c/bed22ee3baa84233a2a54a25d26e17562012-01-30T23:16:12ZWow, looks like somebody bumped this!userkfuryKevin Foxe/c970e27954f349869b58d30a2b75631a/c/c52b519e6cb04a268f76c9ecb84b0be12012-01-30T23:21:48ZI think there were a bunch of spam comments made to some 2009-era posts by FF employees. For some reason even after the spam is nuked, the post stays bumped.userzeigenStephen Macke/c970e27954f349869b58d30a2b75631a/c/0ebcf885818a442bbf773526e49272682012-01-30T23:23:23ZYes, I blocked a spammer that was bumping old posts about FF themes and what not.userzoblueZulema ❧ spicy cocoa tarte/c970e27954f349869b58d30a2b75631a/c/18fcc8e1b02f46fc8a21589681cf0b922012-01-30T23:26:01ZOH HAI!usercstechcastEric - Drop That Beate/c970e27954f349869b58d30a2b75631a/c/244f5398cd4b4d4b9ca344fe66509ca92012-01-30T23:30:29ZWell, let's see this as an opportunity to raise a virtual glass to Ben and FriendFeed-that-was!userkfuryKevin Foxe/c970e27954f349869b58d30a2b75631a/c/5afdbcf261d047b392bed56298492e552012-01-30T23:32:55ZIt probably had something to do with the Tornado 2.2 release. I noticed Ben was the one who posted about the release on HN earlier. Edit: Or it could have just been a spammer. *shrugs*userjimminyTrueJimminy, CoG of FFe/c970e27954f349869b58d30a2b75631a/c/93fc5948d22d4e469ca400e41327b48b2012-01-31T01:17:40ZI don't think it had anything to do with the tornado release - a spammer bumped a bunch of Bret's old posts today.userbdarnellBen Darnelle/c970e27954f349869b58d30a2b75631a/c/2e2bccd6de854ebd8ed345bb15236f5c2012-05-07T17:34:07ZHere, let me save future spammers some time: Hello my name is ____ and I am an attractive young ____ _____ and I would like to contact with you so that together you and I can ___ with ____ while _____ in a highly ____ manner. Please to be responding as soon as is practical. Without your help, the _____ in U.S. dollars will go unclaimed, and the herbal ______ remedy will wither and die. Yours in all urgent seriousness, _____.userzeigenStephen Macke/c970e27954f349869b58d30a2b75631a/c/7eed38db1bb44c3d90ce6a817ae8c1f62012-05-09T03:10:07Z:D, Stephen!useraboueyAnne Boueye/c970e27954f349869b58d30a2b75631a/c/f349034ca1804b3388ca2804156887a32012-08-21T14:40:59Zso sweet))lolusersolnceesolnceee/c970e27954f349869b58d30a2b75631a/c/9ea20c4da85f4c539e02d6e24ac94f452012-09-02T08:06:01ZAwesome Photo :)useradiprcikeAdi Prcikee/c970e27954f349869b58d30a2b75631a/c/53cbf054f1b446fe8c473ef103d101ae2012-09-03T01:06:48ZWhich shows up more, this pic or the Asian gentlemen on the beach?http://friendfeed.com/about/toolsiPhoneuserzeigenStephen Macke/c970e27954f349869b58d30a2b75631a/c/21725041bf364346840c39853efa38292012-09-14T15:39:14Zbret neler oluyor dostum? kardeşi kardeşe kırdıracaksın canım ülkemde!!! işinin başına dön lütfen..useraynebilmaynebilime/c970e27954f349869b58d30a2b75631a/c/4d3788ce9afb420fb95c25ee5ae2d2da2012-09-14T16:03:55Ztesta di cazzo se arcasca tutto te veniamo a cercà e non saremo teneri come i musulmaniuserbonzoTrueFrancesco M.e/c970e27954f349869b58d30a2b75631a/c/63f44ef4d4c7481187d0a199eae11a7c2012-09-14T16:17:29Zkime dedin onu francesco?useraynebilmaynebilime/c970e27954f349869b58d30a2b75631a/c/9298bbd497ff49699e6bdf9f23f7809e2012-09-14T16:33:20ZBence de Friendfeede sahip çıksın artık...userkoleksiyonerkoleksiyonere/c970e27954f349869b58d30a2b75631a/c/890dfb635e734e2f9d0e68fc2ac806da2012-09-14T17:47:38ZWelcome, Ben!userkfuryKevin Foxe/c970e27954f349869b58d30a2b75631a/c/ce9ad2c73c784595929fe89601aab9572012-09-14T17:54:48Z<a href="http://friendfeed.com/search?q=%23timewarp">#timewarp</a>userworldofhigletTrueWoH: Fairy Surreale/c970e27954f349869b58d30a2b75631a/c/29a9cf0c27cd42628fe5192c349c4944userBret's feedbretgroupfriendfeed-newsFriendFeed News2012-09-27T18:45:20ZusergerantamalaTamala Geran2012-09-17T05:12:36Zuserthelarimarshopthelarimarshop2012-09-14T17:59:05ZuserjobblerTrueJoe Silence2012-09-14T16:07:47ZuserkkappAlex Kapranoff2012-09-14T15:39:22Zuseraynebilmaynebilim2012-09-03T09:46:26ZusernganguemvictorTruenganguem victor2012-08-11T14:14:57ZusergoropraskGoro Prask2012-06-29T07:02:56ZuserageuferrazAgeu Ferraz2012-06-05T08:53:02Zuserhewoilsneedhewoilsneed2012-06-04T06:39:34Zuserflorrygripflorrygrip2012-05-24T00:30:59ZuserhcivelekHasanCivelek2012-05-07T17:42:47ZuserworldofhigletTrueWoH: Fairy Surreal2012-05-07T17:38:23ZuserjeffdougTrueJeff (Team マクダジ )2012-05-02T11:57:09ZuserangelramonAngel2012-04-30T08:21:22Zusersogoo/sg2012-04-24T06:17:16ZuseralidafeianTrueعلی دافعیان2012-04-24T06:11:00Zuseramitkumar47amit Kumar2012-04-20T21:45:37Zuserpolymath22Truepolymath222012-04-14T19:49:34Zusercy6erbr4inCy6erBr4in2012-04-02T10:37:30ZuserlisaleneaTrueLisa L. Seifert | FHG™2012-03-24T10:32:02Zuseraidr86Trueaid@2012-02-20T06:40:47ZusermitchnielsenMitch Nielsen2012-02-14T16:09:31Zuserkatiaoинопланетянин со стажем2012-02-14T14:07:33ZuseradamspringAdam Spring2012-01-31T00:46:09Zuserkmohr25Kevin Mohr2012-01-30T23:32:13ZuserjimminyTrueJimminy, CoG of FF2009-12-25T20:16:40Zuserbebekvegebelik"Serhat Ozan"2009-08-11T12:11:30ZuseriphigenieIphigenie2009-08-11T06:53:06ZusermortonfoxMorton Fox2009-08-11T05:28:21Zuseryogamamaamelia arapoff2009-08-10T22:27:13ZuservmlemonTyson Key2009-08-10T22:15:39ZuserkierancrottyKieran Crotty2009-08-10T21:31:59ZuserangusbAngus Burton2009-08-10T21:20:26ZuserberkeleyisbetterKelly2009-08-10T20:14:47ZusersvartlingSvartling2009-08-01T09:35:59ZusertandriamiradoThierry R. Andriamirado2009-07-28T20:14:18ZuserdurukanduruDurukan Duru2009-07-28T19:45:16Zusersilas216Steven Perez2009-07-28T18:54:10Zuserv9yTrueVinay | विनय2009-07-28T18:30:17Zuserstanjourdanstanjourdan2009-07-28T18:12:39ZuserkamathThe Fat Oracle2009-07-28T18:00:07Zuserminusoneminus-one2009-07-28T16:40:19ZuseroflahertyPaul OFlaherty2009-07-28T14:10:49ZuserdpritchettTrueDaniel J. Pritchett2009-07-28T14:00:48ZusersilpolA. T.2009-07-28T13:51:27ZuserajkohnAJ Kohn2009-07-28T13:44:54ZuserdannyrowleyTrueDaniel Rowley2009-07-28T13:40:01ZuserajbatacAJ Batac2009-07-28T12:33:25ZuserstevefarnworthSteve Farnworth2009-07-28T12:23:08ZuserbjtitusBrandon Titus2009-07-28T12:09:31ZusernzbuuJames Myatt2009-07-28T11:11:08Zuserlookonkang2009-07-28T11:08:50ZuserlutaoLu Tao2009-07-28T11:07:33ZuserpellesjoqvistPelle Sjoqvist2009-07-28T10:27:09Zuserpastas9Truepastas92009-07-28T10:19:33ZuseramberspenceTrueThe Amber2009-07-28T10:18:31ZuserourielohayonOuriel Ohayon2009-07-28T10:12:49ZuserdobataDobromir Hadzhiev2009-07-28T09:40:43ZuserzijperspaceTon Zijp2009-07-28T08:50:42ZusersimonwicksSimon Wicks2009-07-28T07:12:26Zuserdffrntvijay2009-07-28T07:00:56ZuserbfosterBonnie Foster2009-07-28T06:54:08ZuserjriveroJordi Rivero2009-07-28T06:51:55ZuserpostoditaccoTrueRoberto2009-07-28T06:51:24ZusernironNir Ben Yona2009-07-28T06:44:26ZuserjoshhaleyTrueJosh Haley2009-07-28T05:54:52ZuserbdarnellBen Darnell2009-07-28T05:02:43ZusermirthnadirAmani2009-07-28T05:02:11Zuserkof2002HealingBrush2009-07-28T04:59:02ZusersusanbeebeSusan Beebe2009-07-28T04:57:19ZuserizuzakIvan Zuzak2009-07-28T04:54:41ZuserkrynskyMark Krynsky2009-07-28T04:23:31ZuserclareClare Dibble2009-07-28T04:12:16ZuserruchiraRuchira S. Datta2009-07-28T04:06:16ZusermalaparteAndrei M. Marinescu2009-07-28T03:56:13ZuseryogarK.D.2009-07-28T03:42:31Zuser1geekyTrueI /-\li2009-07-28T03:41:02ZuserderekDerek Collison2009-07-28T03:40:11ZusermajentoMajento2009-07-28T03:40:08ZusereldiabloPete D2009-07-28T03:37:44Zuserbhc3Hutch Carpenter2009-07-28T03:33:46ZusermonasfeedMona Nomura2009-07-28T03:30:49ZusertimhoeckTim Hoeck2009-07-28T03:28:26ZuserseanpercivalTruesean percival2009-07-28T03:18:41ZusermehmetakifMehmet ALP2009-07-28T03:15:31ZuserchangeforgeKen Stewart | ChangeForge2009-07-28T03:13:56ZuserkarenKaren Padham Taylor2009-07-28T02:47:11ZuserericfloEric Florenzano2009-07-28T02:44:25Zuserimaboneheadimabonehead2009-07-28T02:41:22ZuserrodfatherTrueRodfather2009-07-28T01:51:24ZuserlizunlongLizunlong2009-07-28T01:38:39ZuserpattonrobertaTrueRAPatton2009-07-28T01:09:26ZusernimaaTrueNimaa2009-07-28T01:02:49ZuserlooppacosmosJohni Fisher2009-07-28T00:56:42ZuserstongSimon2009-07-28T00:42:18Zuserbananeanna sauce2009-07-28T00:42:11ZuserparislemonMG Siegler2009-07-28T00:32:40ZuserbettydarnellTrueBetty Darnell2009-07-28T00:22:50ZuserjworthingtonJohnny2009-07-28T00:19:19ZuserleblondbBEX2009-07-28T00:18:17ZuserdalzielGlenn Slaven2009-07-28T00:15:00ZuserphoenixRachel Lea Fox2009-07-28T00:10:05Zuserromanzolotarevromanzolotarev2009-07-28T00:04:42ZusereskimoApril Buchheit2009-07-28T00:04:15Zusertebtunahan2009-07-27T23:59:04ZuserryanmassieRyan Massie2009-07-27T23:58:52ZuserthejbfTrueBurcu Dogan2009-07-27T23:58:24ZusermihaiMihai Parparita2009-07-27T23:56:55Zusertravispuktravispuk2009-07-27T23:55:08ZusermokargasTrueMo Kargas2009-07-27T23:50:45ZuserkoltregaskesKol Tregaskes2009-07-27T23:50:04ZuseritafromaMark Trapp2009-07-27T23:43:39ZuservadimVadim Spivak2009-07-27T23:21:04ZusergottiGOTTi2009-07-27T23:16:10ZuserlanjackalLANjackal2009-07-27T23:14:24ZuserlouisgrayLouis Gray2009-07-27T23:12:43ZusertudorTudor Bosman2009-07-27T23:09:38ZuserhberberogluHüseyin Berberoğlu2009-07-27T23:07:55ZusercaseyCasey Muller2009-07-27T23:03:21ZuserscobleizerRobert Scoble2009-07-27T23:02:17ZusercolladudeKishore Balakrishnan2009-07-27T23:02:15ZuserbgolubBenjamin Golub2009-07-27T22:58:04ZusergingerGinger Makela Riker2009-07-27T22:54:45ZusererensoydasEren Soydaş2009-07-27T22:54:31ZuseratulAtul Arora2009-07-27T22:53:02ZuserthehenryTheHenry2009-07-27T22:52:40ZuserhdiwanProlific Programmer2009-07-27T22:52:40ZuserpaulPaul Buchheit2009-07-27T22:52:37Zuserjeffisageek(jeff)isageek2009-07-27T22:52:11ZuserdhsiaoDan Hsiao2009-07-27T22:52:11ZuserkfuryKevin Fox2009-07-27T22:52:05ZuserrossRoss Miller2009-07-27T22:52:01Ze/c970e27954f349869b58d30a2b75631atdiary-contrib-3.2.2/spec/fixtures/github.json000066400000000000000000000011471213632744000214350ustar00rootroot00000000000000{"type":"User","login":"schacon","public_repos":150,"public_gists":80,"followers":5328,"html_url":"https://github.com/schacon","created_at":"2008-01-27T17:19:28Z","blog":"http://scottchacon.com","company":"GitHub","email":"schacon@gmail.com","avatar_url":"https://secure.gravatar.com/avatar/9375a9529679f1b42b567a640d775e7d?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png","hireable":false,"following":19,"name":"Scott Chacon","bio":null,"id":70,"location":"San Francisco, CA","url":"https://api.github.com/users/schacon","gravatar_id":"9375a9529679f1b42b567a640d775e7d"} tdiary-contrib-3.2.2/spec/fixtures/twitter.xml000066400000000000000000000065671213632744000215170ustar00rootroot00000000000000 65589541 tDiary.org tDiary tDiaryオフィシャルアカウント http://a0.twimg.com/profile_images/379668735/square_logo_normal.png https://si0.twimg.com/profile_images/379668735/square_logo_normal.png http://www.tdiary.org/ false 286 FFFFFF 333333 0084B4 D0FFD0 D0FFD0 261 Fri Aug 14 07:50:23 +0000 2009 3 32400 Tokyo http://a0.twimg.com/images/themes/theme1/bg.png https://si0.twimg.com/images/themes/theme1/bg.png false false false false 313 ja false 31 false false false Mon Sep 17 00:04:52 +0000 2012 247486242491604992 RT @hsbt: DefaultIO から RdbIO へのインポータできた #tdiary <a href="http://www.crowy.net/" rel="nofollow">Crowy</a> false false 2 false Mon Sep 17 00:01:16 +0000 2012 247485333179101185 DefaultIO から RdbIO へのインポータできた #tdiary <a href="http://mzp.github.com/atig/" rel="nofollow">atig.rb</a> false false 2 false tdiary-contrib-3.2.2/spec/gist_spec.rb000066400000000000000000000007541213632744000177170ustar00rootroot00000000000000$:.unshift(File.dirname(__FILE__)) require 'spec_helper' describe "gist plugin" do DUMMY_GIST_ID = 1234567890 it 'should render javascript tag with specified gist-id' do plugin = fake_plugin(:gist) snippet = plugin.gist(DUMMY_GIST_ID) expected = (<<-EOS).chomp EOS snippet.should == expected end end tdiary-contrib-3.2.2/spec/github_link_spec.rb000066400000000000000000000023011213632744000212360ustar00rootroot00000000000000$:.unshift(File.dirname(__FILE__)) require 'spec_helper' describe "github link plugin" do let(:plugin) { fake_plugin(:github_link) } subject { plugin.gh_link(*args) } describe 'repository page' do let(:args) { ['tdiary/tdiary-contrib'] } it 'should render repository a tag' do should == %(tdiary-contrib) end end describe 'issues page' do let(:args) { ['tdiary/tdiary-contrib#100'] } it 'should render issues a tag' do should == %(tdiary-contrib#100) end end context "When given altenative text" do let(:text) { 'This project' } let(:github_identifier) { 'tdiary/tdiary-contrib' } let(:args) { [github_identifier, text] } it 'should render repository a tag with the specified text' do should == %(#{text}) end context "but the text is including ' } it 'should render a link text after sanitizing.' do should_not == %(#{text}) end end end end tdiary-contrib-3.2.2/spec/google_analytics_spec.rb000066400000000000000000000027601213632744000222730ustar00rootroot00000000000000$:.unshift(File.dirname(__FILE__)) require 'spec_helper' describe "google_analytics plugin" do def setup_google_analytics_plugin(profile_id, mode) fake_plugin(:google_analytics) { |plugin| plugin.mode = mode plugin.conf['google_analytics.profile'] = profile_id } end describe "should render javascript" do before do @plugin = setup_google_analytics_plugin('53836-1', 'latest') end it "for footer" do snippet = @plugin.footer_proc snippet.should == expected_html_footer_snippet end end describe "should render javascript" do before do @plugin = setup_google_analytics_plugin('53836-1', 'conf') end it "for footer" do snippet = @plugin.footer_proc snippet.should be_empty end end describe "should not render when profile_id is empty" do before do @plugin = setup_google_analytics_plugin(nil, 'latest') end it "for footer" do snippet = @plugin.footer_proc snippet.should be_empty end end def expected_html_footer_snippet expected = <<-SCRIPT SCRIPT expected.gsub( /^\t/, '' ).chomp end end tdiary-contrib-3.2.2/spec/jdate_spec.rb000066400000000000000000000007651213632744000200420ustar00rootroot00000000000000# -*- coding: utf-8 -*- $:.unshift(File.dirname(__FILE__)) require 'spec_helper' require 'time' describe "jdate plugin" do { '20080121' => '月', '20080122' => '火', '20080123' => '水', '20080124' => '木', '20080125' => '金', '20080126' => '土', '20080127' => '日', }.each do |k,v| it { setup_jdate_plugin(Time.parse(k)).date.strftime('%J').should == v } end def setup_jdate_plugin(date) fake_plugin(:jdate) {|plugin| plugin.date = date} end end tdiary-contrib-3.2.2/spec/jmonth_spec.rb000066400000000000000000000012711213632744000202430ustar00rootroot00000000000000# -*- coding: utf-8 -*- $:.unshift(File.dirname(__FILE__)) require 'spec_helper' require 'time' describe "jmonth plugin" do { '2007/01/01' => '睦月', '2007/02/01' => '如月', '2007/03/01' => '弥生', '2007/04/01' => '卯月', '2007/05/01' => '皐月', '2007/06/01' => '水無月', '2007/07/01' => '文月', '2007/08/01' => '葉月', '2007/09/01' => '長月', '2007/10/01' => '神無月', '2007/11/01' => '霜月', '2007/12/01' => '師走' }.each do |k,v| it { setup_jmonth_plugin(Time.parse(k)).date.strftime('%i').should == v } end def setup_jmonth_plugin(date) fake_plugin(:jmonth) { |plugin| plugin.date = date } end end tdiary-contrib-3.2.2/spec/jyear_spec.rb000066400000000000000000000007541213632744000200630ustar00rootroot00000000000000# -*- coding: utf-8 -*- $:.unshift(File.dirname(__FILE__)) require 'spec_helper' require 'time' describe "jyear plugin" do { '1925/01/01' => '昔々', '1926/12/25' => '昭和元年', '1927/01/01' => '昭和2', '1989/01/08' => '平成元年', '1990/01/01' => '平成2', }.each do |k,v| it { setup_jyear_plugin(Time.parse(k)).date.strftime('%K').should == v } end def setup_jyear_plugin(date) fake_plugin(:jyear) { |plugin| plugin.date = date } end end tdiary-contrib-3.2.2/spec/my_hotentry_spec.rb000066400000000000000000000034751213632744000213350ustar00rootroot00000000000000# -*- coding: utf-8 -*- $:.unshift(File.dirname(__FILE__)) require 'spec_helper' require 'tmpdir' require 'fileutils' describe "MyHotEntry" do def cache_filename "#{File.basename(__FILE__, ".rb")}-#{$$}" end before(:each) do fake_plugin(:my_hotentry) @cache_path = File.join(Dir.tmpdir, cache_filename) Dir.mkdir(@cache_path) @dbfile = "#{@cache_path}/my_hotentry.dat" @base_url = 'http://d.hatena.ne.jp/' @hotentry = MyHotEntry.new(@dbfile) end after(:each) do FileUtils.rmtree(@cache_path) end describe "#update" do before do @hotentry.update(@base_url) @entries = @hotentry.entries end it "キャッシュファイルが生成されていること" do File.should be_file(@dbfile) end it "人気の日記が取得できていること" do @entries.size.should > 0 end it "取得したエントリにbase_urlとタイトルが含まれていること" do @entries.each do |entry| entry[:url].should be_include(@base_url) entry[:title].size.should > 0 end end end describe "何度もupdateした場合" do before do @hotentry.update(@base_url) @original_entry_size = @hotentry.entries.size @hotentry.update(@base_url) @entry_size = @hotentry.entries.size end it "キャッシュサイズが大きくならないこと" do @entry_size.should == @original_entry_size end end describe "取得結果が空の場合" do before do @exist_url = 'http://d.hatena.ne.jp/' @empty_url = 'http://empty-url.example.com/' end it "キャッシュをクリアしないこと" do @hotentry.update(@empty_url) @hotentry.entries.size.should == 0 @hotentry.update(@exist_url) @hotentry.entries.size.should > 0 exist_size = @hotentry.entries.size @hotentry.update(@empty_url) @hotentry.entries.size.should == exist_size end end end tdiary-contrib-3.2.2/spec/openid_spec.rb000066400000000000000000000153621213632744000202300ustar00rootroot00000000000000$:.unshift(File.dirname(__FILE__)) require 'spec_helper' describe "openid plugin w/" do def setup_open_id_plugin(service, userid) fake_plugin(:openid) { |plugin| plugin.mode = 'latest' plugin.conf['openid.service'] = service plugin.conf['openid.id'] = userid } end describe "Hatena" do before do plugin = setup_open_id_plugin('Hatena', 'tdtds') @header_snippet = plugin.header_proc end it { @header_snippet.should include_link_tag_with( :rel => 'openid.server', :href => 'https://www.hatena.ne.jp/openid/server')} it { @header_snippet.should include_link_tag_with( :rel => 'openid.delegate', :href => 'http://www.hatena.ne.jp/tdtds/')} end describe "livedoor" do before do plugin = setup_open_id_plugin('livedoor', 'tdtds') @header_snippet = plugin.header_proc end it { @header_snippet.should include_link_tag_with( :rel => 'openid.server', :href => 'http://auth.livedoor.com/openid/server')} it { @header_snippet.should include_link_tag_with( :rel => 'openid.delegate', :href => 'http://profile.livedoor.com/tdtds')} end describe "LiveJournal" do before do plugin = setup_open_id_plugin('LiveJournal', 'tdtds') @header_snippet = plugin.header_proc end it { @header_snippet.should include_link_tag_with( :rel => 'openid.server', :href => 'http://www.livejournal.com/openid/server.bml')} it { @header_snippet.should include_link_tag_with( :rel => 'openid.delegate', :href => 'http://tdtds.livejournal.com/')} end describe "OpenID.ne.jp" do before do plugin = setup_open_id_plugin('OpenID.ne.jp', 'tdtds') @header_snippet = plugin.header_proc end it { @header_snippet.should include_link_tag_with( :rel => 'openid.server', :href => 'http://www.openid.ne.jp/user/auth')} it { @header_snippet.should include_link_tag_with( :rel => 'openid.delegate', :href => 'http://tdtds.openid.ne.jp')} it { @header_snippet.should include_xrds_meta_tag_with( :content => 'http://tdtds.openid.ne.jp/user/xrds')} end describe "TypeKey" do before do plugin = setup_open_id_plugin('TypeKey', 'tdtds') @header_snippet = plugin.header_proc end it { @header_snippet.should include_link_tag_with( :rel => 'openid.server', :href => 'http://www.typekey.com/t/openid/')} it { @header_snippet.should include_link_tag_with( :rel => 'openid.delegate', :href => 'http://profile.typekey.com/tdtds/')} end describe "Vox" do before do plugin = setup_open_id_plugin('Vox', 'tdtds') @header_snippet = plugin.header_proc end it { @header_snippet.should include_link_tag_with( :rel => 'openid.server', :href => 'http://www.vox.com/services/openid/server')} it { @header_snippet.should include_link_tag_with( :rel => 'openid.delegate', :href => 'http://tdtds.vox.com/')} end describe "myopenid.com" do before do @plugin = setup_open_id_plugin('myopenid.com', 'tdtds') @header_snippet = @plugin.header_proc end it { @header_snippet.should include_xrds_meta_tag_with( :content => "http://www.myopenid.com/xrds?username=tdtds")} it { @header_snippet.should include_link_tag_with( :rel => "openid.server", :href => "http://www.myopenid.com/server")} it { @header_snippet.should include_link_tag_with( :rel => "openid.delegate", :href => "http://tdtds.myopenid.com")} it { @header_snippet.should include_link_tag_with( :rel => "openid2.provider", :href => "http://www.myopenid.com/server")} it { @header_snippet.should include_link_tag_with( :rel => "openid2.local_id", :href => "http://tdtds.myopenid.com")} end describe "claimID.com" do before do @plugin = setup_open_id_plugin('claimID.com', 'tdtds') @header_snippet = @plugin.header_proc end it { @header_snippet.should include_xrds_meta_tag_with( :content => "http://claimid.com/tdtds/xrds")} it { @header_snippet.should include_link_tag_with( :rel => "openid.server", :href => "http://openid.claimid.com/server")} it { @header_snippet.should include_link_tag_with( :rel => "openid.delegate", :href => "http://openid.claimid.com/tdtds")} end describe "Personal Identity Provider (PIP)" do before do @plugin = setup_open_id_plugin('Personal Identity Provider (PIP)', 'tdtds') @header_snippet = @plugin.header_proc end it { @header_snippet.should include_xrds_meta_tag_with( :content => "http://pip.verisignlabs.com/user/tdtds/yadisxrds")} it { @header_snippet.should include_link_tag_with( :rel => "openid.server", :href => "http://pip.verisignlabs.com/server")} it { @header_snippet.should include_link_tag_with( :rel => "openid.delegate", :href => "http://tdtds.pip.verisignlabs.com/")} it { @header_snippet.should include_link_tag_with( :rel => "openid2.provider", :href => "http://pip.verisignlabs.com/server")} it { @header_snippet.should include_link_tag_with( :rel => "openid2.local_id", :href => "http://tdtds.pip.verisignlabs.com/")} end describe "Yahoo! Japan" do before do plugin = setup_open_id_plugin('Yahoo! Japan', 'tdtds') @header_snippet = plugin.header_proc end it { @header_snippet.should include_link_tag_with( :rel => 'openid2.provider', :href => 'https://open.login.yahooapis.jp/openid/op/auth')} it { @header_snippet.should include_link_tag_with( :rel => 'openid2.local_id', :href => 'https://me.yahoo.co.jp/a/tdtds')} it { @header_snippet.should_not include_link_tag_with( :rel => "openid.server")} it { @header_snippet.should_not include_link_tag_with( :rel => "openid.delegate")} end describe "Yahoo!" do before do plugin = setup_open_id_plugin('Yahoo!', 'tdtds') @header_snippet = plugin.header_proc end it { @header_snippet.should include_link_tag_with( :rel => 'openid2.provider', :href => 'https://open.login.yahooapis.com/openid/op/auth')} it { @header_snippet.should include_link_tag_with( :rel => 'openid2.local_id', :href => 'https://me.yahoo.com/a/tdtds')} it { @header_snippet.should_not include_link_tag_with( :rel => "openid.server")} it { @header_snippet.should_not include_link_tag_with( :rel => "openid.delegate")} end RSpec::Matchers.define :include_link_tag_with do |options| description do "include #{options[:rel]} link tag" end match do |actual| expected = %|| if options[:href] actual.include?( expected ) end end RSpec::Matchers.define :include_xrds_meta_tag_with do |options| description do "include XRDS meta tag" end match do |actual| expected = (<<-"EOS").chomp EOS actual.include?( expected ) end end end tdiary-contrib-3.2.2/spec/opensearch_ad_spec.rb000066400000000000000000000026041213632744000215400ustar00rootroot00000000000000$:.unshift(File.dirname(__FILE__)) require 'spec_helper' describe "opensearch_ad plugin w/" do def setup_opensearch_ad_plugin(title, xml, mode) fake_plugin(:opensearch_ad) { |plugin| plugin.mode = mode plugin.conf['opensearch.title'] = title plugin.conf['opensearch.xml'] = xml } end describe "in day mode" do before do plugin = setup_opensearch_ad_plugin('OpenSearch', 'http://example.com/opensearch.xml', 'day') @header_snippet = plugin.header_proc end it { @header_snippet.should == expected_link_tag_with( :title => 'OpenSearch', :xml => 'http://example.com/opensearch.xml')} end describe "in latest mode" do before do plugin = setup_opensearch_ad_plugin('OpenSearch', 'http://example.com/opensearch.xml', 'latest') @header_snippet = plugin.header_proc end it { @header_snippet.should == expected_link_tag_with( :title => 'OpenSearch', :xml => 'http://example.com/opensearch.xml')} end describe "in edit mode" do before do plugin = setup_opensearch_ad_plugin('OpenSearch', 'http://example.com/opensearch.xml', 'edit') @header_snippet = plugin.header_proc end it { @header_snippet.should be_empty } end def expected_link_tag_with(options) result = <<-HTML HTML result.gsub( /^\t/, '' ).chomp end end tdiary-contrib-3.2.2/spec/profile_spec.rb000066400000000000000000000054461213632744000204140ustar00rootroot00000000000000# -*- coding: utf-8 -*- require 'spec_helper' require 'profile' describe "Profile::Service" do describe "GitHub" do before do require 'json' Profile::Service::GitHub.any_instance.stub(:fetch).and_return(JSON.parse(File.read("spec/fixtures/github.json"))) # workaround for run spec on various environment. require 'openssl' OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE # http://develop.github.com/p/general.html @profile = Profile::Service::GitHub.new("schacon", :size => 40) end it "should include name, mail, image properties" do @profile.name.should == "Scott Chacon" @profile.mail.should == "schacon@gmail.com" @profile.image.should == "http://www.gravatar.com/avatar/9375a9529679f1b42b567a640d775e7d.jpg?s=40" end end describe "Twitter" do before do Profile::Service::Twitter.any_instance.stub(:fetch).and_return(REXML::Document.new(File.read("spec/fixtures/twitter.xml"))) # http://twitter.com/tdiary @profile = Profile::Service::Twitter.new("tdiary") end it "should include name, description, image properties" do @profile.name.should == "tDiary.org" @profile.description.should == "tDiaryオフィシャルアカウント" @profile.image.should match(%r{^http://.*\.(png|jpg)$}) end end describe "FriendFeed" do before do Profile::Service::FriendFeed.any_instance.stub(:fetch).and_return(REXML::Document.new(File.read("spec/fixtures/friendfeed.xml"))) # http://friendfeed.com/api/documentation#summary @profile = Profile::Service::FriendFeed.new("bret") end it "should include name, description, image properties" do @profile.name.should == "Bret Taylor" @profile.description.should == "Ex-CTO of Facebook. Previously co-founder and CEO of FriendFeed. Programmer, food lover." @profile.image.should == "http://friendfeed-api.com/v2/picture/bret" end end describe "Gravatar" do # http://ja.gravatar.com/site/implement/url before do @profile = Profile::Service::Gravatar.new("iHaveAn@email.com") end it "should include image property" do @profile.image.should == "http://www.gravatar.com/avatar/3b3be63a4c2a439b013787725dfce802.jpg" end context 'with options' do before do @profile = Profile::Service::Gravatar.new("iHaveAn@email.com", :size => 40) end it "should specify size option" do @profile.image.should == "http://www.gravatar.com/avatar/3b3be63a4c2a439b013787725dfce802.jpg?s=40" end end end describe "Hatena" do before do @profile = Profile::Service::Hatena.new("kmachu") end it "should include image property" do @profile.image.should == "http://www.hatena.ne.jp/users/km/kmachu/profile.gif" end end end tdiary-contrib-3.2.2/spec/rcov.opts000066400000000000000000000000471213632744000172650ustar00rootroot00000000000000-x /var/lib/gem -x spec/spec_helper.rb tdiary-contrib-3.2.2/spec/spec_helper.rb000066400000000000000000000072661213632744000202350ustar00rootroot00000000000000# -*- coding: utf-8 -*- $:.unshift(File.expand_path(File.join(File.dirname(__FILE__), "..", "plugin"))) if ENV['COVERAGE'] == 'simplecov' require 'simplecov' SimpleCov.start do add_filter '/spec/' add_filter '/vendor/' end end require 'erb' # FIXME PluginFake in under construction. class PluginFake include ERB::Util attr_reader :conf attr_accessor :mode, :date def initialize @conf = Config.new @mode = "" @date = nil @header_procs = [] @footer_procs = [] @update_procs = [] @conf_procs = [] @body_enter_procs = [] @body_leave_procs = [] end def add_conf_proc( key, label, genre=nil, &block ) @conf_procs << block end def add_header_proc( block = Proc::new ) @header_procs << block end def add_footer_proc( block = Proc::new ) @footer_procs << block end def add_update_proc( block = Proc::new ) @update_procs << block end def conf_proc r = [] @conf_procs.each do |proc| r << proc.call end r.join.chomp end def header_proc r = [] @header_procs.each do |proc| r << proc.call end r.join.chomp end def footer_proc r = [] @footer_procs.each do |proc| r << proc.call end r.join.chomp end def add_body_enter_proc( block = Proc::new ) @body_enter_procs << block end def body_enter_proc( date ) r = [] @body_enter_procs.each do |proc| r << proc.call( date ) end r.join.chomp end def add_body_leave_proc( block = Proc::new ) @body_leave_procs << block end def body_leave_proc( date ) r = [] @body_leave_procs.each do |proc| r << proc.call( date ) end r.join.chomp end class Config attr_accessor :index, :html_title, :cgi def initialize @cgi = CGIFake.new @options = {} @options2 = {} @index = './' @html_title = '' bot = ["bot", "spider", "antenna", "crawler", "moget", "slurp"] bot += @options['bot'] || [] @bot = Regexp::new( "(#{bot.uniq.join( '|' )})", true ) end def []( key ) @options[key] end def []=( key, val ) @options2[key] = @options[key] = val end def delete( key ) @options.delete( key ) @options2.delete( key ) end def base_url begin if @options['base_url'].length > 0 then return @options['base_url'] end rescue end end def mobile_agent? @cgi.mobile_agent? end def smartphone? @cgi.iphone? end def bot? @bot =~ @cgi.user_agent end end def feed? false end def iphone? @conf.cgi.iphone? end alias ipod? iphone? end class CGIFake attr_accessor :user_agent def initialize @user_agent = "" end def mobile_agent? self.user_agent =~ %r[ ^DoCoMo| ^(?:KDDI|UP\.Browser)| ^(?:J-(?:PHONE|EMULATOR)|Vodafone|SoftBank|MOT-|[VS]emulator)| WILLCOM|DDIPOCKET| PDXGW|ASTEL|Palmscape|Xiino|sharp\ pda\ browser|Windows\ CE|L-mode ]x end def iphone? self.user_agent =~ /iP(?:hone|od)/ end end def fake_plugin( name_sym, cgi=nil, base=nil, &block ) plugin = PluginFake.new yield plugin if block_given? file_path = plugin_path( name_sym, base ) plugin_name = File.basename( file_path, ".rb" ) plugin.instance_eval do eval( File.read( file_path ), binding, "(#{File.basename(file_path)})", 1 ) end plugin_sym = plugin_name.to_sym if plugin.class.private_method_defined?( plugin_sym ) plugin.__send__( :public, plugin_sym ) end plugin end def plugin_path( plugin_sym, base=nil ) paths = [] paths << ( base ? base : "plugin" ) paths << "#{plugin_sym.to_s}.rb" File.expand_path( File.join( paths )) end def anchor( s ) if /^([\-\d]+)#?([pct]\d*)?$/ =~ s then if $2 then "?date=#$1##$2" else "?date=#$1" end else "" end end # Local Variables: # mode: ruby # indent-tabs-mode: t # tab-width: 3 # ruby-indent-level: 3 # End: # vim: ts=3 tdiary-contrib-3.2.2/spec/title_anchor_spec.rb000066400000000000000000000016311213632744000214170ustar00rootroot00000000000000$:.unshift(File.dirname(__FILE__)) require 'spec_helper' describe "title_anchor plugin" do def setup_title_anchor_plugin(mode) fake_plugin(:title_anchor) { |plugin| plugin.mode = mode plugin.conf.index = '' plugin.conf.html_title = "HsbtDiary" } end describe "in day mode" do before do @plugin = setup_title_anchor_plugin('day') end it { @plugin.title_anchor.should == expected_html_title_in_day( :index => '', :html_title => 'HsbtDiary')} end describe "in latest mode" do before do @plugin = setup_title_anchor_plugin('latest') end it { @plugin.title_anchor.should == expected_html_title_in_latest( :html_title => 'HsbtDiary')} end def expected_html_title_in_day(options) expected = %{

        #{options[:html_title]}

        } end def expected_html_title_in_latest(options) expected = %{

        #{options[:html_title]}

        } end end tdiary-contrib-3.2.2/spec/twitter_js_spec.rb000066400000000000000000000060711213632744000211450ustar00rootroot00000000000000$:.unshift(File.dirname(__FILE__)) require 'spec_helper' require 'time' describe "twitter_js plugin" do def setup_twitter_js_plugin(mode, user_id) fake_plugin(:twitter_js) { |plugin| plugin.mode = mode plugin.conf['twitter.user'] = user_id plugin.date = Time.parse("20080124") } end describe "should render javascript and div tag in day" do before do @plugin = setup_twitter_js_plugin("day", "123456789") end it "for header" do snippet = @plugin.header_proc snippet.should == expected_html_header_snippet("123456789") end it "for body leave" do snippet = @plugin.body_leave_proc(Time.parse("20080124")) snippet.should == expected_html_body_snippet end end describe "should render javascript and div tag in latest" do before do @plugin = setup_twitter_js_plugin("latest", "123456789") end it "for header" do snippet = @plugin.header_proc snippet.should == expected_html_header_snippet("123456789") end it "for body leave" do snippet = @plugin.body_leave_proc(Time.parse("20080124")) snippet.should == expected_html_body_snippet end end describe "should not render in edit" do before do @plugin = setup_twitter_js_plugin("edit", "123456789") end it "for header" do snippet = @plugin.header_proc snippet.should be_empty end it "for body leave" do snippet = @plugin.body_leave_proc(Time.parse("20080124")) snippet.should be_empty end end describe "should not render when user_id is empty" do before do @plugin = setup_twitter_js_plugin("edit", "") end it "for header" do snippet = @plugin.header_proc snippet.should be_empty end it "for body leave" do snippet = @plugin.body_leave_proc(Time.parse("20080124")) snippet.should be_empty end end def expected_html_header_snippet(user_id) expected = <<-EXPECTED EXPECTED expected.gsub(/^\t/, '').chomp end def expected_html_body_snippet expected = <<-HTML
        HTML expected.gsub( /^\t/, '' ).chomp end end tdiary-contrib-3.2.2/spec/youtube_spec.rb000066400000000000000000000020511213632744000204350ustar00rootroot00000000000000$:.unshift(File.dirname(__FILE__)) require 'spec_helper' describe "youtube plugin" do DUMMY_YOUTUBE_VIDEO_ID = 1234567890 { 'DoCoMo' => %||, 'iPhone' => %|\t\t\n\t\t\n|, 'Mozilla' => %|\t\t\n| }.each do |k,v| it 'should render object tag in :user_agent' do plugin = fake_plugin(:youtube) cgi = CGIFake.new cgi.user_agent = k plugin.conf.cgi = cgi plugin.youtube(DUMMY_YOUTUBE_VIDEO_ID).should == v end end end tdiary-contrib-3.2.2/style/000077500000000000000000000000001213632744000156125ustar00rootroot00000000000000tdiary-contrib-3.2.2/style/hatena_style.rb000066400000000000000000000623531213632744000206300ustar00rootroot00000000000000#!/usr/bin/env ruby -Ke # Copyright(c) 2004 URABE, Shyouhei. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this code, to deal in the code without restriction, including without # limitation the rights to use, copy, modify, merge, publish, distribute, # sublicense, and/or sell copies of the code, and to permit persons to whom the # code is furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the code. # # THE CODE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHOR OR COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE CODE OR THE USE OR OTHER DEALINGS IN THE # CODE. # $Id: hatena_style.rb,v 1.12 2007-02-27 06:57:14 kazuhiko Exp $ # Hatena::Diary compatible style # Works only under ruby 1.8.1 or later [ 'uri', 'net/http', 'cgi', 'pstore', 'time', ].each {|f| require f } class TDiary::HatenaDiary include TDiary::DiaryBase, TDiary::CategorizableDiary def initialize(date, title, body, modified=Time.now) init_diary @sections = [] replace date, title, body @last_modified = modified end def style 'Hatena' end def replace(date, title, body) set_date date set_title title @sections.clear append body end def append(body, author=nil) @sections.concat Hatena::Diary.parse(body, author) self end def each_section(&block) @sections.each(&block) end def to_src @sections.inject('') {|r, i| r << i.to_src } end def to_html(opt, mode=:HTML) j = 0 @sections.inject('') {|r, i| j += 1 r << '
        ' if mode != :CHTML r << i.convert(mode, date, j, opt) r << '
        ' if mode != :CHTML r } end def to_s sprintf('date=%s, title=%s, body=%s', date.strftime('%Y%m%d'), title, @sections.map {|i| '[%s]' % i}.join) end end # This is the namespace module module Hatena def Hatena.conf ObjectSpace.each_object do |diary| next unless diary.kind_of?(TDiary::TDiaryBase) return diary.instance_eval { @conf } end end Diary = Object.new API = Object.new # get a text of hatena-style, and convert it into parse tree. def Diary.parse(str, author) str.gsub(/\r(?!\n)/,"\n")\ .delete("\r")\ .gsub(/^\*/,'**')\ .split(/^\*/)\ .inject([]) {|r, i| i.empty? ? r : r << Hatena::Section.new(i, author) } end # find the cache_path from entore ruby world # could someone please tell me more eficient way to do this... def API.cache_path ret = Hatena.conf.cache_path || Hatena.conf.data_path + '/cache' unless FileTest.directory?(ret) begin Dir.mkdir(ret) rescue Errno::EEXIST ; # OK end end ret end def API.update_kw(kw) return false if File.exist?(kw) && Time.now - File.mtime(kw) < 86400 File.open(kw, IO::WRONLY|IO::CREAT) do |fp| break unless fp.flock(IO::LOCK_EX|IO::LOCK_NB) uri = ::URI.parse('http://d.hatena.ne.jp/images/keyword/keywordlist') timeout(60) do Net::HTTP.version_1_1 Net::HTTP.new(uri.host, uri.port).start do |http| res, body = http.get(uri.request_uri, {'User-Agent' => "tDiary/#{TDIARY_VERSION}"}) fp.seek(0, IO::SEEK_SET) fp.write(body) end end end true end def API.update_db(kw, db) raise if API.update_kw kw raise unless FileTest.exist? db.path false rescue str = File.open(kw, IO::RDONLY) do |fp| fp.flock(IO::LOCK_SH) fp.read end a = str.gsub(/\\s/,' ') \ .gsub(/\\(?!\|)/,'') \ .scan(/(?:[^|]|\\\|)*[^\\](?=\||\z)/) db.transaction do db['trie'] = Trie.new(a) end true end # The trie of keywords # Keywords are chached, chache expires every day (24h) def API.keywords path = API.cache_path kw = path + '/keywordlist' db = PStore.new(path + '/keywords.pstore') if API.update_db(kw, db) || @ret.nil? db.transaction(IO::RDONLY) do @ret = db['trie'] end end return @ret end end # Deterministic finate automata class Hatena::Trie private def add(kw) h = @hash1 kw.split(//e).each do |c| unless h.has_key? c tmp = Hash.new @ary << tmp h[c] = tmp end h = h[c] end @hash2[h] = kw end def initialize(a) @ary = Array.new @hash1 = Hash.new @hash2 = Hash.new a.each {|kw| add kw } end public def match(str) ret = nil h = @hash1 a = str.split(//e) i = 0 j = 0 while c = a[i + j] if h[c] h = h[c] if @hash2[h] ret = @hash2[h] end f = false j += 1 else return ret if ret h = @hash1 # reset i += 1 j = 0 end end return ret end end # -------- # Parser Tree Nodes class Hatena::Section def initialize(str, author) t = Time.now @author = author.freeze @src = str.gsub(/^\*t\*/, '*%d*' % t.to_i)\ .gsub(/<(ins|del)>/, '<\1 datetime="%s">' % t.xmlschema) @tree = Hatena::Block.new(@src) end def convert(mode, date, i, opt) @tree.convert(mode, date, i, opt, author) end def to_src @src end def categories @tree.title.categories end def author @author end def body @tree.body.to_s end def subtitle @tree.title.to_s end def stripped_subtitle @tree.title.strip.to_s end def body_to_html @tree.body.convert(:HTML) end def subtitle_to_html @tree.title.convert(:HTML) end def stripped_subtitle_to_html @tree.title.strip.convert(:HTML) end end # Block level elements class Hatena::Block attr_reader :to_s, :title, :body def initialize(str) # Too long. Needs refactoring. if str.nil? @title = Hatena::Title.new('') # dummy @body = Hatena::Inline.new('') # dummy @to_s = '' elsif str[0] == ?* t,b = *str.split(/\n/,2) @title = Hatena::Title.new(t) @body = Hatena::BlockAndorInline.new(b, false) @to_s = t + "\n" + (b||'') else @to_s = str @title = Hatena::Title.new('') # dummy @body = Hatena::BlockAndorInline.new(str, false) end end def convert(mode, date=nil, i=nil, opt=nil, author=nil) if title_is_dummy? @body.convert(mode) else @title.convert(mode, date, i, opt, author) + "\n" + @body.convert(mode) end end def title_is_dummy? @to_s[0] == ?* end end # Section subtitle class Hatena::Title attr_reader :to_s, :categories, :strip def initialize(str) if m = /\A\*([0-9]+)\*/.match(str) @time = Time.at(Integer(m[1])) @to_s = m.post_match.freeze elsif m = /\A\*([a-zA-Z0-9_]+)\*/.match(str) @name = m[1] @to_s = m.post_match.freeze else @to_s = (str[1..-1]||'').freeze end @categories = to_s.scan(/\[(.*?)\]/).map{|a| a[0] } @strip = Hatena::Inline.new(Regexp.last_match ? Regexp.last_match.post_match : to_s) end def convert(mode, date=nil, i=nil, opt=nil, author=nil) id = ('p%02d' % (i || 0)) h = '%0.32b' % rand(0x100000000) case when date.nil? categories.map {|i| "<%=category_anchor <<'#{h}'.chomp\n#{i}\n#{h}\n%>" }.join + strip.convert(mode) when mode == :CHTML sprintf('*%s%s', @name ? %Q{ ID"=#@name"} : '', id, (opt['multi_user'] && author) ? "[#{author}]" : '', strip.convert(mode)) else sprintf('#%s">%s%s%s%s %s', @name ? %Q{ id="#@name"} : '', opt['anchor'] ? 'name="%s" ' % id : '', opt['index'], date.strftime('%Y%m%d'), @name || id, opt['section_anchor'], categories.map {|cat| "<%=category_anchor <<'#{h}'.chomp\n#{cat}\n#{h}\n%>" }.join, (opt['multi_user'] && author) ? "[#{author}]" : '', strip.convert(mode), @time ? %Q!#{@time.strftime('%H:%M')}! : '') end end end # Sequence of block level elements and/or inline level elements # or sequence of block level elements only. class Hatena::BlockAndorInline def initialize(str, allowinline = true) @elems = Array.new pbuffer = '' # paragraph buffer flush_pbuffer = lambda{ next if pbuffer.empty? if allowinline @elems.push Hatena::Inline.new(pbuffer) else @elems.push Hatena::Paragraph.new(pbuffer) end pbuffer.replace('') } lines = str.concat("\n").scan(/.*\n/) until lines.empty? case when lines[0][0] == ?- flush_pbuffer.call buffer = '' until lines.empty? break unless lines[0][0] == ?- buffer.concat lines.shift end @elems.push Hatena::Itemize.new(buffer) when lines[0][0] == ?+ flush_pbuffer.call buffer = '' until lines.empty? break unless lines[0][0] == ?+ buffer.concat lines.shift end @elems.push Hatena::Enumerate.new(buffer) when lines[0][0] == ?: flush_pbuffer.call buffer = '' until lines.empty? break unless lines[0][0] == ?: break unless lines[0].rindex(?:) != 0 buffer.concat lines.shift end @elems.push Hatena::Description.new(buffer) when lines[0] == ">>\n" flush_pbuffer.call buffer = '' nest = 0 until lines.empty? nest += 1 if lines[0] == ">>\n" nest -= 1 if lines[0] == "<<\n" buffer.concat lines.shift break if nest <= 0 end @elems.push Hatena::Quote.new(buffer) when lines[0] == ">|\n" flush_pbuffer.call buffer = '' until lines.empty? str1 = lines.shift buffer.concat str1 break if /\|<$/ =~ str1 end @elems.push Hatena::Verbatim.new(buffer) when lines[0] == ">||\n" flush_pbuffer.call buffer = '' until lines.empty? str1 = lines.shift buffer.concat str1 break if /\|\|<$/ =~ str1 end @elems.push Hatena::SuperVerbatim.new(buffer) when lines[0][0,5] == '><$/ =~ lines.shift end when lines[0][0,2] == '><' flush_pbuffer.call buffer = '' until lines.empty? str1 = lines.shift buffer.concat str1 break if /><$/ =~ str1 end @elems.push Hatena::UnParagraph.new(buffer) else pbuffer.concat lines.shift if pbuffer[-3..-1] == "\n\n\n" flush_pbuffer.call end end end flush_pbuffer.call end def convert(mode) @elems.inject('') {|r, i| r << i.convert(mode) << "\n" } end end # Itemize # extension to Hatena: nest can be more than 3 level. class Hatena::Itemize def initialize(str) @elems = Array.new lines = str.gsub(/^-/,'').scan(/.*\n/) buffer = '' until lines.empty? case when lines[0][0] == ?- until lines.empty? break unless lines[0][0] == ?- buffer.concat lines.shift end @elems.push Hatena::BlockAndorInline.new(buffer) buffer = '' when lines[0][0] == ?+ until lines.empty? break unless lines[0][0] == ?+ buffer.concat lines.shift end @elems.push Hatena::BlockAndorInline.new(buffer) buffer = '' when lines[0][0] == ?: until lines.empty? break unless lines[0][0] == ?: break unless lines[0].rindex(?:) != 0 buffer.concat lines.shift end @elems.push Hatena::BlcokAndorInline.new(buffer) buffer = '' else @elems.push Hatena::Inline.new(buffer) unless buffer.empty? buffer = lines.shift end end @elems.push Hatena::Inline.new(buffer) unless buffer.empty? end def convert(mode) template = nil if mode == :CHTML template = ["
          %s\n
        ", "\n
      • %s
      • "] else template = ["
          %s\n
        ", "\n
      • %s
      • "] end template[0] % @elems.inject('') {|r, i| r << template[1] % i.convert(mode) } end end # Enumerate # Extension to Hatena: nest can be more than 3 level class Hatena::Enumerate def initialize(str) @elems = Array.new lines = str.gsub(/^\+/,'').scan(/.*\n/) buffer = '' until lines.empty? case when lines[0][0] == ?- until lines.empty? break unless lines[0][0] == ?- buffer.concat lines.shift end @elems.push Hatena::BlockAndorInline.new(buffer) buffer = '' when lines[0][0] == ?+ until lines.empty? break unless lines[0][0] == ?+ buffer.concat lines.shift end @elems.push Hatena::BlockAndorInline.new(buffer) buffer = '' when lines[0][0] == ?: until lines.empty? break unless lines[0][0] == ?: break unless lines[0].rindex(?:) != 0 buffer.concat lines.shift end @elems.push Hatena::BlcokAndorInline.new(buffer) buffer = '' else @elems.push Hatena::Inline.new(buffer) unless buffer.empty? buffer = lines.shift end end @elems.push Hatena::Inline.new(buffer) unless buffer.empty? end def convert(mode) template = nil if mode == :CHTML template = ["
          %s\n
        ", "\n
      • %s
      • "] else template = ["
          %s\n
        ", "\n
      • %s
      • "] end template[0] % @elems.inject('') {|r, i| r << template[1] % i.convert(mode) } end end # Description list # Extension to hatena : term only and descriotion only are OK # :term: # ::desc # Extension to Hatena : can be combined with lists class Hatena::Description def initialize(str) @elems = Array.new str.each_line do |l| raise SyntaxError unless l[0] == ?: l = l[1..-1] buffer = '' # while l =~ /[^:]*#{URI.regexp}/o # buffer.concat Regexp.last_match.to_s # l = Regexp.last_match.post_match # end dt,dd = *l.split(/:/,2) buffer.concat dt @elems.push([ buffer.empty? ? nil : Hatena::Inline.new(buffer), (dd.nil? || dd.empty?) ? nil : Hatena::Inline.new(dd) ]) end end def convert(mode) template = nil if mode == :CHTML template = ["
        %s\n
        ", "\n
        %s
        ", "
        %s
        "] else template = ["
        %s\n
        ", "\n
        %s
        ", "
        %s
        "] end template[0] % @elems.inject('') {|r, i| r << template[1] % i[0].convert(mode) unless i[0].nil? r << template[2] % i[1].convert(mode) unless i[1].nil? r } end end # block level quote # Extension to hatena : nest can be more than 2 level. class Hatena::Quote def initialize(str) @elems = Hatena::Block.new(str[3..-4]) end def convert(mode) template = nil if mode == :CHTML template = "
        \n%s\n
        " else template = "
        \n%s\n
        " end sprintf(template,@elems.convert(mode)) end end # preformatted text class Hatena::Verbatim def initialize(str) @str = str[3..-4].freeze end def convert(mode) template = nil if mode == :CHTML template = "
        %s
        " else template = "
        %s
        " end sprintf(template,CGI.escapeHTML(@str)) end end # preformatted text class Hatena::SuperVerbatim def initialize(str) @str = str[3..-5].freeze end def convert(mode) template = nil if mode == :CHTML template = "
        %s
        " else template = "
        %s
        " end sprintf(template,CGI.escapeHTML(@str)) end end # non-paragraph blocklevel class Hatena::UnParagraph def initialize(str) @elems = Hatena::Inline.new(str[1..-3]) # 0123... # >
        # ... ... # ...
        <\n # ...-321 end def convert(mode) @elems.convert(mode) end end # paragraph # Extension to Hatena: not using
        but begins next paragraph class Hatena::Paragraph def initialize(str) @elems = Hatena::Inline.new(str.gsub(/\n\n\n/,'')) end def convert(mode) template = nil if mode == :CHTML template = "

        \n%s\n

        " else template = "

        \n%s\n

        " end sprintf(template, @elems.convert(mode)) end end # inline elements class Hatena::Inline def initialize(str) @elems = Array.new inside_a = false return if str == "\n" until str.empty? case str when /\A\[\](.*?)\[\]/m @elems.push Hatena::CDATA.new(Regexp.last_match[1]) when /\A\)\(\((.*?)\)\)\(/m, /\A\(\(\((.*?)\)\)\)/m @elems.push Hatena::CDATA.new('((') @elems.push Hatena::Inline.new(Regexp.last_match[1]) @elems.push Hatena::CDATA.new('))') when /\A\(\((.*?)\)\)/m @elems.push Hatena::Footnote.new(Regexp.last_match[1]) when /\A#{tag_regex}/o @elems.push Hatena::TAG.new(Regexp.last_match.to_s) if str.index("") == 0 inside_a = false end when /\A\[amazon:(.*?)\]/m @elems.push Hatena::AmazonSearch.new(Regexp.last_match[1], true) when /\A\[google:(.*?)\]/m @elems.push Hatena::Google.new(Regexp.last_match[1], true) when /\A\[(?:(#{gid_regex}):)?keyword:(.*?)\]/m, /\A\[\[(.*?)\]\]/m group, keyword = Regexp.last_match.captures @elems.push Hatena::Keyword.new(group, keyword, true) when /\A\[(?:(#{gid_regex}|[ad]):)?id:([a-zA-Z][-a-zA-Z0-9_]{1,30}[a-zA-Z0-9])\]/m, /\A(?:(#{gid_regex}|[ad]):)?id:([a-zA-Z][-a-zA-Z0-9_]{1,30}[a-zA-Z0-9](?::(?:[0-9]+|about))?)/ sid, id = Regexp.last_match.captures @elems.push Hatena::ID.new(sid, id, true) when /\A\[(?i:ISBN|ASIN):(.*?)(?::image(?::(?:small|large))?)?\]/m, /(?i:ISBN|ASIN):([-0-9A-Za-z]+)(?::image(?::(?:small|large))?)?/ @elems.push Hatena::Amazon.new(Regexp.last_match[1], true) when /\A\[tex:(.*?)\]/m @elems.push Hatena::TeX.new(Regexp.last_match[1]) when /\A#{gid_regex}/ @elems.push Hatena::Group.new(Regexp.last_match.to_s, true) when /\A\[((?i:https?|ftp|mailto):.+?)\]/m, /\A(#{URI.regexp})/o @elems.push Hatena::URI.new(Regexp.last_match[1]) else /.+?(?=[\[\]()<>]|(?i:https?|ftp|mailto|id|ISBN|ASIN)|[adg]:|$)/m =~ str if inside_a @elems.push Hatena::CDATA.new(Regexp.last_match.to_s) else @elems.push Hatena::Sentence.new(Regexp.last_match.to_s) end end str = Regexp.last_match.post_match end end def convert(mode) @elems.inject('') {|r, i| r << i.convert(mode) } end private # tag_regex was quoted from http://www.din.or.jp/~ohzaki/perl.htm#HTML_Tag def tag_regex /<[^"'<>]*(?:"[^"]*"[^"'<>]*|'[^']*'[^"'<>]*)*(?:>|(?=<)|$)/ end def gid_regex /g:[a-zA-Z][a-zA-Z0-9]{2,23}/ end end # String that surely doesn't contain any keywords # String that can contain keyword is a Sentence class Hatena::CDATA def initialize(str) @str = str.freeze end def convert(mode) @str end end # footnote # footnote.rb required class Hatena::Footnote def initialize(str) @str = str @heredoc = rand(0x100000000) end def convert(mode) sprintf("<%%=fn <<'%0.32b'.chomp\n%s\n%0.32b\n%%>", @heredoc, @str, @heredoc) end end # HTML tags # Disadvantanegs from hatena : is not supported # Extension to Hatena : ERB expression can be written class Hatena::TAG def initialize(str) @elems = Array.new return if /', @str, @str.delete('-')) # %= else sprintf('http://www.amazon.co.jp/exec/obidos/ASIN/%s/%s', @str, Hatena.conf['amazon.aid'] || '') end end end # Amazon search # http://d.hatena.ne.jp/hatenadiary/20040310#1078879113 class Hatena::AmazonSearch def initialize(str, tag_p) @str = str @tag_p = tag_p end def convert(mode) uri = 'http://www.amazon.co.jp/exec/obidos/external-search?mode=blended&tag=%s&encoding-string-jp=%%c6%%fc%%cb%%dc%%b8%%ec&keyword=%s' % [Hatena.conf['amazon.aid'] || '', URI.escape(@str, /[^-_.!~*'()a-zA-Z0-9]/)] return uri unless @tag_p template=nil if mode == :CHTML template = 'amazon:%s' else template = 'amazon:%s' end sprintf(template, uri, @str) end end # TeX expressoin # texdiary http://kumamushi.org/~k/texdiary/ required class Hatena::TeX def initialize(expr) @expr end def convert(mode) sprintf('<%%=eq "%s"%%>' % @expr) #%= end end # String that can contain keywords # String that cannot contain keywords is a CDATA class Hatena::Sentence def initialize(str) @elems = Array.new return if str.nil? || str.empty? if false # kw = Hatena::API.keywords.match(str) m = Regexp.new(Regexp.quote(kw)).match(str) @elems.push Hatena::CDATA.new(m.pre_match) @elems.push Hatena::Keyword.new(nil, kw, true) @elems.push Hatena::Sentence.new(m.post_match) else @elems.push Hatena::CDATA.new(str) end end def convert(mode) @elems.inject('') {|r, i| r << i.convert(mode) } end end # Local Variables: # mode: ruby # code: euc-jp-unix # End: tdiary-contrib-3.2.2/style/markdown_style.rb000066400000000000000000000125261213632744000212070ustar00rootroot00000000000000# # markdown_style.rb: Markdown style for tDiary 2.x format. $Revision: 1.10 $ # # if you want to use this style, add @style into tdiary.conf below: # # @style = 'Markdown' # # Copyright (C) 2003, TADA Tadashi # Copyright (C) 2004, MoonWolf # You can distribute this under GPL. # require 'bluecloth' module TDiary class MarkdownSection attr_reader :subtitle, :author attr_reader :categories, :stripped_subtitle attr_reader :subtitle_to_html, :stripped_subtitle_to_html, :body_to_html def initialize( fragment, author = nil ) @author = author @subtitle, @body = fragment.split( /\n/, 2 ) @subtitle.sub!(/^\#\s*/,'') @body ||= '' @categories = get_categories @stripped_subtitle = strip_subtitle @subtitle_to_html = @subtitle ? to_html('# ' + @subtitle).gsub(/\A|<\/h\d>\z/io, '') : nil @stripped_subtitle_to_html = @stripped_subtitle ? to_html('# ' + @stripped_subtitle).gsub(/\A|<\/h\d>\z/io, '') : nil @body_to_html = to_html(@body) end def subtitle=(subtitle) @categories = categories cat_str = "" categories.each {|cat| cat_str << "[#{cat}]" } @subtitle = (subtitle || '').sub(/^# /,"\##{cat_str} ") @strip_subtitle = strip_subtitle end def body @body.dup end def body=(str) @body = str end def categories=(categories) @categories = categories cat_str = "" categories.each {|cat| cat_str << "[#{cat}]" } @subtitle = "#{cat_str} " + (strip_subtitle || '') @strip_subtitle = strip_subtitle end def to_src r = '' r << "\##{@subtitle}\n" if @subtitle r << @body end def html4( date, idx, opt ) r = %Q[
        \n] r << do_html4( date, idx, opt ) r << "
        \n" end def do_html4( date, idx, opt ) r = '' subtitle = to_html('# ' + @subtitle) subtitle = subtitle.sub(/(\[([^\[]+?)\])+/) { $&.gsub(/\[(.*?)\]/) { $1.split(/,/).collect {|c| %Q|<%= category_anchor("#{c}") %>| }.join } } subtitle.sub!(/

        /,%Q[

        ">#{opt['section_anchor']} ]) if opt['anchor'] then subtitle.sub!(/

        /,%Q|[#{@author}]

        |) end r << subtitle r << @body_to_html r end def chtml( date, idx, opt ) r = '' r << to_html(@subtitle) r << @body_to_html r end def to_s to_src end private def to_html(string) r = BlueCloth.new( string ).to_html r.gsub!(/" } r end def get_categories return [] unless @subtitle cat = /(\\?\[([^\[]+?)\\?\])+/.match(@subtitle).to_a[0] return [] unless cat cat.scan(/\\?\[(.*?)\\?\]/).collect do |c| c[0].split(/,/) end.flatten end def strip_subtitle return nil unless @subtitle r = @subtitle.sub(/^((\\?\[[^\[]+?\]\\?)+\s+)?/, '') if r.empty? nil else r end end end class MarkdownDiary include DiaryBase include CategorizableDiary def initialize( date, title, body, modified = Time::now ) init_diary replace( date, title, body ) @last_modified = modified end def style 'Markdown' end def replace( date, title, body ) set_date( date ) set_title( title ) @sections = [] append( body ) end def append( body, author = nil ) section = nil body.each_line do |l| case l when /^\#[^\#]/ @sections << MarkdownSection::new( section, author ) if section section = l else section = '' unless section section << l end end if section section << "\n" unless section=~/\n\n\z/ @sections << MarkdownSection::new( section, author ) end @last_modified = Time::now self end def each_section @sections.each do |section| yield section end end def add_section(subtitle, body) sec = MarkdownSection::new("\n") sec.subtitle = subtitle sec.body = body @sections << sec @sections.size end def delete_section(index) @sections.delete_at(index - 1) end def to_src r = '' each_section do |section| r << section.to_src end r end def to_html( opt, mode = :HTML ) case mode when :CHTML to_chtml( opt ) else to_html4( opt ) end end def to_html4( opt ) r = '' idx = 1 each_section do |section| r << section.html4( date, idx, opt ) idx += 1 end r end def to_chtml( opt ) r = '' idx = 1 each_section do |section| r << section.chtml( date, idx, opt ) idx += 1 end r end def to_s "date=#{date.strftime('%Y%m%d')}, title=#{title}, body=[#{@sections.join('][')}]" end end end tdiary-contrib-3.2.2/style/wikiext_style.rb000066400000000000000000000006201213632744000210410ustar00rootroot00000000000000# wikiext_style.rb: when using wiki style, extends behavior. # # Just place this file into tdiary/style directory. # # Copyright (C) 2012, kdmsnr # You can distribute this under GPL. # module TDiary class WikiextDiary # dummy class end end require "hikidoc" class HikiDoc class HTMLOutput def paragraph(lines) @f.puts "

        #{lines.join("")}

        " end end end tdiary-contrib-3.2.2/util/000077500000000000000000000000001213632744000154275ustar00rootroot00000000000000tdiary-contrib-3.2.2/util/clean-spam/000077500000000000000000000000001213632744000174475ustar00rootroot00000000000000tdiary-contrib-3.2.2/util/clean-spam/README.ja000066400000000000000000000000721213632744000207170ustar00rootroot00000000000000See http://www.namazu.org/~satoru/diary/20040923.html#p01 tdiary-contrib-3.2.2/util/clean-spam/tdiary-comment-clean000077500000000000000000000016651213632744000234210ustar00rootroot00000000000000#!/usr/bin/env ruby # # Copyright (C) 2004 Satoru Takabayashi # You can redistribute it and/or modify it under GPL2. # puts "Usage: tdiary-comment-clean PATTERN FILE..." if ARGV.length == 0 pattern = Regexp.new(ARGV.shift) file_names = ARGV deleted_comments = [] file_names.each {|file_name| i = File.open(file_name) first_line = i.gets comments = [] comment = "" while line = i.gets if line == ".\n" comments.push(comment) comment = "" else comment << line end end i.close tmp_name = "tmp.#{Process.pid}" File.open(tmp_name, "w") {|o| o.print first_line comments.each {|comment| if pattern.match(comment) deleted_comments.push(comment) else o.print comment o.puts "." end } } File.rename(file_name, file_name + ".bak") File.rename(tmp_name, file_name) } deleted_comments.each {|comment| print comment puts "." } tdiary-contrib-3.2.2/util/clean-spam/tdiary-comment-clean2000077500000000000000000000033321213632744000234740ustar00rootroot00000000000000#!/usr/bin/env ruby # # Copyright (C) 2004 Satoru Takabayashi # You can redistribute it and/or modify it under GPL2. # # Modified by machu ( http://www.machu.jp/diary/ ) # 2008-03-07: adding last-modified filter with -a and -b option # require 'optparse' after_date = Time.at(0) before_date = Time.now test = false opt = OptionParser.new opt.on('-a AFTER_HOUR') {|v| after_date = Time.at(Time.now - 60 * 60 * v.to_i) } opt.on('-b BEFORE_HOUR') {|v| before_date = Time.at(Time.now - 60 * 60 * v.to_i) } opt.on('-t') {|v| test = true } opt.parse!(ARGV) puts "Usage: tdiary-comment-clean [-a AFTER_HOUR] [-b BEFORE_HOUR] PATTERN FILE..." if ARGV.length == 0 pattern = Regexp.new(ARGV.shift) file_names = ARGV class Comment attr_accessor :body, :date def initialize @body = "" end def <<(body) if body.match(/^Last-Modified: (\d+)$/) @date = Time.at($1.to_i) end @body << body end end deleted_comments = [] file_names.each {|file_name| i = File.open(file_name) first_line = i.gets comments = [] comment = Comment.new while line = i.gets if line == ".\n" comments.push(comment) comment = Comment.new else comment << line end end i.close tmp_name = "tmp.#{Process.pid}" File.open(tmp_name, "w") {|o| o.print first_line comments.each {|comment| if pattern.match(comment.body) and (before_date > comment.date) and (after_date < comment.date) deleted_comments.push(comment) else o.print comment.body o.puts "." end } } File.rename(file_name, file_name + ".bak") unless test File.rename(tmp_name, file_name) unless test } deleted_comments.each {|comment| print comment.body puts "." } tdiary-contrib-3.2.2/util/clean-spam/tdiary-referer-clean000077500000000000000000000020041213632744000233750ustar00rootroot00000000000000#!/usr/bin/env ruby # # Copyright (C) 2004 Satoru Takabayashi # You can redistribute it and/or modify it under GPL2. # puts "Usage: tdiary-referer-clean PATTERN FILE..." if ARGV.length == 0 pattern = Regexp.new(ARGV.shift) file_names = ARGV deleted_referers = [] file_names.each {|file_name| tmp_name = "tmp.#{Process.pid}" i = File.open(file_name) o = File.open(tmp_name, "w") first_line = i.gets o.print first_line while true date_line = i.gets break if date_line.nil? raise unless /^Date: /.match(date_line) blank_line = i.gets raise unless blank_line == "\n" o.print date_line o.print blank_line while line = i.gets if line == ".\n" o.print line next end if pattern.match(line) deleted_referers.push(line) else o.print line end end end i.close o.close File.rename(file_name, file_name + ".bak") File.rename(tmp_name, file_name) } deleted_referers.each {|referer| print referer } tdiary-contrib-3.2.2/util/convert_pstore.rb000066400000000000000000000025121213632744000210300ustar00rootroot00000000000000# # convert utf-8 in pstore. # # usage: convert_pstore.rb file1 # $KCODE = 'u' require 'nkf' require "pstore" begin require "iconv" rescue LoadError end def convert_pstore( file ) db = PStore.new( file ) begin roots = db.transaction{ db.roots } rescue ArgumentError if /\Aundefined class\/module (.+?)(::)?\z/ =~ $!.message klass = $1 if /EmptdiaryString\z/ =~ klass eval( "class #{klass} < String; end" ) else eval( "class #{ klass}; end" ) end retry end end db.transaction do roots.each do |root| convert_element( db[root] ) end end end def convert_element( data ) case data when Hash, Array data.each_with_index do |e, i| if String === e data[i] = migrate_to_utf8( e ) else convert_element( e ) end end else data.instance_variables.each do |e| var = data.instance_variable_get( e ) if String === var data.instance_variable_set( e, migrate_to_utf8( var ) ) else convert_element( var ) end end end end def migrate_to_utf8( str ) to_native( str, 'EUC-JP' ) end def to_native( str, charset = nil ) begin Iconv.conv('utf-8', charset || 'utf-8', str) rescue from = case charset when /^utf-8$/i 'W' when /^shift_jis/i 'S' when /^EUC-JP/i 'E' else '' end NKF::nkf("-m0 -#{from}w", str) end end convert_pstore( ARGV[0] ) tdiary-contrib-3.2.2/util/estraier-search/000077500000000000000000000000001213632744000205105ustar00rootroot00000000000000tdiary-contrib-3.2.2/util/estraier-search/ChangeLog000066400000000000000000000020161213632744000222610ustar00rootroot000000000000002007-02-23 SHIBATA Hiroshi * estraier-search.rb: add override whatsnew plugin. 2007-02-18 Kazuhiko * estraier-search.rb: add 'require "date"'. 2007-02-16 Kazuhiko * estraier-register.rb, estraier-search.rb: rename @last_modified attribute to @mdate. * estraier-register.rb: register all visible comments (ie. not limit to 100). 2007-02-15 Kazuhiko * estraier-search.rb, estraier.rhtml: support similarity search. * estraier-register.rb, estraier-search.rb: support "estraier.with_user_name" option. * estraier-search.rb, estraier.rhtml: support changing a phrase format. 2007-02-14 Kazuhiko * estraier.rxml: add guid elements and escape contents of description elements. * estraier-register.rb, estraier-search.rb: add the 'estraier.path' variable. * estraier.rhtml: revise for more tdiary-like outputs. 2007-02-13 Kazuhiko * initial release: ported from rast-search. tdiary-contrib-3.2.2/util/estraier-search/README.ja000066400000000000000000000104741213632744000217670ustar00rootroot00000000000000estraier-search README =================== Hyper Estraier を用いた tDiary 検索環境です。 特徴 ---------- 日記の更新と連動して自動的にインデックスを更新するので、いつでも最新の 情報で検索することができます。日記を HTML 化した後に必要な部分だけを取 り出してインデックスを作成するので、ヘッダやフッタなどによる検索ノイズ がなく、また、プラグインの出力が検索対象になるという特徴があります。 必要なもの ---------- * tDiary 1.5 以降 * Ruby 1.8.2 以降 * Hyper Estraier 1.4 以降 (ピュアRubyインターフェイス estraierpure.rb も必要です) セットアップ ------------ 1. estraier-register.rb を tDiary の プラグインディレクトリにコピーします。 2. estraier-search.rb を tDiary の index.rb があるディレクトリにコピー します。必要なら index.rb と同じようにシンボリックリンクを張ったり 名前を変えたりしてください。 3. CGI として実行可能にします。 $ chmod a+x estraier-search.rb 4. 必要なら #! のパスを変更します。 5. estraier.rhtml と estraier.rxml と i.estraier.rhtml を tDiary の skel/ ディレクトリにコピーします。 6. Hyper Estraier のノードマスタをセットアップします。その際、設定ファ イル(ノードマスタのrootdirの下の_conf)に、以下を追加してください。 attrindex: @uri{{!}}str この設定がないと、登録エントリが増えた際に、著しくパフォーマンスが 低下します。 7. ノードマスタから、tDiary用のノードサーバを作成し、その接続情報を tdiary.conf に記述します。デフォルトでは、以下のように記述したのと 同じ設定です。 @options["estraier.host"] = "localhost" @options["estraier.port"] = 1978 @options["estraier.path"] = "/node/" @options["estraier.node"] = "tdiary" @options["estraier.name"] = "admin" @options["estraier.password"] = "admin" 8. estraier-register.rb プラグインを有効にします。(tDiary の plugin/ ディレクトリにコピーするか、プラグイン選択のディレクトリにコピーし てブラウザから有効に設定します。言語リソースファイルの en/estraier-register.rb と ja/estraier-register.rb も、プラグインディ レクトリの en/ 以下およびja/ 以下にコピーしてください。) 9. 既存の日記コンテンツに対して検索インデックスを作成します。tDiary の 設定画面から「Estraier検索」を選び、「Estraier検索のインデックスを 再構築する場合は、チェックボックスをチェックしてOKを押してください」 というメッセージに従ってチェックしてOKを押すと、 インデックスの作成は、tDiary の CGI の実行権限で以下のように実行する ことでも可能です。 ruby estraier-register.rb [-p tdiary.rbのあるディレクトリ] [-c tdiary.confのあるディレクトリ] 10. 自分の tDiary の好きな場所 (例えばヘッダ) に以下のようなフォームを加 えてください。 search-form.rb プラグインを有効にしている場合は、以下のように書くこ ともできます。 <%= search_form("estraier-search.rb", "query") %> 以上です。 検索のしかた ------------ estraier-search の検索対象は、日記本文、ツッコミ、TrackBack です。 検索方法については、 http://hyperestraier.sourceforge.net/uguide-ja.html#searchcond をご覧 ください。検索条件の書式を指定していない場合は、「簡便書式」で検索を行 います。 連絡先 ------ かずひこ http://www.fdiary.net/ バグ報告は以下のどこかにお願いします。 * tdiary-devel ML * 直接メール tdiary-contrib-3.2.2/util/estraier-search/en/000077500000000000000000000000001213632744000211125ustar00rootroot00000000000000tdiary-contrib-3.2.2/util/estraier-search/en/estraier-register.rb000066400000000000000000000003361213632744000251010ustar00rootroot00000000000000@estraier_register_conf_label = 'Estraier Search' @estraier_register_conf_header = 'Rebuild Estraier search index' @estraier_register_conf_description = 'To rebuild Estraier search index, check the box and submit \'OK\'.' tdiary-contrib-3.2.2/util/estraier-search/estraier-register.rb000077500000000000000000000163411213632744000245050ustar00rootroot00000000000000#!/usr/bin/env ruby # estraier-register.rb # # Copyright (C) 2007 Kazuhiko # You can redistribute it and/or modify it under GPL2. # require "estraierpure" unless $tdiary_estraier_register_loaded $tdiary_estraier_register_loaded ||= true mode = "" if $0 == __FILE__ require 'cgi' ARGV << '' # dummy argument against cgi.rb offline mode. @cgi = CGI::new mode = "CMD" else mode = "PLUGIN" end if mode == "CMD" tdiary_path = "." tdiary_conf = "." $stdout.sync = true def usage puts "hyper-estraier-register.rb $Revision: 1.1.2.13 $" puts " register to hyper-estraier index files from tDiary's database." puts " usage: ruby hyper-estraier-regiser.rb [-p ] [-c ]" exit end require 'getoptlong' parser = GetoptLong::new parser.set_options(['--path', '-p', GetoptLong::REQUIRED_ARGUMENT], ['--conf', '-c', GetoptLong::REQUIRED_ARGUMENT]) begin parser.each do |opt, arg| case opt when '--path' tdiary_path = arg when '--conf' tdiary_conf = arg end end rescue usage exit( 1 ) end tdiary_conf = tdiary_path unless tdiary_conf Dir::chdir( tdiary_conf ) begin $:.unshift tdiary_path require "#{tdiary_path}/tdiary" rescue LoadError $stderr.puts "hyper-estraier-register.rb: cannot load tdiary.rb. <#{tdiary_path}/tdiary>\n" $stderr.puts " usage: ruby hyper-estraier-regiser.rb [-p ] [-c ]" exit( 1 ) end end module ::TDiary # # Database # class EstraierDB attr_accessor :db attr_reader :conf def initialize(conf) @conf = conf @host = @conf["estraier.host"] || "localhost" @port = @conf["estraier.port"] || 1978 @path = @conf["estraier.path"] || "/node/" @node = @conf["estraier.node"] || "tdiary" @name = @conf["estraier.name"] || "admin" @password = @conf["estraier.password"] || "admin" end def transaction db = EstraierPure::Node.new db.set_url("http://#{@host}:#{@port}#{@path}#{@node}") db.set_auth(@name, @password) if db.doc_num < 0 raise "Database not found : http://#{@host}:#{@port}#{@path}#{@node}" end @db = db yield self end def cache_path @conf.cache_path || "#{@conf.data_path}cache" end end # # Register # class EstraierRegister < TDiaryBase def initialize(estraier_db, diary) @db = estraier_db.db super(CGI::new, 'day.rhtml', estraier_db.conf) @diary = diary @date = diary.date @diaries = {@date.strftime('%Y%m%d') => @diary} if @diaries.empty? @plugin = ::TDiary::Plugin::new( 'conf' => @conf, 'cgi' => @cgi, 'cache_path' => @io.cache_path, 'diaries' => @diaries ) def @plugin.apply_plugin_alt( str, remove_tag = false ) apply_plugin( str, remove_tag ) end end def execute(force = false) date = @date.strftime('%Y%m%d') cond = EstraierPure::Condition.new if @conf["estraier.with_user_name"] cond.add_attr("@uri STRBW #{@conf.user_name}:#{date}") else cond.add_attr("@uri STRBW #{date}") end result = @db.search(cond, 0) if result for i in 0...result.doc_num doc_id = result.get_doc(i).attr("@id") @db.out_doc(doc_id) end end return unless @diary.visible? # body index = 0 anchor = '' @diary.each_section do |section| index += 1 @conf['apply_plugin'] = true anchor = "#{date}p%02d" % index title = CGI.unescapeHTML( @plugin.apply_plugin_alt( section.subtitle_to_html, true ).strip ) if title.empty? title = @plugin.apply_plugin_alt( section.body_to_html, true ).strip title = @conf.shorten( CGI.unescapeHTML( title ), 20 ) end last_modified = @diary.last_modified.strftime("%FT%T") body = CGI.unescapeHTML( @plugin.apply_plugin_alt( section.body_to_html, true ).strip ) doc = EstraierPure::Document.new doc.add_attr("@title", title) if @conf["estraier.with_user_name"] doc.add_attr("@uri", "#{@conf.user_name}:#{anchor}") else doc.add_attr("@uri", anchor) end doc.add_attr("@mdate", last_modified) doc.add_hidden_text(title) doc.add_text(body) @db.put_doc(doc) end # comment @diary.each_visible_comment do |comment, index| if /^(TrackBack|Pingback)$/i =~ comment.name anchor = "#{date}t%02d" % index title = "TrackBack (#{comment.name})" else anchor = "#{date}c%02d" % index title = "#{@plugin.comment_description_short} (#{comment.name})" end body = comment.body doc = EstraierPure::Document.new doc.add_attr("@title", title) if @conf["estraier.with_user_name"] doc.add_attr("@uri", "#{@conf.user_name}:#{anchor}") else doc.add_attr("@uri", anchor) end doc.add_attr("@mdate", comment.date.strftime("%FT%T")) doc.add_hidden_text(title) doc.add_text(body) @db.put_doc(doc) end end protected def mode; 'day'; end def cookie_name; ''; end def cookie_mail; ''; end def convert(str) str end end # # Main # class EstraierRegisterMain < TDiaryBase def initialize(conf) super(CGI::new, 'day.rhtml', conf) end def execute(out = $stdout) require 'fileutils' calendar db = EstraierDB.new(conf) db.transaction do |estraier_db| @years.keys.sort.reverse_each do |year| out << "(#{year.to_s}/) " @years[year.to_s].sort.reverse_each do |month| @io.transaction(Time::local(year.to_i, month.to_i)) do |diaries| diaries.sort.reverse_each do |day, diary| EstraierRegister.new(estraier_db, diary).execute out << diary.date.strftime('%m%d ') end false end end end end end end end if mode == "CMD" begin require 'cgi' if TDiary::Config.instance_method(:initialize).arity != 0 # for tDiary 2.1 or later cgi = CGI.new conf = TDiary::Config::new(cgi) else # for tDiary 2.0 or earlier conf = TDiary::Config::new end conf.header = '' conf.footer = '' conf.show_comment = true conf.hide_comment_form = true conf.show_nyear = false def conf.bot?; true; end TDiary::EstraierRegisterMain.new(conf).execute rescue print $!, "\n" $@.each do |v| print v, "\n" end exit( 1 ) end puts else add_update_proc do conf = @conf.clone conf.header = '' conf.footer = '' conf.show_comment = true conf.hide_comment_form = true conf.show_nyear = false def conf.bot?; true; end diary = @diaries[@date.strftime('%Y%m%d')] TDiary::EstraierDB.new(conf).transaction do |estraier_db| TDiary::EstraierRegister.new(estraier_db, diary).execute(true) end end if !@conf['estraier.hideconf'] && (@mode == 'conf' || @mode == 'saveconf') args = ['estraier_register', @estraier_register_conf_label] args << 'update' if TDIARY_VERSION > '2.1.3' add_conf_proc(*args) do str = <<-HTML

        #{@estraier_register_conf_header}

        HTML if @mode == 'saveconf' if @cgi.valid?( 'estraier_register_rebuild' ) str << '

        The following diaries were registered.

        ' out = '' TDiary::EstraierRegisterMain.new(@conf).execute(out) str << "

        #{out}

        " end end str end end end end # $tdiary_estraier_register_loaded tdiary-contrib-3.2.2/util/estraier-search/estraier-search.rb000077500000000000000000000155361213632744000241330ustar00rootroot00000000000000#!/usr/bin/env ruby # -*- coding: utf-8; -*- # estraier-search.rb $Revision: 1.1.2.12 $ # # Copyright (C) 2007 Kazuhiko # You can redistribute it and/or modify it under GPL2. # BEGIN { $stdout.binmode } begin Encoding::default_external = 'UTF-8' rescue NameError $KCODE = 'n' end require "estraierpure" require "enumerator" require "date" if FileTest::symlink?( __FILE__ ) then org_path = File::dirname( File::readlink( __FILE__ ) ) else org_path = File::dirname( __FILE__ ) end $:.unshift( org_path.untaint ) require 'tdiary' # # class TDiaryEstraier # module TDiary class TDiaryEstraier < ::TDiary::TDiaryBase MAX_PAGES = 20 SORT_OPTIONS = [ ["score", "スコア順"], ["date", "日付順"], ] ORDER_OPTIONS = [ ["asc", "昇順"], ["desc", "降順"], ] FORM_OPTIONS = [ ["simple", "簡便書式"], ["normal", "通常書式"], ] NUM_OPTIONS = [10, 20, 30, 50, 100] def initialize( cgi, rhtml, conf ) super @host = @conf["estraier.host"] || "localhost" @port = @conf["estraier.port"] || 1978 @path = @conf["estraier.path"] || "/node/" @node = @conf["estraier.node"] || "tdiary" parse_args format_form if @query.empty? @msg = '検索条件を入力して、「検索」ボタンを押してください' else search end end def load_plugins super # add a opensearch rss link @plugin.instance_variable_get('@header_procs').unshift Proc.new { cgi_url = @conf.base_url.sub(%r|/[^/]*$|, '/') + (@cgi.script_name ? _(File.basename(@cgi.script_name)) : '') %Q|\t\n| } # override some plugins def @plugin.sn(number = nil); ''; end def @plugin.whats_new; ''; end end def eval_rxml require 'time' load_plugins ERB::new( File::open( "#{PATH}/skel/estraier.rxml" ){|f| f.read }.untaint ).result( binding ) end private def parse_args @query = @cgi["query"].strip @start = @cgi["start"].to_i @num = @cgi["num"].to_i if @num < 1 @num = 10 elsif @num > 100 @num = 100 end @sort = @cgi["sort"].empty? ? "score" : @cgi["sort"] @order = @cgi["order"].empty? ? "desc" : @cgi["order"] @form = @cgi["form"].empty? ? "simple" : @cgi["form"] end def search @db = EstraierPure::Node.new @db.set_url("http://#{@host}:#{@port}#{@path}#{@node}") begin t = Time.now cond = create_search_options cond.set_phrase(convert(@query)) @result = @db.search(cond, 0) @secs = Time.now - t rescue @msg = "エラー: #{_($!.to_s + $@.join)}

        " end end def format_result_item(item) @date = item.attr('@uri') if @conf["estraier.with_user_name"] @date.gsub!(/.*:/, "") end @date_str = Date.parse(@date).strftime(@conf.date_format) @last_modified = item.attr('@mdate') @title = _(item.attr('@title')) @summary = _(item.snippet).gsub(/\t.*/, "").gsub(/\n\n/, " ... ").delete("\n") for term in @query.split @title.gsub!(Regexp.new(Regexp.quote(CGI.escapeHTML(term)), true, @encoding), "\\&") @summary.gsub!(Regexp.new(Regexp.quote(CGI.escapeHTML(term)), true, @encoding), "\\&") end query = "[SIMILAR]" item.keywords.split(/\t/).each_slice(2).collect do |k, s| query << " WITH #{s} #{k}" end @similar = "%s?query=%s" % [_(@cgi.script_name || ""), CGI::escape(query)] end def format_links(result) page_count = (result.doc_num - 1) / @num + 1 current_page = @start / @num + 1 first_page = current_page - (MAX_PAGES / 2 - 1) if first_page < 1 first_page = 1 end last_page = first_page + MAX_PAGES - 1 if last_page > page_count last_page = page_count end buf = "

        \n" if current_page > 1 buf.concat(format_link("前へ", @start - @num, @num)) end if first_page > 1 buf.concat("... ") end for i in first_page..last_page if i == current_page buf.concat("#{i} ") else buf.concat(format_link(i.to_s, (i - 1) * @num, @num)) end end if last_page < page_count buf.concat("... ") end if current_page < page_count buf.concat(format_link("次へ", @start + @num, @num)) end buf.concat("

        \n") return buf end def format_anchor(start, num) return format('?query=%s;start=%d;num=%d;sort=%s;order=%s', CGI::escape(@query), start, num, _(@sort), _(@order)) end def format_link(label, start, num) return format('
        %s ', _(@cgi.script_name ? @cgi.script_name : ""), format_anchor(start, num), _(label)) end def create_search_options cond = EstraierPure::Condition.new if @conf["estraier.with_user_name"] cond.add_attr("@uri STRBW #{@conf.user_name}:") end if @sort == "date" order = "@uri" else order = "" end if @order == "asc" order = "[SCA]" if order.empty? else unless order.empty? order << " STRD" end end if @form == "simple" cond.set_options(EstraierPure::Condition::SIMPLE) end cond.set_order(order) return cond end def format_options(options, value) return options.collect { |val, label| if val == value "" else "" end }.join("\n") end def format_form @num_options = NUM_OPTIONS.collect { |n| if n == @num "" else "" end }.join("\n") @sort_options = format_options(SORT_OPTIONS, @sort) @order_options = format_options(ORDER_OPTIONS, @order) @form_options = format_options(FORM_OPTIONS, @form) end def _(str) CGI::escapeHTML(str) end def convert(str) @conf.to_native(str) end end end begin @cgi = CGI::new if ::TDiary::Config.instance_method(:initialize).arity != 0 # for tDiary 2.1 or later conf = ::TDiary::Config::new(@cgi) else # for tDiary 2.0 or earlier conf = ::TDiary::Config::new end tdiary = TDiary::TDiaryEstraier::new( @cgi, 'estraier.rhtml', conf ) head = { 'type' => 'text/html', 'Vary' => 'User-Agent' } if @cgi.mobile_agent? then body = conf.to_mobile( tdiary.eval_rhtml( 'i.' ) ) head['charset'] = conf.mobile_encoding head['Content-Length'] = body.bytesize.to_s else if @cgi['type'] == 'rss' head['type'] = "application/xml; charset=#{conf.encoding}" body = tdiary.eval_rxml else body = tdiary.eval_rhtml end head['charset'] = conf.encoding head['Content-Length'] = body.bytesize.to_s head['Pragma'] = 'no-cache' head['Cache-Control'] = 'no-cache' end print @cgi.header( head ) print body rescue Exception if @cgi then print @cgi.header( 'type' => 'text/plain' ) else print "Content-Type: text/plain\n\n" end puts "#$! (#{$!.class})" puts "" puts $@.join( "\n" ) end tdiary-contrib-3.2.2/util/estraier-search/estraier.rhtml000066400000000000000000000036561213632744000234100ustar00rootroot00000000000000
        <%%=navi_user%>

        <%= _(@conf.html_title) %> [全文検索]

        検索方法

        並べ替え: 表示件数: 検索条件の書式:

        <% if @msg %>

        <%= @msg %>

        <% else %> <% @end = [@result.doc_num, @start + @num].min %>

        <%= _(@conf.to_native(@query)) %> の検索結果 <%= @result.doc_num %> 件中 <%= @start + 1 %> - <%= @end %> 件目 (<%= @secs %> 秒)

        <% if @result.doc_num > @num %> <%= format_links(@result) %> <% end %> <% for i in @start...@end %> <% item = @result.get_doc(i) || next %> <% format_result_item(item) %>

        <%= @date_str %> [類似検索]

        <%= @conf.section_anchor %><%= @conf.to_native(@title) %>

        <%= @conf.to_native(@summary) %>

        <%= @conf.comment_anchor %>  (スコア:<%= item.attr("#nodescore") %>)

        <% end %> <% if @result.doc_num > @num %> <%= format_links(@result) %> <% end %> <% end %> tdiary-contrib-3.2.2/util/estraier-search/estraier.rxml000066400000000000000000000024031213632744000232310ustar00rootroot00000000000000"?> <%= _( @conf.html_title ) %> [全文検索]: <%= _(@query) %> <%= @conf.base_url.sub(%r|/[^/]*$|, '/') %><%= _(@cgi.script_name ? File.basename(@cgi.script_name) : "") %><%= format_anchor(@start, @num) %> HyperEstraier 検索: <%= _(@query) %> ja-JP <%= @result.doc_num %> <%= @start + 1 %> <%= @num %> <% for i in @start...@start+@num %> <% item = @result.get_doc(i) || next %> <% format_result_item(item) %> <%= _(@date.sub(/^(\d{4})(\d{2})(\d{2}).*/, "\\1-\\2-\\3")) %> <%= _(@conf.to_native(@title)) %> <%= @conf.base_url %><%= @plugin.anchor(@date) %> <%= _(CGI.rfc1123_date(Time.parse(@last_modified))) %> <%= _(@conf.to_native(@summary)) %> <%= @conf.base_url %><%= @plugin.anchor(@date) %> <% end %> tdiary-contrib-3.2.2/util/estraier-search/i.estraier.rhtml000066400000000000000000000017041213632744000236270ustar00rootroot00000000000000

        <%= _(@conf.html_title) %> [全文検索]

        並べ替え: 表示件数:

        <% if @msg %>

        <%= @msg %>

        <% else %>

        <%= @result.doc_num %>件中<%= @start + 1 %>-<%= [@result.doc_num, @start + @num].min %>件目

        <% for i in @start...@start+@num %><% item = @result.get_doc(i) || next %><% format_result_item(item) %>

        <%= _(@date.sub(/^(\d{4})(\d{2})(\d{2}).*/, "\\1-\\2-\\3")) %><%= @conf.to_native(@title) %>(スコア:<%= item.attr("#nodescore") %>)

        <% end %> <% if @result.doc_num > @num %> <%= format_links(@result) %> <% end %> <% end %> tdiary-contrib-3.2.2/util/estraier-search/ja/000077500000000000000000000000001213632744000211025ustar00rootroot00000000000000tdiary-contrib-3.2.2/util/estraier-search/ja/estraier-register.rb000066400000000000000000000004651213632744000250740ustar00rootroot00000000000000@estraier_register_conf_label = 'Estraier検索' @estraier_register_conf_header = 'Estraier検索インデックスの再構築' @estraier_register_conf_description = 'Estraier検索のインデックスを再構築する場合は、チェックボックスをチェックしてOKを押してください。' tdiary-contrib-3.2.2/util/image-gallery/000077500000000000000000000000001213632744000201465ustar00rootroot00000000000000tdiary-contrib-3.2.2/util/image-gallery/README.ja000066400000000000000000000020261213632744000214170ustar00rootroot00000000000000tDiary Image Gallery Ver 2.0.3 -- README.ja -- Copyright (c) 2005-2012 N.KASHIJUKU You can redistribute it and/or modify it under GPL2. =================== ■概要 image or image_ex プラグインで日記に貼り付けた画像ファイルの一覧表示ページを生成する、  tDiaryの拡張機能(プラグイン & Ruby CGI)です。 ■使い方の詳細は…  以下のサイトをご覧下さい。 ・配布サイト    http://www1.whi.m-net.ne.jp/n-kashi/image-gallery2.html ・作者の日記のサポート・ページ    http://exception.rash.jp/diary/?date=20010101 ■サンプルは…  ・作者の日記    http://exception.rash.jp/diary/  ・Image Gallery Listモード http://exception.rash.jp/diary/image-gallery.rb  ・Image Gallery SideShowモード http://exception.rash.jp/diary/image-gallery.rb?mode=slide  ・Image Gallery Viewerモード http://exception.rash.jp/diary/image-gallery.rb?mode=viewer;key=20090222_0 tdiary-contrib-3.2.2/util/image-gallery/image-gallery.rb000066400000000000000000000374361213632744000232270ustar00rootroot00000000000000#!/usr/bin/env ruby # -*- coding: utf-8 -*- # image-gallery.rb $Revision: 2.0.3 $ # # Copyright (c) 2005-2012 N.KASHIJUKU # You can redistribute it and/or modify it under GPL2. if RUBY_VERSION >= '1.9.0' Encoding::default_external = 'UTF-8' $LOAD_PATH.push('./') end if FileTest::symlink?( __FILE__ ) then org_path = File::dirname( File::readlink( __FILE__ ) ) else org_path = File::dirname( __FILE__ ) end $:.unshift( org_path.untaint ) require 'tdiary' require 'pstore' require 'date' # class TDiaryGallery # module TDiary class ImageData attr_reader :file, :url, :title, :subtitle, :date, :width, :height, :type attr_writer :file, :url, :title, :subtitle, :date, :width, :height, :type end class TDiaryGallery < ::TDiary::TDiaryBase MAX_PAGES = 20 ORDER_OPTIONS = [ ["asc", "新しい順"], ["desc", "古い順"], ] MODE_OPTIONS = [ ["list", "リスト"], ["slide", "スライド"], ] def initialize( cgi, rhtml, conf ) super @img_version = "2.0.3" @image_hash = Hash[] @image_num = 0 @image_keys = [] @images = [] @exifstr = [] @t_page_title = "" get_conf(conf) parse_args(cgi) format_form read_cache make_image_data check_name_filter_dateformat make_page_title end private def get_conf(conf) @column = conf.options['image-gallery.column'].to_i @column = 3 if @column == 0 @line = conf.options['image-gallery.line'].to_i @line = 4 if @line == 0 @num = @line * @column @width = conf.options['image-gallery.width'] @width = "160" if @width == nil @vwidth = conf.options['image-gallery.vwidth'] @vwidth = "640" if @vwidth == nil @show_exif = conf.options['image-gallery.show_exif'] @show_exif = false if @show_exif == nil @use_mid_image = conf.options['image-gallery.use_mid_image'] @use_mid_image = false if @use_mid_image == nil end def parse_args(cgi) @start = cgi["start"].to_i @order = @cgi["order"].empty? ? "asc" : @cgi["order"] @name_filter = @cgi["name"].empty? ? "" : @cgi["name"].strip @title_filter = @cgi["title"].empty? ? "" : @cgi["title"].strip @subtitle_filter = @cgi["subtitle"].empty? ? "" : @cgi["subtitle"].strip @mode = @cgi["mode"].empty? ? "list" : @cgi["mode"].strip @mode = "list" if @mode != "viewer" and @mode != "slide" and @mode != "fslide" @key = cgi["key"].empty? ? "" : cgi["key"].strip @page_title = cgi["pagetitle"].empty? ? "" : @cgi["pagetitle"].strip @show_inputfield = true; show_inputfield = @cgi["showinputfield"].strip @show_inputfield = false if show_inputfield == "false" end def read_cache begin db = PStore.new("#{@io.cache_path}/gallery/image-gallery2.dat") # for tDiary 3.1.3 or later rescue db = PStore.new("#{cache_path}/gallery/image-gallery2.dat") # for tDiary 3.1.2 or faster end db.transaction do @image_hash = db["recent_image_hash"] @image_keys = db["recent_image_keys"] @image_url = db["recent_image_url"] @image_dir = db["recent_image_dir"] db.abort end end def make_image_data if @name_filter != "" or @title_filter != "" or @subtitle_filter != "" @image_keys.reject! { |key| image = @image_hash[key] (@name_filter != "" and image.file.match(@name_filter) == nil) or (@title_filter != "" and image.title.match(@title_filter) == nil) or (@subtitle_filter != "" and image.subtitle.match(@subtitle_filter) == nil) } end @image_num = @image_keys.length @image_keys = @image_keys.reverse if @order == "asc" if @mode == "list" or @mode == "slide" or @mode == "fslide" if @key != "" index = @image_keys.index(@key) if index != nil @start = (index / @num) * @num else return end end @num.times do |i| index = @start + i break if @image_keys[index] == nil @images.push(@image_hash[@image_keys[index]]) end elsif @mode == "viewer" if @key != "" index = @image_keys.index(@key) if index != nil @start = index else @start = 0 end end @images.push(@image_hash[@image_keys[@start]]) width, height = @images[0].width.to_i, @images[0].height.to_i size = ((width > height ? width : height) > @vwidth.to_i) ? @vwidth : width if width > height @sizestr = %Q[width="#{size}" height="#{(size.to_i*height/width).to_s}"] else @sizestr = %Q[width="#{(size.to_i*width/height).to_s}" height="#{size}"] end if @show_exif and @images[0].type == "jpg" begin require 'exifparser' @exifstr = read_exif_data("#{@image_dir}/#{@images[0].file}") rescue exp = [] exp.push(($!).to_s) ($!).backtrace.each do |btinfo| exp.push(btinfo) end @exifstr = exp end end end end def check_name_filter_dateformat @page_year = "" @page_month = "" @page_day = "" @page_date = nil return if @name_filter == "" begin if @name_filter.index(/[\d]{8}/) != nil @page_year = @name_filter[0,4] @page_month = @name_filter[4,2] @page_day = @name_filter[6,2] @page_date = Date.new(@page_year.to_i, @page_month.to_i, @page_day.to_i) elsif @name_filter.index(/[\d]{6}/) != nil @page_year = @name_filter[0,4] @page_month = @name_filter[4,2] @page_date = Date.new(@page_year.to_i, @page_month.to_i, 1) elsif @name_filter.index(/[\d]{4}/) != nil @page_year = @name_filter[0,4] @page_date = Date.new(@page_year.to_i, 1, 1) end rescue @page_year = "" @page_month = "" @page_day = "" @page_date = nil return end end def make_page_title return if @page_title == "" @t_page_title = String.new(@page_title) @t_page_title.gsub!("@year", @page_year) @t_page_title.gsub!("@month", @page_month) @t_page_title.gsub!("@day", @page_day) begin @t_page_title.gsub!("@subtitle", @images[0].subtitle) rescue end end def format_links(count) page_count = (count - 1) / @num + 1 current_page = @start / @num + 1 first_page = current_page - (MAX_PAGES / 2 - 1) if first_page < 1 first_page = 1 end last_page = first_page + MAX_PAGES - 1 if last_page > page_count last_page = page_count end buf = "

        \n" if current_page > 1 buf << format_link("«先頭へ ", 0, 0, @mode) buf << format_link("<前へ", @start - @num, @num, @mode) end if first_page > 1 buf << "... " end for i in first_page..last_page if i == current_page buf << "#{i} " else buf << format_link(i.to_s, (i - 1) * @num, @num, @mode) end end if last_page < page_count buf << "... " end if current_page < page_count buf << format_link("次へ>", @start + @num, @num, @mode) buf.concat(format_link(" 最後へ»", (page_count - 1) * @num, 0, @mode)) end buf << "

        \n" return buf end def format_link(label, start, num, mode) return format('%s ', _(@cgi.script_name ? @cgi.script_name : ''), mode, make_cgi_param, start, label) end def format_links_viewer buf = "

        \n" if @start == 0 buf << "«前へ" else buf << format_link_viewer("«前へ", @image_keys[@start - 1]) end buf << "  |  " buf << format_link("一覧へ", (@start / @num) * @num, 0, "list") buf << "  |  " if @start == @image_keys.length - 1 buf << "次へ»" else buf << format_link_viewer("次へ»", @image_keys[@start + 1]) end buf << "

        \n" return buf end def format_link_viewer(label, key) return format('%s', _(@cgi.script_name ? @cgi.script_name : ''), make_cgi_param, key, label) end def format_link_viewer_image(key) return format('%s?%smode=viewer;key=%s', _(@cgi.script_name ? @cgi.script_name : ''), make_cgi_param, key) end def format_links_date return "" unless @name_filter != "" and @title_filter == "" and @subtitle_filter == "" begin buf = "

        \n" if @page_day != "" yesterday = (@page_date - 1).strftime("%Y%m%d") tomorrow = (@page_date + 1).strftime("%Y%m%d") buf << format_link_date(%Q[«#{(@page_date - 1).to_s}], yesterday) buf << format('  |  %s  |  ', _(@cgi.script_name ? @cgi.script_name : ''), _(@mode), _(@order), '全画像') buf << format_link_date(%Q[#{(@page_date + 1).to_s}»], tomorrow) elsif @page_month != "" prevmonth = (@page_date << 1).strftime("%Y%m") nextmonth = (@page_date >> 1).strftime("%Y%m") buf << format_link_date(%Q[«#{(@page_date << 1).to_s[0,7]}], prevmonth) buf << format('  |  %s  |  ', _(@cgi.script_name ? @cgi.script_name : ''), _(@mode), _(@order), '全画像') buf << format_link_date(%Q[#{(@page_date >> 1).to_s[0,7]}»], nextmonth) elsif @page_year != "" year = @page_year.to_i buf << format_link_date(%Q[«#{(year - 1).to_s}], (year - 1).to_s) buf << format('  |  %s  |  ', _(@cgi.script_name ? @cgi.script_name : ''), _(@mode), _(@order), '全画像') buf << format_link_date(%Q[#{(year + 1).to_s}»], (year + 1).to_s) end buf << "

        \n" return buf rescue return "" end end def format_link_date(label, name_filter) cgi_params = make_cgi_param if cgi_params.gsub!(/name=[^;]*;/, "name=#{CGI::escape(name_filter)};") == nil cgi_params = "name=" + CGI::escape(name_filter) + ";" + cgi_params end return format('%s', _(@cgi.script_name ? @cgi.script_name : ''), @mode, cgi_params, label) end def format_link_viewer_date(label, name_filter) return format('%s', _(@cgi.script_name ? @cgi.script_name : ''), name_filter, label) end def format_link_viewer_category(subtitle) buf = "" subtitle.scan(/\[[^\]]*\]/).each do |category| tag = category[1..-2] next if tag[0] == ?[ buf << format('[%s]', _(@cgi.script_name ? @cgi.script_name : ''), CGI::escape("\\[" + tag + "\\]"), tag) end return buf end def format_link_list_category(images) categories = [] images.each do |image| categories |= image.subtitle.scan(/\[[^\]]*\]/) end buf = "" categories.each do |category| tag = category[1..-2] next if tag[0] == ?[ buf << format('[%s]', _(@cgi.script_name ? @cgi.script_name : ''), CGI::escape("\\[" + tag + "\\]"), tag) end return buf end def get_other_mode_link case @mode when "list" format_link("[SLIDESHOW]", @start, @num, "slide") + format_link("[SLIDESHOW(FullScreen)]", @start, @num, "fslide") when "slide" format_link("[LIST]", @start, @num, "list") + format_link("[SLIDESHOW(FullScreen)]", @start, @num, "fslide") when "fslide" format_link("[LIST]", @start, @num, "list") + format_link("[SLIDESHOW]", @start, @num, "slide") end end def make_cgi_param buf = "" buf << "name=#{CGI::escape(@name_filter)};" if @name_filter != "" buf << "title=#{CGI::escape(@title_filter)};" if @title_filter != "" buf << "subtitle=#{CGI::escape(@subtitle_filter)};" if @subtitle_filter != "" buf << "pagetitle=#{CGI::escape(@page_title)};" if @page_title != "" buf << "showinputfield=false;" if not @show_inputfield buf << "order=#{@order};" return buf end def format_options(options, value) return options.collect { |val, label| if val == value "" else "" end }.join("\n") end def format_form @order_options = format_options(ORDER_OPTIONS, @order) @mode_options = format_options(MODE_OPTIONS, @mode ) end def _(str) CGI::escapeHTML(str) end def read_exif_data(file) exifstr = [] str = "" exif = ExifParser.new(file) return exifstr if exif == nil exifstr.push("-- IFD0 (main image) --") exif.each(:IFD0) do |tag| next if tag.name == "Unknown" str = "#{tag.name} : #{tag.to_s}" exifstr.push(str) end exifstr.push("-- Exif SubIFD --") exif.each(:Exif) do |tag| next if tag.name == "Unknown" str = "#{tag.name} : #{tag.to_s}" exifstr.push(str) end exifstr.push("-- MakerNote --") exif.each(:MakerNote) do |tag| next if tag.name == "Unknown" or tag.name == "NikonCameraSerialNumber" str = "#{tag.name} : #{tag.to_s}" exifstr.push(str) end exifstr.push("-- GPS --") exif.each(:GPS) do |tag| next if tag.name == "Unknown" str = "#{tag.name} : #{tag.to_s}" exifstr.push(str) end return exifstr end def js_start_gallery if @mode == "fslide" <<-EOS EOS elsif @mode == "slide" <<-EOS2 EOS2 end end end end begin @cgi = CGI::new if TDiary::Config.instance_method(:initialize).arity == 0 # for tDiary 2.0 or earlier conf = TDiary::Config::new else # for tDiary 2.1 or later conf = TDiary::Config::new(@cgi) end tdiary = TDiary::TDiaryGallery::new( @cgi, 'gallery.rhtml', conf ) head = { 'type' => 'text/html', 'Vary' => 'User-Agent' } body = tdiary.eval_rhtml head['charset'] = conf.encoding head['Content-Length'] = body.bytesize.to_s head['Pragma'] = 'no-cache' head['Cache-Control'] = 'no-cache' print @cgi.header( head ) print body rescue Exception if @cgi then print @cgi.header( 'type' => 'text/plain' ) else print "Content-Type: text/plain\n\n" end puts "#$! (#{$!.class})" puts "" puts $@.join( "\n" ) end tdiary-contrib-3.2.2/util/image-gallery/image-gallery.rb.euc-jp000066400000000000000000000371121213632744000244000ustar00rootroot00000000000000#!/usr/bin/env ruby # -*- coding: euc-jp -*- # image-gallery.rb $Revision: 2.0.3 $ # # Copyright (c) 2005-2012 N.KASHIJUKU # You can redistribute it and/or modify it under GPL2. if RUBY_VERSION >= '1.9.0' Encoding::default_external = 'EUC-JP' $LOAD_PATH.push('./') end if FileTest::symlink?( __FILE__ ) then org_path = File::dirname( File::readlink( __FILE__ ) ) else org_path = File::dirname( __FILE__ ) end $:.unshift( org_path.untaint ) require 'tdiary' require 'pstore' require 'date' # class TDiaryGallery # module TDiary class ImageData attr_reader :file, :url, :title, :subtitle, :date, :width, :height, :type attr_writer :file, :url, :title, :subtitle, :date, :width, :height, :type end class TDiaryGallery < ::TDiary::TDiaryBase MAX_PAGES = 20 ORDER_OPTIONS = [ ["asc", ""], ["desc", "Ť"], ] MODE_OPTIONS = [ ["list", "ꥹ"], ["slide", "饤"], ] def initialize( cgi, rhtml, conf ) super @img_version = "2.0.3" @image_hash = Hash[] @image_num = 0 @image_keys = [] @images = [] @exifstr = [] @t_page_title = "" get_conf(conf) parse_args(cgi) format_form read_cache make_image_data check_name_filter_dateformat make_page_title end private def get_conf(conf) @column = conf.options['image-gallery.column'].to_i @column = 3 if @column == 0 @line = conf.options['image-gallery.line'].to_i @line = 4 if @line == 0 @num = @line * @column @width = conf.options['image-gallery.width'] @width = "160" if @width == nil @vwidth = conf.options['image-gallery.vwidth'] @vwidth = "640" if @vwidth == nil @show_exif = conf.options['image-gallery.show_exif'] @show_exif = false if @show_exif == nil @use_mid_image = conf.options['image-gallery.use_mid_image'] @use_mid_image = false if @use_mid_image == nil end def parse_args(cgi) @start = cgi["start"].to_i @order = @cgi["order"].empty? ? "asc" : @cgi["order"] @name_filter = @cgi["name"].empty? ? "" : @cgi["name"].strip @title_filter = @cgi["title"].empty? ? "" : @cgi["title"].strip @subtitle_filter = @cgi["subtitle"].empty? ? "" : @cgi["subtitle"].strip @mode = @cgi["mode"].empty? ? "list" : @cgi["mode"].strip @mode = "list" if @mode != "viewer" and @mode != "slide" and @mode != "fslide" @key = cgi["key"].empty? ? "" : cgi["key"].strip @page_title = cgi["pagetitle"].empty? ? "" : @cgi["pagetitle"].strip @show_inputfield = true; show_inputfield = @cgi["showinputfield"].strip @show_inputfield = false if show_inputfield == "false" end def read_cache db = PStore.new("#{cache_path}/gallery/image-gallery2.dat") db.transaction do @image_hash = db["recent_image_hash"] @image_keys = db["recent_image_keys"] @image_url = db["recent_image_url"] @image_dir = db["recent_image_dir"] db.abort end end def make_image_data if @name_filter != "" or @title_filter != "" or @subtitle_filter != "" @image_keys.reject! { |key| image = @image_hash[key] (@name_filter != "" and image.file.match(@name_filter) == nil) or (@title_filter != "" and image.title.match(@title_filter) == nil) or (@subtitle_filter != "" and image.subtitle.match(@subtitle_filter) == nil) } end @image_num = @image_keys.length @image_keys = @image_keys.reverse if @order == "asc" if @mode == "list" or @mode == "slide" or @mode == "fslide" if @key != "" index = @image_keys.index(@key) if index != nil @start = (index / @num) * @num else return end end @num.times do |i| index = @start + i break if @image_keys[index] == nil @images.push(@image_hash[@image_keys[index]]) end elsif @mode == "viewer" if @key != "" index = @image_keys.index(@key) if index != nil @start = index else @start = 0 end end @images.push(@image_hash[@image_keys[@start]]) width, height = @images[0].width.to_i, @images[0].height.to_i size = ((width > height ? width : height) > @vwidth.to_i) ? @vwidth : width if width > height @sizestr = %Q[width="#{size}" height="#{(size.to_i*height/width).to_s}"] else @sizestr = %Q[width="#{(size.to_i*width/height).to_s}" height="#{size}"] end if @show_exif and @images[0].type == "jpg" begin require 'exifparser' @exifstr = read_exif_data("#{@image_dir}/#{@images[0].file}") rescue exp = [] exp.push(($!).to_s) ($!).backtrace.each do |btinfo| exp.push(btinfo) end @exifstr = exp end end end end def check_name_filter_dateformat @page_year = "" @page_month = "" @page_day = "" @page_date = nil return if @name_filter == "" begin if @name_filter.index(/[\d]{8}/) != nil @page_year = @name_filter[0,4] @page_month = @name_filter[4,2] @page_day = @name_filter[6,2] @page_date = Date.new(@page_year.to_i, @page_month.to_i, @page_day.to_i) elsif @name_filter.index(/[\d]{6}/) != nil @page_year = @name_filter[0,4] @page_month = @name_filter[4,2] @page_date = Date.new(@page_year.to_i, @page_month.to_i, 1) elsif @name_filter.index(/[\d]{4}/) != nil @page_year = @name_filter[0,4] @page_date = Date.new(@page_year.to_i, 1, 1) end rescue @page_year = "" @page_month = "" @page_day = "" @page_date = nil return end end def make_page_title return if @page_title == "" @t_page_title = String.new(@page_title) @t_page_title.gsub!("@year", @page_year) @t_page_title.gsub!("@month", @page_month) @t_page_title.gsub!("@day", @page_day) begin @t_page_title.gsub!("@subtitle", @images[0].subtitle) rescue end end def format_links(count) page_count = (count - 1) / @num + 1 current_page = @start / @num + 1 first_page = current_page - (MAX_PAGES / 2 - 1) if first_page < 1 first_page = 1 end last_page = first_page + MAX_PAGES - 1 if last_page > page_count last_page = page_count end buf = "

        \n" if current_page > 1 buf << format_link("«Ƭ ", 0, 0, @mode) buf << format_link("<", @start - @num, @num, @mode) end if first_page > 1 buf << "... " end for i in first_page..last_page if i == current_page buf << "#{i} " else buf << format_link(i.to_s, (i - 1) * @num, @num, @mode) end end if last_page < page_count buf << "... " end if current_page < page_count buf << format_link(">", @start + @num, @num, @mode) buf.concat(format_link(" Ǹ»", (page_count - 1) * @num, 0, @mode)) end buf << "

        \n" return buf end def format_link(label, start, num, mode) return format('%s ', _(@cgi.script_name ? @cgi.script_name : ''), mode, make_cgi_param, start, label) end def format_links_viewer buf = "

        \n" if @start == 0 buf << "«" else buf << format_link_viewer("«", @image_keys[@start - 1]) end buf << "  |  " buf << format_link("", (@start / @num) * @num, 0, "list") buf << "  |  " if @start == @image_keys.length - 1 buf << "»" else buf << format_link_viewer("»", @image_keys[@start + 1]) end buf << "

        \n" return buf end def format_link_viewer(label, key) return format('%s', _(@cgi.script_name ? @cgi.script_name : ''), make_cgi_param, key, label) end def format_link_viewer_image(key) return format('%s?%smode=viewer;key=%s', _(@cgi.script_name ? @cgi.script_name : ''), make_cgi_param, key) end def format_links_date return "" unless @name_filter != "" and @title_filter == "" and @subtitle_filter == "" begin buf = "

        \n" if @page_day != "" yesterday = (@page_date - 1).strftime("%Y%m%d") tomorrow = (@page_date + 1).strftime("%Y%m%d") buf << format_link_date(%Q[«#{(@page_date - 1).to_s}], yesterday) buf << format('  |  %s  |  ', _(@cgi.script_name ? @cgi.script_name : ''), _(@mode), _(@order), '') buf << format_link_date(%Q[#{(@page_date + 1).to_s}»], tomorrow) elsif @page_month != "" prevmonth = (@page_date << 1).strftime("%Y%m") nextmonth = (@page_date >> 1).strftime("%Y%m") buf << format_link_date(%Q[«#{(@page_date << 1).to_s[0,7]}], prevmonth) buf << format('  |  %s  |  ', _(@cgi.script_name ? @cgi.script_name : ''), _(@mode), _(@order), '') buf << format_link_date(%Q[#{(@page_date >> 1).to_s[0,7]}»], nextmonth) elsif @page_year != "" year = @page_year.to_i buf << format_link_date(%Q[«#{(year - 1).to_s}], (year - 1).to_s) buf << format('  |  %s  |  ', _(@cgi.script_name ? @cgi.script_name : ''), _(@mode), _(@order), '') buf << format_link_date(%Q[#{(year + 1).to_s}»], (year + 1).to_s) end buf << "

        \n" return buf rescue return "" end end def format_link_date(label, name_filter) cgi_params = make_cgi_param if cgi_params.gsub!(/name=[^;]*;/, "name=#{CGI::escape(name_filter)};") == nil cgi_params = "name=" + CGI::escape(name_filter) + ";" + cgi_params end return format('%s', _(@cgi.script_name ? @cgi.script_name : ''), @mode, cgi_params, label) end def format_link_viewer_date(label, name_filter) return format('%s', _(@cgi.script_name ? @cgi.script_name : ''), name_filter, label) end def format_link_viewer_category(subtitle) buf = "" subtitle.scan(/\[[^\]]*\]/).each do |category| tag = category[1..-2] next if tag[0] == ?[ buf << format('[%s]', _(@cgi.script_name ? @cgi.script_name : ''), CGI::escape("\\[" + tag + "\\]"), tag) end return buf end def format_link_list_category(images) categories = [] images.each do |image| categories |= image.subtitle.scan(/\[[^\]]*\]/) end buf = "" categories.each do |category| tag = category[1..-2] next if tag[0] == ?[ buf << format('[%s]', _(@cgi.script_name ? @cgi.script_name : ''), CGI::escape("\\[" + tag + "\\]"), tag) end return buf end def get_other_mode_link case @mode when "list" format_link("[SLIDESHOW]", @start, @num, "slide") + format_link("[SLIDESHOW(FullScreen)]", @start, @num, "fslide") when "slide" format_link("[LIST]", @start, @num, "list") + format_link("[SLIDESHOW(FullScreen)]", @start, @num, "fslide") when "fslide" format_link("[LIST]", @start, @num, "list") + format_link("[SLIDESHOW]", @start, @num, "slide") end end def make_cgi_param buf = "" buf << "name=#{CGI::escape(@name_filter)};" if @name_filter != "" buf << "title=#{CGI::escape(@title_filter)};" if @title_filter != "" buf << "subtitle=#{CGI::escape(@subtitle_filter)};" if @subtitle_filter != "" buf << "pagetitle=#{CGI::escape(@page_title)};" if @page_title != "" buf << "showinputfield=false;" if not @show_inputfield buf << "order=#{@order};" return buf end def format_options(options, value) return options.collect { |val, label| if val == value "" else "" end }.join("\n") end def format_form @order_options = format_options(ORDER_OPTIONS, @order) @mode_options = format_options(MODE_OPTIONS, @mode ) end def _(str) CGI::escapeHTML(str) end def read_exif_data(file) exifstr = [] str = "" exif = ExifParser.new(file) return exifstr if exif == nil exifstr.push("-- IFD0 (main image) --") exif.each(:IFD0) do |tag| next if tag.name == "Unknown" str = "#{tag.name} : #{tag.to_s}" exifstr.push(str) end exifstr.push("-- Exif SubIFD --") exif.each(:Exif) do |tag| next if tag.name == "Unknown" str = "#{tag.name} : #{tag.to_s}" exifstr.push(str) end exifstr.push("-- MakerNote --") exif.each(:MakerNote) do |tag| next if tag.name == "Unknown" or tag.name == "NikonCameraSerialNumber" str = "#{tag.name} : #{tag.to_s}" exifstr.push(str) end exifstr.push("-- GPS --") exif.each(:GPS) do |tag| next if tag.name == "Unknown" str = "#{tag.name} : #{tag.to_s}" exifstr.push(str) end return exifstr end def js_start_gallery if @mode == "fslide" <<-EOS EOS elsif @mode == "slide" <<-EOS2 EOS2 end end end end begin @cgi = CGI::new if TDiary::Config.instance_method(:initialize).arity == 0 # for tDiary 2.0 or earlier conf = TDiary::Config::new else # for tDiary 2.1 or later conf = TDiary::Config::new(@cgi) end tdiary = TDiary::TDiaryGallery::new( @cgi, 'gallery.rhtml', conf ) head = { 'type' => 'text/html', 'Vary' => 'User-Agent' } body = tdiary.eval_rhtml head['charset'] = conf.encoding head['Content-Length'] = body.bytesize.to_s head['Pragma'] = 'no-cache' head['Cache-Control'] = 'no-cache' print @cgi.header( head ) print body rescue Exception if @cgi then print @cgi.header( 'type' => 'text/plain' ) else print "Content-Type: text/plain\n\n" end puts "#$! (#{$!.class})" puts "" puts $@.join( "\n" ) end tdiary-contrib-3.2.2/util/image-gallery/js/000077500000000000000000000000001213632744000205625ustar00rootroot00000000000000tdiary-contrib-3.2.2/util/image-gallery/js/SmoothGallery/000077500000000000000000000000001213632744000233535ustar00rootroot00000000000000tdiary-contrib-3.2.2/util/image-gallery/js/SmoothGallery/Changelog000066400000000000000000000041231213632744000251650ustar00rootroot00000000000000v1.0: * Initial release v1.0.1: * Fixed bug in jd.gallery.js that prevented more than 10 images in carousel. * Fixed bug in resizer.php that prevented filenames with extensions in uppercase. v1.2: * Fixed thumbGenerator name * Fixed jumping thumbnails bug * In options: - Added useExternalCarousel (boolean, with carouselElement as an element) - Added populateFrom option (element) - Added showCarouselLabel option (boolean) - Added activateCarouselScroller (boolean) - Added slideInfoZoneSlide (boolean) * Switched to mootools 1.11 * Added plugin support for digitarald's history manager * Made a version compatible with name-spaced mootools (to be used with prototype, jquery or others) v2.0: * Code got cleaner, with some refactored functions. Should still be 80% backward-compatible. * Gallery Set (to select which gallery you want to see and switch between galleries) mode. > (replaces the buggy picture wall in earlier betas). * Changed populate functions (more modular) * Added Flush and recreate functions for slides and carousel * Added transitions engine * Real preloader for the slides. * Preloader for the carousel thanks to Tomocchino's preloader class. * In options: - Added options related to new features - Added thumbIdleOpacity (float) - Allowed carouselElement to be an ID of the element (string) - Added thumbCloseCarousel (boolean) - Added carouselHorizontal (boolean) to prevent spliting the carousel in multiple lines if it's horizontal (default: true) * Transitions (change the effect using defaultTransition option): - Old default is fade. - Real Cross-Fading for transparent PNGs: crossfade. - Fading to background: fadebg. - Some example of a neat fade&slide effect: fadeslideleft. - Continuous scrolling : + continuoushorizontal + continuousvertical v2.1beta1: * Compatible with mootools 1.2 * Fixed carouselHorizontal * Fixed external carousel bug * Update History manager from Digitarald * Added plugin support for digitarald's ReMooz (demozoom.html to see it)tdiary-contrib-3.2.2/util/image-gallery/js/SmoothGallery/css/000077500000000000000000000000001213632744000241435ustar00rootroot00000000000000tdiary-contrib-3.2.2/util/image-gallery/js/SmoothGallery/css/ReMooz.css000066400000000000000000000056711213632744000261010ustar00rootroot00000000000000.remooz-element { cursor: -moz-zoom-in; } /** * Box layout */ .remooz-box { position: absolute; top: 0; left: 0; background: #000 no-repeat center; z-index: 100; } .remooz-loading { background-image: url(spinner.gif); } .remooz-body { width: 100%; height: 100%; } .remooz-box-focus.remooz-type-image .remooz-body { cursor: -moz-zoom-out; } .remooz-box-dragging .remooz-body { cursor: move; } /** * Close button */ .remooz-btn-close { position: absolute; left: -15px; top: -15px; width: 30px; height: 30px; text-decoration: none; border: 0; background: url(closebox.png) no-repeat center; visibility: hidden; cursor: pointer; } .remooz-engine-trident4 .remooz-btn-close { background-image: url(closebox.gif); } /** * Caption title */ .remooz-title { position: relative; left: 0; top: 15px; text-align: left; } .remooz-title-bg { position: absolute; left: 0; top: 0; width: 100%; height: 100%; background-color: #000; z-index: 99; -moz-border-radius: 5px; -webkit-border-radius: 5px; /* shadow opacity differs from box shadow because its default set to opacity 0.8 */ -webkit-box-shadow: 0 0 10px rgba(0, 0, 0, 0.9); } .remooz-title-content { position: relative; padding: 5px 15px; color: #fff; z-index: 101; font: 11px/1.5 Verdana, Geneva, Arial, Helvetica, sans-serif; } .remooz-engine-trident4 .remooz-title-bg { display: none; } .remooz-engine-trident4 .remooz-title-content { background-color: #333; } .remooz-title-content h6 { font-size: 1.2em; font-weight: bold; color: #eee; } .remooz-title-content p { color: #eee; } /** * Type specific */ .remooz-type-image img { display: block; border: 0; width: 100%; height: 100%; } /** * Shadow */ .remooz-bg { position: absolute; width: 33px; height: 40px; } .remooz-bg-n { left: 0; top: -40px; width: 100%; background: url(remo_bg_n.png) repeat-x; } .remooz-bg-ne { right: -33px; top: -40px; background: url(remo_bg_ne.png) no-repeat; } .remooz-bg-e { right: -33px; top: 0; height: 100%; background: url(remo_bg_e.png) repeat-y; } .remooz-bg-se { right: -33px; bottom: -40px; background: url(remo_bg_se.png) no-repeat; } .remooz-bg-s { left: 0; bottom: -40px; width: 100%; background: url(remo_bg_s.png) repeat-x; } .remooz-bg-sw { left: -33px; bottom: -40px; background: url(remo_bg_sw.png) no-repeat; } .remooz-bg-w { left: -33px; top: 0; height: 100%; background: url(remo_bg_w.png) repeat-y; } .remooz-bg-nw { left: -33px; top: -40px; background: url(remo_bg_nw.png) no-repeat; } tdiary-contrib-3.2.2/util/image-gallery/js/SmoothGallery/css/img/000077500000000000000000000000001213632744000247175ustar00rootroot00000000000000tdiary-contrib-3.2.2/util/image-gallery/js/SmoothGallery/css/img/carrow1.gif000066400000000000000000000003631213632744000267660ustar00rootroot00000000000000GIF89a+++,,,222... 000111///  ***!!!###---  &&&333!,p'$Ag E[u0ϋ`B1*Bap$)!y&)#šT dC',D{kvg,ޑ9R~wOK)BE)@B>7 37$.!;tdiary-contrib-3.2.2/util/image-gallery/js/SmoothGallery/css/img/carrow2.gif000066400000000000000000000003611213632744000267650ustar00rootroot00000000000000GIF89a+++,,,222... 000111///  ***!!!###---  &&&333!,n'AhRGeK,]:'`+ !8y$H Qa5Gh>>DN;(E]HS(F{$N6AC>"@ D" "!;tdiary-contrib-3.2.2/util/image-gallery/js/SmoothGallery/css/img/closebox.gif000066400000000000000000000005371213632744000272310ustar00rootroot00000000000000GIF89a eee%%%===***000qqqRRR򠠠MMMBBB!,` "2B1p Bb ;t H$ :^!l$ǩ8TtH4+#  \&Md`%A$0A]B1z~ B&Ny`A(WyN'W{'NyB&]iAyB*AVBfp." aWd; MH$S^:ug`:7- t NPs ] xq0d5 "B)HPLLƍd_͜9󗛛7koo߿wHccc9` ̄ aBO]eժU@3~ ڹs`~A3g/(r!P1bWW04ϟ?0!}&d) ԶY>}@)))YP;@v1̷@#"""eݻ-0b)2e3q b P8@Algg`D_5J}ƈc11/?Y .ӧAf}-ހ7dˁ[7pEpB+//@1Pp(yxx XRRf֭X*@Yc?yCI߿T @( x߿,޽˗/(r?lLd)02C-f c|Ý;wX LڇwȆֲ `V3''' h把(Nг0}FJyNNXv`a"bB;ԟǏ TL7o9fd=˗W.]Z `>@MM-o\ %WTIz(:t >mg'ٽˀy<|I NHH-2D9Pd,;en`VHH(9%%e&,@j)X+H?a(Ķ@1#8I8>> ߌ׷yyyʹaaa999'''배||| )))<<<dddfffiiiXXX---ΞCCC+++(((@@@NNNէrrrBBB&&&uuukkkǜooo...RRRۊ!},&0|}yyzzy  y}| U) y{AVMQ@3 {(EB'10 ܹ|ߔ;_xd. ̼co %N2ppgY1H ", 1(ubFg" G f [$17Ad Oz@)M@GhYALqx@ :r FT`@+S];FZ*@!K"p.!O0DM%8Ac"&)22(Sz(LK #^$NϟBM 7DTA7AC`Ǿ$%HY@Zj˛?oylڶq!]tտ*Y1cǐ%SY3B=E]xŗ_ fKa\ɗ}%Yf[n5IEUnԱPE`AȋdbN1ˊ AK/bA1H.tG13hёё$Ikā A#؃Ó@FS9ܱN;SITsM6۴/ S1@C,g&"Jhϡ6ZJ\B^$;tdiary-contrib-3.2.2/util/image-gallery/js/SmoothGallery/css/img/fleche1.png000066400000000000000000000051021213632744000267320ustar00rootroot00000000000000PNG  IHDR&0}(gAMA7tEXtSoftwareAdobe ImageReadyqe< IDATxb? l@9lN(BCf԰#a6(f@ n1@0P!9LUq/?F @L4p N`dC?aM2@ 3 XmXJcҌЀ`? i] @,TB9(߿3 cffffFfeee ,,,4q)@usߙ|7V (ʙ 7Œ BH>:gQ %%Kxā /AA"""?GDD|p"V+ﰰ3zzzAr<"aK'OL#oÀ̠B[ ItrrpB6!G3a t_E/4Z@D; X3~!ڵkwHH~ G$..r(@=4p4(}ӧOLvvvI+!_ W__54ggPC*.A~ǏJ{i%!Gyzz|m VȂ*s:9 :ի'͛7 SEE Rp,V@9R&P=u@1@E<0WϟϔFB! LC^z%{a` JܠA`0(_r  ?P@:#@w1 -V[@s~ @3w11oRRR@MVVP &\( * A Zi oP@jqU; J{ 3>@G9@j.13h- \V)5ʡ?h5s@0gdĄG mŀ(9M 7AmR @ʱ3geeM,@\! ̙AMj` ̝7z!@.,Q^^^E޽'T+R5!&.fX3J B/R!+@UU;J֓ϟ?&T%C;+P ߒA9Z$Fh^%B9N }X;} %%.|jٝmΝׯ_O̠>%JYJOCTRp@ J'N 97ns͛݀wE0/u?|=/"=J\uy,.] 69TA6?՟HCo Z qZ9s& Xׯ_T ǁZ t 2*dpn߾}<<|`%A=/>76xTR0o6W‎csZ?m2MБm,qWֵk]_{Uy%!@>xHb0?0q xŊ;ck]rS*-v|!I.Mlxrd Lx#P|AtقeŌ d <1劑̌89ҧQ<ɔ-c]gω6X1'j6ܺw m XfѢ#$OEJj* E@3̚崔%#!U yT,bF&A/@T{sg @A>ss$L4(6܈#$0+- +" -0d$2 )JH`%89"eyf";tdiary-contrib-3.2.2/util/image-gallery/js/SmoothGallery/css/img/fleche2.png000066400000000000000000000055111213632744000267370ustar00rootroot00000000000000PNG  IHDR&0}(gAMA7tEXtSoftwareAdobe ImageReadyqe< IDATxb?@l @, D߁ߑ|3ĂELX PH'Â8!8,OmR810$aN@d?$߿H31fC(-2ifFFF&(`dcc8zpF) 0:& ed^ ySRVf6"љ<}`fU~@ @̇+Mr-r?2~3 PFPh2333pqq% IH-BOL6MϞ=|%8?t<\]]feeed:ׯ_ 1C(G!)﷬cǎ  h+0X!*f{ɽy柔`hr 訟h HarX ZAƿ¿>8p@Ǐ@KYO<:+`_ 7ȁ 9hai@+O\\]vIh!30@ zO?9聿?~T ~2q$arX=@ PW{-..Nײ`ؤ hW@X`u 5 h`޼yryyyIm6wC䨏4!uIr… esss9 alZ:+񉇇[jZ/] E%#!&/_.GQ^n33}DJ||&@_@GW !"cbbcݺu9997>CII70};5@ UpeCj۶mb&t ? ,Z˫Ϡv`k1!b48 \VV,ZZZ7AA/P9+0ҿ@81U@@+pةSjkkm">Gquu= o; @F-u-@r%'.]f )\Ƈ}||- DJ G:7бEI bVВ,ĀmwSj,2@=(fxx1` Z߁ACA.Bt:!tt0B9A0 w9A#:V (m` /@Gߐ[?&.N@(4@lPuW1aж(؀$+0DX@@4mTP] _@@';;_hQkb| W@z  t.E@VXa 1}b03]0`&.pƢ tfD ~r81AZPXa*3ZbźӪѨZrjW+XA-ZpSYK‚vpgɭ;n^św/_ E\8`q&Y]ʴӅYb̀-EB-,,Jk;u]Ǿ,ݻe |7y\䰏Ås_Wݛt Ө-mא`͟~~z݋/v_]xxpƊf1 voNZbHI!YX?8Yh Ao5USta)cs;h\8xTB*GciձƣLʋ& P ^ԗaW&~`JIbnզXo^Wh `4 F}>'Ngjg h+.٠H:أ*M*ꨤj*]ꪬ꫰*무j'! , dihlp,tmx|pHrl:ШtJZجv:( 6ap݃z݆|Jy㙗w=}Ko\?g<,! |_v0XV X[d]b^'ͅjZɵA!v !lsb+ZW/ 6Z^7\"rx v`X$5$#ʸ#*v!{.*a(8ar GfdNa}%B"&hܛ|b]p_m-tݢ2vz)y()fr G+)bBfvvP*{9Zxvu,Q!z^"+kik9gJ`k.Da>#|H卦99>2I8gH@ `.YLf4|҈Fs ,O% l' map2@,Y(fIi+*{r c2httM?4Ԁn7zEF1I،4g/ `,Gpjh-{5TbӭxyZۋHl砇.SEꬷ.~B! , dihlp,tmx|pHrl:ШtJZجv:ix6hpA!M_ x<@lx}ipo}{jon|nwli{km`^+]k  gt Аg hhet}ڈiV4 7P8(``A A.(p@ɓ| )AI `T$P@M2c\fN<\d1քpΞE=)է֠d ThX!A0+䄻wxfz 2ΛC7Fvy%868rLǔV3eH5m軪'oԬYxӮ!gw< 0OAss,HOu K>aA]k0|Λξ{зWw}<]uwY|] 2ũp\P`l]gAymLxȄ5l2 N@c'RL4g`"8/ʸc=V,B5NV$,fN7b)h8&X{)htezʼ' ȷfY烲!z墆ieIgR-_yv*hpy $Ph@ ݂݊;F1Y t2 d<#Zuׄvkoia&1?b+n&BChkna-[E{Er *+Y@$n).2 )&ty$x-yL2^Rd K%4Va_3VI8Fo5nL(7{0mX2l05$h`[y->sЧ} XKG9'*y[3P_ZXYʩ&-LQKvGhOX*wɫnfx2-E7K1 yxޥIo7ݎ8V8|/o<]7G/Wo'! , dihlp,tmx|pHrl:ШtJZجv:g0tqpچ1O yy}u~m{|~jxqov}jwn~poxzzpeg,]wo  h ih~ؒ juuNХG\A?T@0S0$yA L e'QBX`M2g>в2i\ %\,З&ss$Ԙ(d3̣<.Aȕ1hEH0n , `]x%o߿uƣY38V,ٚ*+1g~C fӊUho!]A !ூ $XFxǑU| 'P'jt{~SaL2#^r VWT̊^@>cCx׉Hbw<"w)VK!wvc is)ʓfyщ̜l0|2 ܉Y pb(gz'ꢡ%t)] 4i$ TO,hmg_' 0]lפ77ÜKXYCeq%(6maPD" kagw]Y }ܮ劽v-k%$o{?/q [;?o^ӻ-T=rtB $Pi &z-&_H=l@]gV|ebfe֘ovih3D8tp x኏xMy#:g"vmAbnuPf=f ^0 ~ Ȣ[xXNhԉt#Q%i22֗43&@]&֠eZt(%ߊȚQV7h1 &ommۗXג)(ڱb `v}A!^sܧSZ*Uu~ͅyyIz'AYٙio6'l^N) Տz4f [AuF6Z]8ڋ}뛆2[z oGȚ@lІG05&H, ɯ&g1P`pŌL|-KV؀Mis=h9s Y&\:ۇhrJ-jW]sud3l^HAʉv&ph-/&ܼ8K8\*,yx-<CXn=*|7 6[TtQo'7П! , dihlp,tmx|pHrl:ШtJZجv:);Oano#~x< 7 yye||g~vx o{fzhwy qrwpnGea^+yɂ  ѵۀlvɊmnA$߷ps` X0eB 0$Ǝ$ir#J `\˘%c:g#M-} JRP/ UN<dP ʧ7 Й,bXʝpNP[qu k  Ob72$38[rFYh3GN|z&sB fWAbtZ0܂v^q;[9l .tv<7V^^!j nYuvYd@ Te]Afuq=[f&Z&R&"{n.quAb̂ HY8̊!8׆!1ɣ`P` ^0Ф\ahYRh؍ȧ%`]F @'\rk2@'3>&z9܌o䵝fxʼn͡Ee'LVݕ@sJ&7N0~'ZN\ـ'c^#lڪ"쉭+z|ĩj]Ǟg' v]c/ڐ^&fE!H^ ݆6k9ʫ0Jp &c*kp@x[辙1]Eez&Zsv%~gRۀ\'8k@|z+i[W6^0cvcs3Is}zb3GUp/GW_\?Kp|wu~Wv'p*tzr_= 1cbD.n;]/o'! , dihlp,tmx|pHrl:ШtJZجv:ph4i7f9=x$ِ6=vx|jwzciu p~xfc~y{~yv{o ea^+ `Ô ºy”mٕm“nгCLۛz 0a@Qƒ2j\@/\ԸAE %H'+l1%Ŕ3IL gN |<3ˡ!BSҠ|Zfŕ-K@ 1EچҪpǚj`Ѯjε sӂT@Ykk \ u%e` WÁ&P0as뎶a1굪1T vI~kmC  $(.wʙWH+!za޲oWλq/x`엝b 'ͻ9rl)m* B)ßeA˜Fle}r e!ah!gtۃɇH3*px8`բXcjI` S%kY@o j j][ed%Y0fl)bg g'E&ϭYfqfpxB  G9|g,u\٘l-yU] Qzn)Z-* 暤[*쫦'†JZuW5͹(\}W'4)!ofnj#zغY5cKVl[,YNpYek\ 0]K"ž H ,UZWia:ہͥɌfJ䍎N2jL,'JlB]eZShj^YArcdrWffC+RʲP킧]دR dP̘Ʊs)'pjp lpo#yˍH`;⒫exٕf=7ޞ;]!o'7'! , dihlp,tmx|pHrl:ШtJZجv:P h)l#1O;~x{}~cvw ~|zx| gkk|kyqzd^+ oypo zB90a GE @qA\@#Ǎ rCɓ?-^=Hl/SE'7G/WB! , dihlp,tmx|pHrl:ШtJZجv:(8!6̮{~6x y}~ul lcp tkizzoye^+ {`фzͿ ьyq[ =k$0  (p@ŋ4\̶#ǏDxAI @b%ʕ f,i2ȟ [s$͡' ZNJFw3FScδ8hhh(@`@@Aʝ R5ΝA$jZl6̭`{뮭p_ niH yH +,ʋ1EzeEw{Y,0ٻ ,{8Z 7 '>aAlktqǵ޶q7UY:k=6m* @c%s}eV3GۂX!3!_ b kZff%B`{}^2&[bȕ|}HXF` "h1qS֠Vf{ӥiYMz7AYc&$tԵpnةxxꉀ2v)Emx.e5)W< i T@$|05"HΑZjt~ިx kE+t}'k[[IJV(+!+Apbی'&XmVq2'>;m"^8kay6tIb2&|- 0r$'d"E]\_Λr Xe-Y G]BޟHh.iYIGF4L\%6dɅVo `c +m;\ Hjt#wYH~0q*vk| .ANdBP\+!/`#ꬷNEEn/ !;tdiary-contrib-3.2.2/util/image-gallery/js/SmoothGallery/css/img/open.gif000066400000000000000000000007511213632744000263520ustar00rootroot00000000000000GIF89a*0fff !!!̊$$$xxxKKKZZZWWWNNNrrr---cccϫ```]]]333***ᓓ!0,*@p(tHRl6L-I:MYpJ_  F<q&<M@$@[ @a(5a_2O4IeӦMjϟ?|8H\RR򭼼k//EEE"q  @ p"wp[[Fw@uaaaSLYjlBYapp B#h %Z hf &hKuڵd&^HB`t5,߼y#@GJ LA__* YHBZH۱c Y Hƻy,B3K @x>|ࡖEhfȢ0jYf?Y}O-z @ x/e+$3YM-|}}ͺ@ d4x~bJ}-?%|y 666X<5G`H">>$=d @y)V }'nr,ٳH @LHb3&((,% 3\Â4py]YY9ǏXݻ3!*4 ĄURheeuT߀ Yf CHzT"##a3 q%$$޿G%^x1 )U1@>mmm>Z$*b &,zm2kk'Z]@,kpqqyIEoEa uuZ ] YZ,3/b|FW@L8>@x|\RcS@@ YLd̠m3H> c444,^~L0^d@kAq/~@jE"x[o۶m WH 6 &`@jE" l"GG 5"•@\g@@).00># a(2 |0 6q_ <]v֣˗!T3f@1jg f%gA%: >K@11~ & b,'. +R>-u|ςIENDB`tdiary-contrib-3.2.2/util/image-gallery/js/SmoothGallery/css/img/remo_bg_e.png000066400000000000000000000017361213632744000273520ustar00rootroot00000000000000PNG  IHDR!A pHYs  iCCPPhotoshop ICC profilexc``$PPTR~!11 !/?/020|pYɕ4\PTp(%8 CzyIA c HRvA cHvH3c OIjE s~AeQfzFcJ~RBpeqIjng^r~QA~QbIj ^<#U*( >1H.-*%CC"C= o]KW0cc btY9y!K[z,٦}cg͡3#nM4}2?~ 4]gAMA|Q cHRMz%u0`:o_F0IDATxTű 01Ky^J1=eĨ|RpIENDB`tdiary-contrib-3.2.2/util/image-gallery/js/SmoothGallery/css/img/remo_bg_n.png000066400000000000000000000017321213632744000273570ustar00rootroot00000000000000PNG  IHDR(X pHYs  iCCPPhotoshop ICC profilexc``$PPTR~!11 !/?/020|pYɕ4\PTp(%8 CzyIA c HRvA cHvH3c OIjE s~AeQfzFcJ~RBpeqIjng^r~QA~QbIj ^<#U*( >1H.-*%CC"C= o]KW0cc btY9y!K[z,٦}cg͡3#nM4}2?~ 4]gAMA|Q cHRMz%u0`:o_F,IDATxb``db`!F a0!qPpQE1H/`ZIENDB`tdiary-contrib-3.2.2/util/image-gallery/js/SmoothGallery/css/img/remo_bg_ne.png000066400000000000000000000025271213632744000275270ustar00rootroot00000000000000PNG  IHDR!([, pHYs  iCCPPhotoshop ICC profilexc``$PPTR~!11 !/?/020|pYɕ4\PTp(%8 CzyIA c HRvA cHvH3c OIjE s~AeQfzFcJ~RBpeqIjng^r~QA~QbIj ^<#U*( >1H.-*%CC"C= o]KW0cc btY9y!K[z,٦}cg͡3#nM4}2?~ 4]gAMA|Q cHRMz%u0`:o_FIDATxڬV0Ec{!B e}'C1L#B3d` e#LZ9 b<eU=Lìl dD Fs(Ď=[,Y0cH5(a%ٱeŒSe9*q́VF]du+oyenĖUx烳(čO89ԻW1/q̘*VB8*+U!_Qn3ܞ*|IENDB`tdiary-contrib-3.2.2/util/image-gallery/js/SmoothGallery/css/img/remo_bg_nw.png000066400000000000000000000023361213632744000275470ustar00rootroot00000000000000PNG  IHDR!([, pHYs  iCCPPhotoshop ICC profilexc``$PPTR~!11 !/?/020|pYɕ4\PTp(%8 CzyIA c HRvA cHvH3c OIjE s~AeQfzFcJ~RBpeqIjng^r~QA~QbIj ^<#U*( >1H.-*%CC"C= o]KW0cc btY9y!K[z,٦}cg͡3#nM4}2?~ 4]gAMA|Q cHRMz%u0`:o_F0IDATxڤ DKe8iu9lC7NxE?TXz@^hCglP p`~!ZȀYh)CXvER2;UG܋o,: H! B $A:tm'wCxBT_F_&*M\͍t_;6JIENDB`tdiary-contrib-3.2.2/util/image-gallery/js/SmoothGallery/css/img/remo_bg_s.png000066400000000000000000000017311213632744000273630ustar00rootroot00000000000000PNG  IHDR! 4 pHYs  iCCPPhotoshop ICC profilexc``$PPTR~!11 !/?/020|pYɕ4\PTp(%8 CzyIA c HRvA cHvH3c OIjE s~AeQfzFcJ~RBpeqIjng^r~QA~QbIj ^<#U*( >1H.-*%CC"C= o]KW0cc btY9y!K[z,٦}cg͡3#nM4}2?~ 4]gAMA|Q cHRMz%u0`:o_F+IDATxb`0fb`fb*cdž C-IENDB`tdiary-contrib-3.2.2/util/image-gallery/js/SmoothGallery/css/img/remo_bg_se.png000066400000000000000000000023541213632744000275320ustar00rootroot00000000000000PNG  IHDR!! pHYs  iCCPPhotoshop ICC profilexc``$PPTR~!11 !/?/020|pYɕ4\PTp(%8 CzyIA c HRvA cHvH3c OIjE s~AeQfzFcJ~RBpeqIjng^r~QA~QbIj ^<#U*( >1H.-*%CC"C= o]KW0cc btY9y!K[z,٦}cg͡3#nM4}2?~ 4]gAMA|Q cHRMz%u0`:o_F>IDATxڜk ?C$])k:XaFQJC&B{RzjjX?>UNy4[:I"xNP;h 99^&ɹdY<Z"'@epS=RN. !z1$2>LS9Po5fb!yC| V{4cPCvxB $,㠇p}!'dfĪ'NjZs\7]̶P/OŞd~vvxS7S 鶳?%IENDB`tdiary-contrib-3.2.2/util/image-gallery/js/SmoothGallery/css/img/remo_bg_sw.png000066400000000000000000000023071213632744000275520ustar00rootroot00000000000000PNG  IHDR!! pHYs  iCCPPhotoshop ICC profilexc``$PPTR~!11 !/?/020|pYɕ4\PTp(%8 CzyIA c HRvA cHvH3c OIjE s~AeQfzFcJ~RBpeqIjng^r~QA~QbIj ^<#U*( >1H.-*%CC"C= o]KW0cc btY9y!K[z,٦}cg͡3#nM4}2?~ 4]gAMA|Q cHRMz%u0`:o_FIDATxڌ Cvtil a@ zsF.{VT ]9˻s|tD1H.-*%CC"C= o]KW0cc btY9y!K[z,٦}cg͡3#nM4}2?~ 4]gAMA|Q cHRMz%u0`:o_F'IDATxbd`dF4D23010Aif$:K_IENDB`tdiary-contrib-3.2.2/util/image-gallery/js/SmoothGallery/css/img/spinner.gif000066400000000000000000000030411213632744000270620ustar00rootroot00000000000000GIF89a? %%%666DDDLLLTTT[[[dddlllttt{{{! NETSCAPE2.0!?,n RC~oY-1JeF$v1_oa SFr29?,  8:BS".J#EJ')C-W7"# ,W6C.&>K,C9!;K 6?>$'75-8)+b1)#/(?5)?:>!?!4W1/? >8K>?$:IBA!?, Xp$zD+!=3~/T))@BXr C Ȅ w6D(>IB$0B1D3,?:%A!?,QpXi Bc~6CY[@~g#lAPT:ȆE ~'FD2:C<7 >B.%HMC"31WBA!?, OLH,M?ܢU2? 4B0%Y*@~7jP/D~ JH).{?(<{?A!?,PoY _);^dOXʱ8"$ gr)12Db8 ?*=B1f.f6^A!?, OpňB,CwȅFU!2d21AHߢx$- @~-X=? ?(D0D =?NCA!?, VpH̸S ɼ>SHT.YB 8dDA6 )hB d+h ? ?,C"+?=2"C=a5 qG>7B OGA!?, N0 BEp ! CzZS+䞞_` ~ꩠ8VH( ?4G.M? ?6zG_?HA!?, U3ȟ!B_vѣu SV1 FY꓾M ݘ]>ZX*X "/I8??PG/ )??8i$>?A!?,SWW O\~AWP~(9Fñ6js|G ! 5!'7?&*?0)#C:?!C1/? A;tdiary-contrib-3.2.2/util/image-gallery/js/SmoothGallery/css/jd.gallery.css000066400000000000000000000133671213632744000267220ustar00rootroot00000000000000#myGallery, #myGallerySet, #flickrGallery { width: 720px; height: 720px; z-index:5; border: 1px solid #000; } .jdGallery a { outline:0; } #flickrGallery { width: 500px; height: 334px; } #myGallery img.thumbnail, #myGallerySet img.thumbnail { display: none; } .jdGallery { overflow: hidden; position: relative; } .jdGallery img { border: 0; margin: 0; } .jdGallery .slideElement { width: 100%; height: 100%; background-color: #000; background-repeat: no-repeat; background-position: center center; background-image: url('img/loading-bar-black.gif'); } .jdGallery .loadingElement { width: 100%; height: 100%; position: absolute; left: 0; top: 0; background-color: #000; background-repeat: no-repeat; background-position: center center; background-image: url('img/loading-bar-black.gif'); } .jdGallery .slideInfoZone { position: absolute; z-index: 10; width: 100%; margin: 0px; left: 0; bottom: 0; height: 40px; background: #333; color: #fff; text-indent: 0; overflow: hidden; } * html .jdGallery .slideInfoZone { bottom: -1px; } .jdGallery .slideInfoZone h2 { padding: 0; font-size: 80%; margin: 0; margin: 2px 5px; font-weight: bold; color: inherit; } .jdGallery .slideInfoZone p { padding: 0; font-size: 60%; margin: 2px 5px; color: #eee; } .jdGallery div.carouselContainer { position: absolute; height: 135px; width: 100%; z-index: 10; margin: 0px; left: 0; top: 0; } .jdGallery a.carouselBtn { position: absolute; bottom: 0; right: 30px; height: 20px; /*width: 100px; background: url('img/carousel_btn.gif') no-repeat;*/ text-align: center; padding: 0 10px; font-size: 13px; background: #333; color: #fff; cursor: pointer; } .jdGallery .carousel { position: absolute; width: 100%; margin: 0px; left: 0; top: 0; height: 115px; background: #333; color: #fff; text-indent: 0; overflow: hidden; } .jdExtCarousel { overflow: hidden; position: relative; } .jdGallery .carousel .carouselWrapper, .jdExtCarousel .carouselWrapper { position: absolute; width: 100%; height: 78px; top: 10px; left: 0; overflow: hidden; } .jdGallery .carousel .carouselInner, .jdExtCarousel .carouselInner { position: relative; } .jdGallery .carousel .carouselInner .thumbnail, .jdExtCarousel .carouselInner .thumbnail { cursor: pointer; background: #000; background-position: center center; float: left; border: solid 1px #fff; } .jdGallery .wall .thumbnail, .jdExtCarousel .wall .thumbnail { margin-bottom: 10px; } .jdGallery .carousel .label, .jdExtCarousel .label { font-size: 13px; position: absolute; bottom: 5px; left: 10px; padding: 0; margin: 0; } .jdGallery .carousel .wallButton, .jdExtCarousel .wallButton { font-size: 10px; position: absolute; bottom: 5px; right: 10px; padding: 1px 2px; margin: 0; background: #222; border: 1px solid #888; cursor: pointer; } .jdGallery .carousel .label .number, .jdExtCarousel .label .number { color: #b5b5b5; } .jdGallery a { font-size: 100%; text-decoration: none; color: inherit; } .jdGallery a.right, .jdGallery a.left { position: absolute; height: 99%; width: 25%; cursor: pointer; z-index:10; filter:alpha(opacity=20); -moz-opacity:0.2; -khtml-opacity: 0.2; opacity: 0.2; } * html .jdGallery a.right, * html .jdGallery a.left { filter:alpha(opacity=50); } .jdGallery a.right:hover, .jdGallery a.left:hover { filter:alpha(opacity=80); -moz-opacity:0.8; -khtml-opacity: 0.8; opacity: 0.8; } .jdGallery a.left { left: 0; top: 0; background: url('img/fleche1.png') no-repeat center left; } * html .jdGallery a.left { background: url('img/fleche1.gif') no-repeat center left; } .jdGallery a.right { right: 0; top: 0; background: url('img/fleche2.png') no-repeat center right; } * html .jdGallery a.right { background: url('img/fleche2.gif') no-repeat center right; } .jdGallery a.open { left: 0; top: 0; width: 100%; height: 100%; } .withArrows a.open { position: absolute; top: 0; left: 25%; height: 99%; width: 50%; cursor: pointer; z-index: 10; background: none; -moz-opacity:0.8; -khtml-opacity: 0.8; opacity: 0.8; } .withArrows a.open:hover { background: url('img/open.png') no-repeat center center; } * html .withArrows a.open:hover { background: url('img/open.gif') no-repeat center center; filter:alpha(opacity=80); } /* Gallery Sets */ .jdGallery a.gallerySelectorBtn { z-index: 15; position: absolute; top: 0; left: 30px; height: 20px; /*width: 100px; background: url('img/carousel_btn.gif') no-repeat;*/ text-align: center; padding: 0 10px; font-size: 13px; background: #333; color: #fff; cursor: pointer; opacity: .4; -moz-opacity: .4; -khtml-opacity: 0.4; filter:alpha(opacity=40); } .jdGallery .gallerySelector { z-index: 20; width: 100%; height: 100%; position: absolute; top: 0; left: 0; background: #000; } .jdGallery .gallerySelector h2 { margin: 0; padding: 10px 20px 10px 20px; font-size: 20px; line-height: 30px; color: #fff; } .jdGallery .gallerySelector .gallerySelectorWrapper { overflow: hidden; } .jdGallery .gallerySelector .gallerySelectorInner div.galleryButton { margin-left: 10px; margin-top: 10px; border: 1px solid #888; padding: 5px; height: 40px; color: #fff; cursor: pointer; float: left; } .jdGallery .gallerySelector .gallerySelectorInner div.hover { background: #333; } .jdGallery .gallerySelector .gallerySelectorInner div.galleryButton div.preview { background: #000; background-position: center center; float: left; border: none; width: 40px; height: 40px; margin-right: 5px; } .jdGallery .gallerySelector .gallerySelectorInner div.galleryButton h3 { margin: 0; padding: 0; font-size: 12px; font-weight: normal; } .jdGallery .gallerySelector .gallerySelectorInner div.galleryButton p.info { margin: 0; padding: 0; font-size: 12px; font-weight: normal; color: #aaa; } tdiary-contrib-3.2.2/util/image-gallery/js/SmoothGallery/css/layout.css000066400000000000000000000020751213632744000261760ustar00rootroot00000000000000body { color: #ccc; font-family: "Trebuchet MS", "Lucida Grande", Arial, Helvetica, sans-serif; margin: 0 auto; padding: 0; font-size: 0.6em; background: #111 url('../images/bg/gradient1.gif') top left repeat-x; } h1 { color: #fff; font-size: 47px; font-weight: bolder; margin: 0 40px; padding: 0.08em 0; } h1 sup { color: #ddd; } h1 a { color: #fff; text-decoration: none; } h1 .company, h1 a .company { color: #d01a71; } h2 { color: #ddd; font-size: 2.5em; } h3 { color: #fff; font-size: 1.5em; } h4 { font-size: 1.3em; } .content { margin: 0 20px; } .content a { color: #fff; } .content p.linkage { margin-top: 2em; text-align: right; font-size: 1.7em; color: #ddd; } .content p.linkage a { color: #fff; } /*.content p.linkage a { color: #fff; background: url('../images/bg/biglink_off.gif') center right no-repeat; padding: 10px 20px; text-decoration: none; } .content p.linkage a:hover { background: url('../images/bg/biglink_on.gif') center right no-repeat; font-style: italic; }*/ #myGallery { text-align: left; margin: 0 auto; }tdiary-contrib-3.2.2/util/image-gallery/js/SmoothGallery/license.txt000066400000000000000000000773271213632744000255560ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONStdiary-contrib-3.2.2/util/image-gallery/js/SmoothGallery/resizer.php000066400000000000000000000066051213632744000255560ustar00rootroot00000000000000tdiary-contrib-3.2.2/util/image-gallery/js/SmoothGallery/scripts/000077500000000000000000000000001213632744000250425ustar00rootroot00000000000000tdiary-contrib-3.2.2/util/image-gallery/js/SmoothGallery/scripts/Changelog000066400000000000000000000041231213632744000266540ustar00rootroot00000000000000v1.0: * Initial release v1.0.1: * Fixed bug in jd.gallery.js that prevented more than 10 images in carousel. * Fixed bug in resizer.php that prevented filenames with extensions in uppercase. v1.2: * Fixed thumbGenerator name * Fixed jumping thumbnails bug * In options: - Added useExternalCarousel (boolean, with carouselElement as an element) - Added populateFrom option (element) - Added showCarouselLabel option (boolean) - Added activateCarouselScroller (boolean) - Added slideInfoZoneSlide (boolean) * Switched to mootools 1.11 * Added plugin support for digitarald's history manager * Made a version compatible with name-spaced mootools (to be used with prototype, jquery or others) v2.0: * Code got cleaner, with some refactored functions. Should still be 80% backward-compatible. * Gallery Set (to select which gallery you want to see and switch between galleries) mode. > (replaces the buggy picture wall in earlier betas). * Changed populate functions (more modular) * Added Flush and recreate functions for slides and carousel * Added transitions engine * Real preloader for the slides. * Preloader for the carousel thanks to Tomocchino's preloader class. * In options: - Added options related to new features - Added thumbIdleOpacity (float) - Allowed carouselElement to be an ID of the element (string) - Added thumbCloseCarousel (boolean) - Added carouselHorizontal (boolean) to prevent spliting the carousel in multiple lines if it's horizontal (default: true) * Transitions (change the effect using defaultTransition option): - Old default is fade. - Real Cross-Fading for transparent PNGs: crossfade. - Fading to background: fadebg. - Some example of a neat fade&slide effect: fadeslideleft. - Continuous scrolling : + continuoushorizontal + continuousvertical v2.1beta1: * Compatible with mootools 1.2 * Fixed carouselHorizontal * Fixed external carousel bug * Update History manager from Digitarald * Added plugin support for digitarald's ReMooz (demozoom.html to see it)tdiary-contrib-3.2.2/util/image-gallery/js/SmoothGallery/scripts/History.Routing.js000066400000000000000000000062131213632744000304710ustar00rootroot00000000000000/** * History.Routing * * @version 2.0 * * @license MIT License * @author Harald Kirschner * @copyright 2008 Author */ History.implement(new Options()); History.implement({ options: { separator: ';' }, routes: [], register: function(route) { if (this.routes.push(route) == 1) this.addEvent('changed', this.match); }, unregister: function(route) { this.routes.remove(route); }, match: function(state, previous, manual) { if (!manual) this.routes.each(Function.methodize('match', this.state)); }, generate: function() { return this.routes.map(Function.methodize('generate')).clean().join(this.options.separator); }, update: function() { return this.setState(this.generate()); } }); History.Route = new Class({ Implements: [Events, Options], /** * pattern: Regular expression that matches the string updated from onGenerate * defaults: Default values array, initially empty. * flags: When regexp is a String, this is the second argument for new RegExp. * skipDefaults: default true; generate is not called when current values are similar to the default values. * generate: Should return the string for the state string, values are first argument * onMatch: Will be called when the regexp matches, with the new values as argument. */ options: { skipDefaults: true, defaults: [], pattern: null, flags: '', generate: function(values) { return values[0]; }, onMatch: $empty }, initialize: function(options){ this.setOptions(options); this.pattern = this.options.pattern || '(.*)'; if ($type(this.pattern) == 'string') this.pattern = new RegExp(this.pattern, this.options.flags); this.values = this.defaults = this.options.defaults.slice(); History.register(this); return this; }, setValues: function(values) { if (this.values.toString() == values.toString()) return this; this.values = values; History.update(); return this; }, setValue: function(index, value) { if (this.values[index] == value) return this; this.values[index] = value; History.update(); return this; }, build: function(values) { var tmp = this.values.slice(); this.values = values; var state = History.generate(); this.values = tmp; return state; }, destroy: function() { History.unregister(this); }, generate: function() { if (this.options.skipDefaultMatch && (String(this.values) == String(this.defaults))) return null; return this.options.generate.call(this, this.values); }, match: function(state) { var bits = state.match(this.pattern); var defaults = this.defaults; if (bits) { bits.splice(0, 1); for (var i = 0, j = bits.length; i < j; i++) bits[i] = $pick(bits[i], defaults[i] || null); if (String(bits) != String(defaults)) this.values = bits; } else { this.values = this.defaults.slice(); } this.fireEvent('onMatch', [this.values, this.defaults]); } }); Function.methodize = function(name) { var args = Array.slice(arguments, 1); return function(obj) { return obj[name].apply(obj, args); }; }; tdiary-contrib-3.2.2/util/image-gallery/js/SmoothGallery/scripts/History.js000066400000000000000000000051251213632744000270440ustar00rootroot00000000000000/** * History * * @version 1.0 * * @license MIT License * @author Harald Kirschner * @copyright 2008 Author */ var History = $extend(history, { implement: function(obj) { return $extend(this, obj); } }); History.implement(new Events($empty)); History.implement({ state: null, start: function() { if (this.started) return this; this.state = this.getHash(); if (Browser.Engine.trident) { var iframe = new Element('iframe', { 'src': "javascript:''", 'styles': { 'position': 'absolute', 'top': '-1000px' } }).inject(document.body).contentWindow; var writeState = function(state) { iframe.document.write('Moo!'); iframe.document.close(); }; $extend(this, { '$listener': function(state) { state = decodeURIComponent(state); if (this.state != state) this.setHash(state).changeState(state); }.bind(this), 'setState': function(state, force) { if (this.state != state || force) { if (!force) this.setHash(state).changeState(state, true); writeState(state); } return this; }, 'trace': function() { var state = this.getHash(); if (state != this.state) writeState(state); } }); var check = (function() { if (iframe.document && iframe.document.body) { check = $clear(check); if (!iframe.document.body.innerHTML) this.setState(this.state); } }).periodical(50, this); } else { if (Browser.Engine.presto915) { new Element('img', { 'src': "javascript:location.href='javascript:History.trace();';", 'styles': { 'position': 'absolute', 'top': '-1000px' } }).inject(document.body); } } this.trace.periodical(150, this); this.started = true; return this; }, changeState: function(state, manual) { var stateOld = this.state; this.state = state; this.fireEvent('changed', [state, stateOld, manual]); }, trace: function() { var state = this.getHash(); if (state != this.state) this.changeState(state); }, getHash: function() { var href = location.href, pos = href.indexOf('#') + 1; return (pos) ? href.substr(pos) : ''; }, setHash: function(state) { location.hash = '#' + state; return this; }, setState: function(state) { if (this.state !== state) this.setHash(state).changeState(state, true); return this; }, getState: function() { return this.state; } }); tdiary-contrib-3.2.2/util/image-gallery/js/SmoothGallery/scripts/ReMooz.js000066400000000000000000000256471213632744000266310ustar00rootroot00000000000000/** * ReMooz - Zoomer * * Inspired by so many boxes and zooms * * @version 1.0 * * @license MIT-style license * @author Harald Kirschner * @copyright Author */ var ReMooz = new Class({ Implements: [Events, Options, Chain], options: { link: null, type: 'image', container: null, className: null, centered: false, dragging: true, closeOnClick: true, shadow: (Browser.Engine.trident) ? 'onOpenEnd' : 'onOpen', // performance resize: true, margin: 20, resizeFactor: 0.95, resizeLimit: false, // {x: 640, y: 640} fixedSize: false, cutOut: true, addClick: true, opacityLoad: 0.6, opacityResize: 1, opacityTitle: 0.9, resizeOptions: {}, fxOptions: {}, closer: true, parse: false, // 'rel' parseSecure: false, temporary: false, onBuild: $empty, onLoad: $empty, onOpen: $empty, onOpenEnd: $empty, onClose: $empty, onCloseEnd: $empty, generateTitle: function(el) { var text = el.get('title'); if (!text) return false; var title = text.split(' :: '); var head = new Element('h6', {'html': title[0]}); return (title[1]) ? [head, new Element('p', {'html': title[1]})] : head; } }, initialize: function(element, options) { this.element = $(element); this.setOptions(options); if (this.options.parse) { var obj = this.element.getProperty(this.options.parse); if (obj && (obj = JSON.decode(obj, this.options.parseSecure))) this.setOptions(obj); } var origin = this.options.origin; this.origin = ((origin) ? $(origin) || this.element.getElement(origin) : null) || this.element; this.link = this.options.link || this.element.get('href') || this.element.get('src'); this.container = $(this.options.container) || this.element.getDocument(); this.bound = { 'click': function(e) { this.open.delay(1, this); return false; }.bind(this), 'close': this.close.bind(this), 'dragClose': function(e) { if (e.rightClick) return; this.close(); }.bind(this) }; if (this.options.addClick) this.bindToElement(); }, destroy: function() { if (this.box) this.box.destroy(); this.box = this.tweens = this.body = this.content = null; }, bindToElement: function(element) { ($(element) || this.element).addClass('remooz-element').addEvent('click', this.bound.click); return this; }, getOriginCoordinates: function() { var coords = this.origin.getCoordinates(); delete coords.right; delete coords.bottom; return coords; }, open: function(e) { if (this.opened) return (e) ? this.close() : this; this.opened = this.loading = true; if (!this.box) this.build(); this.coords = this.getOriginCoordinates(); this.coords.opacity = this.options.opacityLoad; this.coords.display = ''; this.tweens.box.set(this.coords); this.box.addClass('remooz-loading'); ReMooz.open(this.fireEvent('onLoad')); this['open' + this.options.type.capitalize()](); return this; }, finishOpen: function() { this.tweens.fade.start(0, 1); this.drag.attach(); this.fireEvent('onOpenEnd').callChain(); }, close: function() { if (!this.opened) return this; this.opened = false; ReMooz.close(this.fireEvent('onClose')); if (this.loading) { this.box.setStyle('display', 'none'); return this; } this.drag.detach(); this.tweens.fade.cancel().set(0).fireEvent('onComplete'); if (this.tweens.box.timer) this.tweens.box.clearChain(); var vars = this.getOriginCoordinates(); if (this.options.opacityResize != 1) vars.opacity = this.options.opacityResize; this.tweens.box.start(vars).chain(this.closeEnd.bind(this)); return this; }, closeEnd: function() { if (this.options.cutOut) this.element.setStyle('visibility', 'visible'); this.box.setStyle('display', 'none'); this.fireEvent('onCloseEnd').callChain(); if (this.options.temporary) this.destroy(); }, openImage: function() { var tmp = new Image(); tmp.onload = tmp.onabort = tmp.onerror = function(fast) { this.loading = tmp.onload = tmp.onabort = tmp.onerror = null; if (!tmp.width || !this.opened) { this.fireEvent('onError').close(); return; } var to = {x: tmp.width, y: tmp.height}; if (!this.content) this.content = $(tmp).inject(this.body); else tmp = null; this[(this.options.resize) ? 'zoomRelativeTo' : 'zoomTo'].create({ 'delay': (tmp && fast !== true) ? 1 : null, 'arguments': [to], 'bind': this })(); }.bind(this); tmp.src = this.link; if (tmp && tmp.complete && tmp.onload) tmp.onload(true); }, /** * @todo Test implementation */ openElement: function() { this.content = this.content || $(this.link) || $E(this.link); if (!this.content) { this.fireEvent('onError').close(); return; } this.content.inject(this.body); this.zoomTo({x: this.content.scrollWidth, y: this.content.scrollHeight}); }, zoomRelativeTo: function(to) { var scale = this.options.resizeLimit; if (!scale) { scale = this.container.getSize(); scale.x *= this.options.resizeFactor; scale.y *= this.options.resizeFactor; } for (var i = 2; i--;) { if (to.x > scale.x) { to.y *= scale.x / to.x; to.x = scale.x; } else if (to.y > scale.y) { to.x *= scale.y / to.y; to.y = scale.y; } } return this.zoomTo({x: to.x.toInt(), y: to.y.toInt()}); }, zoomTo: function(to) { to = this.options.fixedSize || to; var box = this.container.getSize(), scroll = this.container.getScroll(); var pos = (!this.options.centered) ? { x: (this.coords.left + (this.coords.width / 2) - to.x / 2).toInt() .limit(scroll.x + this.options.margin, scroll.x + box.x - this.options.margin - to.x), y: (this.coords.top + (this.coords.height / 2) - to.y / 2).toInt() .limit(scroll.y + this.options.margin, scroll.y + box.y - this.options.margin - to.y) } : { x: scroll.x + ((box.x - to.x) / 2).toInt(), y: scroll.y + ((box.y - to.y) / 2).toInt() }; if (this.options.cutOut) this.element.setStyle('visibility', 'hidden'); this.box.removeClass('remooz-loading'); var vars = {left: pos.x, top: pos.y, width: to.x, height: to.y}; if (this.options.opacityResize != 1) vars.opacity = [this.options.opacityResize, 1]; else this.box.set('opacity', 1); this.tweens.box.start(vars).chain(this.finishOpen.bind(this)); this.fireEvent('onOpen'); }, build: function() { this.addEvent('onBlur', function() { this.focused = false; this.box.removeClass('remooz-box-focus').setStyle('z-index', ReMooz.options.zIndex); }, true); this.addEvent('onFocus', function() { this.focused = true; this.box.addClass('remooz-box-focus').setStyle('z-index', ReMooz.options.zIndexFocus); }, true); var classes = ['remooz-box', 'remooz-type-' + this.options.type, 'remooz-engine-' + Browser.Engine.name + Browser.Engine.version]; if (this.options.className) classes.push(this.options.className); this.box = new Element('div', { 'class': classes.join(' '), 'styles': { 'display': 'none', 'top': 0, 'left': 0, 'zIndex': ReMooz.options.zIndex } }); this.tweens = { 'box': new Fx.Morph(this.box, $merge({ 'duration': 400, 'unit': 'px', 'transition': Fx.Transitions.Quart.easeOut, 'chain': 'cancel' }, this.options.resizeOptions) ), 'fade': new Fx.Tween(null, $merge({ 'property': 'opacity', 'duration': (Browser.Engine.trident) ? 0 : 300, 'chain': 'cancel' }, this.options.fxOptions)).addEvents({ 'onComplete': function() { if (!this.element.get('opacity')) this.element.setStyle('display', 'none'); }, 'onStart': function() { if (!this.element.get('opacity')) this.element.setStyle('display', ''); } } ) }; this.tweens.fade.element = $$(); if (this.options.shadow) { if (Browser.Engine.webkit420) { this.box.setStyle('-webkit-box-shadow', '0 0 10px rgba(0, 0, 0, 0.7)'); } else if (!Browser.Engine.trident4) { var shadow = new Element('div', {'class': 'remooz-bg-wrap'}).inject(this.box); ['n', 'ne', 'e', 'se', 's', 'sw', 'w', 'nw'].each(function(dir) { new Element('div', {'class': 'remooz-bg remooz-bg-' + dir}).inject(shadow); }); this.tweens.bg = new Fx.Tween(shadow, { 'property': 'opacity', 'chain': 'cancel' }).set(0); this.addEvent(this.options.shadow, this.tweens.bg.set.bind(this.tweens.bg, 1), true); this.addEvent('onClose', this.tweens.bg.set.bind(this.tweens.bg, 0), true); } } if (this.options.closer) { var closer = new Element('a', { 'class': 'remooz-btn-close', 'events': {'click': this.bound.close} }).inject(this.box); this.tweens.fade.element.push(closer); } this.body = new Element('div', {'class': 'remooz-body'}).inject(this.box); var title = this.options.title || this.options.generateTitle.call(this, this.element); if (title) { // thx ie6 var title = new Element('div', {'class': 'remooz-title'}).adopt( new Element('div', {'class': 'remooz-title-bg', 'opacity': this.options.opacityTitle}), new Element('div', {'class': 'remooz-title-content'}).adopt(title) ).inject(this.box); this.tweens.fade.element.push(title); } this.tweens.fade.set(0).fireEvent('onComplete'); this.drag = new Drag.Move(this.box, { 'snap': 15, 'preventDefault': true, 'onBeforeStart': function() { if (!this.focused && !this.loading) ReMooz.focus(this); else if (this.loading || this.options.closeOnClick) this.box.addEvent('mouseup', this.bound.dragClose); }.bind(this), 'onSnap': function() { this.box.removeEvent('mouseup', this.bound.dragClose); if (!this.options.dragging) this.drag.stop(); else this.box.addClass('remooz-box-dragging'); }.bind(this), 'onComplete': function() { this.box.removeClass('remooz-box-dragging'); }.bind(this) }); this.drag.detach(); this.fireEvent('onBuild', this.box, this.element); this.box.inject(this.element.getDocument().body); } }); ReMooz.factory = function(extended) { return $extend(this, extended); }; ReMooz.factory(new Options).factory({ options: { zIndex: 41, zIndexFocus: 42, query: 'a.remooz', modal: false }, assign: function(elements, options) { return $$(elements).map(function(element) { return new ReMooz(element, options); }, this); }, stack: [], open: function(obj) { var last = this.stack.getLast(); this.focus(obj); if (last && this.options.modal) last.close(); }, close: function(obj) { var length = this.stack.length - 1; if (length > 1 && this.stack[length] == obj) this.focus(this.stack[length - 1]); this.stack.erase(obj); }, focus: function(obj) { var last = this.stack.getLast(); obj.fireEvent('onFocus', [obj]); if (last == obj) return; if (last) last.fireEvent('onBlur', [last]); this.stack.erase(obj).push(obj); } });tdiary-contrib-3.2.2/util/image-gallery/js/SmoothGallery/scripts/jd.gallery.js000066400000000000000000000707701213632744000274460ustar00rootroot00000000000000/* This file is part of JonDesign's SmoothGallery v2.1beta1. JonDesign's SmoothGallery is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. JonDesign's SmoothGallery is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with JonDesign's SmoothGallery; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Main Developer: Jonathan Schemoul (JonDesign: http://www.jondesign.net/) Contributed code by: - Christian Ehret (bugfix) - Nitrix (bugfix) - Valerio from Mad4Milk for his great help with the carousel scrolling and many other things. - Archie Cowan for helping me find a bugfix on carousel inner width problem. - Tomocchino from #mootools for the preloader class Many thanks to: - The mootools team for the great mootools lib, and it's help and support throughout the project. - Harald Kirschner (digitarald: http://digitarald.de/) for all his great libs. Some used here as plugins. */ /* some quirks to circumvent broken stuff in mt1.2 */ function isBody(element){ return (/^(?:body|html)$/i).test(element.tagName); }; Element.implement({ getPosition: function(relative){ if (isBody(this)) return {x: 0, y: 0}; var el = this, position = {x: 0, y: 0}; while (el){ position.x += el.offsetLeft; position.y += el.offsetTop; el = el.offsetParent; } var rpos = (relative) ? $(relative).getPosition() : {x: 0, y: 0}; return {x: position.x - rpos.x, y: position.y - rpos.y}; } }); // declaring the class var gallery = { Implements: [Events, Options], options: { showArrows: true, showCarousel: true, showInfopane: true, embedLinks: true, fadeDuration: 500, timed: false, delay: 9000, preloader: true, preloaderImage: true, preloaderErrorImage: true, fullScreen: false, // TEST /* Data retrieval */ manualData: [], populateFrom: false, populateData: true, destroyAfterPopulate: true, elementSelector: "div.imageElement", titleSelector: "h3", subtitleSelector: "p", linkSelector: "a.open", imageSelector: "img.full", thumbnailSelector: "img.thumbnail", defaultTransition: "fade", /* InfoPane options */ slideInfoZoneOpacity: 0.7, slideInfoZoneSlide: true, /* Carousel options */ carouselMinimizedOpacity: 0.4, carouselMinimizedHeight: 20, carouselMaximizedOpacity: 0.9, thumbHeight: 75, thumbWidth: 100, thumbSpacing: 10, thumbIdleOpacity: 0.2, textShowCarousel: 'Pictures', showCarouselLabel: true, thumbCloseCarousel: true, useThumbGenerator: false, thumbGenerator: 'resizer.php', useExternalCarousel: false, carouselElement: false, carouselHorizontal: true, activateCarouselScroller: true, carouselPreloader: true, textPreloadingCarousel: 'Loading...', /* CSS Classes */ baseClass: 'jdGallery', withArrowsClass: 'withArrows', /* Plugins: HistoryManager */ useHistoryManager: false, customHistoryKey: false, /* Plugins: ReMooz */ useReMooz: false, useMediaboxAdvanced: false }, initialize: function(element, options) { this.setOptions(options); this.fireEvent('onInit'); this.currentIter = 0; this.lastIter = 0; this.maxIter = 0; this.galleryElement = element; this.topElement = element; this.galleryData = this.options.manualData; this.galleryInit = 1; this.galleryElements = Array(); this.thumbnailElements = Array(); this.galleryElement.addClass(this.options.baseClass); if (this.options.useReMooz&&(this.options.defaultTransition=="fade")) this.options.defaultTransition="crossfade"; this.populateFrom = element; if (this.options.populateFrom) this.populateFrom = this.options.populateFrom; if (this.options.populateData) this.populateData(); element.style.display="block"; if(this.options.fullScreen) //TEST { var size = window.getSize(); // if(document.body.offsetHeight>window.innerHeight) // size.x-=18; element.setStyles({ 'position':'absolute', 'top':'0px', 'left':'0px', 'width':size.x + 14, 'height':size.y - 8 }); } if (this.options.useHistoryManager) this.initHistory(); if ((this.options.embedLinks)|(this.options.useReMooz)|(this.options.useMediaboxAdvanced)) { this.currentLink = new Element('a').addClass('open').setProperties({ href: '#', title: '', rel: 'lightbox' }).injectInside(element); if ((!this.options.showArrows) && (!this.options.showCarousel)) this.galleryElement = element = this.currentLink; else this.currentLink.setStyle('display', 'none'); } this.constructElements(); if ((this.galleryData.length>1)&&(this.options.showArrows)) { var leftArrow = new Element('a').addClass('left').addEvent( 'click', this.prevItem.bind(this) ).injectInside(element); var rightArrow = new Element('a').addClass('right').addEvent( 'click', this.nextItem.bind(this) ).injectInside(element); this.galleryElement.addClass(this.options.withArrowsClass); } this.loadingElement = new Element('div').addClass('loadingElement').injectInside(element); if (this.options.showInfopane) this.initInfoSlideshow(); if (this.options.showCarousel) this.initCarousel(); this.doSlideShow(1); }, populateData: function() { currentArrayPlace = this.galleryData.length; options = this.options; var data = $A(this.galleryData); data.extend(this.populateGallery(this.populateFrom, currentArrayPlace)); this.galleryData = data; this.fireEvent('onPopulated'); }, populateGallery: function(element, startNumber) { var data = []; options = this.options; currentArrayPlace = startNumber; element.getElements(options.elementSelector).each(function(el) { elementDict = $H({ image: el.getElement(options.imageSelector).getProperty('src'), number: currentArrayPlace, transition: this.options.defaultTransition }); if ((options.showInfopane) | (options.showCarousel)) elementDict.extend({ title: el.getElement(options.titleSelector).innerHTML, description: el.getElement(options.subtitleSelector).innerHTML }); if ((options.embedLinks) | (options.useReMooz)) elementDict.extend({ link: el.getElement(options.linkSelector).href||false, linkTitle: el.getElement(options.linkSelector).title||false, linkTarget: el.getElement(options.linkSelector).getProperty('target')||false }); if ((!options.useThumbGenerator) && (options.showCarousel)) elementDict.extend({ thumbnail: el.getElement(options.thumbnailSelector).getProperty('src') }); else if (options.useThumbGenerator) elementDict.extend({ thumbnail: options.thumbGenerator + '?imgfile=' + elementDict.image + '&max_width=' + options.thumbWidth + '&max_height=' + options.thumbHeight }); data.extend([elementDict]); currentArrayPlace++; if (this.options.destroyAfterPopulate) el.dispose(); }); return data; }, constructElements: function() { el = this.galleryElement; top_el = this.galleryElement; if (this.options.embedLinks && (!this.options.showArrows)) el = this.currentLink; this.maxIter = this.galleryData.length; var currentImg; for(i=0;i= img.width){ new_height = top_height; new_width = Math.round(top_height*img.width/img.height); } else if(top_width < img.width && img.height <= img.width) { new_width = top_width; new_height = Math.round(top_width*img.height/img.width); margin_top = Math.round((top_height - new_height)/2); } else { margin_top = Math.round((top_height - img.height)/2); } img.element.appendChild(new Element('img').set('src',img.source).setStyles({ 'margin':'0 auto', 'display':'block', 'width':new_width+'px', 'height':new_height+'px', 'margin-top':margin_top+'px' })); }.pass([imageStyle, i], this) }); } }.pass([currentImg, i], this); } else { currentImg.element.appendChild(new Element('img').set('src',this.galleryData[i].image).setStyles({ 'margin':'0 auto', 'display':'block' })); } this.galleryElements[parseInt(i)] = currentImg; } }, destroySlideShow: function(element) { var myClassName = element.className; var newElement = new Element('div').addClass('myClassName'); element.parentNode.replaceChild(newElement, element); }, startSlideShow: function() { this.fireEvent('onStart'); this.loadingElement.style.display = "none"; this.lastIter = this.maxIter - 1; this.currentIter = 0; this.galleryInit = 0; this.galleryElements[parseInt(this.currentIter)].set({opacity: 1}); if (this.options.showInfopane) this.showInfoSlideShow.delay(1000, this); if (this.options.useReMooz) this.makeReMooz.delay(1000, this); var textShowCarousel = formatString(this.options.textShowCarousel, this.currentIter+1, this.maxIter); if (this.options.showCarousel&&(!this.options.carouselPreloader)&&(!this.options.useExternalCarousel)) this.carouselBtn.set('html', textShowCarousel).setProperty('title', textShowCarousel); this.prepareTimer(); if (this.options.embedLinks) this.makeLink(this.currentIter); }, nextItem: function() { this.fireEvent('onNextCalled'); this.nextIter = this.currentIter+1; if (this.nextIter >= this.maxIter) this.nextIter = 0; this.galleryInit = 0; this.goTo(this.nextIter); }, prevItem: function() { this.fireEvent('onPreviousCalled'); this.nextIter = this.currentIter-1; if (this.nextIter <= -1) this.nextIter = this.maxIter - 1; this.galleryInit = 0; this.goTo(this.nextIter); }, goTo: function(num) { this.clearTimer(); if(this.options.preloader) { this.galleryElements[num].load(); if (num==0) this.galleryElements[this.maxIter - 1].load(); else this.galleryElements[num - 1].load(); if (num==(this.maxIter - 1)) this.galleryElements[0].load(); else this.galleryElements[num + 1].load(); } if (this.options.embedLinks) this.clearLink(); if (this.options.showInfopane) { this.slideInfoZone.clearChain(); this.hideInfoSlideShow().chain(this.changeItem.pass(num, this)); } else this.currentChangeDelay = this.changeItem.delay(500, this, num); if (this.options.embedLinks) this.makeLink(num); this.prepareTimer(); /*if (this.options.showCarousel) this.clearThumbnailsHighlights();*/ }, changeItem: function(num) { this.fireEvent('onStartChanging'); this.galleryInit = 0; if (this.currentIter != num) { for(i=0;i' + (myself.relatedImage.number + 1) + "/" + this.maxIter + ": " + myself.relatedImage.title); }.pass(currentImg, this), 'mouseout': function (myself) { myself.cancel(); myself.start({'opacity': this.options.thumbIdleOpacity}); }.pass(currentImg, this), 'click': function (myself) { this.goTo(myself.relatedImage.number); if (this.options.thumbCloseCarousel&&(!this.options.useExternalCarousel)) this.hideCarousel(); }.pass(currentImg, this) }); currentImg.relatedImage = this.galleryData[i]; this.thumbnailElements[parseInt(i)] = currentImg; } }, log: function(value) { if(console.log) console.log(value); }, preloadThumbnails: function() { var thumbnails = []; for(i=0;i 8) && (this.rel == el.rel)); }); } else{ this.currentLink.setProperties({ href: this.galleryData[num].link, title: this.galleryData[num].linkTitle }) if (!((this.options.embedLinks) && (!this.options.showArrows) && (!this.options.showCarousel))) this.currentLink.setStyle('display', 'block'); } }, clearLink: function() { this.currentLink.setProperties({href: '', title: ''}); if (!((this.options.embedLinks) && (!this.options.showArrows) && (!this.options.showCarousel))) this.currentLink.setStyle('display', 'none'); }, makeReMooz: function() { this.currentLink.setProperties({ href: '#' }); this.currentLink.setStyles({ 'display': 'block' }); this.galleryElements[this.currentIter].element.set('title', this.galleryData[this.currentIter].title + ' :: ' + this.galleryData[this.currentIter].description); this.ReMooz = new ReMooz(this.galleryElements[this.currentIter].element, { link: this.galleryData[this.currentIter].link, shadow: false, dragging: false, addClick: false, resizeOpacity: 1 }); var img = this.galleryElements[this.currentIter]; var coords = img.element.getCoordinates(); delete coords.right; delete coords.bottom; widthDiff = coords.width - img.width; heightDiff = coords.height - img.height; coords.width = img.width; coords.height = img.height; coords.left += Math.ceil(widthDiff/2)+1; coords.top += Math.ceil(heightDiff/2)+1; this.ReMooz.getOriginCoordinates = function(coords) { return coords; }.bind(this, coords); this.currentLink.onclick = function () { this.ReMooz.open.bind(this.ReMooz)(); return false; }.bind(this); }, /* To change the gallery data, those two functions : */ flushGallery: function() { this.galleryElements.each(function(myFx) { myFx.element.dispose(); myFx = myFx.element = null; }); this.galleryElements = []; }, changeData: function(data) { this.galleryData = data; this.clearTimer(); this.flushGallery(); if (this.options.showCarousel) this.flushCarousel(); this.constructElements(); if (this.options.showCarousel) this.fillCarousel(); if (this.options.showInfopane) this.hideInfoSlideShow(); this.galleryInit=1; this.lastIter=0; this.currentIter=0; this.doSlideShow(1); }, /* Plugins: HistoryManager */ initHistory: function() { this.fireEvent('onHistoryInit'); this.historyKey = this.galleryElement.id + '-picture'; if (this.options.customHistoryKey) this.historyKey = this.options.customHistoryKey; this.history = new History.Route({ defaults: [1], pattern: this.historyKey + '\\((\\d+)\\)', generate: function(values) { return [this.historyKey, '(', values[0], ')'].join('') }.bind(this), onMatch: function(values, defaults) { if (parseInt(values[0])-1 < this.maxIter) this.goTo(parseInt(values[0])-1); }.bind(this) }); this.addEvent('onChanged', function(){ this.history.setValue(0, this.currentIter+1); this.history.defaults=[this.currentIter+1]; }.bind(this)); this.fireEvent('onHistoryInited'); } }; gallery = new Class(gallery); gallery.Transitions = new Hash ({ fade: function(oldFx, newFx, oldPos, newPos){ oldFx.options.transition = newFx.options.transition = Fx.Transitions.linear; oldFx.options.duration = newFx.options.duration = this.options.fadeDuration; if (newPos > oldPos) newFx.start({opacity: 1}); else { newFx.set({opacity: 1}); oldFx.start({opacity: 0}); } }, crossfade: function(oldFx, newFx, oldPos, newPos){ oldFx.options.transition = newFx.options.transition = Fx.Transitions.linear; oldFx.options.duration = newFx.options.duration = this.options.fadeDuration; newFx.start({opacity: 1}); oldFx.start({opacity: 0}); }, fadebg: function(oldFx, newFx, oldPos, newPos){ oldFx.options.transition = newFx.options.transition = Fx.Transitions.linear; oldFx.options.duration = newFx.options.duration = this.options.fadeDuration / 2; oldFx.start({opacity: 0}).chain(newFx.start.pass([{opacity: 1}], newFx)); } }); /* All code copyright 2007 Jonathan Schemoul */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Follows: Preloader (class) * Simple class for preloading images with support for progress reporting * Copyright 2007 Tomocchino. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ var Preloader = new Class({ Implements: [Events, Options], options: { root : '', period : 100 }, initialize: function(options){ this.setOptions(options); }, load: function(sources) { this.index = 0; this.images = []; this.sources = this.temps = sources; this.total = this. sources.length; this.fireEvent('onStart', [this.index, this.total]); this.timer = this.progress.periodical(this.options.period, this); this.sources.each(function(source, index){ this.images[index] = new Asset.image(this.options.root + source, { 'onload' : function(){ this.index++; if(this.images[index]) this.fireEvent('onLoad', [this.images[index], index, source]); }.bind(this), 'onerror' : function(){ this.index++; this.fireEvent('onError', [this.images.splice(index, 1), index, source]); }.bind(this), 'onabort' : function(){ this.index++; this.fireEvent('onError', [this.images.splice(index, 1), index, source]); }.bind(this) }); }, this); }, progress: function() { this.fireEvent('onProgress', [Math.min(this.index, this.total), this.total]); if(this.index >= this.total) this.complete(); }, complete: function(){ $clear(this.timer); this.fireEvent('onComplete', [this.images]); }, cancel: function(){ $clear(this.timer); } }); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Follows: formatString (function) * Original name: Yahoo.Tools.printf * Copyright Yahoo. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ function formatString() { var num = arguments.length; var oStr = arguments[0]; for (var i = 1; i < num; i++) { var pattern = "\\{" + (i-1) + "\\}"; var re = new RegExp(pattern, "g"); oStr = oStr.replace(re, arguments[i]); } return oStr; } tdiary-contrib-3.2.2/util/image-gallery/js/SmoothGallery/scripts/jd.gallery.set.js000066400000000000000000000155771213632744000302440ustar00rootroot00000000000000/* This file is part of JonDesign's SmoothGallery v2.1beta1. JonDesign's SmoothGallery is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. JonDesign's SmoothGallery is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with JonDesign's SmoothGallery; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Main Developer: Jonathan Schemoul (JonDesign: http://www.jondesign.net/) */ var gallerySet = new Class({ Extends: gallery, initialize: function(element, options) { this.setOptions({ manualSetData: [], gallerySelector: "div.galleryElement", galleryTitleSelector: "h2", textGallerySelector: 'Galleries', textShowGallerySelector: 'Other Galleries', textGalleryInfo: '{0} pictures', startWithSelector: true, /* Changing default options */ textShowCarousel: '{0}/{1} Pictures', carouselPreloader: false }); this.setOptions(options); this.gallerySet = this.options.manualSetData; this.addEvent('onPopulated', this.createGallerySelectorTab.bind(this)); this.addEvent('onPopulated', this.createGallerySelector.bind(this)); this.startWithSelectorFn = this.toggleGallerySelector.pass(true, this); if (this.options.startWithSelector) this.addEvent('onGallerySelectorCreated', this.startWithSelectorFn); this.parent(element, this.options); }, populateData: function() { options = this.options; var data = $A(this.gallerySet); this.populateFrom.getElements(options.gallerySelector).each(function (galEl) { currentGalArrayPlace = 0; galleryDict = { title: galEl.getElement(options.galleryTitleSelector).innerHTML, elements: [] } galleryDict.elements.extend(this.populateGallery(galEl, 0)); data.extend([galleryDict]); if (this.options.destroyAfterPopulate) galEl.dispose(); }, this); this.gallerySet = data; this.galleryData = data[0].elements; this.currentGallery = 0; this.fireEvent('onPopulated'); }, changeGallery: function(number) { if (number!=this.currentGallery) { this.changeData(this.gallerySet[number].elements); this.maxIter = this.gallerySet[number].elements.length; this.currentGallery = number; this.gallerySelectorBtn.set('html', this.gallerySet[number].title); this.fireEvent('onGalleryChanged'); } this.toggleGallerySelector(false); }, createGallerySelectorTab: function() { this.gallerySelectorBtn = new Element('a').addClass('gallerySelectorBtn').setProperties({ title: this.options.textShowGallerySelector }).set('html', this.options.textShowGallerySelector).addEvent( 'click', function(){ this.toggleGallerySelector(true); }.bind(this) ).injectInside(this.galleryElement); this.addEvent('onShowCarousel', function(){this.gallerySelectorBtn.setStyle('zIndex', 10)}.bind(this)); this.addEvent('onCarouselHidden', function(){this.gallerySelectorBtn.setStyle('zIndex', 15)}.bind(this)); }, createGallerySelector: function() { this.gallerySelector = new Fx.Morph( new Element('div').addClass( 'gallerySelector' ).injectInside( this.galleryElement ).setStyles({ 'display': 'none', 'opacity': '0' }) ); this.gallerySelectorTitle = new Element('h2').set('html', this.options.textGallerySelector ).injectInside(this.gallerySelector.element); var gallerySelectorHeight = this.galleryElement.offsetHeight - 50 - 10 - 2; this.gallerySelectorWrapper = new Fx.Morph( new Element('div').addClass( 'gallerySelectorWrapper' ).setStyle( 'height', gallerySelectorHeight + "px" ).injectInside(this.gallerySelector.element) ); this.gallerySelectorInner = new Element('div').addClass('gallerySelectorInner').injectInside(this.gallerySelectorWrapper.element); this.gallerySelectorWrapper.scroller = new Scroller(this.gallerySelectorWrapper.element, { area: 100, velocity: 0.3 }).start(); this.createGalleryButtons(); this.fireEvent('onGallerySelectorCreated'); }, createGalleryButtons: function () { var galleryButtonWidth = ((this.galleryElement.offsetWidth - 30) / 2) - 14; this.gallerySet.each(function(galleryItem, index){ var button = new Element('div').addClass('galleryButton').injectInside( this.gallerySelectorInner ).addEvents({ 'mouseover': function(myself){ myself.button.addClass('hover'); }.pass(galleryItem, this), 'mouseout': function(myself){ myself.button.removeClass('hover'); }.pass(galleryItem, this), 'click': function(myself, number){ this.changeGallery.pass(number,this)(); }.pass([galleryItem, index], this) }).setStyle('width', galleryButtonWidth); galleryItem.button = button; var thumbnail = ""; if (this.options.showCarousel) thumbnail = galleryItem.elements[0].thumbnail; else thumbnail = galleryItem.elements[0].image; new Element('div').addClass('preview').setStyle( 'backgroundImage', "url('" + thumbnail + "')" ).injectInside(button); new Element('h3').set('html', galleryItem.title).injectInside(button); new Element('p').addClass('info').set('html', formatString(this.options.textGalleryInfo, galleryItem.elements.length)).injectInside(button); }, this); new Element('br').injectInside(this.gallerySelectorInner).setStyle('clear','both'); }, toggleGallerySelector: function(state) { if (state) this.gallerySelector.start({'opacity' : 1}).element.setStyle('display','block'); else this.gallerySelector.start({'opacity' : 0}); }, initHistory: function() { this.fireEvent('onHistoryInit'); this.historyKey = this.galleryElement.id + '-gallery'; if (this.options.customHistoryKey) this.historyKey = this.options.customHistoryKey(); this.history = new History.Route({ defaults: [1,1], pattern: this.historyKey + '\\((\\d+)\\)-picture\\((\\d+)\\)', generate: function(values) { return [this.historyKey, '(', values[0], ')', '-picture','(', values[1], ')'].join(''); }.bind(this), onMatch: function(values, defaults) { this.changeGallery.pass(parseInt(values[0]) - 1, this).delay(10); if(this.gallerySelector) this.toggleGallerySelector.pass(false, this).delay(500); this.goTo.pass(parseInt(values[1]) - 1, this).delay(100); }.bind(this) }); updateHistory = function(){ this.history.setValues([this.currentGallery + 1, this.currentIter + 1]); this.history.defaults=[this.currentGallery + 1, this.currentIter + 1]; }.bind(this); this.addEvent('onChanged', updateHistory); this.addEvent('onGalleryChanged', updateHistory); this.fireEvent('onHistoryInited'); } });tdiary-contrib-3.2.2/util/image-gallery/js/SmoothGallery/scripts/jd.gallery.transitions.js000066400000000000000000000057731213632744000320230ustar00rootroot00000000000000/* This file is part of JonDesign's SmoothGallery v2.1beta1. JonDesign's SmoothGallery is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. JonDesign's SmoothGallery is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with JonDesign's SmoothGallery; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Main Developer: Jonathan Schemoul (JonDesign: http://www.jondesign.net/) */ gallery.Transitions.extend({ fadeslideleft: function(oldFx, newFx, oldPos, newPos){ oldFx.options.transition = newFx.options.transition = Fx.Transitions.Cubic.easeOut; oldFx.options.duration = newFx.options.duration = 1500; if (newPos > oldPos) { newFx.start({ left: [this.galleryElement.offsetWidth, 0], opacity: 1 }); oldFx.start({opacity: [1,0]}); } else { newFx.start({opacity: [0,1]}); oldFx.start({ left: [0, this.galleryElement.offsetWidth], opacity: 0 }).chain(function(fx){fx.set({left: 0});}.pass(oldFx)); } }, continuoushorizontal: function(oldFx, newFx, oldPos, newPos){ oldFx.options.transition = newFx.options.transition = Fx.Transitions.linear; if ( ((newPos > oldPos) || ((newPos==0) && (oldPos == (this.maxIter-1) ))) && (!((newPos == (this.maxIter-1 )) && (oldPos == 0))) ) { oldFx.set({opacity: 1}); oldFx.start({ left: [0, this.galleryElement.offsetWidth * -1] }); newFx.set({opacity: 1, left: this.galleryElement.offsetWidth}); newFx.start({ left: [this.galleryElement.offsetWidth, 0] }); } else { oldFx.set({opacity: 1}); oldFx.start({ left: [0, this.galleryElement.offsetWidth] }); newFx.set({opacity: 1, left: this.galleryElement.offsetWidth * -1}); newFx.start({ left: [this.galleryElement.offsetWidth * -1, 0] }); } }, continuousvertical: function(oldFx, newFx, oldPos, newPos){ oldFx.options.transition = newFx.options.transition = Fx.Transitions.linear; if ( ((newPos > oldPos) || ((newPos==0) && (oldPos == (this.maxIter-1) ))) && (!((newPos == (this.maxIter-1 )) && (oldPos == 0))) ) { oldFx.set({opacity: 1}); oldFx.start({ top: [0, this.galleryElement.offsetHeight * -1] }); newFx.set({opacity: 1, top: this.galleryElement.offsetHeight}); newFx.start({ top: [this.galleryElement.offsetHeight, 0] }); } else { oldFx.set({opacity: 1}); oldFx.start({ top: [0, this.galleryElement.offsetHeight] }); newFx.set({opacity: 1, top: this.galleryElement.offsetHeight * -1}); newFx.start({ top: [this.galleryElement.offsetHeight * -1, 0] }); } } });tdiary-contrib-3.2.2/util/image-gallery/js/SmoothGallery/scripts/jdgalleryresize.js000066400000000000000000000702641213632744000306100ustar00rootroot00000000000000/* This file is part of JonDesign's SmoothGallery v2.1beta1. JonDesign's SmoothGallery is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. JonDesign's SmoothGallery is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with JonDesign's SmoothGallery; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Main Developer: Jonathan Schemoul (JonDesign: http://www.jondesign.net/) Contributed code by: - Christian Ehret (bugfix) - Nitrix (bugfix) - Valerio from Mad4Milk for his great help with the carousel scrolling and many other things. - Archie Cowan for helping me find a bugfix on carousel inner width problem. - Tomocchino from #mootools for the preloader class Many thanks to: - The mootools team for the great mootools lib, and it's help and support throughout the project. - Harald Kirschner (digitarald: http://digitarald.de/) for all his great libs. Some used here as plugins. */ /* some quirks to circumvent broken stuff in mt1.2 */ function isBody(element){ return (/^(?:body|html)$/i).test(element.tagName); }; Element.implement({ getPosition: function(relative){ if (isBody(this)) return {x: 0, y: 0}; var el = this, position = {x: 0, y: 0}; while (el){ position.x += el.offsetLeft; position.y += el.offsetTop; el = el.offsetParent; } var rpos = (relative) ? $(relative).getPosition() : {x: 0, y: 0}; return {x: position.x - rpos.x, y: position.y - rpos.y}; } }); // declaring the class var gallery = { Implements: [Events, Options], options: { showArrows: true, showCarousel: true, showInfopane: true, embedLinks: true, fadeDuration: 500, timed: false, delay: 9000, preloader: true, preloaderImage: true, preloaderErrorImage: true, /* Data retrieval */ manualData: [], populateFrom: false, populateData: true, destroyAfterPopulate: true, elementSelector: "div.imageElement", titleSelector: "h3", subtitleSelector: "p", linkSelector: "a.open", imageSelector: "img.full", thumbnailSelector: "img.thumbnail", defaultTransition: "fade", /* InfoPane options */ slideInfoZoneOpacity: 0.7, slideInfoZoneSlide: true, /* Carousel options */ carouselMinimizedOpacity: 0.4, carouselMinimizedHeight: 20, carouselMaximizedOpacity: 0.9, thumbHeight: 75, thumbWidth: 100, thumbSpacing: 10, thumbIdleOpacity: 0.2, textShowCarousel: 'Pictures', showCarouselLabel: true, thumbCloseCarousel: true, useThumbGenerator: false, thumbGenerator: 'resizer.php', useExternalCarousel: false, carouselElement: false, carouselHorizontal: true, activateCarouselScroller: true, carouselPreloader: true, textPreloadingCarousel: 'Loading...', /* CSS Classes */ baseClass: 'jdGallery', withArrowsClass: 'withArrows', /* Plugins: HistoryManager */ useHistoryManager: false, customHistoryKey: false, /* Plugins: ReMooz */ useReMooz: false, useMediaboxAdvanced: false }, initialize: function(element, options) { this.setOptions(options); this.fireEvent('onInit'); this.currentIter = 0; this.lastIter = 0; this.maxIter = 0; this.galleryElement = element; this.topElement = element; this.galleryData = this.options.manualData; this.galleryInit = 1; this.galleryElements = Array(); this.thumbnailElements = Array(); this.galleryElement.addClass(this.options.baseClass); if (this.options.useReMooz&&(this.options.defaultTransition=="fade")) this.options.defaultTransition="crossfade"; this.populateFrom = element; if (this.options.populateFrom) this.populateFrom = this.options.populateFrom; if (this.options.populateData) this.populateData(); element.style.display="block"; if (this.options.useHistoryManager) this.initHistory(); if ((this.options.embedLinks)|(this.options.useReMooz)|(this.options.useMediaboxAdvanced)) { this.currentLink = new Element('a').addClass('open').setProperties({ href: '#', title: '', rel: 'lightbox' }).injectInside(element); if ((!this.options.showArrows) && (!this.options.showCarousel)) this.galleryElement = element = this.currentLink; else this.currentLink.setStyle('display', 'none'); } this.constructElements(); if ((this.galleryData.length>1)&&(this.options.showArrows)) { var leftArrow = new Element('a').addClass('left').addEvent( 'click', this.prevItem.bind(this) ).injectInside(element); var rightArrow = new Element('a').addClass('right').addEvent( 'click', this.nextItem.bind(this) ).injectInside(element); this.galleryElement.addClass(this.options.withArrowsClass); } this.loadingElement = new Element('div').addClass('loadingElement').injectInside(element); if (this.options.showInfopane) this.initInfoSlideshow(); if (this.options.showCarousel) this.initCarousel(); this.doSlideShow(1); }, populateData: function() { currentArrayPlace = this.galleryData.length; options = this.options; var data = $A(this.galleryData); data.extend(this.populateGallery(this.populateFrom, currentArrayPlace)); this.galleryData = data; this.fireEvent('onPopulated'); }, populateGallery: function(element, startNumber) { var data = []; options = this.options; currentArrayPlace = startNumber; element.getElements(options.elementSelector).each(function(el) { elementDict = $H({ image: el.getElement(options.imageSelector).getProperty('src'), number: currentArrayPlace, transition: this.options.defaultTransition }); if ((options.showInfopane) | (options.showCarousel)) elementDict.extend({ title: el.getElement(options.titleSelector).innerHTML, description: el.getElement(options.subtitleSelector).innerHTML }); if ((options.embedLinks) | (options.useReMooz)) elementDict.extend({ link: el.getElement(options.linkSelector).href||false, linkTitle: el.getElement(options.linkSelector).title||false, linkTarget: el.getElement(options.linkSelector).getProperty('target')||false }); if ((!options.useThumbGenerator) && (options.showCarousel)) elementDict.extend({ thumbnail: el.getElement(options.thumbnailSelector).getProperty('src') }); else if (options.useThumbGenerator) elementDict.extend({ thumbnail: options.thumbGenerator + '?imgfile=' + elementDict.image + '&max_width=' + options.thumbWidth + '&max_height=' + options.thumbHeight }); data.extend([elementDict]); currentArrayPlace++; if (this.options.destroyAfterPopulate) el.dispose(); }); return data; }, constructElements: function() { el = this.galleryElement; top_el = this.galleryElement; if (this.options.embedLinks && (!this.options.showArrows)) el = this.currentLink; this.maxIter = this.galleryData.length; var currentImg; for(i=0;i= img.width){ new_height = top_height; new_width = Math.round(top_height*img.width/img.height); } else if(top_width < img.width && img.height <= img.width) { new_width = top_width; new_height = Math.round(top_width*img.height/img.width); margin_top = Math.round((top_height - new_height)/2); } else { margin_top = Math.round((top_height - img.height)/2); } img.element.appendChild(new Element('img').set('src',img.source).setStyles({ 'margin':'0 auto', 'display':'block', 'width':new_width+'px', 'height':new_height+'px', 'margin-top':margin_top+'px' })); }.pass([imageStyle, i], this) }); } }.pass([currentImg, i], this); } else { currentImg.element.appendChild(new Element('img').set('src',this.galleryData[i].image).setStyles({ 'margin':'0 auto', 'display':'block' })); } this.galleryElements[parseInt(i)] = currentImg; } }, destroySlideShow: function(element) { var myClassName = element.className; var newElement = new Element('div').addClass('myClassName'); element.parentNode.replaceChild(newElement, element); }, startSlideShow: function() { this.fireEvent('onStart'); this.loadingElement.style.display = "none"; this.lastIter = this.maxIter - 1; this.currentIter = 0; this.galleryInit = 0; this.galleryElements[parseInt(this.currentIter)].set({opacity: 1}); if (this.options.showInfopane) this.showInfoSlideShow.delay(1000, this); if (this.options.useReMooz) this.makeReMooz.delay(1000, this); var textShowCarousel = formatString(this.options.textShowCarousel, this.currentIter+1, this.maxIter); if (this.options.showCarousel&&(!this.options.carouselPreloader)&&(!this.options.useExternalCarousel)) this.carouselBtn.set('html', textShowCarousel).setProperty('title', textShowCarousel); this.prepareTimer(); if (this.options.embedLinks) this.makeLink(this.currentIter); }, nextItem: function() { this.fireEvent('onNextCalled'); this.nextIter = this.currentIter+1; if (this.nextIter >= this.maxIter) this.nextIter = 0; this.galleryInit = 0; this.goTo(this.nextIter); }, prevItem: function() { this.fireEvent('onPreviousCalled'); this.nextIter = this.currentIter-1; if (this.nextIter <= -1) this.nextIter = this.maxIter - 1; this.galleryInit = 0; this.goTo(this.nextIter); }, goTo: function(num) { this.clearTimer(); if(this.options.preloader) { this.galleryElements[num].load(); if (num==0) this.galleryElements[this.maxIter - 1].load(); else this.galleryElements[num - 1].load(); if (num==(this.maxIter - 1)) this.galleryElements[0].load(); else this.galleryElements[num + 1].load(); } if (this.options.embedLinks) this.clearLink(); if (this.options.showInfopane) { this.slideInfoZone.clearChain(); this.hideInfoSlideShow().chain(this.changeItem.pass(num, this)); } else this.currentChangeDelay = this.changeItem.delay(500, this, num); if (this.options.embedLinks) this.makeLink(num); this.prepareTimer(); /*if (this.options.showCarousel) this.clearThumbnailsHighlights();*/ }, changeItem: function(num) { this.fireEvent('onStartChanging'); this.galleryInit = 0; if (this.currentIter != num) { for(i=0;i' + (myself.relatedImage.number + 1) + "/" + this.maxIter + ": " + myself.relatedImage.title); }.pass(currentImg, this), 'mouseout': function (myself) { myself.cancel(); myself.start({'opacity': this.options.thumbIdleOpacity}); }.pass(currentImg, this), 'click': function (myself) { this.goTo(myself.relatedImage.number); if (this.options.thumbCloseCarousel&&(!this.options.useExternalCarousel)) this.hideCarousel(); }.pass(currentImg, this) }); currentImg.relatedImage = this.galleryData[i]; this.thumbnailElements[parseInt(i)] = currentImg; } }, log: function(value) { if(console.log) console.log(value); }, preloadThumbnails: function() { var thumbnails = []; for(i=0;i 8) && (this.rel == el.rel)); }); } else{ this.currentLink.setProperties({ href: this.galleryData[num].link, title: this.galleryData[num].linkTitle }) if (!((this.options.embedLinks) && (!this.options.showArrows) && (!this.options.showCarousel))) this.currentLink.setStyle('display', 'block'); } }, clearLink: function() { this.currentLink.setProperties({href: '', title: ''}); if (!((this.options.embedLinks) && (!this.options.showArrows) && (!this.options.showCarousel))) this.currentLink.setStyle('display', 'none'); }, makeReMooz: function() { this.currentLink.setProperties({ href: '#' }); this.currentLink.setStyles({ 'display': 'block' }); this.galleryElements[this.currentIter].element.set('title', this.galleryData[this.currentIter].title + ' :: ' + this.galleryData[this.currentIter].description); this.ReMooz = new ReMooz(this.galleryElements[this.currentIter].element, { link: this.galleryData[this.currentIter].link, shadow: false, dragging: false, addClick: false, resizeOpacity: 1 }); var img = this.galleryElements[this.currentIter]; var coords = img.element.getCoordinates(); delete coords.right; delete coords.bottom; widthDiff = coords.width - img.width; heightDiff = coords.height - img.height; coords.width = img.width; coords.height = img.height; coords.left += Math.ceil(widthDiff/2)+1; coords.top += Math.ceil(heightDiff/2)+1; this.ReMooz.getOriginCoordinates = function(coords) { return coords; }.bind(this, coords); this.currentLink.onclick = function () { this.ReMooz.open.bind(this.ReMooz)(); return false; }.bind(this); }, /* To change the gallery data, those two functions : */ flushGallery: function() { this.galleryElements.each(function(myFx) { myFx.element.dispose(); myFx = myFx.element = null; }); this.galleryElements = []; }, changeData: function(data) { this.galleryData = data; this.clearTimer(); this.flushGallery(); if (this.options.showCarousel) this.flushCarousel(); this.constructElements(); if (this.options.showCarousel) this.fillCarousel(); if (this.options.showInfopane) this.hideInfoSlideShow(); this.galleryInit=1; this.lastIter=0; this.currentIter=0; this.doSlideShow(1); }, /* Plugins: HistoryManager */ initHistory: function() { this.fireEvent('onHistoryInit'); this.historyKey = this.galleryElement.id + '-picture'; if (this.options.customHistoryKey) this.historyKey = this.options.customHistoryKey; this.history = new History.Route({ defaults: [1], pattern: this.historyKey + '\\((\\d+)\\)', generate: function(values) { return [this.historyKey, '(', values[0], ')'].join('') }.bind(this), onMatch: function(values, defaults) { if (parseInt(values[0])-1 < this.maxIter) this.goTo(parseInt(values[0])-1); }.bind(this) }); this.addEvent('onChanged', function(){ this.history.setValue(0, this.currentIter+1); this.history.defaults=[this.currentIter+1]; }.bind(this)); this.fireEvent('onHistoryInited'); } }; gallery = new Class(gallery); gallery.Transitions = new Hash ({ fade: function(oldFx, newFx, oldPos, newPos){ oldFx.options.transition = newFx.options.transition = Fx.Transitions.linear; oldFx.options.duration = newFx.options.duration = this.options.fadeDuration; if (newPos > oldPos) newFx.start({opacity: 1}); else { newFx.set({opacity: 1}); oldFx.start({opacity: 0}); } }, crossfade: function(oldFx, newFx, oldPos, newPos){ oldFx.options.transition = newFx.options.transition = Fx.Transitions.linear; oldFx.options.duration = newFx.options.duration = this.options.fadeDuration; newFx.start({opacity: 1}); oldFx.start({opacity: 0}); }, fadebg: function(oldFx, newFx, oldPos, newPos){ oldFx.options.transition = newFx.options.transition = Fx.Transitions.linear; oldFx.options.duration = newFx.options.duration = this.options.fadeDuration / 2; oldFx.start({opacity: 0}).chain(newFx.start.pass([{opacity: 1}], newFx)); } }); /* All code copyright 2007 Jonathan Schemoul */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Follows: Preloader (class) * Simple class for preloading images with support for progress reporting * Copyright 2007 Tomocchino. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ var Preloader = new Class({ Implements: [Events, Options], options: { root : '', period : 100 }, initialize: function(options){ this.setOptions(options); }, load: function(sources) { this.index = 0; this.images = []; this.sources = this.temps = sources; this.total = this. sources.length; this.fireEvent('onStart', [this.index, this.total]); this.timer = this.progress.periodical(this.options.period, this); this.sources.each(function(source, index){ this.images[index] = new Asset.image(this.options.root + source, { 'onload' : function(){ this.index++; if(this.images[index]) this.fireEvent('onLoad', [this.images[index], index, source]); }.bind(this), 'onerror' : function(){ this.index++; this.fireEvent('onError', [this.images.splice(index, 1), index, source]); }.bind(this), 'onabort' : function(){ this.index++; this.fireEvent('onError', [this.images.splice(index, 1), index, source]); }.bind(this) }); }, this); }, progress: function() { this.fireEvent('onProgress', [Math.min(this.index, this.total), this.total]); if(this.index >= this.total) this.complete(); }, complete: function(){ $clear(this.timer); this.fireEvent('onComplete', [this.images]); }, cancel: function(){ $clear(this.timer); } }); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Follows: formatString (function) * Original name: Yahoo.Tools.printf * Copyright Yahoo. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ function formatString() { var num = arguments.length; var oStr = arguments[0]; for (var i = 1; i < num; i++) { var pattern = "\\{" + (i-1) + "\\}"; var re = new RegExp(pattern, "g"); oStr = oStr.replace(re, arguments[i]); } return oStr; } tdiary-contrib-3.2.2/util/image-gallery/js/SmoothGallery/scripts/license.txt000066400000000000000000000773271213632744000272450ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONStdiary-contrib-3.2.2/util/image-gallery/js/SmoothGallery/scripts/mootools-1.2-more.js000066400000000000000000000446201213632744000305170ustar00rootroot00000000000000//MooTools More, . Copyright (c) 2006-2008 Valerio Proietti, , MIT Style License. Fx.Slide=new Class({Extends:Fx,options:{mode:"vertical"},initialize:function(B,A){this.addEvent("complete",function(){this.open=(this.wrapper["offset"+this.layout.capitalize()]!=0); if(this.open&&Browser.Engine.webkit419){this.element.dispose().inject(this.wrapper);}},true);this.element=this.subject=$(B);this.parent(A);var C=this.element.retrieve("wrapper"); this.wrapper=C||new Element("div",{styles:$extend(this.element.getStyles("margin","position"),{overflow:"hidden"})}).wraps(this.element);this.element.store("wrapper",this.wrapper).setStyle("margin",0); this.now=[];this.open=true;},vertical:function(){this.margin="margin-top";this.layout="height";this.offset=this.element.offsetHeight;},horizontal:function(){this.margin="margin-left"; this.layout="width";this.offset=this.element.offsetWidth;},set:function(A){this.element.setStyle(this.margin,A[0]);this.wrapper.setStyle(this.layout,A[1]); return this;},compute:function(E,D,C){var B=[];var A=2;A.times(function(F){B[F]=Fx.compute(E[F],D[F],C);});return B;},start:function(B,E){if(!this.check(arguments.callee,B,E)){return this; }this[E||this.options.mode]();var D=this.element.getStyle(this.margin).toInt();var C=this.wrapper.getStyle(this.layout).toInt();var A=[[D,C],[0,this.offset]]; var G=[[D,C],[-this.offset,0]];var F;switch(B){case"in":F=A;break;case"out":F=G;break;case"toggle":F=(this.wrapper["offset"+this.layout.capitalize()]==0)?A:G; }return this.parent(F[0],F[1]);},slideIn:function(A){return this.start("in",A);},slideOut:function(A){return this.start("out",A);},hide:function(A){this[A||this.options.mode](); this.open=false;return this.set([-this.offset,0]);},show:function(A){this[A||this.options.mode]();this.open=true;return this.set([0,this.offset]);},toggle:function(A){return this.start("toggle",A); }});Element.Properties.slide={set:function(B){var A=this.retrieve("slide");if(A){A.cancel();}return this.eliminate("slide").store("slide:options",$extend({link:"cancel"},B)); },get:function(A){if(A||!this.retrieve("slide")){if(A||!this.retrieve("slide:options")){this.set("slide",A);}this.store("slide",new Fx.Slide(this,this.retrieve("slide:options"))); }return this.retrieve("slide");}};Element.implement({slide:function(D,E){D=D||"toggle";var B=this.get("slide"),A;switch(D){case"hide":B.hide(E);break;case"show":B.show(E); break;case"toggle":var C=this.retrieve("slide:flag",B.open);B[(C)?"slideOut":"slideIn"](E);this.store("slide:flag",!C);A=true;break;default:B.start(D,E); }if(!A){this.eliminate("slide:flag");}return this;}});Fx.Scroll=new Class({Extends:Fx,options:{offset:{x:0,y:0},wheelStops:true},initialize:function(B,A){this.element=this.subject=$(B); this.parent(A);var D=this.cancel.bind(this,false);if($type(this.element)!="element"){this.element=$(this.element.getDocument().body);}var C=this.element; if(this.options.wheelStops){this.addEvent("start",function(){C.addEvent("mousewheel",D);},true);this.addEvent("complete",function(){C.removeEvent("mousewheel",D); },true);}},set:function(){var A=Array.flatten(arguments);this.element.scrollTo(A[0],A[1]);},compute:function(E,D,C){var B=[];var A=2;A.times(function(F){B.push(Fx.compute(E[F],D[F],C)); });return B;},start:function(C,H){if(!this.check(arguments.callee,C,H)){return this;}var E=this.element.getSize(),F=this.element.getScrollSize();var B=this.element.getScroll(),D={x:C,y:H}; for(var G in D){var A=F[G]-E[G];if($chk(D[G])){D[G]=($type(D[G])=="number")?D[G].limit(0,A):A;}else{D[G]=B[G];}D[G]+=this.options.offset[G];}return this.parent([B.x,B.y],[D.x,D.y]); },toTop:function(){return this.start(false,0);},toLeft:function(){return this.start(0,false);},toRight:function(){return this.start("right",false);},toBottom:function(){return this.start(false,"bottom"); },toElement:function(B){var A=$(B).getPosition(this.element);return this.start(A.x,A.y);}});Fx.Elements=new Class({Extends:Fx.CSS,initialize:function(B,A){this.elements=this.subject=$$(B); this.parent(A);},compute:function(G,H,I){var C={};for(var D in G){var A=G[D],E=H[D],F=C[D]={};for(var B in A){F[B]=this.parent(A[B],E[B],I);}}return C; },set:function(B){for(var C in B){var A=B[C];for(var D in A){this.render(this.elements[C],D,A[D],this.options.unit);}}return this;},start:function(C){if(!this.check(arguments.callee,C)){return this; }var H={},I={};for(var D in C){var F=C[D],A=H[D]={},G=I[D]={};for(var B in F){var E=this.prepare(this.elements[D],B,F[B]);A[B]=E.from;G[B]=E.to;}}return this.parent(H,I); }});var Drag=new Class({Implements:[Events,Options],options:{snap:6,unit:"px",grid:false,style:true,limit:false,handle:false,invert:false,preventDefault:false,modifiers:{x:"left",y:"top"}},initialize:function(){var B=Array.link(arguments,{options:Object.type,element:$defined}); this.element=$(B.element);this.document=this.element.getDocument();this.setOptions(B.options||{});var A=$type(this.options.handle);this.handles=(A=="array"||A=="collection")?$$(this.options.handle):$(this.options.handle)||this.element; this.mouse={now:{},pos:{}};this.value={start:{},now:{}};this.selection=(Browser.Engine.trident)?"selectstart":"mousedown";this.bound={start:this.start.bind(this),check:this.check.bind(this),drag:this.drag.bind(this),stop:this.stop.bind(this),cancel:this.cancel.bind(this),eventStop:$lambda(false)}; this.attach();},attach:function(){this.handles.addEvent("mousedown",this.bound.start);return this;},detach:function(){this.handles.removeEvent("mousedown",this.bound.start); return this;},start:function(C){if(this.options.preventDefault){C.preventDefault();}this.fireEvent("beforeStart",this.element);this.mouse.start=C.page; var A=this.options.limit;this.limit={x:[],y:[]};for(var D in this.options.modifiers){if(!this.options.modifiers[D]){continue;}if(this.options.style){this.value.now[D]=this.element.getStyle(this.options.modifiers[D]).toInt(); }else{this.value.now[D]=this.element[this.options.modifiers[D]];}if(this.options.invert){this.value.now[D]*=-1;}this.mouse.pos[D]=C.page[D]-this.value.now[D]; if(A&&A[D]){for(var B=2;B--;B){if($chk(A[D][B])){this.limit[D][B]=$lambda(A[D][B])();}}}}if($type(this.options.grid)=="number"){this.options.grid={x:this.options.grid,y:this.options.grid}; }this.document.addEvents({mousemove:this.bound.check,mouseup:this.bound.cancel});this.document.addEvent(this.selection,this.bound.eventStop);},check:function(A){if(this.options.preventDefault){A.preventDefault(); }var B=Math.round(Math.sqrt(Math.pow(A.page.x-this.mouse.start.x,2)+Math.pow(A.page.y-this.mouse.start.y,2)));if(B>this.options.snap){this.cancel();this.document.addEvents({mousemove:this.bound.drag,mouseup:this.bound.stop}); this.fireEvent("start",this.element).fireEvent("snap",this.element);}},drag:function(A){if(this.options.preventDefault){A.preventDefault();}this.mouse.now=A.page; for(var B in this.options.modifiers){if(!this.options.modifiers[B]){continue;}this.value.now[B]=this.mouse.now[B]-this.mouse.pos[B];if(this.options.invert){this.value.now[B]*=-1; }if(this.options.limit&&this.limit[B]){if($chk(this.limit[B][1])&&(this.value.now[B]>this.limit[B][1])){this.value.now[B]=this.limit[B][1];}else{if($chk(this.limit[B][0])&&(this.value.now[B]B.left&&A.xB.top);},checkDroppables:function(){var A=this.droppables.filter(this.checkAgainst,this).getLast(); if(this.overed!=A){if(this.overed){this.fireEvent("leave",[this.element,this.overed]);}if(A){this.overed=A;this.fireEvent("enter",[this.element,A]);}else{this.overed=null; }}},drag:function(A){this.parent(A);if(this.droppables.length){this.checkDroppables();}},stop:function(A){this.checkDroppables();this.fireEvent("drop",[this.element,this.overed]); this.overed=null;return this.parent(A);}});Element.implement({makeDraggable:function(A){return new Drag.Move(this,A);}});Hash.Cookie=new Class({Extends:Cookie,options:{autoSave:true},initialize:function(B,A){this.parent(B,A); this.load();},save:function(){var A=JSON.encode(this.hash);if(!A||A.length>4096){return false;}if(A=="{}"){this.dispose();}else{this.write(A);}return true; },load:function(){this.hash=new Hash(JSON.decode(this.read(),true));return this;}});Hash.Cookie.implement((function(){var A={};Hash.each(Hash.prototype,function(C,B){A[B]=function(){var D=C.apply(this.hash,arguments); if(this.options.autoSave){this.save();}return D;};});return A;})());var Color=new Native({initialize:function(B,C){if(arguments.length>=3){C="rgb";B=Array.slice(arguments,0,3); }else{if(typeof B=="string"){if(B.match(/rgb/)){B=B.rgbToHex().hexToRgb(true);}else{if(B.match(/hsb/)){B=B.hsbToRgb();}else{B=B.hexToRgb(true);}}}}C=C||"rgb"; switch(C){case"hsb":var A=B;B=B.hsbToRgb();B.hsb=A;break;case"hex":B=B.hexToRgb(true);break;}B.rgb=B.slice(0,3);B.hsb=B.hsb||B.rgbToHsb();B.hex=B.rgbToHex(); return $extend(B,this);}});Color.implement({mix:function(){var A=Array.slice(arguments);var C=($type(A.getLast())=="number")?A.pop():50;var B=this.slice(); A.each(function(D){D=new Color(D);for(var E=0;E<3;E++){B[E]=Math.round((B[E]/100*(100-C))+(D[E]/100*C));}});return new Color(B,"rgb");},invert:function(){return new Color(this.map(function(A){return 255-A; }));},setHue:function(A){return new Color([A,this.hsb[1],this.hsb[2]],"hsb");},setSaturation:function(A){return new Color([this.hsb[0],A,this.hsb[2]],"hsb"); },setBrightness:function(A){return new Color([this.hsb[0],this.hsb[1],A],"hsb");}});function $RGB(C,B,A){return new Color([C,B,A],"rgb");}function $HSB(C,B,A){return new Color([C,B,A],"hsb"); }function $HEX(A){return new Color(A,"hex");}Array.implement({rgbToHsb:function(){var B=this[0],C=this[1],J=this[2];var G,F,H;var I=Math.max(B,C,J),E=Math.min(B,C,J); var K=I-E;H=I/255;F=(I!=0)?K/I:0;if(F==0){G=0;}else{var D=(I-B)/K;var A=(I-C)/K;var L=(I-J)/K;if(B==I){G=L-A;}else{if(C==I){G=2+D-L;}else{G=4+A-D;}}G/=6; if(G<0){G++;}}return[Math.round(G*360),Math.round(F*100),Math.round(H*100)];},hsbToRgb:function(){var C=Math.round(this[2]/100*255);if(this[1]==0){return[C,C,C]; }else{var A=this[0]%360;var E=A%60;var F=Math.round((this[2]*(100-this[1]))/10000*255);var D=Math.round((this[2]*(6000-this[1]*E))/600000*255);var B=Math.round((this[2]*(6000-this[1]*(60-E)))/600000*255); switch(Math.floor(A/60)){case 0:return[C,B,F];case 1:return[D,C,F];case 2:return[F,C,B];case 3:return[F,D,C];case 4:return[B,F,C];case 5:return[C,F,D]; }}return false;}});String.implement({rgbToHsb:function(){var A=this.match(/\d{1,3}/g);return(A)?hsb.rgbToHsb():null;},hsbToRgb:function(){var A=this.match(/\d{1,3}/g); return(A)?A.hsbToRgb():null;}});var Group=new Class({initialize:function(){this.instances=Array.flatten(arguments);this.events={};this.checker={};},addEvent:function(B,A){this.checker[B]=this.checker[B]||{}; this.events[B]=this.events[B]||[];if(this.events[B].contains(A)){return false;}else{this.events[B].push(A);}this.instances.each(function(C,D){C.addEvent(B,this.check.bind(this,[B,C,D])); },this);return this;},check:function(C,A,B){this.checker[C][B]=true;var D=this.instances.every(function(F,E){return this.checker[C][E]||false;},this);if(!D){return ; }this.checker[C]={};this.events[C].each(function(E){E.call(this,this.instances,A);},this);}});var Asset=new Hash({javascript:function(F,D){D=$extend({onload:$empty,document:document,check:$lambda(true)},D); var B=new Element("script",{src:F,type:"text/javascript"});var E=D.onload.bind(B),A=D.check,G=D.document;delete D.onload;delete D.check;delete D.document; B.addEvents({load:E,readystatechange:function(){if(["loaded","complete"].contains(this.readyState)){E();}}}).setProperties(D);if(Browser.Engine.webkit419){var C=(function(){if(!$try(A)){return ; }$clear(C);E();}).periodical(50);}return B.inject(G.head);},css:function(B,A){return new Element("link",$merge({rel:"stylesheet",media:"screen",type:"text/css",href:B},A)).inject(document.head); },image:function(C,B){B=$merge({onload:$empty,onabort:$empty,onerror:$empty},B);var D=new Image();var A=$(D)||new Element("img");["load","abort","error"].each(function(E){var F="on"+E; var G=B[F];delete B[F];D[F]=function(){if(!D){return ;}if(!A.parentNode){A.width=D.width;A.height=D.height;}D=D.onload=D.onabort=D.onerror=null;G.delay(1,A,A); A.fireEvent(E,A,1);};});D.src=A.src=C;if(D&&D.complete){D.onload.delay(1);}return A.setProperties(B);},images:function(D,C){C=$merge({onComplete:$empty,onProgress:$empty},C); if(!D.push){D=[D];}var A=[];var B=0;D.each(function(F){var E=new Asset.image(F,{onload:function(){C.onProgress.call(this,B,D.indexOf(F));B++;if(B==D.length){C.onComplete(); }}});A.push(E);});return new Elements(A);}});var Slider=new Class({Implements:[Events,Options],options:{onTick:function(A){if(this.options.snap){A=this.toPosition(this.step); }this.knob.setStyle(this.property,A);},snap:false,offset:0,range:false,wheel:false,steps:100,mode:"horizontal"},initialize:function(E,A,D){this.setOptions(D); this.element=$(E);this.knob=$(A);this.previousChange=this.previousEnd=this.step=-1;this.element.addEvent("mousedown",this.clickedElement.bind(this));if(this.options.wheel){this.element.addEvent("mousewheel",this.scrolledElement.bindWithEvent(this)); }var F,B={},C={x:false,y:false};switch(this.options.mode){case"vertical":this.axis="y";this.property="top";F="offsetHeight";break;case"horizontal":this.axis="x"; this.property="left";F="offsetWidth";}this.half=this.knob[F]/2;this.full=this.element[F]-this.knob[F]+(this.options.offset*2);this.min=$chk(this.options.range[0])?this.options.range[0]:0; this.max=$chk(this.options.range[1])?this.options.range[1]:this.options.steps;this.range=this.max-this.min;this.steps=this.options.steps||this.full;this.stepSize=Math.abs(this.range)/this.steps; this.stepWidth=this.stepSize*this.full/Math.abs(this.range);this.knob.setStyle("position","relative").setStyle(this.property,-this.options.offset);C[this.axis]=this.property; B[this.axis]=[-this.options.offset,this.full-this.options.offset];this.drag=new Drag(this.knob,{snap:0,limit:B,modifiers:C,onDrag:this.draggedKnob.bind(this),onStart:this.draggedKnob.bind(this),onComplete:function(){this.draggedKnob(); this.end();}.bind(this)});if(this.options.snap){this.drag.options.grid=Math.ceil(this.stepWidth);this.drag.options.limit[this.axis][1]=this.full;}},set:function(A){if(!((this.range>0)^(A0)^(A>this.max))){A=this.max;}this.step=Math.round(A);this.checkStep();this.end();this.fireEvent("tick",this.toPosition(this.step));return this; },clickedElement:function(C){var B=this.range<0?-1:1;var A=C.page[this.axis]-this.element.getPosition()[this.axis]-this.half;A=A.limit(-this.options.offset,this.full-this.options.offset); this.step=Math.round(this.min+B*this.toStep(A));this.checkStep();this.end();this.fireEvent("tick",A);},scrolledElement:function(A){var B=(this.options.mode=="horizontal")?(A.wheel<0):(A.wheel>0); this.set(B?this.step-this.stepSize:this.step+this.stepSize);A.stop();},draggedKnob:function(){var B=this.range<0?-1:1;var A=this.drag.value.now[this.axis]; A=A.limit(-this.options.offset,this.full-this.options.offset);this.step=Math.round(this.min+B*this.toStep(A));this.checkStep();},checkStep:function(){if(this.previousChange!=this.step){this.previousChange=this.step; this.fireEvent("change",this.step);}},end:function(){if(this.previousEnd!==this.step){this.previousEnd=this.step;this.fireEvent("complete",this.step+""); }},toStep:function(A){var B=(A+this.options.offset)*this.stepSize/this.full*this.steps;return this.options.steps?Math.round(B-=B%this.stepSize):B;},toPosition:function(A){return(this.full*Math.abs(this.min-A))/(this.steps*this.stepSize)-this.options.offset; }});var Scroller=new Class({Implements:[Events,Options],options:{area:20,velocity:1,onChange:function(A,B){this.element.scrollTo(A,B);}},initialize:function(B,A){this.setOptions(A); this.element=$(B);this.listener=($type(this.element)!="element")?$(this.element.getDocument().body):this.element;this.timer=null;this.coord=this.getCoords.bind(this); },start:function(){this.listener.addEvent("mousemove",this.coord);},stop:function(){this.listener.removeEvent("mousemove",this.coord);this.timer=$clear(this.timer); },getCoords:function(A){this.page=(this.listener.get("tag")=="body")?A.client:A.page;if(!this.timer){this.timer=this.scroll.periodical(50,this);}},scroll:function(){var B=this.element.getSize(),A=this.element.getScroll(),E=this.element.getPosition(),D={x:0,y:0}; for(var C in this.page){if(this.page[C]<(this.options.area+E[C])&&A[C]!=0){D[C]=(this.page[C]-this.options.area-E[C])*this.options.velocity;}else{if(this.page[C]+this.options.area>(B[C]+E[C])&&B[C]+B[C]!=A[C]){D[C]=(this.page[C]-B[C]+this.options.area-E[C])*this.options.velocity; }}}if(D.y||D.x){this.fireEvent("change",[A.x+D.x,A.y+D.y]);}}});tdiary-contrib-3.2.2/util/image-gallery/js/SmoothGallery/scripts/mootools-1.2.1-core-yc.js000066400000000000000000001767131213632744000312660ustar00rootroot00000000000000//MooTools, , My Object Oriented (JavaScript) Tools. Copyright (c) 2006-2008 Valerio Proietti, , MIT Style License. var MooTools={version:"1.2.1",build:"0d4845aab3d9a4fdee2f0d4a6dd59210e4b697cf"};var Native=function(K){K=K||{};var A=K.name;var I=K.legacy;var B=K.protect; var C=K.implement;var H=K.generics;var F=K.initialize;var G=K.afterImplement||function(){};var D=F||I;H=H!==false;D.constructor=Native;D.$family={name:"native"}; if(I&&F){D.prototype=I.prototype;}D.prototype.constructor=D;if(A){var E=A.toLowerCase();D.prototype.$family={name:E};Native.typize(D,E);}var J=function(N,L,O,M){if(!B||M||!N.prototype[L]){N.prototype[L]=O; }if(H){Native.genericize(N,L,B);}G.call(N,L,O);return N;};D.alias=function(N,L,O){if(typeof N=="string"){if((N=this.prototype[N])){return J(this,L,N,O); }}for(var M in N){this.alias(M,N[M],L);}return this;};D.implement=function(M,L,O){if(typeof M=="string"){return J(this,M,L,O);}for(var N in M){J(this,N,M[N],L); }return this;};if(C){D.implement(C);}return D;};Native.genericize=function(B,C,A){if((!A||!B[C])&&typeof B.prototype[C]=="function"){B[C]=function(){var D=Array.prototype.slice.call(arguments); return B.prototype[C].apply(D.shift(),D);};}};Native.implement=function(D,C){for(var B=0,A=D.length;B-1:this.indexOf(A)>-1;},trim:function(){return this.replace(/^\s+|\s+$/g,"");},clean:function(){return this.replace(/\s+/g," ").trim(); },camelCase:function(){return this.replace(/-\D/g,function(A){return A.charAt(1).toUpperCase();});},hyphenate:function(){return this.replace(/[A-Z]/g,function(A){return("-"+A.charAt(0).toLowerCase()); });},capitalize:function(){return this.replace(/\b[a-z]/g,function(A){return A.toUpperCase();});},escapeRegExp:function(){return this.replace(/([-.*+?^${}()|[\]\/\\])/g,"\\$1"); },toInt:function(A){return parseInt(this,A||10);},toFloat:function(){return parseFloat(this);},hexToRgb:function(B){var A=this.match(/^#?(\w{1,2})(\w{1,2})(\w{1,2})$/); return(A)?A.slice(1).hexToRgb(B):null;},rgbToHex:function(B){var A=this.match(/\d{1,3}/g);return(A)?A.rgbToHex(B):null;},stripScripts:function(B){var A=""; var C=this.replace(/]*>([\s\S]*?)<\/script>/gi,function(){A+=arguments[1]+"\n";return"";});if(B===true){$exec(A);}else{if($type(B)=="function"){B(A,C); }}return C;},substitute:function(A,B){return this.replace(B||(/\\?\{([^{}]+)\}/g),function(D,C){if(D.charAt(0)=="\\"){return D.slice(1);}return(A[C]!=undefined)?A[C]:""; });}});Hash.implement({has:Object.prototype.hasOwnProperty,keyOf:function(B){for(var A in this){if(this.hasOwnProperty(A)&&this[A]===B){return A;}}return null; },hasValue:function(A){return(Hash.keyOf(this,A)!==null);},extend:function(A){Hash.each(A,function(C,B){Hash.set(this,B,C);},this);return this;},combine:function(A){Hash.each(A,function(C,B){Hash.include(this,B,C); },this);return this;},erase:function(A){if(this.hasOwnProperty(A)){delete this[A];}return this;},get:function(A){return(this.hasOwnProperty(A))?this[A]:null; },set:function(A,B){if(!this[A]||this.hasOwnProperty(A)){this[A]=B;}return this;},empty:function(){Hash.each(this,function(B,A){delete this[A];},this); return this;},include:function(B,C){var A=this[B];if(A==undefined){this[B]=C;}return this;},map:function(B,C){var A=new Hash;Hash.each(this,function(E,D){A.set(D,B.call(C,E,D,this)); },this);return A;},filter:function(B,C){var A=new Hash;Hash.each(this,function(E,D){if(B.call(C,E,D,this)){A.set(D,E);}},this);return A;},every:function(B,C){for(var A in this){if(this.hasOwnProperty(A)&&!B.call(C,this[A],A)){return false; }}return true;},some:function(B,C){for(var A in this){if(this.hasOwnProperty(A)&&B.call(C,this[A],A)){return true;}}return false;},getKeys:function(){var A=[]; Hash.each(this,function(C,B){A.push(B);});return A;},getValues:function(){var A=[];Hash.each(this,function(B){A.push(B);});return A;},toQueryString:function(A){var B=[]; Hash.each(this,function(F,E){if(A){E=A+"["+E+"]";}var D;switch($type(F)){case"object":D=Hash.toQueryString(F,E);break;case"array":var C={};F.each(function(H,G){C[G]=H; });D=Hash.toQueryString(C,E);break;default:D=E+"="+encodeURIComponent(F);}if(F!=undefined){B.push(D);}});return B.join("&");}});Hash.alias({keyOf:"indexOf",hasValue:"contains"}); var Event=new Native({name:"Event",initialize:function(A,F){F=F||window;var K=F.document;A=A||F.event;if(A.$extended){return A;}this.$extended=true;var J=A.type; var G=A.target||A.srcElement;while(G&&G.nodeType==3){G=G.parentNode;}if(J.test(/key/)){var B=A.which||A.keyCode;var M=Event.Keys.keyOf(B);if(J=="keydown"){var D=B-111; if(D>0&&D<13){M="f"+D;}}M=M||String.fromCharCode(B).toLowerCase();}else{if(J.match(/(click|mouse|menu)/i)){K=(!K.compatMode||K.compatMode=="CSS1Compat")?K.html:K.body; var I={x:A.pageX||A.clientX+K.scrollLeft,y:A.pageY||A.clientY+K.scrollTop};var C={x:(A.pageX)?A.pageX-F.pageXOffset:A.clientX,y:(A.pageY)?A.pageY-F.pageYOffset:A.clientY}; if(J.match(/DOMMouseScroll|mousewheel/)){var H=(A.wheelDelta)?A.wheelDelta/120:-(A.detail||0)/3;}var E=(A.which==3)||(A.button==2);var L=null;if(J.match(/over|out/)){switch(J){case"mouseover":L=A.relatedTarget||A.fromElement; break;case"mouseout":L=A.relatedTarget||A.toElement;}if(!(function(){while(L&&L.nodeType==3){L=L.parentNode;}return true;}).create({attempt:Browser.Engine.gecko})()){L=false; }}}}return $extend(this,{event:A,type:J,page:I,client:C,rightClick:E,wheel:H,relatedTarget:L,target:G,code:B,key:M,shift:A.shiftKey,control:A.ctrlKey,alt:A.altKey,meta:A.metaKey}); }});Event.Keys=new Hash({enter:13,up:38,down:40,left:37,right:39,esc:27,space:32,backspace:8,tab:9,"delete":46});Event.implement({stop:function(){return this.stopPropagation().preventDefault(); },stopPropagation:function(){if(this.event.stopPropagation){this.event.stopPropagation();}else{this.event.cancelBubble=true;}return this;},preventDefault:function(){if(this.event.preventDefault){this.event.preventDefault(); }else{this.event.returnValue=false;}return this;}});var Class=new Native({name:"Class",initialize:function(B){B=B||{};var A=function(){for(var E in this){if($type(this[E])!="function"){this[E]=$unlink(this[E]); }}this.constructor=A;if(Class.prototyping){return this;}var D=(this.initialize)?this.initialize.apply(this,arguments):this;if(this.options&&this.options.initialize){this.options.initialize.call(this); }return D;};for(var C in Class.Mutators){if(!B[C]){continue;}B=Class.Mutators[C](B,B[C]);delete B[C];}$extend(A,this);A.constructor=Class;A.prototype=B; return A;}});Class.Mutators={Extends:function(C,A){Class.prototyping=A.prototype;var B=new A;delete B.parent;B=Class.inherit(B,C);delete Class.prototyping; return B;},Implements:function(A,B){$splat(B).each(function(C){Class.prototying=C;$extend(A,($type(C)=="class")?new C:C);delete Class.prototyping;});return A; }};Class.extend({inherit:function(B,E){var A=arguments.callee.caller;for(var D in E){var C=E[D];var G=B[D];var F=$type(C);if(G&&F=="function"){if(C!=G){if(A){C.__parent=G; B[D]=C;}else{Class.override(B,D,C);}}}else{if(F=="object"){B[D]=$merge(G,C);}else{B[D]=C;}}}if(A){B.parent=function(){return arguments.callee.caller.__parent.apply(this,arguments); };}return B;},override:function(B,A,E){var D=Class.prototyping;if(D&&B[A]!=D[A]){D=null;}var C=function(){var F=this.parent;this.parent=D?D[A]:B[A];var G=E.apply(this,arguments); this.parent=F;return G;};B[A]=C;}});Class.implement({implement:function(){var A=this.prototype;$each(arguments,function(B){Class.inherit(A,B);});return this; }});var Chain=new Class({$chain:[],chain:function(){this.$chain.extend(Array.flatten(arguments));return this;},callChain:function(){return(this.$chain.length)?this.$chain.shift().apply(this,arguments):false; },clearChain:function(){this.$chain.empty();return this;}});var Events=new Class({$events:{},addEvent:function(C,B,A){C=Events.removeOn(C);if(B!=$empty){this.$events[C]=this.$events[C]||[]; this.$events[C].include(B);if(A){B.internal=true;}}return this;},addEvents:function(A){for(var B in A){this.addEvent(B,A[B]);}return this;},fireEvent:function(C,B,A){C=Events.removeOn(C); if(!this.$events||!this.$events[C]){return this;}this.$events[C].each(function(D){D.create({bind:this,delay:A,"arguments":B})();},this);return this;},removeEvent:function(B,A){B=Events.removeOn(B); if(!this.$events[B]){return this;}if(!A.internal){this.$events[B].erase(A);}return this;},removeEvents:function(C){if($type(C)=="object"){for(var D in C){this.removeEvent(D,C[D]); }return this;}if(C){C=Events.removeOn(C);}for(var D in this.$events){if(C&&C!=D){continue;}var B=this.$events[D];for(var A=B.length;A--;A){this.removeEvent(D,B[A]); }}return this;}});Events.removeOn=function(A){return A.replace(/^on([A-Z])/,function(B,C){return C.toLowerCase();});};var Options=new Class({setOptions:function(){this.options=$merge.run([this.options].extend(arguments)); if(!this.addEvent){return this;}for(var A in this.options){if($type(this.options[A])!="function"||!(/^on[A-Z]/).test(A)){continue;}this.addEvent(A,this.options[A]); delete this.options[A];}return this;}});var Element=new Native({name:"Element",legacy:window.Element,initialize:function(A,B){var C=Element.Constructors.get(A); if(C){return C(B);}if(typeof A=="string"){return document.newElement(A,B);}return $(A).set(B);},afterImplement:function(A,B){Element.Prototype[A]=B;if(Array[A]){return ; }Elements.implement(A,function(){var C=[],G=true;for(var E=0,D=this.length;E";}return $.element(this.createElement(A)).set(B);},newTextNode:function(A){return this.createTextNode(A); },getDocument:function(){return this;},getWindow:function(){return this.window;}});Window.implement({$:function(B,C){if(B&&B.$family&&B.uid){return B;}var A=$type(B); return($[A])?$[A](B,C,this.document):null;},$$:function(A){if(arguments.length==1&&typeof A=="string"){return this.document.getElements(A);}var F=[];var C=Array.flatten(arguments); for(var D=0,B=C.length;D1);A.each(function(E){var F=this.getElementsByTagName(E.trim());(B)?C.extend(F):C=F;},this);return new Elements(C,{ddup:B,cash:!D}); }});(function(){var H={},F={};var I={input:"checked",option:"selected",textarea:(Browser.Engine.webkit&&Browser.Engine.version<420)?"innerHTML":"value"}; var C=function(L){return(F[L]||(F[L]={}));};var G=function(N,L){if(!N){return ;}var M=N.uid;if(Browser.Engine.trident){if(N.clearAttributes){var P=L&&N.cloneNode(false); N.clearAttributes();if(P){N.mergeAttributes(P);}}else{if(N.removeEvents){N.removeEvents();}}if((/object/i).test(N.tagName)){for(var O in N){if(typeof N[O]=="function"){N[O]=$empty; }}Element.dispose(N);}}if(!M){return ;}H[M]=F[M]=null;};var D=function(){Hash.each(H,G);if(Browser.Engine.trident){$A(document.getElementsByTagName("object")).each(G); }if(window.CollectGarbage){CollectGarbage();}H=F=null;};var J=function(N,L,S,M,P,R){var O=N[S||L];var Q=[];while(O){if(O.nodeType==1&&(!M||Element.match(O,M))){if(!P){return $(O,R); }Q.push(O);}O=O[L];}return(P)?new Elements(Q,{ddup:false,cash:!R}):null;};var E={html:"innerHTML","class":"className","for":"htmlFor",text:(Browser.Engine.trident||(Browser.Engine.webkit&&Browser.Engine.version<420))?"innerText":"textContent"}; var B=["compact","nowrap","ismap","declare","noshade","checked","disabled","readonly","multiple","selected","noresize","defer"];var K=["value","accessKey","cellPadding","cellSpacing","colSpan","frameBorder","maxLength","readOnly","rowSpan","tabIndex","useMap"]; Hash.extend(E,B.associate(B));Hash.extend(E,K.associate(K.map(String.toLowerCase)));var A={before:function(M,L){if(L.parentNode){L.parentNode.insertBefore(M,L); }},after:function(M,L){if(!L.parentNode){return ;}var N=L.nextSibling;(N)?L.parentNode.insertBefore(M,N):L.parentNode.appendChild(M);},bottom:function(M,L){L.appendChild(M); },top:function(M,L){var N=L.firstChild;(N)?L.insertBefore(M,N):L.appendChild(M);}};A.inside=A.bottom;Hash.each(A,function(L,M){M=M.capitalize();Element.implement("inject"+M,function(N){L(this,$(N,true)); return this;});Element.implement("grab"+M,function(N){L($(N,true),this);return this;});});Element.implement({set:function(O,M){switch($type(O)){case"object":for(var N in O){this.set(N,O[N]); }break;case"string":var L=Element.Properties.get(O);(L&&L.set)?L.set.apply(this,Array.slice(arguments,1)):this.setProperty(O,M);}return this;},get:function(M){var L=Element.Properties.get(M); return(L&&L.get)?L.get.apply(this,Array.slice(arguments,1)):this.getProperty(M);},erase:function(M){var L=Element.Properties.get(M);(L&&L.erase)?L.erase.apply(this):this.removeProperty(M); return this;},setProperty:function(M,N){var L=E[M];if(N==undefined){return this.removeProperty(M);}if(L&&B[M]){N=!!N;}(L)?this[L]=N:this.setAttribute(M,""+N); return this;},setProperties:function(L){for(var M in L){this.setProperty(M,L[M]);}return this;},getProperty:function(M){var L=E[M];var N=(L)?this[L]:this.getAttribute(M,2); return(B[M])?!!N:(L)?N:N||null;},getProperties:function(){var L=$A(arguments);return L.map(this.getProperty,this).associate(L);},removeProperty:function(M){var L=E[M]; (L)?this[L]=(L&&B[M])?false:"":this.removeAttribute(M);return this;},removeProperties:function(){Array.each(arguments,this.removeProperty,this);return this; },hasClass:function(L){return this.className.contains(L," ");},addClass:function(L){if(!this.hasClass(L)){this.className=(this.className+" "+L).clean(); }return this;},removeClass:function(L){this.className=this.className.replace(new RegExp("(^|\\s)"+L+"(?:\\s|$)"),"$1");return this;},toggleClass:function(L){return this.hasClass(L)?this.removeClass(L):this.addClass(L); },adopt:function(){Array.flatten(arguments).each(function(L){L=$(L,true);if(L){this.appendChild(L);}},this);return this;},appendText:function(M,L){return this.grab(this.getDocument().newTextNode(M),L); },grab:function(M,L){A[L||"bottom"]($(M,true),this);return this;},inject:function(M,L){A[L||"bottom"](this,$(M,true));return this;},replaces:function(L){L=$(L,true); L.parentNode.replaceChild(this,L);return this;},wraps:function(M,L){M=$(M,true);return this.replaces(M).grab(M,L);},getPrevious:function(L,M){return J(this,"previousSibling",null,L,false,M); },getAllPrevious:function(L,M){return J(this,"previousSibling",null,L,true,M);},getNext:function(L,M){return J(this,"nextSibling",null,L,false,M);},getAllNext:function(L,M){return J(this,"nextSibling",null,L,true,M); },getFirst:function(L,M){return J(this,"nextSibling","firstChild",L,false,M);},getLast:function(L,M){return J(this,"previousSibling","lastChild",L,false,M); },getParent:function(L,M){return J(this,"parentNode",null,L,false,M);},getParents:function(L,M){return J(this,"parentNode",null,L,true,M);},getChildren:function(L,M){return J(this,"nextSibling","firstChild",L,true,M); },getWindow:function(){return this.ownerDocument.window;},getDocument:function(){return this.ownerDocument;},getElementById:function(O,N){var M=this.ownerDocument.getElementById(O); if(!M){return null;}for(var L=M.parentNode;L!=this;L=L.parentNode){if(!L){return null;}}return $.element(M,N);},getSelected:function(){return new Elements($A(this.options).filter(function(L){return L.selected; }));},getComputedStyle:function(M){if(this.currentStyle){return this.currentStyle[M.camelCase()];}var L=this.getDocument().defaultView.getComputedStyle(this,null); return(L)?L.getPropertyValue([M.hyphenate()]):null;},toQueryString:function(){var L=[];this.getElements("input, select, textarea",true).each(function(M){if(!M.name||M.disabled){return ; }var N=(M.tagName.toLowerCase()=="select")?Element.getSelected(M).map(function(O){return O.value;}):((M.type=="radio"||M.type=="checkbox")&&!M.checked)?null:M.value; $splat(N).each(function(O){if(typeof O!="undefined"){L.push(M.name+"="+encodeURIComponent(O));}});});return L.join("&");},clone:function(O,L){O=O!==false; var R=this.cloneNode(O);var N=function(V,U){if(!L){V.removeAttribute("id");}if(Browser.Engine.trident){V.clearAttributes();V.mergeAttributes(U);V.removeAttribute("uid"); if(V.options){var W=V.options,S=U.options;for(var T=W.length;T--;){W[T].selected=S[T].selected;}}}var X=I[U.tagName.toLowerCase()];if(X&&U[X]){V[X]=U[X]; }};if(O){var P=R.getElementsByTagName("*"),Q=this.getElementsByTagName("*");for(var M=P.length;M--;){N(P[M],Q[M]);}}N(R,this);return $(R);},destroy:function(){Element.empty(this); Element.dispose(this);G(this,true);return null;},empty:function(){$A(this.childNodes).each(function(L){Element.destroy(L);});return this;},dispose:function(){return(this.parentNode)?this.parentNode.removeChild(this):this; },hasChild:function(L){L=$(L,true);if(!L){return false;}if(Browser.Engine.webkit&&Browser.Engine.version<420){return $A(this.getElementsByTagName(L.tagName)).contains(L); }return(this.contains)?(this!=L&&this.contains(L)):!!(this.compareDocumentPosition(L)&16);},match:function(L){return(!L||(L==this)||(Element.get(this,"tag")==L)); }});Native.implement([Element,Window,Document],{addListener:function(O,N){if(O=="unload"){var L=N,M=this;N=function(){M.removeListener("unload",N);L(); };}else{H[this.uid]=this;}if(this.addEventListener){this.addEventListener(O,N,false);}else{this.attachEvent("on"+O,N);}return this;},removeListener:function(M,L){if(this.removeEventListener){this.removeEventListener(M,L,false); }else{this.detachEvent("on"+M,L);}return this;},retrieve:function(M,L){var O=C(this.uid),N=O[M];if(L!=undefined&&N==undefined){N=O[M]=L;}return $pick(N); },store:function(M,L){var N=C(this.uid);N[M]=L;return this;},eliminate:function(L){var M=C(this.uid);delete M[L];return this;}});window.addListener("unload",D); })();Element.Properties=new Hash;Element.Properties.style={set:function(A){this.style.cssText=A;},get:function(){return this.style.cssText;},erase:function(){this.style.cssText=""; }};Element.Properties.tag={get:function(){return this.tagName.toLowerCase();}};Element.Properties.html=(function(){var C=document.createElement("div"); var A={table:[1,"","
        "],select:[1,""],tbody:[2,"","
        "],tr:[3,"","
        "]}; A.thead=A.tfoot=A.tbody;var B={set:function(){var E=Array.flatten(arguments).join("");var F=Browser.Engine.trident&&A[this.get("tag")];if(F){var G=C;G.innerHTML=F[1]+E+F[2]; for(var D=F[0];D--;){G=G.firstChild;}this.empty().adopt(G.childNodes);}else{this.innerHTML=E;}}};B.erase=B.set;return B;})();if(Browser.Engine.webkit&&Browser.Engine.version<420){Element.Properties.text={get:function(){if(this.innerText){return this.innerText; }var A=this.ownerDocument.newElement("div",{html:this.innerHTML}).inject(this.ownerDocument.body);var B=A.innerText;A.destroy();return B;}};}Element.Properties.events={set:function(A){this.addEvents(A); }};Native.implement([Element,Window,Document],{addEvent:function(E,G){var H=this.retrieve("events",{});H[E]=H[E]||{keys:[],values:[]};if(H[E].keys.contains(G)){return this; }H[E].keys.push(G);var F=E,A=Element.Events.get(E),C=G,I=this;if(A){if(A.onAdd){A.onAdd.call(this,G);}if(A.condition){C=function(J){if(A.condition.call(this,J)){return G.call(this,J); }return true;};}F=A.base||F;}var D=function(){return G.call(I);};var B=Element.NativeEvents[F];if(B){if(B==2){D=function(J){J=new Event(J,I.getWindow()); if(C.call(I,J)===false){J.stop();}};}this.addListener(F,D);}H[E].values.push(D);return this;},removeEvent:function(C,B){var A=this.retrieve("events");if(!A||!A[C]){return this; }var F=A[C].keys.indexOf(B);if(F==-1){return this;}A[C].keys.splice(F,1);var E=A[C].values.splice(F,1)[0];var D=Element.Events.get(C);if(D){if(D.onRemove){D.onRemove.call(this,B); }C=D.base||C;}return(Element.NativeEvents[C])?this.removeListener(C,E):this;},addEvents:function(A){for(var B in A){this.addEvent(B,A[B]);}return this; },removeEvents:function(A){if($type(A)=="object"){for(var C in A){this.removeEvent(C,A[C]);}return this;}var B=this.retrieve("events");if(!B){return this; }if(!A){for(var C in B){this.removeEvents(C);}this.eliminate("events");}else{if(B[A]){while(B[A].keys[0]){this.removeEvent(A,B[A].keys[0]);}B[A]=null;}}return this; },fireEvent:function(D,B,A){var C=this.retrieve("events");if(!C||!C[D]){return this;}C[D].keys.each(function(E){E.create({bind:this,delay:A,"arguments":B})(); },this);return this;},cloneEvents:function(D,A){D=$(D);var C=D.retrieve("events");if(!C){return this;}if(!A){for(var B in C){this.cloneEvents(D,B);}}else{if(C[A]){C[A].keys.each(function(E){this.addEvent(A,E); },this);}}return this;}});Element.NativeEvents={click:2,dblclick:2,mouseup:2,mousedown:2,contextmenu:2,mousewheel:2,DOMMouseScroll:2,mouseover:2,mouseout:2,mousemove:2,selectstart:2,selectend:2,keydown:2,keypress:2,keyup:2,focus:2,blur:2,change:2,reset:2,select:2,submit:2,load:1,unload:1,beforeunload:2,resize:1,move:1,DOMContentLoaded:1,readystatechange:1,error:1,abort:1,scroll:1}; (function(){var A=function(B){var C=B.relatedTarget;if(C==undefined){return true;}if(C===false){return false;}return($type(this)!="document"&&C!=this&&C.prefix!="xul"&&!this.hasChild(C)); };Element.Events=new Hash({mouseenter:{base:"mouseover",condition:A},mouseleave:{base:"mouseout",condition:A},mousewheel:{base:(Browser.Engine.gecko)?"DOMMouseScroll":"mousewheel"}}); })();Element.Properties.styles={set:function(A){this.setStyles(A);}};Element.Properties.opacity={set:function(A,B){if(!B){if(A==0){if(this.style.visibility!="hidden"){this.style.visibility="hidden"; }}else{if(this.style.visibility!="visible"){this.style.visibility="visible";}}}if(!this.currentStyle||!this.currentStyle.hasLayout){this.style.zoom=1;}if(Browser.Engine.trident){this.style.filter=(A==1)?"":"alpha(opacity="+A*100+")"; }this.style.opacity=A;this.store("opacity",A);},get:function(){return this.retrieve("opacity",1);}};Element.implement({setOpacity:function(A){return this.set("opacity",A,true); },getOpacity:function(){return this.get("opacity");},setStyle:function(B,A){switch(B){case"opacity":return this.set("opacity",parseFloat(A));case"float":B=(Browser.Engine.trident)?"styleFloat":"cssFloat"; }B=B.camelCase();if($type(A)!="string"){var C=(Element.Styles.get(B)||"@").split(" ");A=$splat(A).map(function(E,D){if(!C[D]){return"";}return($type(E)=="number")?C[D].replace("@",Math.round(E)):E; }).join(" ");}else{if(A==String(Number(A))){A=Math.round(A);}}this.style[B]=A;return this;},getStyle:function(G){switch(G){case"opacity":return this.get("opacity"); case"float":G=(Browser.Engine.trident)?"styleFloat":"cssFloat";}G=G.camelCase();var A=this.style[G];if(!$chk(A)){A=[];for(var F in Element.ShortStyles){if(G!=F){continue; }for(var E in Element.ShortStyles[F]){A.push(this.getStyle(E));}return A.join(" ");}A=this.getComputedStyle(G);}if(A){A=String(A);var C=A.match(/rgba?\([\d\s,]+\)/); if(C){A=A.replace(C[0],C[0].rgbToHex());}}if(Browser.Engine.presto||(Browser.Engine.trident&&!$chk(parseInt(A)))){if(G.test(/^(height|width)$/)){var B=(G=="width")?["left","right"]:["top","bottom"],D=0; B.each(function(H){D+=this.getStyle("border-"+H+"-width").toInt()+this.getStyle("padding-"+H).toInt();},this);return this["offset"+G.capitalize()]-D+"px"; }if((Browser.Engine.presto)&&String(A).test("px")){return A;}if(G.test(/(border(.+)Width|margin|padding)/)){return"0px";}}return A;},setStyles:function(B){for(var A in B){this.setStyle(A,B[A]); }return this;},getStyles:function(){var A={};Array.each(arguments,function(B){A[B]=this.getStyle(B);},this);return A;}});Element.Styles=new Hash({left:"@px",top:"@px",bottom:"@px",right:"@px",width:"@px",height:"@px",maxWidth:"@px",maxHeight:"@px",minWidth:"@px",minHeight:"@px",backgroundColor:"rgb(@, @, @)",backgroundPosition:"@px @px",color:"rgb(@, @, @)",fontSize:"@px",letterSpacing:"@px",lineHeight:"@px",clip:"rect(@px @px @px @px)",margin:"@px @px @px @px",padding:"@px @px @px @px",border:"@px @ rgb(@, @, @) @px @ rgb(@, @, @) @px @ rgb(@, @, @)",borderWidth:"@px @px @px @px",borderStyle:"@ @ @ @",borderColor:"rgb(@, @, @) rgb(@, @, @) rgb(@, @, @) rgb(@, @, @)",zIndex:"@",zoom:"@",fontWeight:"@",textIndent:"@px",opacity:"@"}); Element.ShortStyles={margin:{},padding:{},border:{},borderWidth:{},borderStyle:{},borderColor:{}};["Top","Right","Bottom","Left"].each(function(G){var F=Element.ShortStyles; var B=Element.Styles;["margin","padding"].each(function(H){var I=H+G;F[H][I]=B[I]="@px";});var E="border"+G;F.border[E]=B[E]="@px @ rgb(@, @, @)";var D=E+"Width",A=E+"Style",C=E+"Color"; F[E]={};F.borderWidth[D]=F[E][D]=B[D]="@px";F.borderStyle[A]=F[E][A]=B[A]="@";F.borderColor[C]=F[E][C]=B[C]="rgb(@, @, @)";});(function(){Element.implement({scrollTo:function(H,I){if(B(this)){this.getWindow().scrollTo(H,I); }else{this.scrollLeft=H;this.scrollTop=I;}return this;},getSize:function(){if(B(this)){return this.getWindow().getSize();}return{x:this.offsetWidth,y:this.offsetHeight}; },getScrollSize:function(){if(B(this)){return this.getWindow().getScrollSize();}return{x:this.scrollWidth,y:this.scrollHeight};},getScroll:function(){if(B(this)){return this.getWindow().getScroll(); }return{x:this.scrollLeft,y:this.scrollTop};},getScrolls:function(){var I=this,H={x:0,y:0};while(I&&!B(I)){H.x+=I.scrollLeft;H.y+=I.scrollTop;I=I.parentNode; }return H;},getOffsetParent:function(){var H=this;if(B(H)){return null;}if(!Browser.Engine.trident){return H.offsetParent;}while((H=H.parentNode)&&!B(H)){if(D(H,"position")!="static"){return H; }}return null;},getOffsets:function(){if(Browser.Engine.trident){var L=this.getBoundingClientRect(),J=this.getDocument().documentElement;return{x:L.left+J.scrollLeft-J.clientLeft,y:L.top+J.scrollTop-J.clientTop}; }var I=this,H={x:0,y:0};if(B(this)){return H;}while(I&&!B(I)){H.x+=I.offsetLeft;H.y+=I.offsetTop;if(Browser.Engine.gecko){if(!F(I)){H.x+=C(I);H.y+=G(I); }var K=I.parentNode;if(K&&D(K,"overflow")!="visible"){H.x+=C(K);H.y+=G(K);}}else{if(I!=this&&Browser.Engine.webkit){H.x+=C(I);H.y+=G(I);}}I=I.offsetParent; }if(Browser.Engine.gecko&&!F(this)){H.x-=C(this);H.y-=G(this);}return H;},getPosition:function(K){if(B(this)){return{x:0,y:0};}var L=this.getOffsets(),I=this.getScrolls(); var H={x:L.x-I.x,y:L.y-I.y};var J=(K&&(K=$(K)))?K.getPosition():{x:0,y:0};return{x:H.x-J.x,y:H.y-J.y};},getCoordinates:function(J){if(B(this)){return this.getWindow().getCoordinates(); }var H=this.getPosition(J),I=this.getSize();var K={left:H.x,top:H.y,width:I.x,height:I.y};K.right=K.left+K.width;K.bottom=K.top+K.height;return K;},computePosition:function(H){return{left:H.x-E(this,"margin-left"),top:H.y-E(this,"margin-top")}; },position:function(H){return this.setStyles(this.computePosition(H));}});Native.implement([Document,Window],{getSize:function(){var I=this.getWindow(); if(Browser.Engine.presto||Browser.Engine.webkit){return{x:I.innerWidth,y:I.innerHeight};}var H=A(this);return{x:H.clientWidth,y:H.clientHeight};},getScroll:function(){var I=this.getWindow(); var H=A(this);return{x:I.pageXOffset||H.scrollLeft,y:I.pageYOffset||H.scrollTop};},getScrollSize:function(){var I=A(this);var H=this.getSize();return{x:Math.max(I.scrollWidth,H.x),y:Math.max(I.scrollHeight,H.y)}; },getPosition:function(){return{x:0,y:0};},getCoordinates:function(){var H=this.getSize();return{top:0,left:0,bottom:H.y,right:H.x,height:H.y,width:H.x}; }});var D=Element.getComputedStyle;function E(H,I){return D(H,I).toInt()||0;}function F(H){return D(H,"-moz-box-sizing")=="border-box";}function G(H){return E(H,"border-top-width"); }function C(H){return E(H,"border-left-width");}function B(H){return(/^(?:body|html)$/i).test(H.tagName);}function A(H){var I=H.getDocument();return(!I.compatMode||I.compatMode=="CSS1Compat")?I.html:I.body; }})();Native.implement([Window,Document,Element],{getHeight:function(){return this.getSize().y;},getWidth:function(){return this.getSize().x;},getScrollTop:function(){return this.getScroll().y; },getScrollLeft:function(){return this.getScroll().x;},getScrollHeight:function(){return this.getScrollSize().y;},getScrollWidth:function(){return this.getScrollSize().x; },getTop:function(){return this.getPosition().y;},getLeft:function(){return this.getPosition().x;}});Native.implement([Document,Element],{getElements:function(H,G){H=H.split(","); var C,E={};for(var D=0,B=H.length;D1),cash:!G});}});Element.implement({match:function(B){if(!B||(B==this)){return true;}var D=Selectors.Utils.parseTagAndID(B); var A=D[0],E=D[1];if(!Selectors.Filters.byID(this,E)||!Selectors.Filters.byTag(this,A)){return false;}var C=Selectors.Utils.parseSelector(B);return(C)?Selectors.Utils.filter(this,C,{}):true; }});var Selectors={Cache:{nth:{},parsed:{}}};Selectors.RegExps={id:(/#([\w-]+)/),tag:(/^(\w+|\*)/),quick:(/^(\w+|\*)$/),splitter:(/\s*([+>~\s])\s*([a-zA-Z#.*:\[])/g),combined:(/\.([\w-]+)|\[(\w+)(?:([!*^$~|]?=)(["']?)([^\4]*?)\4)?\]|:([\w-]+)(?:\(["']?(.*?)?["']?\)|$)/g)}; Selectors.Utils={chk:function(B,C){if(!C){return true;}var A=$uid(B);if(!C[A]){return C[A]=true;}return false;},parseNthArgument:function(F){if(Selectors.Cache.nth[F]){return Selectors.Cache.nth[F]; }var C=F.match(/^([+-]?\d*)?([a-z]+)?([+-]?\d*)?$/);if(!C){return false;}var E=parseInt(C[1]);var B=(E||E===0)?E:1;var D=C[2]||false;var A=parseInt(C[3])||0; if(B!=0){A--;while(A<1){A+=B;}while(A>=B){A-=B;}}else{B=A;D="index";}switch(D){case"n":C={a:B,b:A,special:"n"};break;case"odd":C={a:2,b:0,special:"n"}; break;case"even":C={a:2,b:1,special:"n"};break;case"first":C={a:0,special:"index"};break;case"last":C={special:"last-child"};break;case"only":C={special:"only-child"}; break;default:C={a:(B-1),special:"index"};}return Selectors.Cache.nth[F]=C;},parseSelector:function(E){if(Selectors.Cache.parsed[E]){return Selectors.Cache.parsed[E]; }var D,H={classes:[],pseudos:[],attributes:[]};while((D=Selectors.RegExps.combined.exec(E))){var I=D[1],G=D[2],F=D[3],B=D[5],C=D[6],J=D[7];if(I){H.classes.push(I); }else{if(C){var A=Selectors.Pseudo.get(C);if(A){H.pseudos.push({parser:A,argument:J});}else{H.attributes.push({name:C,operator:"=",value:J});}}else{if(G){H.attributes.push({name:G,operator:F,value:B}); }}}}if(!H.classes.length){delete H.classes;}if(!H.attributes.length){delete H.attributes;}if(!H.pseudos.length){delete H.pseudos;}if(!H.classes&&!H.attributes&&!H.pseudos){H=null; }return Selectors.Cache.parsed[E]=H;},parseTagAndID:function(B){var A=B.match(Selectors.RegExps.tag);var C=B.match(Selectors.RegExps.id);return[(A)?A[1]:"*",(C)?C[1]:false]; },filter:function(F,C,E){var D;if(C.classes){for(D=C.classes.length;D--;D){var G=C.classes[D];if(!Selectors.Filters.byClass(F,G)){return false;}}}if(C.attributes){for(D=C.attributes.length; D--;D){var B=C.attributes[D];if(!Selectors.Filters.byAttribute(F,B.name,B.operator,B.value)){return false;}}}if(C.pseudos){for(D=C.pseudos.length;D--;D){var A=C.pseudos[D]; if(!Selectors.Filters.byPseudo(F,A.parser,A.argument,E)){return false;}}}return true;},getByTagAndID:function(B,A,D){if(D){var C=(B.getElementById)?B.getElementById(D,true):Element.getElementById(B,D,true); return(C&&Selectors.Filters.byTag(C,A))?[C]:[];}else{return B.getElementsByTagName(A);}},search:function(I,H,N){var B=[];var C=H.trim().replace(Selectors.RegExps.splitter,function(Y,X,W){B.push(X); return":)"+W;}).split(":)");var J,E,U;for(var T=0,P=C.length;T":function(H,G,I,A,F){var C=Selectors.Utils.getByTagAndID(G,I,A);for(var E=0,D=C.length;EA){return false;}}return(C==A);},even:function(B,A){return Selectors.Pseudo["nth-child"].call(this,"2n+1",A); },odd:function(B,A){return Selectors.Pseudo["nth-child"].call(this,"2n",A);}});Element.Events.domready={onAdd:function(A){if(Browser.loaded){A.call(this); }}};(function(){var B=function(){if(Browser.loaded){return ;}Browser.loaded=true;window.fireEvent("domready");document.fireEvent("domready");};if(Browser.Engine.trident){var A=document.createElement("div"); (function(){($try(function(){A.doScroll("left");return $(A).inject(document.body).set("html","temp").dispose();}))?B():arguments.callee.delay(50);})(); }else{if(Browser.Engine.webkit&&Browser.Engine.version<525){(function(){(["loaded","complete"].contains(document.readyState))?B():arguments.callee.delay(50); })();}else{window.addEvent("load",B);document.addEvent("DOMContentLoaded",B);}}})();var JSON=new Hash({$specialChars:{"\b":"\\b","\t":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"},$replaceChars:function(A){return JSON.$specialChars[A]||"\\u00"+Math.floor(A.charCodeAt()/16).toString(16)+(A.charCodeAt()%16).toString(16); },encode:function(B){switch($type(B)){case"string":return'"'+B.replace(/[\x00-\x1f\\"]/g,JSON.$replaceChars)+'"';case"array":return"["+String(B.map(JSON.encode).filter($defined))+"]"; case"object":case"hash":var A=[];Hash.each(B,function(E,D){var C=JSON.encode(E);if(C){A.push(JSON.encode(D)+":"+C);}});return"{"+A+"}";case"number":case"boolean":return String(B); case false:return"null";}return null;},decode:function(string,secure){if($type(string)!="string"||!string.length){return null;}if(secure&&!(/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(string.replace(/\\./g,"@").replace(/"[^"\\\n\r]*"/g,""))){return null; }return eval("("+string+")");}});Native.implement([Hash,Array,String,Number],{toJSON:function(){return JSON.encode(this);}});var Cookie=new Class({Implements:Options,options:{path:false,domain:false,duration:false,secure:false,document:document},initialize:function(B,A){this.key=B; this.setOptions(A);},write:function(B){B=encodeURIComponent(B);if(this.options.domain){B+="; domain="+this.options.domain;}if(this.options.path){B+="; path="+this.options.path; }if(this.options.duration){var A=new Date();A.setTime(A.getTime()+this.options.duration*24*60*60*1000);B+="; expires="+A.toGMTString();}if(this.options.secure){B+="; secure"; }this.options.document.cookie=this.key+"="+B;return this;},read:function(){var A=this.options.document.cookie.match("(?:^|;)\\s*"+this.key.escapeRegExp()+"=([^;]*)"); return(A)?decodeURIComponent(A[1]):null;},dispose:function(){new Cookie(this.key,$merge(this.options,{duration:-1})).write("");return this;}});Cookie.write=function(B,C,A){return new Cookie(B,A).write(C); };Cookie.read=function(A){return new Cookie(A).read();};Cookie.dispose=function(B,A){return new Cookie(B,A).dispose();};var Swiff=new Class({Implements:[Options],options:{id:null,height:1,width:1,container:null,properties:{},params:{quality:"high",allowScriptAccess:"always",wMode:"transparent",swLiveConnect:true},callBacks:{},vars:{}},toElement:function(){return this.object; },initialize:function(L,M){this.instance="Swiff_"+$time();this.setOptions(M);M=this.options;var B=this.id=M.id||this.instance;var A=$(M.container);Swiff.CallBacks[this.instance]={}; var E=M.params,G=M.vars,F=M.callBacks;var H=$extend({height:M.height,width:M.width},M.properties);var K=this;for(var D in F){Swiff.CallBacks[this.instance][D]=(function(N){return function(){return N.apply(K.object,arguments); };})(F[D]);G[D]="Swiff.CallBacks."+this.instance+"."+D;}E.flashVars=Hash.toQueryString(G);if(Browser.Engine.trident){H.classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"; E.movie=L;}else{H.type="application/x-shockwave-flash";H.data=L;}var J=''; }}J+="";this.object=((A)?A.empty():new Element("div")).set("html",J).firstChild;},replaces:function(A){A=$(A,true);A.parentNode.replaceChild(this.toElement(),A); return this;},inject:function(A){$(A,true).appendChild(this.toElement());return this;},remote:function(){return Swiff.remote.apply(Swiff,[this.toElement()].extend(arguments)); }});Swiff.CallBacks={};Swiff.remote=function(obj,fn){var rs=obj.CallFunction(''+__flash__argumentsToXML(arguments,2)+""); return eval(rs);};var Fx=new Class({Implements:[Chain,Events,Options],options:{fps:50,unit:false,duration:500,link:"ignore"},initialize:function(A){this.subject=this.subject||this; this.setOptions(A);this.options.duration=Fx.Durations[this.options.duration]||this.options.duration.toInt();var B=this.options.wait;if(B===false){this.options.link="cancel"; }},getTransition:function(){return function(A){return -(Math.cos(Math.PI*A)-1)/2;};},step:function(){var A=$time();if(A=(7-4*B)/11){C=A*A-Math.pow((11-6*B-11*D)/4,2); break;}}return C;},Elastic:function(B,A){return Math.pow(2,10*--B)*Math.cos(20*B*Math.PI*(A[0]||1)/3);}});["Quad","Cubic","Quart","Quint"].each(function(B,A){Fx.Transitions[B]=new Fx.Transition(function(C){return Math.pow(C,[A+2]); });});var Request=new Class({Implements:[Chain,Events,Options],options:{url:"",data:"",headers:{"X-Requested-With":"XMLHttpRequest",Accept:"text/javascript, text/html, application/xml, text/xml, */*"},async:true,format:false,method:"post",link:"ignore",isSuccess:null,emulation:true,urlEncoded:true,encoding:"utf-8",evalScripts:false,evalResponse:false},initialize:function(A){this.xhr=new Browser.Request(); this.setOptions(A);this.options.isSuccess=this.options.isSuccess||this.isSuccess;this.headers=new Hash(this.options.headers);},onStateChange:function(){if(this.xhr.readyState!=4||!this.running){return ; }this.running=false;this.status=0;$try(function(){this.status=this.xhr.status;}.bind(this));if(this.options.isSuccess.call(this,this.status)){this.response={text:this.xhr.responseText,xml:this.xhr.responseXML}; this.success(this.response.text,this.response.xml);}else{this.response={text:null,xml:null};this.failure();}this.xhr.onreadystatechange=$empty;},isSuccess:function(){return((this.status>=200)&&(this.status<300)); },processScripts:function(A){if(this.options.evalResponse||(/(ecma|java)script/).test(this.getHeader("Content-type"))){return $exec(A);}return A.stripScripts(this.options.evalScripts); },success:function(B,A){this.onSuccess(this.processScripts(B),A);},onSuccess:function(){this.fireEvent("complete",arguments).fireEvent("success",arguments).callChain(); },failure:function(){this.onFailure();},onFailure:function(){this.fireEvent("complete").fireEvent("failure",this.xhr);},setHeader:function(A,B){this.headers.set(A,B); return this;},getHeader:function(A){return $try(function(){return this.xhr.getResponseHeader(A);}.bind(this));},check:function(A){if(!this.running){return true; }switch(this.options.link){case"cancel":this.cancel();return true;case"chain":this.chain(A.bind(this,Array.slice(arguments,1)));return false;}return false; },send:function(I){if(!this.check(arguments.callee,I)){return this;}this.running=true;var G=$type(I);if(G=="string"||G=="element"){I={data:I};}var D=this.options; I=$extend({data:D.data,url:D.url,method:D.method},I);var E=I.data,B=I.url,A=I.method;switch($type(E)){case"element":E=$(E).toQueryString();break;case"object":case"hash":E=Hash.toQueryString(E); }if(this.options.format){var H="format="+this.options.format;E=(E)?H+"&"+E:H;}if(this.options.emulation&&["put","delete"].contains(A)){var F="_method="+A; E=(E)?F+"&"+E:F;A="post";}if(this.options.urlEncoded&&A=="post"){var C=(this.options.encoding)?"; charset="+this.options.encoding:"";this.headers.set("Content-type","application/x-www-form-urlencoded"+C); }if(E&&A=="get"){B=B+(B.contains("?")?"&":"?")+E;E=null;}this.xhr.open(A.toUpperCase(),B,this.options.async);this.xhr.onreadystatechange=this.onStateChange.bind(this); this.headers.each(function(K,J){try{this.xhr.setRequestHeader(J,K);}catch(L){this.fireEvent("exception",[J,K]);}},this);this.fireEvent("request");this.xhr.send(E); if(!this.options.async){this.onStateChange();}return this;},cancel:function(){if(!this.running){return this;}this.running=false;this.xhr.abort();this.xhr.onreadystatechange=$empty; this.xhr=new Browser.Request();this.fireEvent("cancel");return this;}});(function(){var A={};["get","post","put","delete","GET","POST","PUT","DELETE"].each(function(B){A[B]=function(){var C=Array.link(arguments,{url:String.type,data:$defined}); return this.send($extend(C,{method:B.toLowerCase()}));};});Request.implement(A);})();Element.Properties.send={set:function(A){var B=this.retrieve("send"); if(B){B.cancel();}return this.eliminate("send").store("send:options",$extend({data:this,link:"cancel",method:this.get("method")||"post",url:this.get("action")},A)); },get:function(A){if(A||!this.retrieve("send")){if(A||!this.retrieve("send:options")){this.set("send",A);}this.store("send",new Request(this.retrieve("send:options"))); }return this.retrieve("send");}};Element.implement({send:function(A){var B=this.get("send");B.send({data:this,url:A||B.options.url});return this;}});Request.HTML=new Class({Extends:Request,options:{update:false,evalScripts:true,filter:false},processHTML:function(C){var B=C.match(/]*>([\s\S]*?)<\/body>/i); C=(B)?B[1]:C;var A=new Element("div");return $try(function(){var D=""+C+"",G;if(Browser.Engine.trident){G=new ActiveXObject("Microsoft.XMLDOM"); G.async=false;G.loadXML(D);}else{G=new DOMParser().parseFromString(D,"text/xml");}D=G.getElementsByTagName("root")[0];for(var F=0,E=D.childNodes.length; Ftdiary-contrib-3.2.2/util/image-gallery/misc/000077500000000000000000000000001213632744000211015ustar00rootroot00000000000000tdiary-contrib-3.2.2/util/image-gallery/misc/plugin/000077500000000000000000000000001213632744000223775ustar00rootroot00000000000000tdiary-contrib-3.2.2/util/image-gallery/misc/plugin/recent_image.rb000066400000000000000000000316431213632744000253550ustar00rootroot00000000000000# recent_image.rb $Revision: 2.0.2 $ # # Copyright (c) 2005-2010 N.KASHIJUKU # You can redistribute it and/or modify it under GPL2. # # http://www1.whi.m-net.ne.jp/n-kashi/recent_image.htm # eval( <_" => ImageData Objects @recent_image_keys = [] # sorted keys of '@recent_image_hash' @recent_image_rkeys = [] # reverse sorted keys of '@recent_image_hash' @recent_image_use_cache = true @recent_image_show_exif = @options['image-gallery.show_exif'] @recent_image_show_exif = false if @recent_image_show_exif == nil @recent_image_cache = "#{@cache_path}/gallery/image-gallery2.dat" @recent_image_imgre = /[^_]image(?:_left|_right|_gps)?\s*\(?\s*([0-9]*)\s*\,?\s*[\"']([^'\"]*)[\"']/ # Local Functions # Search 'image' directory(s) and return a hash table. # "yyyymmdd_nn" => "File name" (or Thmbnail's File name) def get_filehash_rcimg(target) f_imghash = Hash[] f_list = Dir.glob(%Q[#{@recent_image_dir}/**/#{target}].untaint) f_list = f_list + Dir.glob(%Q[#{@recent_image_dir}/**/s#{target}].untaint) if target != "*" f_list.each do |f_name| b_name = File.basename(f_name) next unless b_name.match("^([0-9]{8}_[0-9]+)\..+") tmb_name = %Q[#{File.dirname(f_name)}/s#{b_name}] file = (f_list.include?(tmb_name) ? tmb_name : f_name) f_imghash[$1] = (@recent_imageex_yearlydir == 1 ? %Q[#{$1[0,4]}/#{File.basename(file)}] : File.basename(file)) end return f_imghash end def image_info_rcimg( filename ) image_type = nil image_height = nil image_width = nil f = File.open(filename.untaint, "rb") return image_type, image_height, image_width if f == nil sig = f.read( 24 ) if /\A\x89PNG\x0D\x0A\x1A\x0A(....)IHDR(........)/on =~ sig image_type = 'png' image_width, image_height = $2.unpack( 'NN' ) elsif /\AGIF8[79]a(....)/on =~ sig image_type = 'gif' image_width, image_height = $1.unpack( 'vv' ) elsif /\A\xFF\xD8/on =~ sig image_type = 'jpg' data = $' until data.empty? if RUBY_VERSION >= '1.9.0' break if data[0].unpack("C").first != 0xFF break if data[1].unpack("C").first == 0xD9 else break if data[0] != 0xFF break if data[1] == 0xD9 end data_size = data[2,2].unpack( 'n' ).first + 2 datax = data[1] datax_s = [0xc0, 0xc1, 0xc2, 0xc3, 0xc5, 0xc6, 0xc7, 0xc9, 0xca, 0xcb, 0xcd, 0xce, 0xcf] if RUBY_VERSION >= '1.9.0' datax = data[1].unpack("C").first datax_s = [0xc0] end if datax_s.index(datax) != nil image_height, image_width = data[5,4].unpack('nn') break else if data.size < data_size f.seek(data_size - data.size, IO::SEEK_CUR) data = '' else data = data[data_size .. -1] end data << f.read( 128 ) if data.size <= 4 end end end f.close return image_type, image_height, image_width end # Make sorted keys of @recent_image_hash def keysort_rcimg sortproc = Proc.new {|a, b| a.gsub(/_(\d+)/) {"_%05d" % $1.to_i} <=> b.gsub(/_(\d+)/) {"_%05d" % $1.to_i} } @recent_image_keys = @recent_image_hash.keys.sort(&sortproc) @recent_image_rkeys = @recent_image_keys.reverse end def load_cache_rcimg db = PStore.new(@recent_image_cache) db.transaction(true) do @recent_image_hash = db["recent_image_hash"] @recent_image_keys = db["recent_image_keys"] @recent_image_rkeys= db["recent_image_rkeys"] db.abort end end def save_cache_rcimg return if @recent_image_hash.length == 0 cache_dir = File.dirname( @recent_image_cache ) Dir.mkdir(cache_dir) unless File.directory?(cache_dir) db = PStore.new(@recent_image_cache) db.transaction do db["recent_image_hash"] = @recent_image_hash db["recent_image_keys"] = @recent_image_keys db["recent_image_rkeys"] = @recent_image_rkeys db["recent_image_dir"] = @recent_image_dir db["recent_image_url"] = @recent_image_url db.commit db.abort end end def make_image_hash_rcimg f_imghash = Hash[] f_imghash = get_filehash_rcimg("*") cgi = CGI::new def cgi.referer; nil; end @years.keys.sort.reverse_each do |year| @years[year].sort.reverse_each do |month| cgi.params['date'] = ["#{year}#{month}"] m = TDiaryMonth::new(cgi, '', @conf) m.diaries.keys.sort.reverse_each do |date| next unless m.diaries[date].visible? m.diaries[date].each_section do |section| subtitle = "" subtitle = section.subtitle.gsub(/[<{](.*?)[}>]/,'') if section.subtitle search_img_rcimg(date, section.subtitle, subtitle, f_imghash) search_img_rcimg(date, section.body, subtitle, f_imghash) end end end end end def search_img_rcimg(date, body, subtitle, f_imghash) body.to_s.scan(@recent_image_imgre).each do |num, title| # Search "image plugin" in all diaries f_name = f_imghash[%Q[#{date}_#{num}]] # and pick up params. -> image[0]=number, image[1]=title next if f_name == nil begin type, height, width = image_info_rcimg(%Q[#{@recent_image_dir}/#{f_name.delete("s")}]) image = ImageData.new image.url = f_name image.file = f_name.delete("s") image.date = date image.title = title image.subtitle = subtitle image.type = type image.height = height image.width = width @recent_image_hash[%Q[#{date}_#{num}]] = image rescue end end end # Initial Function ... Make a hash table : "_" => ["Filename", "title"] def init_rcimg return if @recent_image_hash != nil and @recent_image_hash.length != 0 return unless @mode == 'day' or @mode == 'month' or @mode == 'latest' or @mode == 'preview' or @mode == 'nyear' if @recent_image_use_cache and File.exist?(@recent_image_cache) load_cache_rcimg else make_image_hash_rcimg keysort_rcimg if @recent_image_use_cache save_cache_rcimg end end end # PLUGIN body # recent_image() # def recent_image(items = 4, width = 80, link_mode = 1, name_filter = nil, title_filter = nil, reverse = false, random = false) items = items.to_i images = [] keys = [] init_rcimg return ("") if items == -1 keys = (random ? @recent_image_keys.randomize : (reverse ? @recent_image_keys : @recent_image_rkeys)) catch(:exit) { keys.each do |key| image = @recent_image_hash[key] next if name_filter != nil and image.file.match(name_filter) == nil next if title_filter != nil and image.title.match(title_filter) == nil images.push(image) if items != 0 throw :exit if items == images.length end end } result = %Q[
        \n] images.each do |image| if image.height.to_i > image.width.to_i sizestr = %Q[width="#{width*image.width.to_i/image.height.to_i}" height="#{width}"] else sizestr = %Q[width="#{width}" height="#{width*image.height.to_i/image.width.to_i}"] end case link_mode when 0 result << %Q[#{image.title}\n] when 1 result << %Q[#{image.title}\n] when 2 result << %Q[#{image.title}\n] when 3 result << %Q[#{image.title}\n] when Array result << %Q[#{image.title}\n] if link_mode[0] == 3 else end end result << "
        " end # PLUGIN body # count_image() # def count_image(name_filter = nil, title_filter = nil) count = 0 init_rcimg if name_filter == nil and title_filter == nil count = @recent_image_keys.length else @recent_image_keys.each do |key| image = @recent_image_hash[key] next if name_filter != nil and image.file.match(name_filter) == nil next if title_filter != nil and image.title.match(title_filter) == nil count = count + 1 end end count.to_s.reverse.gsub(/\d\d\d/, '\0,').reverse.sub(/^([-]{0,1}),/, '\1') end # PLUGIN body # view_exif() ... input EXIF datas of images in your diary. # def view_exif(id = 0, exifparam ="") init_rcimg if @recent_image_hash == nil or @recent_image_hash.length == 0 begin require 'exifparser' @image_date_exif ||= @date.strftime("%Y%m%d") @exifparser = ExifParser.new(%Q[#{@image_dir}/#{@recent_image_hash[@image_date_exif+"_"+id.to_s].file}].untaint) if exifparam == "" # return a formatted string. model = @exifparser['Model'].to_s focallength = @exifparser['FocalLength'].to_s fnumber = @exifparser['FNumber'].to_s exposuretime = @exifparser['ExposureTime'].to_s isospeedratings = @exifparser['ISOSpeedRatings'].to_s exposurebiasvalue = @exifparser['ExposureBiasValue'].to_s if @exifparser.tag?('LensParameters') lensname = "("+ @exifparser['LensParameters'].to_s + ")" else lensname = "" end return %Q[

        #{model}, #{focallength}, #{fnumber}, #{exposuretime}, ISO#{isospeedratings}, #{exposurebiasvalue}EV #{lensname}

        ] else # return the requested value. return @exifparser[exifparam.untaint].to_s end rescue exp = ($!).to_s + "
        " ($!).backtrace.each do |btinfo| exp += btinfo exp += "
        " end return exp end end # Callback Functions # this is for view_exif(). add_body_enter_proc(Proc.new do |date| @image_date_exif = date.strftime("%Y%m%d") "" end) # Update Proc of the plugin add_update_proc do f_imghash = Hash[] if @recent_image_hash.length == 0 if @recent_image_use_cache load_cache_rcimg else make_image_hash_rcimg end end date = @date.strftime('%Y%m%d') @recent_image_hash.keys.each do |key| # Clear all data of the day in @recent_image_hash if key.include?(date) @recent_image_hash.delete(key) end end diary = @diaries[date] if diary.visible? f_imghash = get_filehash_rcimg(%Q|#{date}_*|) diary.each_section do |section| subtitle = "" subtitle = section.subtitle.gsub(/[<{](.*?)[}>]/,'') if section.subtitle search_img_rcimg(date, section.subtitle, subtitle, f_imghash) search_img_rcimg(date, section.body, subtitle, f_imghash) end end keysort_rcimg save_cache_rcimg if @recent_image_use_cache end # for SmoothGallery (SildeShow mode of 'tDiary Image Gallery') if /image-gallery\.(?:cgi|rb)$/ =~ $0 add_header_proc do < EOS end end tdiary-contrib-3.2.2/util/image-gallery/skel/000077500000000000000000000000001213632744000211045ustar00rootroot00000000000000tdiary-contrib-3.2.2/util/image-gallery/skel/gallery.rhtml000066400000000000000000000141631213632744000236200ustar00rootroot00000000000000<%# gallery.rhtml $Revision: 2.0.0 $ %> <%# Copyright (c) 2005-2010 N.KASHIJUKU %> <%# You can redistribute it and/or modify it under GPL2. %>
        <%%=navi_user%>

        <%= CGI::escapeHTML( @conf.html_title ) %> [Image Gallery]

        <% if @images.length == 0 %>

        該当するファイルはありません

        <%= format_links_date %> <% else %> <% if @mode == "list" or @mode == "slide" or @mode == "fslide" %> <%= format_links_date %>
        <% if @images.length != 0 %>

        <%= _(@conf.to_native(@t_page_title)) %>  Page <%=@start / @num + 1 %> [<%= @image_num %> 枚中 <%= @start + 1 %> - <%= @start + @images.length %> 枚目]  <%= get_other_mode_link %>

        <% end %>
        <% if @mode == "list" %> <% @line.times do |line|%> <% @column.times do |column| %> <% i = line * @column + column %> <% end %> <% break if @images[(line + 1) * @column] == nil %> <% end %>
        <% if @images[i] != nil %> <% if @images[i].width.to_i > @images[i].height.to_i %>

        <%= @images[i].file %>

        <% else %>

        <%= @images[i].file %>

        <% end %>

        <%= CGI::escapeHTML(@images[i].title) %>

        <%= @images[i].date.sub(/(\d{4})(\d{2})(\d{2})/, '\1-\2-\3') %>

        <% end %>
        <% elsif @mode == "slide" or @mode == "fslide" %> <%= js_start_gallery %>
        <% (@line * @column).times do |i| %>

        <%= CGI::escapeHTML(@images[i].title) %>[<%= @images[i].date.sub(/(\d{4})(\d{2})(\d{2})/, '\1-\2-\3') %>]

        <%= CGI::escapeHTML(@images[i].subtitle) %>

        <% image_file = (@use_mid_image && @mode == "slide") ? "m"+@images[i].file : @images[i].file %>
        <% break if @images[i+1] == nil %> <% end %>
        <% end %>
        <% if @image_num > 0 %> <%= format_links(@image_num) %> <% end %>
        <% elsif @mode == "viewer" %> <%= format_links_viewer %>

         <%= @images[0].date.sub(/(\d{4})(\d{2})(\d{2})/, '\1-\2-\3') %>  <%= CGI::escapeHTML(@images[0].title) %>  [<%= @images[0].file %>:<%= @images[0].width %>(w)×<%= @images[0].height %>(h)]

        <% end %>
        <% image_file = (@use_mid_image) ? "m"+@images[0].file : @images[0].file %> alt="<%= CGI::escapeHTML(@images[0].title) %>" title="<%= CGI::escapeHTML(@images[0].title) %>" class="imagebody">
        <% if @show_exif and @exifstr.length != 0 %>

        - EXIF Data -

        <%= @exifstr[0] %>

          <% i = 1 %> <% while i < @exifstr.length %> <% if @exifstr.length > 5 and i == @exifstr.length / 2 %>
          <% end %> <% if @exifstr[i][0,2] == "--" %>

        <%= @exifstr[i] %>

          <% else %>
        • <%= @exifstr[i] %>
        • <% end %> <% i = i + 1 %> <% end %>
        <% end %> <% end %> <% if @show_inputfield %>

        画像の選択: ファイル名:  日記のサブタイトル:  画像のタイトル:

        並べ替え:    表示形式:

        <% end %> tdiary-contrib-3.2.2/util/image-gallery/skel/gallery.rhtml.euc-jp000066400000000000000000000140741213632744000250030ustar00rootroot00000000000000<%# gallery.rhtml $Revision: 2.0.0 $ %> <%# Copyright (c) 2005-2010 N.KASHIJUKU %> <%# You can redistribute it and/or modify it under GPL2. %>
        <%%=navi_user%>

        <%= CGI::escapeHTML( @conf.html_title ) %> [Image Gallery]

        <% if @images.length == 0 %>

        եϤޤ

        <%= format_links_date %> <% else %> <% if @mode == "list" or @mode == "slide" or @mode == "fslide" %> <%= format_links_date %>
        <% if @images.length != 0 %>

        <%= _(@conf.to_native(@t_page_title)) %>  Page <%=@start / @num + 1 %> [<%= @image_num %> <%= @start + 1 %> - <%= @start + @images.length %> ]  <%= get_other_mode_link %>

        <% end %>
        <% if @mode == "list" %> <% @line.times do |line|%> <% @column.times do |column| %> <% i = line * @column + column %> <% end %> <% break if @images[(line + 1) * @column] == nil %> <% end %>
        <% if @images[i] != nil %> <% if @images[i].width.to_i > @images[i].height.to_i %>

        <%= @images[i].file %>

        <% else %>

        <%= @images[i].file %>

        <% end %>

        <%= CGI::escapeHTML(@images[i].title) %>

        <%= @images[i].date.sub(/(\d{4})(\d{2})(\d{2})/, '\1-\2-\3') %>

        <% end %>
        <% elsif @mode == "slide" or @mode == "fslide" %> <%= js_start_gallery %>
        <% (@line * @column).times do |i| %>

        <%= CGI::escapeHTML(@images[i].title) %>[<%= @images[i].date.sub(/(\d{4})(\d{2})(\d{2})/, '\1-\2-\3') %>]

        <%= CGI::escapeHTML(@images[i].subtitle) %>

        <% image_file = (@use_mid_image && @mode == "slide") ? "m"+@images[i].file : @images[i].file %>
        <% break if @images[i+1] == nil %> <% end %>
        <% end %>
        <% if @image_num > 0 %> <%= format_links(@image_num) %> <% end %>
        <% elsif @mode == "viewer" %> <%= format_links_viewer %>

         <%= @images[0].date.sub(/(\d{4})(\d{2})(\d{2})/, '\1-\2-\3') %>  <%= CGI::escapeHTML(@images[0].title) %>  [<%= @images[0].file %>:<%= @images[0].width %>(w)<%= @images[0].height %>(h)]

        <% end %>
        <% image_file = (@use_mid_image) ? "m"+@images[0].file : @images[0].file %> alt="<%= CGI::escapeHTML(@images[0].title) %>" title="<%= CGI::escapeHTML(@images[0].title) %>" class="imagebody">
        <% if @show_exif and @exifstr.length != 0 %>

        - EXIF Data -

        <%= @exifstr[0] %>

          <% i = 1 %> <% while i < @exifstr.length %> <% if @exifstr.length > 5 and i == @exifstr.length / 2 %>
          <% end %> <% if @exifstr[i][0,2] == "--" %>

        <%= @exifstr[i] %>

          <% else %>
        • <%= @exifstr[i] %>
        • <% end %> <% i = i + 1 %> <% end %>
        <% end %> <% end %> <% if @show_inputfield %>

        : ե̾  Υ֥ȥ:  Υȥ:

        ¤ؤ:    ɽ:

        <% end %> tdiary-contrib-3.2.2/util/image-gallery/tdiary.conf.igsample000066400000000000000000000002751213632744000241150ustar00rootroot00000000000000# # tDiary configuration file # @options['image-gallery.show_exif'] = true @options['image-gallery.column'] = 4 @options['image-gallery.line'] = 10 @options['image-gallery.width'] = "160" tdiary-contrib-3.2.2/util/image-gallery/theme/000077500000000000000000000000001213632744000212505ustar00rootroot00000000000000tdiary-contrib-3.2.2/util/image-gallery/theme/image-gallery.css000066400000000000000000000020131213632744000244750ustar00rootroot00000000000000/* css for tDiary Image Gallery */ /* for List mode */ table.imagelist { margin: 0 auto; text-align: center; } table.imagelist p.imagetitle { margin-top: 0px; margin-bottom: 0px; } table.imagelist td { width: 33%; } table.imageview td { width: 50%; } table.imagelist p.imagedate { margin-top: 0px; } table.imageview { margin-left: auto; margin-right: auto; } table.imageview td { text-align: center; } p.exiftitle { text-align: left; } table.imageview li { text-align: left; } img.imagebody { border-style: solid; border-width: 1px; border-color: #fff; padding: 4px; margin: 0 auto; } p.infobar { text-align: center; } div.categorylink { font-size: small; text-align: right; margin-right: 0.3em; } /* for SlideShow mode */ .content { margin: 0 20px; } .content a { color: #fff; } .content p.linkage { margin-top: 2em; text-align: right; font-size: 1.7em; color: #ddd; } .content p.linkage a { color: #fff; } #myGallery { text-align: left; margin: 0 auto; } tdiary-contrib-3.2.2/util/image2flickr.rb000077500000000000000000000227031213632744000203220ustar00rootroot00000000000000#!/usr/bin/env ruby # -*- coding: utf-8 -*- # = Image2Flickr # imageプラグインからflickrプラグインへのマイグレーションツール # # Author:: MATSUOKA Kohei # Copyright:: Copyright (c) MATSUOKA Kohei # License:: GPL # # USEGE: # imageプラグインからflickrプラグインへ移行するためのツールです。 # このツールの機能は、以下の2つです。 # (1) tDiaryのimageプラグインを利用して日記に載せた写真を、 # Flickrへアップロードします。 # (2) 日記データのimageプラグインの呼び出しを、 # flickrプラグインへと置き換えます。 # 古い日記データは .bak.YYYYmmddHHMMSS を付けてバックアップします。 # # == 注意 # # (1) tDiary2.3.1以降が対象です。 # 日記データがUTF-8に変換されている必要があります。 # (2) Wiki記法で記述された日記が対象です。 # # # == 移行手順 # # 1. Flickr APIキーの取得 # # flickr.comのAPIサイトにアクセスし、"Apply for a new API Key"にて # 新しいAPIキーを生成します。 # http://www.flickr.com/services/api/keys/ # # Authentication TypeはAuthentication Typeを選択してください。 # # # 2. tDiaryデータフォルダのバックアップ # # このマイグレーションツールはtDiaryの日記データを書き換えます。 # 古い日記データを残す仕様ですが、万が一に備えて # 事前にtDiaryのデータフォルダをバックアップしてください。 # # # 3. rflickrライブラリの取得 # # このマイグレーションツールはFlickrへの写真のアップロードに # rflickrライブラリを使用します。 # 以下のサイトからrflickrライブラリを取得して、インストールしてください。 # http://rubyforge.org/projects/rflickr/ # # RubyGemsが利用できる場合は、以下のコマンドでインストールできます。 # $ gem install rflickr # # # 4. マイグレーションツールの設定 # # image2flickr.rbをエディタで開き、以下の4つのパラメータを設定します。 # # # FlickrのAPIキー # @api_key = '123456789012345678901234567890' # # Flickr APIのシークレットキー # @secret = '1234567890' # # tDiaryのデータフォルダ # @data_path = '/var/tdiary' # # tDiaryのイメージフォルダ # @image_dir = '/var//www/tdiary/images' # # # 5. マイグレーションツールの実行 # # tDiaryのデータフォルダに書き込む権限を持つアカウントで、 # コマンドラインからimage2flickr.rbを実行してください。 # $ ./image2flickr # # すると、以下のメッセージが表示されます。 # ---- # Flickrへ写真をアップロードするためのトークンを取得します。 # Webブラウザで下記のURLへアクセスしたら、何かキーを押してください。 # http://www.flickr.com/services/auth/?api_sig=.... # ---- # # 指定されたURLへWebブラウザでアクセスし、トークンの発行を許可してください。 # コマンドラインへ戻り何かキーを押すと、マイグレーションが始まります。 # # なお、ツールを途中で中断し、2回目に実行するときはトークンを取得する # 必要はありません。 # # # 6. 実行結果の確認 # # ツールが終了したらtDiaryのデータフォルダを開き、 # imageプラグインの呼び出しがflickrプラグインの呼び出しへ # 置き換わっていることを確認してください。 # 古い日記データは .bak.20081024090000 などの拡張子がついて # バックアップされていますので、問題があれば元に戻してください。 # # ツールを実行すると、以下の2つのファイルが作成されます。 # (1) flickr.token # Flickrへ写真をアップロードするためのトークン。 # (2) image2flickr.yaml # tDiaryのイメージフォルダに存在するJPEGファイル (ex. 20081025_0.jpg) と # Flickrへアップロードしたphoto_idの対応付けを記録したファイル。 # # これらのファイルは、マイグレーションツールを途中で中断したときのために # 用意されています。 # マイグレーションが完了したら、少なくともflickr.tokenは削除してください。 # (トークンの不正利用を防ぐためです) # # $KCODE = 'utf8' begin require 'rubygems' gem 'rflickr' rescue end require 'flickr' require 'yaml/store' require 'tempfile' require 'fileutils' # FlickrのAPIキー @api_key = '123456789012345678901234567890' # Flickr APIのシークレットキー @secret = '1234567890' # tDiaryのデータフォルダ @data_path = '/var/tdiary' # tDiaryのイメージフォルダ @image_dir = '/var/www/tdiary/images' def main uploader = FlickrUploder.new('image2flickr.yaml', 'flickr.token', @api_key, @secret) parser = TDiaryParser.new(@data_path) i2f = Image2Flickr.new(parser, uploader, @image_dir) # tDiaryのimagesフォルダから対象日記を取得 files = Dir.glob("#{@image_dir}/*.{jp{,e}g,png,gif}").map{|file| File.basename(file).match(/^(\d{6})/) $1 }.compact.uniq # 対象日記を変換 files.each do |file| i2f.convert(file) end # cache のクリア Dir["#{@data_path}/cache/*.rb"].each{|f| FileUtils.rm_f( f )} Dir["#{@data_path}/cache/*.parser"].each{|f| FileUtils.rm_f( f )} end # Flickrへ写真をアップロードし、元ファイル名とphoto_idのペアをYAMLに記録する class FlickrUploder def initialize(yaml, token, api_key, secret) @flickr = Flickr.new(token, api_key, secret) # トークンが無ければ取得する unless @flickr.auth.token puts "Flickrへ写真をアップロードするためのトークンを取得します。" puts "Webブラウザで下記のURLへアクセスしたら、何かキーを押してください。" puts @flickr.auth.login_link # キー入力待ち gets @flickr.auth.getToken @flickr.auth.cache_token puts "トークンを取得し、#{token} へ保存しました。" puts end @db = YAML::Store.new(yaml) @db.transaction { @db['photos'] ||= {} } end # Flickrへ写真をアップロードする def upload(file, title) id = 0 @db.transaction { basename = File.basename(file) if @db['photos'][basename] # アップロード済みの場合はスキップ STDERR.puts "passed updating #{basename} (#{title}) ..." id = @db['photos'][basename] @db.abort else # 写真をアップロードする STDERR.puts "updating #{basename} (#{title}) ..." id = @flickr.photos.upload.upload_file(file, title) @db['photos'][basename] = id end } id end end class TDiaryParser include FileUtils def initialize(data_path) @data_path = data_path end # tDiaryの日記を置換する # 拡張子に ".bak.yyyymmddHHMMSS" を付けて日記データをバックアップする def each_diary(yearmonth) yearmonth.match(/(\d{4})(\d{2})/) year = $1 month = $2 file = "#{@data_path}/#{year}/#{yearmonth}.td2" # ファイルをバックアップ backup = "#{file}.bak.#{Time.now.strftime('%Y%m%d%H%M%S')}" cp(file, backup, :preserve => true) # 一時ファイルを生成 tmp = Tempfile.new('tmp') open(file) do |fin| fin.each('') do |headers| date = headers.grep(/^Date:\s*(\d{4}\d{2}\d{2})/){$1}[0] diary = fin.gets("\n.\n") diary = yield(date, diary) tmp.print headers tmp.print diary end end tmp.close cp(tmp.path, file) end end class Image2Flickr def initialize(parser, uploader, image_dir) @parser = parser @uploader = uploader @image_dir = image_dir end # imageプラグインをflickrプラグインへ置き換える def convert(yearmonth) @parser.each_diary(yearmonth) do |@date, diary| # 現在はWiki記法のみ対応 diary.gsub!(/\{\{(image[^}]+)\}\}/) {|match| begin STDERR.puts "found: #{match}" # image, image_left, image_right のいずれかに対応 replace = "{{#{eval($1)}}}" STDERR.puts "replace: #{replace}" STDERR.puts replace rescue => e # 例外が発生したら置換しない STDERR.puts "ERROR: #{e}" STDERR.puts match end } diary end end def image( index, title = nil, thumbnail = nil, size = nil, place = 'photo' ) replace("flickr", @date, index, title) end def image_center( index, title = nil, thumbnail = nil, size = nil, place = 'photo' ) replace("flickr", @date, index, title) end def image_left( index, title = nil, thumbnail = nil, size = nil, place = 'photo' ) replace("flickr_left", @date, index, title) end def image_right( index, title = nil, thumbnail = nil, size = nil, place = 'photo' ) replace("flickr_right", @date, index, title) end def replace(method, date, index, title) file = Dir.glob("#{@image_dir}/#{date}_#{index}.{jp{,e}g,png,gif}").shift # タイトルが未指定の場合はファイル名 title ||= File.basename(file) id = @uploader.upload(file, title) "#{method} #{id}" end end main tdiary-contrib-3.2.2/util/posttdiary/000077500000000000000000000000001213632744000176315ustar00rootroot00000000000000tdiary-contrib-3.2.2/util/posttdiary/README.ja000066400000000000000000000004751213632744000211100ustar00rootroot00000000000000posttdiary.rb is a updater of diary via E-mail with images. see: http://tdiary-users.sourceforge.jp/cgi-bin/wiki.cgi?posttdiary%2Erb -- posttdiary-ex.rb is a more enhanced posttdiary.rb. see: http://ks.nwr.jp/wiki/wiki.cgi?posttdiary%2erb%b2%fe%c2%a4 (Japanese) http://ks.nwr.jp/prog/posttdiary.html (English) tdiary-contrib-3.2.2/util/posttdiary/posttdiary-ex.rb000077500000000000000000001113121213632744000227740ustar00rootroot00000000000000#!/usr/bin/env ruby # # posttdiary-ex: update tDiary via e-mail. $Revision: 1.2 $ # # Copyright (C) 2002, All right reserved by TADA Tadashi # You can redistribute it and/or modify it under GPL2. # # 2010.10.19: v.1.71: Modified by K.Sakurai (http://ks.nwr.jp) # Acknowledgements: # * Based on posttdiary.rb & tdiary.rb by TADA. # * Some codes partially imported from Enikki Plugin Ex. : # http://shimoi.s26.xrea.com/hiki/hiki.cgi?TdiaryEnikkiEx # * Thanks to taketori for image size detection method. # * Thanks to NOB for debugging. # * Thanks to tamo (http://tamo.tdiary.net) for image-POSTing codes & testing. # # language setup for tdiary.conf (for both @data_path & @tdiary_dirname) @tdencoding = 'UTF-8' # @tdencoding = 'US-ASCII' # @tdencoding = 'EUC-JP' # @tdencoding = 'Big5' #---------------------------------------------- def usage( detailed_help ) # (if "!" is at the head of the line, it is to be shown only when detailed_help == true (-h option) ) text = <<-TEXT #{File::basename __FILE__}: update tDiary via e-mail (v1.64). usage: ruby posttdiary-ex.rb [options (without -d)] ruby posttdiary-ex.rb [options (with -d)] arguments: url: update.rb's URL of your diary user: username for your tDiary system passwd: password for your tDiary system ! If the To: field is formatted as "user-passwd@example.com", ! you can omit user and passwd arguments. options: ! ============ for automatic configuration ========== --read-conffile, -a dirname: read settings from (dirname)/tdiary.conf ! Reads configuration parameters of image_ex plugin as well. ! (The default values of -i, -u, -t, -z, -o, -y, -C can be imported.) ! Specify the localtion (or fullpathname) of tDiary conf file. ! ex. -a /home/hoge/htdocs/diary/tdiary.conf ! ! ============ basic options ============== --image-path, -i dirname: directory to store the image(s) in. --image-url, -u URL: URL of the image directory. ! You must specify both -i and -u options ! (unless they are available from tdiary.conf + image_ex plugin) ! When using --remote-mode or --use-image-ex, -u is not required. --use-subject, -s: use mail subject as subtitle ! Also inserts attached image(s) between subtitle and body. --make-thumbnail, -t size: Create thumbnail with a link to the original image ! Works only when the original image is larger than the specified size ! (see --threshold-size also) ! ex. -t 80x80 --image-geometry, -g size: resize image(s). ! The original image would be overwritten. ! Does not change the image size when the original image is smaller. ! ex. -g 800x800 (change the image size to "fit in" to 800x800 pixels) --use-image-ex, -e: Recognize & auto-generate tags for image.rb (Enikki) or image_ex.rb (Enikki ex.) plugin ! Tag format: <%=image (serialno),"(alt text)"%> ! Serialno starts from 0. Will be automatically increased to match ! the real filename. ! Overrides -f option. --wiki-style, -w: output image tags in Wiki style ! Suppress adding a whitespace before each tag ! Adds "!" to subject when -s option is given ! Recognize Wiki style tags and rewrite ! Must be used with image.rb or image_ex.rb plugin. --blog-style, -B: do not specify date to append unless specified ! Suitable for use with blogkit --read-exif, -c: read "User Comment" tag from EXIF and use as ALT text ! If not specified, filename would be used as ALT text. ! Requires libexif and "exif" command. --hour-offset, -o offset: hour_offset of tDiary ! (ex. -o +4 (do not change date until 28:00)) --yearly-dir, -y: put images in yearly separated directories ! ( 2004/ , 2005/ , ...) --help, -h: show detailed help & advanced options ! ! ============ advanced options ============== ! --convert-path, -C fullpath_of_convert: location of "convert" command ! Use this option when ImageMagick's commands are not path-reachable. ! Assumes the same location for "identify" command as well. ! --exif-path, -E fullpath_of_exif: location of "exif" command ! Enables --read-exif command as well. ! Use this option when "exif" command is not path-reachable. ! --remote-mode, -R: upload images via update.rb using HTTP POST. ! Allows user to separate the mailserver and the webserver. ! Note: Thumbnails would not be posted. ! --remote-image-path,-D remote_dirname: ! Specify the image directory of the remote webserver. ! Required when using image_ex.rb with --remote-mode option. ! --remote-yearly-dir,-Y switch: ! Specify whether to put images in yearly separated directories ! at the remote webserver. ! Required when image_ex.rb with --remote-mode option. ! 0: do not separate, 1: separate ! --preserve-local-images, -P: ! Do not delete local image files. ! Effective only when --remote-mode is enabled. ! --upload-only, -U: ! Upload the attached images to server, but do not update the diary. ! Also possible by adding "_UPLONLY#" to mail body. ! --group-id, -G: specify the group name (or GID) of the image file. ! Also makes the file group writable (chmod 664). ! ex1. -G www ! ex2. -G 67 ! --class-name, -n class_name: ! Class name for each photo (default: photo) ! Invalid when --use-image-ex or --wiki-style option is enabled. ! --add-div, -v number_of_images: ! Encapsule all attached images with
        ...
        ! When specified number of (or more) images are attached. ! Set to 2 when not given. Specify 0 to disable. ! Automatically set to 0 when --wiki-style is enabled. ! ex. -v 3 (works only when 3 or more images are attached) ! --threshold-size, -z threshold_image_size: ! Make thumbnail if image size is larger. ! ex1. -z 120x140 ! ex2. -z 140 (same to 140x140) ! --image-format, -f format string: ! Specify the format string of the image tag ! These variables can be used in the format string: ! $0 : image serial number ! $1 : image url ! $2 : thumbnail image url (when -t is specified) ! $3 : class name ! $4 : ALT text (filename, or EXIF comment when -c is specified) ! ex. -f \\\"{{image \\\$0}}\\\" ! --use-original-name, -r: ! use original filename as ALT text when not specified ! --pass-filename, -p: ! Pass real filename (instead of serialno) to image_ex plugin ! (EXPERIMENTAL: Has no meanings so far) ! Effective only with -e option. ! --filter-mode, -d: print to stdout (does not call update.rb) ! --write-to-file, -b filename: writeout to file (does not call update.rb) ! --date-margin, -j date_margin: avoid writing diaries for future dates ! ex. -j 30 (default=7, 0=disabled) ! --rotate, -T LEFT or RIGHT: rotate images ! ex. -T RIGHT (rotate 90degrees clockwise) ! Also possible by adding "_ROT_LEFT#" or "_ROT_RIGHT#"to mail body. ! ! Output format: ! without -e/f, without -t: $4 ! without -e/f, with -t: $4 ! with -e: <%=image $0,'$4'%> ! with -w: {{image $0,'$4'}} (overrides -e) ! with -f: (specified format) (overrides -e, -w) ! ! Date specification format in mail body text: ! ex. when you want to append this mail to "2005 Feb 15" 's diary, ! add this line to mail body: ! ! _Date#2005-2-15 ! Examples: posttdiary-ex.rb -a /home/hoge/htdocs/diary/tdiary.conf http://yoursite.jp/~hoge/diary/update.rb (tDiary username) (passwd) posttdiary-ex.rb -w -i /home/hoge/htdocs/diary-images/ -y -t 120x120 -s -g 800x800 http://yoursite.jp/~hoge/diary/update.rb (tDiary username) (passwd) ! posttdiary-ex.rb -i /home/hoge/htdocs/diary-images/ -u http://yoursite.jp/~hoge/diary-images/ -t 120x120 -s -g 800x800 http://yoursite.jp/~hoge/diary/update.rb (tDiary username) (passwd) ! posttdiary-ex.rb -R -i /home/hoge/tmp -D /home/hoge/htdocs/diary-images -Y 1 -s -g 800x800 http://yoursite.jp/~hoge/diary/update.rb (tDiary username) (passwd) TEXT if( detailed_help ) text.gsub!( /\!/, '' ) else text.gsub!( /\![^\r\n]*[\r\n]+/, '' ) end text.delete("\t") end #--- override functions in the original tdiary.rb def base_url return '' end def TDiaryError( msg ) print msg + "\n" exit 0 end def load_cgi_conf raise TDiaryError, 'posttdiary-ex: No @data_path variable.' unless @data_path @data_path = add_delimiter( @data_path ) raise TDiaryError, 'posttdiary-ex: Do not set @data_path as same as tDiary system directory.' if @data_path == @tdiary_dirname def_vars1 = '' def_vars2 = '' variables = [:author_name, :author_mail, :index_page, :hour_offset] variables.each do |var| def_vars1 << "#{var} = nil\n" def_vars2 << "@#{var} = #{var} unless #{var} == nil\n" end begin cgi_conf = File::open( "#{@data_path}tdiary.conf" ){|f| f.read } cgi_conf.untaint unless @secure cgi_conf.force_encoding( @tdencoding ) b = binding.taint eval( cgi_conf, b, "(cgi_conf)", 1 ) eval( def_vars2, b ) rescue IOError, Errno::ENOENT end end #--- read tdiary.conf def read_tdiary_conf( dfname ) if test( ?d , dfname ) then @tdiary_dirname = dfname @tdiary_conf_file = 'tdiary.conf' elsif test( ?f , dfname ) then dfname =~ /(.*)[\/\\]([^\/\\]+)/ @tdiary_dirname = $1 @tdiary_conf_file = $2 end @tdiary_dirname = add_delimiter( @tdiary_dirname ) orgdir = Dir.pwd Dir.chdir( @tdiary_dirname ) @secure = false @options = {} # evaluate tdiary.conf (load_cgi_conf() would be called as well, via tdiary.conf) f = File::open( @tdiary_dirname + @tdiary_conf_file ){|f| f.read }.untaint.force_encoding(@tdencoding) eval( f, binding, "(tdiary.conf)", 1 ) Dir.chdir( orgdir ) true; rescue IOError, Errno::ENOENT raise 'posttdiary-ex: failed to read tdiary configuration file' end def check_local_images( date, path ) available_list = [] exist_list = [] maxnum = -1 Dir.foreach( path ) do |file| if file =~ /(\d{8,})_(\d+)\.([^\.]*)/ then if $1 == date then serial = $2.to_i maxnum = serial if serial > maxnum exist_list[serial]=true end end end num = 0 for i in 0 .. 200 if !exist_list[i] then available_list[num] = i num += 1 end end maxnum += 1 [maxnum, available_list] end def bmp_to_png( bmp ) png = bmp.sub( /\.bmp$/, '.png' ) stat = system( "#{@convertpath} #{bmp} #{png}" ) raise "posttdiary-ex: could not run convert command (#{@convertpath})" if !stat if FileTest::exist?( png ) File::delete( bmp ) png else bmp end end def check_command( cmdname ) raise 'posttdiary-ex: program bug found in check_command() (call the programmer!)' unless cmdname if @pt_exist_cmd then for priv in @pt_exist_cmd if priv == cmdname then return true end end end stat = false if ( test( ?x , cmdname ) ) then stat = true else require 'shell' sh = Shell.new searchdir = sh.system_path for dir in searchdir fullpath = add_delimiter( dir ) + cmdname if sh.executable?(fullpath) then stat = true break end end end if stat then @pt_exist_cmd = [] unless @pt_exist_cmd @pt_exist_cmd << cmdname else raise "posttdiary-ex: execution failed: #{cmdname} not found" end stat end def check_image_size( name, geo ) cmdstr = @magickpath + "identify" check_command( cmdstr ) return false if !FileTest::exist?( name ) begin imgsize = %x[#{cmdstr} '#{name}'].sub(/#{name}/, '').split[1][/\d+x\d+/] i = imgsize.split(/x/) j = geo.split(/x/) return false if !i[1] or !j[1] return false if i[0].to_i < j[0].to_i and i[1].to_i < j[1].to_i rescue return false end true end def change_image_size( org, geo ) check_command( @convertpath ) system( "#{@convertpath} -size #{geo}\\\> #{org} -geometry #{geo}\\\> #{org}" ) if FileTest::exist?( org ) org else "" end end def read_exif_comment( fullpath_imgname ) require 'nkf' v = "" check_command( @exifpath ) return "" if !FileTest::exist?( fullpath_imgname ) open( "| #{@exifpath} -t \"User Comment\" #{fullpath_imgname}", "r" ) do |f| s = f.readlines s.each do |t| t.gsub!( /.*Value:/, '' ) v = NKF::nkf( '-m0 -Xwd', t ).gsub!( /^\s+/, '' ).chomp! if $& end end v = '' if v =~ /^\(null\)$/i v end def read_exif_orientation( fullpath_imgname ) # returns orientaion value # top-left : 1 # right-top : 6 # left-bottom : 8 # bottom-right : 3 val = 1 v = '' check_command( @exifpath ) return 1 if !FileTest::exist?( fullpath_imgname ) open( "| #{@exifpath} -t \"Orientation\" #{fullpath_imgname}", "r" ) do |f| s = f.readlines s.each do |t| t.gsub!( /.*Value:/, '' ) if $& then v = t break end end end val = 6 if v =~ /right.+top/i val = 8 if v =~ /left.+bottom/i val = 3 if v =~ /bottom.+right/i val end def rotation_degree( ori ) deg = 0 deg = 90 if ori == 6 deg = -90 if ori == 8 deg = 180 if ori == 3 deg end def rotate_image( org, deg ) if FileTest::exist?( org ) then check_command( @convertpath ) system( "#{@convertpath} -rotate #{deg} #{org} #{org}" ) end if FileTest::exist?( org ) org else "" end end def make_thumbnail( idir, iname , newsize , gid ) org_full = idir + iname tb_name = "s" + iname tb_full = idir + tb_name begin check_command( @convertpath ) # only for imagemagick 6 and later!! system( "#{@convertpath} -thumbnail #{newsize}\\\> #{org_full} #{tb_full}" ) end if FileTest::exist?( tb_full ) if gid then require 'shell' sh = Shell.new sh.chown( nil , gid , tb_full ) sh.chmod( 00664 , tb_full ) end tb_name else iname end end def add_body_text( prev, sub_head , sub_body ) addtext = prev if prev.size > 0 and !(prev =~ /\n$/) then addtext += "\n" end if sub_head =~ %r[^Content-Transfer-Encoding:\s*base64]i then addtext += NKF::nkf( '-wXd -mB', sub_body ) elsif addtext += sub_body end addtext end def add_delimiter( orgpath ) if !orgpath or orgpath.size < 1 then newpath = "" else if !(orgpath =~ /[\/\\]$/) then if !(orgpath =~ /\//) and orgpath =~ /\\/ then newpath = orgpath + "\\" else newpath = orgpath + "/" end else newpath = orgpath.dup end end newpath end def make_image_body( imgdata , imgname , remotedir , now , image_boundary, protection_key ) fname = "" extension = "" image_body = "" if imgname =~ /^(.*)(\.jpg|\.jpeg|\.gif|\.png)\z/i extension = $2.downcase fname = $1 + extension else return nil end typestr = "image/jpeg" if extension =~ /jpe??g/i typestr = "image/bmp" if extension =~ /bmp/i typestr = "image/gif" if extension =~ /gif/i typestr = "image/png" if extension =~ /png/i if remotedir and remotedir.length > 0 then image_body.concat < 0 then image_body.concat < "Basic #{auth}", 'Content-Length' => image_body.length.to_s, 'Content-Type' => "multipart/form-data; boundary=#{image_boundary}", 'Referer' => refurl, } response, = http.post( cgi, image_body, image_header ) raise "posttdiary-ex: failed to upload image (#{imgname}) to remote server" if response.code.to_i < 200 or response.code.to_i > 202 end (image_body ? true : false) end def get_date_to_append( http, cgi, user, pass, now ) # call update.rb via HTTP and get the date to append str = cgi req = Net::HTTP::Get.new( str ) req.basic_auth user, pass response, = http.request(req) body = response.body year = now.strftime( "%Y" ) month = now.strftime( "%m" ) day = now.strftime( "%d" ) bodytmp = body.split(/$/); bodytmp.each do |oneline| if oneline =~ /\]*)\>/ then if $1 =~ /value=\"(\d\d\d\d)"/ then year = $1 end end if oneline =~ /\]*)\>/ then if $1 =~ /value=\"(\d+)\"/ then month = $1 end end if oneline =~ /\]*)\>/ then if $1 =~ /value=\"(\d+)\"/ then day = $1 end end end Time::local( year, month, day ) end def parse_mail( head, body , image_dir ) imglist = [] orglist = [] textbody = "" imgnum = -1 imgdir = add_delimiter( image_dir ) if head =~ /Content-Type:\s*Multipart\/Mixed.*boundary=\"*([^\"\r\n]*)\"*/im or head =~ /Content-Type:\s*Multipart\/Related.*boundary=\"*([^\"\r\n]*)\"*/im then bound = "--" + $1 body_sub = body.split( Regexp.compile( Regexp.escape( bound ) ) ) body_sub.each do |b| sub_head, sub_body = b.split( /(?:\r\n){2}|\r\r|\n\n/, 2 ) sub_body = "" unless sub_body next unless sub_head =~ /Content-Type/i if sub_head =~ %r[^Content-Type:\s*text/plain]i then textbody = add_body_text( textbody , sub_head, sub_body ) elsif sub_head =~ %r[^Content-Type:\s*(image\/|application\/octet-stream).*name=\"*(.*)(\.[^\"\r\n]*)\"*]im imgnum += 1 orgname = $2 orgname = "" if !orgname image_ext = $3.downcase image_name = "_tmp" + Process.pid.to_s + "_" + imgnum.to_s + image_ext File::umask( 022 ) open( imgdir + image_name, "wb" ) do |s| begin s.print Base64::decode64( sub_body.strip ) rescue NameError s.print decode64( sub_body.strip ) end end if /\.bmp$/i =~ image_name then bmp_to_png( imgdir + image_name ) image_name.sub!( /\.bmp$/, '.png' ) end imglist[imgnum] = imgdir + image_name orglist[imgnum] = orgname end end elsif head =~ /^Content-Type:\s*text\/plain/i textbody = add_body_text( textbody , head, body ) else raise "posttdiary-ex: can not read this mail (illegal format)" end addr = nil if /^To:(.*)$/ =~ head then to = $1.strip if /.*?\s*<(.*)>/ =~ to then addr = $1 elsif /(.*?)\s*\(.*\)/ =~ to addr = $1 else addr = to end end subject = '' nextline = false headlines = head.split( /[\r\n]+/ ) for n in 0 .. headlines.size-1 if nextline then if /^[ \t]/ =~ headlines[n] then s = headlines[n].sub( /^[ \t]/, '' ) subject += NKF::nkf( '-wXd', s ) else break end end if /^Subject:(.*)$/ =~ headlines[n] then s = $1.sub( /^\s+/, '' ) subject = NKF::nkf( '-wXd', s ) nextline = true end end [addr, subject, imglist, orglist, textbody] end begin raise usage(false) if ARGV.length < 1 require 'getoptlong' parser = GetoptLong::new conf_df_name = nil image_dir = nil image_url = nil use_subject = false thumbnail_size = nil image_geometry = nil use_image_ex = false hour_offset = nil @hour_offset = nil yearly_dir = false thumbnail_name = Hash.new("") exif_comment = Hash.new("") exif_orientation = Hash.new(1) image_orgname = Hash.new("") remote_mode = false remote_image_dir = nil remote_yearly_dir = false preserve_local_images = false upload_only = false class_name = 'photo' group_id = nil add_div_imgnum = 2 add_div_imgnum_specified = nil threshold_size = nil pass_filename = false filter_mode = false writeout_filename = nil read_exif = false image_format = ' $4' image_format_with_thumbnail = ' $4' image_format_specified = nil wiki_style = false blog_style = false use_original_name = false date_margin = 7 convertpath_specified = nil @convertpath = "convert" @magickpath = "" exifpath_specified = nil @exifpath = "exif" rotation_degree_specified = nil parser.set_options( ['--read-conffile', '-a', GetoptLong::REQUIRED_ARGUMENT], ['--image-path', '-i', GetoptLong::REQUIRED_ARGUMENT], ['--image-url', '-u', GetoptLong::REQUIRED_ARGUMENT], ['--use-subject', '-s', GetoptLong::NO_ARGUMENT], ['--make-thumbnail', '-t', GetoptLong::REQUIRED_ARGUMENT], ['--image-geometry', '-g', GetoptLong::REQUIRED_ARGUMENT], ['--use-image-ex', '-e', GetoptLong::NO_ARGUMENT], ['--hour-offset', '-o', GetoptLong::REQUIRED_ARGUMENT], ['--yearly-dir', '-y', GetoptLong::NO_ARGUMENT], ['--help', '-h', GetoptLong::NO_ARGUMENT], ['--convert-path', '-C', GetoptLong::REQUIRED_ARGUMENT], ['--exif-path', '-E', GetoptLong::REQUIRED_ARGUMENT], ['--remote-mode', '-R', GetoptLong::NO_ARGUMENT], ['--remote-image-path', '-D', GetoptLong::REQUIRED_ARGUMENT], ['--remote-yearly-dir', '-Y', GetoptLong::REQUIRED_ARGUMENT], ['--preserve-local-images', '-P', GetoptLong::NO_ARGUMENT], ['--upload-only', '-U', GetoptLong::NO_ARGUMENT], ['--group-id', '-G', GetoptLong::REQUIRED_ARGUMENT], ['--class-name', '-n', GetoptLong::REQUIRED_ARGUMENT], ['--add-div', '-v', GetoptLong::REQUIRED_ARGUMENT], ['--threshold-size', '-z', GetoptLong::REQUIRED_ARGUMENT], ['--image-format', '-f', GetoptLong::REQUIRED_ARGUMENT], ['--use-original-name', '-r', GetoptLong::NO_ARGUMENT], ['--wiki-style', '-w', GetoptLong::NO_ARGUMENT], ['--blog-style', '-B', GetoptLong::NO_ARGUMENT], ['--read-exif', '-c', GetoptLong::NO_ARGUMENT], ['--margin-time', '-m', GetoptLong::REQUIRED_ARGUMENT], ['--pass-filename', '-p', GetoptLong::NO_ARGUMENT], ['--filter-mode', '-d', GetoptLong::NO_ARGUMENT], ['--write-to-file', '-b', GetoptLong::REQUIRED_ARGUMENT], ['--date-margin', '-j', GetoptLong::REQUIRED_ARGUMENT], ['--rotate', '-T', GetoptLong::REQUIRED_ARGUMENT] ) begin parser.each do |opt, arg| case opt when '--read-conffile' conf_df_name = arg.dup when '--image-path' image_dir = arg.dup when '--image-url' image_url = arg.dup when '--use-subject' use_subject = true when '--make-thumbnail' thumbnail_size = arg.dup when '--image-geometry' image_geometry = arg.dup when '--use-image-ex' use_image_ex = true when '--hour-offset' hour_offset = arg.to_i when '--yearly-dir' yearly_dir = true when '--help' print usage(true) exit 0 when '--convert-path' convertpath_specified = arg.dup when '--exif-path' exifpath_specified = arg.dup read_exif = true when '--remote-mode' remote_mode = true when '--remote-image-path' remote_image_dir = add_delimiter(arg.dup) when '--remote-yearly-dir' remote_yearly_dir = (arg.dup =~ /[1yt]/i) when '--preserve-local-images' preserve_local_images = true when '--upload-only' upload_only = true filter_mode = true when '--group-id' if arg =~ /\D/ then require 'etc' group_id = Etc.getgrnam( arg.dup )['gid'] else group_id = arg.to_i end group_id = nil if group_id <= 0 or group_id > 65535 when '--add-div' add_div_imgnum_specified = arg.to_i when '--threshold-size' threshold_size = arg.dup when '--image-format' image_format_specified = arg.dup when '--use-original-name' use_original_name = true when '--wiki-style' wiki_style = true use_image_ex = true when '--blog-style' blog_style = true when '--read-exif' read_exif = true when '--pass-filename' pass_filename = true when '--filter-mode' filter_mode = true when '--write-to-file' filter_mode = true writeout_filename = arg.dup when '--date-margin' date_margin = arg.to_i when '--rotate' rotation_degree_specified = 0 rotation_degree_specified = 90 if arg =~ /right/i rotation_degree_specified = -90 if arg =~ /left/i end end rescue raise usage(false) end if conf_df_name then if read_tdiary_conf( conf_df_name ) then image_dir = @options['image.dir'] if @options['image.dir'] and !image_dir image_url = @options['image.url'] if @options['image.url'] and !image_url yearly_dir = true if @options['image_ex.yearlydir'] and @options['image_ex.yearlydir'] == 1 thumbnail_size = @options['image_ex.convertedwidth'].to_s + "x" + @options['image_ex.convertedheight'].to_s if @options['image_ex.convertedwidth'] and @options['image_ex.convertedheight'] and thumbnail_size == nil threshold_size = @options['image_ex.thresholdsize'].to_s if @options['image_ex.thresholdsize'] and !threshold_size @convertpath= @options['image_ex.convertpath'] if @options['image_ex.convertpath'] and !convertpath_specified @exifpath = @options['image_ex.exifpath'] if @options['image_ex.exifpath'] and !exifpath_specified else conf_df_name = '' end end image_url = "" if use_image_ex and !image_url raise 'posttdiary-ex: image-path (-i) or image-url (-u) missing...' if (!image_url and image_dir) or (!image_dir and image_url) if image_dir then image_dir = add_delimiter( image_dir ) end if image_url then image_url += '/' unless %r[/$] =~ image_url end if thumbnail_size then thumbnail_size.gsub!(/[\>\\\s]/, '') thumbnail_size = thumbnail_size + 'x' + thumbnail_size if !(thumbnail_size =~ /x/ ) raise usage if !(thumbnail_size =~ /^\d+x\d+/) end threshold_size = thumbnail_size if !threshold_size if threshold_size and threshold_size.size > 0 then threshold_size.gsub!(/[\>\\\s]/, '') threshold_size = threshold_size + 'x' + threshold_size if !(threshold_size =~ /x/ ) raise usage if !(threshold_size =~ /^\d+x\d+/) end if image_geometry then image_geometry.gsub!(/[\>\\\s]/, '') image_geometry = image_geometry + 'x' + image_geometry if !(image_geometry =~ /x/ ) raise usage if !(image_geometry =~ /^\d+x\d+/) end hour_offset = @hour_offset if !hour_offset hour_offset = 0 if !hour_offset if image_format_specified then image_format = image_format_specified image_format_with_thumbnail = image_format else if use_image_ex then image_format = '<%=image $0,\'$4\'%>' image_format_with_thumbnail = image_format end if wiki_style then image_format = '{{image $0,\'$4\'}}' image_format_with_thumbnail = image_format end end if wiki_style then add_div_imgnum = 0 else add_div_imgnum = add_div_imgnum_specified if add_div_imgnum_specified end @convertpath = convertpath_specified if convertpath_specified @convertpath = add_delimiter( @convertpath ) + "convert" if test( ?d , @convertpath ) @magickpath = $1 if @convertpath =~ /(.*[\/\\])[^\/\\]+$/ @exifpath = exifpath_specified if exifpath_specified @exifpath = add_delimiter( @exifpath ) + "exif" if test( ?d , @exifpath ) if filter_mode == false then url = ARGV.shift.dup if %r|http://([^:/]*):?(\d*)(/.*)| =~ url then host = $1 port = $2.to_i cgi = $3 raise 'posttdiary-ex: invalid url for update.rb.' if not host or not cgi port = 80 if port == 0 else raise 'posttdiary-ex: invalid url for update.rb.' end user = ARGV.shift.dup pass = ARGV.shift.dup end require 'base64' require 'nkf' require 'net/http' require 'shell' Net::HTTP.version_1_2 mail = NKF::nkf( '-m0 -Xwd', ARGF.read ) raise "posttdiary-ex: no mail text." if not mail or mail.length == 0 head, body = mail.split( /(?:\r\n){2}|\r\r|\n\n/, 2 ) body = "" unless body addr, subject, tmpimglist, orglist, @body = parse_mail( head, body, image_dir ) if /([^-]+)-(.*)@/ =~ addr then user = $1 unless user pass = $2 unless pass end raise "posttdiary-ex: please specify the username for your tdiary system." unless user or filter_mode if tmpimglist.length > 0 and ( !image_dir or !image_url ) then raise "posttdiary-ex: please specify image-path (-i) and/or image-url (-u)" end now = Time::now + hour_offset * 3600 tmp = Time::now + hour_offset * 3600 if @body.gsub!( /^\_date\#([\d\-\/\.]+)[^\r\n]*[\r\n]+/i , '' ) then t = $1 if /(\d\d\d\d)[^\d]*(\d\d)[^\d]*(\d\d)/ =~ t then tmp = Time::local( $1.to_i, $2.to_i, $3.to_i ); end if /(\d\d\d\d)[^\d]+(\d+)[^\d]+(\d+)/ =~ t then tmp = Time::local( $1.to_i, $2.to_i, $3.to_i ); end else if blog_style and !filter_mode then Net::HTTP.start( host, port ) do |http| tmp = get_date_to_append( http, cgi, user, pass, now ) end end end if @body.gsub!( /^\_up[ld]+only\#[ \t]*[\r\n]+/i , '' ) then upload_only = true end if @body.gsub!( /^\_rot[ate]*\_right\#[ \t]*[\r\n]+/i , '' ) then rotation_degree_specified = 90 end if @body.gsub!( /^\_rot[ate]*\_left\#[ \t]*[\r\n]+/i , '' ) then rotation_degree_specified = -90 end if @body.gsub!( /^\_rot[ate]*\_none\#[ \t]*[\r\n]+/i , '' ) then rotation_degree_specified = 0 end if date_margin != 0 and (tmp - now).abs >= date_margin * 24 * 3600 then # raise "posttdiary-ex: specified date is too far from today" # # use current date (now) instead of specified date(tmp).. else now = tmp end topic_year = now.strftime( "%Y" ) topic_month = now.strftime( "%m" ) topic_date = now.strftime( "%d" ) if image_dir then image_dir = add_delimiter( image_dir + now.strftime( "%Y" ) ) if yearly_dir Dir.mkdir( image_dir ) if !test( ?d , image_dir ) if remote_mode then image_url += topic_year + "/" if remote_yearly_dir else image_url += topic_year + "/" if yearly_dir end end nextnum = -1 av_list = [] if remote_mode then if !remote_image_dir or remote_image_dir.length < 1 then # needed when using image_ex.rb, but not when using image.rb... # raise 'posttdiary-ex: please specify --remote-image-path' remote_image_dir = "" else if remote_yearly_dir then remote_image_dir = add_delimiter( remote_image_dir + topic_year ) end end Net::HTTP.start( host, port ) do |http| nextnum,av_list = check_remote_images( http, cgi, user, pass, now) end else nextnum,av_list = check_local_images( now.strftime( "%Y%m%d" ), image_dir ) end @image_name = nil sh = Shell.new for i in 0 .. (tmpimglist.length-1) tmpimgname = tmpimglist[i] raise "posttdiary-ex: program bug found: no extension in tmpimgname" if !(tmpimgname =~ /(\.[^\.]*?)$/) image_ext = $1.downcase image_name = now.strftime( "%Y%m%d" ) + "_" + nextnum.to_s + image_ext nextnum += 1 sh.rename( tmpimgname , image_dir + image_name ) exif_comment[image_name] = (read_exif ? read_exif_comment(image_dir + image_name) : "" ) exif_orientation[image_name] = (read_exif ? read_exif_orientation(image_dir + image_name) : "" ) image_orgname[image_name] = orglist[i] change_image_size( image_dir + image_name , image_geometry ) if image_geometry if rotation_degree_specified then if rotation_degree_specified != 0 then rotate_image( image_dir + image_name , rotation_degree_specified ) end elsif read_exif and exif_orientation[image_name] != 1 then rotate_image( image_dir + image_name , rotation_degree( exif_orientation[image_name] ) ) end if group_id then sh.chown( nil , group_id , image_dir + image_name ) sh.chmod( 00664 , image_dir + image_name ) end thumbnail_name[image_name] = "" thumbnail_name[image_name] = make_thumbnail( image_dir, image_name , thumbnail_size , group_id ) if thumbnail_size and check_image_size( image_dir + image_name, threshold_size) @image_name = [] unless @image_name @image_name << image_name end if @image_name then img_src = "" marker = "_posttdiary_ex_temporary_marker_" img_in_div = 0 for j in 0 .. @image_name.size-1 i = @image_name[j] serial = i.sub( /^\d+_(\d+)\.[^\.]*?$/, '\1' ) serial = i if use_image_ex and pass_filename cm = "" cm = exif_comment[i] if read_exif and exif_comment[i] and exif_comment[i].size > 0 cm = image_orgname[i] if use_original_name and (!cm or cm.size == 0) cm = i.gsub(/\.[^\.]*?$/, '') if !cm or cm.size == 0 if use_image_ex then # modify <%=image (num),'comment'%> or <%=image (num)%> tags if @body =~ /\<\%\=image[^\s]*\s+#{j}\s*\,\s*[\"\'](.*)[\"\']\s*\%*\>/i then alttext = $1; alttext = cm if alttext.length < 1 @body.gsub!( /\<\%\=(image[^\s]*)\s+#{j}\s*\,\s*[\"\'].*[\"\']\s*\%*\>/i, '<%=\1 '+marker+serial.to_s+',\''+alttext+'\'%>' ) next elsif @body =~ /\<\%\=image[^\s]*\s+#{j}\s*\%*\>/i then alttext = cm @body.gsub!( /\<\%\=(image[^\s]*)\s+#{j}\s*\%*\>/i, '<%=\1 '+marker+serial.to_s+',\''+alttext+'\'%>' ) next end end if wiki_style then # modify {{image (num),"comment"}} or {{image (num)}} tags (also recognizes image_left, image_right) if @body =~ /\{\{image[^\s]*\s+#{j}\s*\,\s*[\"\'](.*)[\"\']\s*\}\}/i then alttext = $1; alttext = cm if alttext.length < 1 @body.gsub!( /\{\{(image[^\s]*)\s+#{j}\s*\,\s*[\"\'].*[\"\']\s*\}\}/i, '{{\1 '+marker+serial.to_s+',\''+alttext+'\'}}' ) next elsif @body =~ /\{\{image[^\s]*\s+#{j}\s*\}\}/i then alttext = cm @body.gsub!( /\{\{(image[^\s]*)\s+#{j}\s*\}\}/i, '{{\1 '+marker+serial.to_s+',\''+alttext+'\'}}' ) next end end img_in_div+=1 if thumbnail_size and thumbnail_name[i].size > 0 then t = thumbnail_name[i] img_src += image_format_with_thumbnail.gsub( /\$0/, serial ).gsub( /\$1/, image_url + i ).gsub( /\$2/, image_url + t ).gsub( /\$3/, class_name ).gsub( /\$4/, cm ) else img_src += image_format.gsub( /\$0/, serial ).gsub( /\$1/, image_url + i ).gsub( /\$3/, class_name ).gsub( /\$4/, cm ) end end @body.gsub!( /#{marker}/ , '' ) if img_src =~ /^\s+$/ then img_src = '' else if add_div_imgnum <= img_in_div and add_div_imgnum > 0 then img_src = "
        " + img_src + "
        " end end img_src.sub!( /^/ , ' ' ) if ! wiki_style if use_subject then img_src = img_src + "\n" if !(img_src =~ /^\s*$/) @body = "#{img_src}#{@body.sub( /\n+\z/, '' )}" else @body = "#{@body.sub( /\n+\z/, '' )}\n#{img_src}" end end if use_subject then title = '' @body = "#{subject}\n#{@body}" @body = "!" + @body if wiki_style else title = subject end if upload_only then exit 0 end require 'cgi' require 'nkf' if filter_mode then data = title + "\n"; data << @body + "\n"; if writeout_filename then open( writeout_filename, "wb" ) do |s| s.print data end else print data end else data = "title=#{CGI::escape title}" data << "&body=#{CGI::escape @body}" data << "&append=true" data << "&year=#{topic_year}" data << "&month=#{topic_month}" data << "&day=#{topic_date}" auth = ["#{user}:#{pass}"].pack( 'm' ).strip Net::HTTP.start( host, port ) do |http| protection_key = nil res = http.get( cgi, 'Authorization' => "Basic #{auth}", 'Referer' => url ) if %r|| =~ res.body then protection_key = $1 data << "&csrf_protection_key=#{CGI::escape( CGI::unescapeHTML( protection_key ) )}" end if remote_mode and @image_name then for i in 0 .. (@image_name.length - 1) imagename = @image_name[i] thumbnailname = thumbnail_name[imagename] post_image( http, cgi, user, pass, image_dir, imagename, remote_image_dir, now, protection_key, url ) File.delete( image_dir + imagename ) if !preserve_local_images File.delete( image_dir + thumbnailname ) if !preserve_local_images and test( ?f , image_dir + thumbnailname ) end end response = http.post( cgi, data, 'Authorization' => "Basic #{auth}", 'Referer' => url ) end end rescue $stderr.puts $! exit 1 end tdiary-contrib-3.2.2/util/posttdiary/posttdiary.rb000077500000000000000000000142411213632744000223650ustar00rootroot00000000000000#!/usr/bin/env ruby $KCODE= 'u' # # posttdiary: update tDiary via e-mail. $Revision: 1.5 $ # # Copyright (C) 2002, All right reserved by TADA Tadashi # You can redistribute it and/or modify it under GPL2. # def usage <<-TEXT.gsub( /^\t{2}/, '' ) #{File::basename __FILE__}: update tDiary via e-mail. usage: ruby #{File::basename __FILE__} [options] [user] [passwd] arguments: url: update.rb's URL of your diary. user: user ID of your diary updating. passwd: password of your diary updating. If To: field of the mail likes "user-passwd@example.com", you can omit user and passwd arguments. options: --image-path, -i: directory of image saving into. --image-url, -u: URL of image. You have to specify both options when using images. --image-format, -f: format of image tag specified image serial number as '$0' and image url as '$1'. default format is ' '. --use-subject, -s: use mail subject to subtitle. and insert image between subtitle and body. TEXT end def image_list( date, path ) image_path = [] Dir.foreach( path ) do |file| if file =~ /(\d{8,})_(\d+)\./ and $1 == date then image_path[$2.to_i] = file end end image_path end def bmp_to_png( bmp ) png = bmp.sub( /\.bmp$/, '.png' ) begin require 'magick' img = Magick::Image::new( bmp ) img.write( 'magick' => 'png', 'filename' => png ) rescue LoadError system( "convert #{bmp} #{png}" ) end if FileTest::exist?( png ) File::delete( bmp ) png else bmp end end begin raise usage if ARGV.length < 1 require 'getoptlong' parser = GetoptLong::new image_dir = nil image_url = nil image_format = ' ' use_subject = false parser.set_options( ['--image-path', '-i', GetoptLong::REQUIRED_ARGUMENT], ['--image-url', '-u', GetoptLong::REQUIRED_ARGUMENT], ['--image-format', '-f', GetoptLong::REQUIRED_ARGUMENT], ['--use-subject', '-s', GetoptLong::NO_ARGUMENT] ) begin parser.each do |opt, arg| case opt when '--image-path' image_dir = arg when '--image-url' image_url = arg when '--image-format' image_format = arg when '--use-subject' use_subject = true end end rescue raise usage end raise usage if (image_dir and not image_url) or (not image_dir and image_url) image_dir = image_dir.sub( %r[/*$], '/' ) if image_dir image_url = image_url.sub( %r[/*$], '/' ) if image_url url = ARGV.shift if %r|http://([^:/]+)(?::(\d+))?(/.*)| =~ url then host = $1 port = ($2 || 80).to_i cgi = $3 else raise 'bad url.' end user = ARGV.shift pass = ARGV.shift require 'base64' require 'nkf' image_name = nil mail = NKF::nkf( '-m0 -Xwd', ARGF.read ) raise "#{File::basename __FILE__}: no mail text." if not mail or mail.length == 0 head, body = mail.split( /(?:\r?\n){2}/, 2 ) if head =~ %r|Content-Type:\s*Multipart/Mixed.*boundary="?(.*?)"?[\r\n]|im then if not image_dir or not image_url then raise "no --image-path and --image-url options" end bound = "--" + $1 body_sub = body.split( Regexp.compile( Regexp.escape( bound ) ) ) body_sub.each do |b| sub_head, sub_body = b.split( /(?:\r?\n){2}/, 2 ) next unless sub_head =~ /Content-Type:/i if sub_head =~ %r[^Content-Type:\s*text/plain]i then @body = sub_body elsif sub_head =~ %r[ ^Content-Type:\s* (?:image/|application/octet-stream).+ name="?.+(\.\w{3})"? (?# 1: extension) ]imx image_ext = $1.downcase now = Time::now list = image_list( now.strftime( "%Y%m%d" ), image_dir ) image_name = now.strftime( "%Y%m%d" ) + "_" + list.length.to_s + image_ext File::umask( 022 ) open( image_dir + image_name, "wb" ) do |s| begin s.print Base64::decode64( sub_body.strip ) rescue NameError s.print decode64( sub_body.strip ) end end if /\.bmp$/i =~ image_name then bmp_to_png( image_dir + image_name ) image_name.sub!( /\.bmp$/i, '.png' ) end @image_name ||= [] @image_name << image_name end end elsif head =~ /^Content-Type:\s*text\/plain/i if head =~ /^Content-Transfer-Encoding:\squoted-printable/ @body = body.unpack("M").map {|str| NKF::nkf("-wJd", str) } else @body = body end else raise "cannot read this mail" end if @image_name then img_src = "" @image_name.each do |i| serial = i.sub( /^\d+_(\d+)\..*$/n, '\1' ) img_src += image_format.gsub( /\$0/, serial ).gsub( /\$1/, image_url + i ) end if use_subject then @body = "#{img_src}\n#{@body}".sub( /(?:\r?\n|\r)+\z/, "\n" ) else @body = "#{@body}".sub( /(?:\r?\n|\r)+\z/, "\n" ) << img_src end end addr = nil if /^To:(.*)$/ =~ head then addr = case to = $1.strip when /.*?\s*<(.+)>/, /(.+?)\s*\(.*\)/ $1 else to end end if /([^-]+)-(.*)@/ =~ addr then user ||= $1 pass ||= $2 end raise "no user." unless user raise "no passwd." unless pass subject = '' nextline = false headlines = head.split( /(?:\r?\n|\r)+/ ) for n in 0 .. headlines.size-1 if nextline then if /^[ \t]/ =~ headlines[n] then s = headlines[n].sub( /^[ \t]/, '' ) subject += NKF::nkf( '-wXd', s ) else break end end if /^Subject:\s*(.+)$/i =~ headlines[n] then subject = NKF::nkf( '-wXd', $1 ) nextline = true end end subject.strip! if use_subject then title = '' @body = "#{subject}\n#{@body}" else title = subject end require 'cgi' require 'nkf' data = "title=#{CGI::escape title}" data << "&body=#{CGI::escape @body}" data << "&append=true" require 'net/http' Net::HTTP.start( host, port ) do |http| auth = ["#{user}:#{pass}"].pack( 'm' ).strip res, = http.get( cgi, { 'Authorization' => "Basic #{auth}", 'Referer' => url }) if %r|| =~ res.body then data << "&csrf_protection_key=#{CGI::escape( CGI::unescapeHTML( $1 ) )}" end res, = http.post( cgi, data, { 'Authorization' => "Basic #{auth}", 'Referer' => url }) end rescue $stderr.puts $! $stderr.puts $@.join( "\n" ) File::delete( image_dir + image_name ) if image_dir and image_name and FileTest::exist?( image_dir + image_name ) exit 1 end tdiary-contrib-3.2.2/util/rast-search/000077500000000000000000000000001213632744000176435ustar00rootroot00000000000000tdiary-contrib-3.2.2/util/rast-search/ChangeLog000066400000000000000000000035121213632744000214160ustar00rootroot000000000000002007-01-08 Kazuhiko * rast-register.rb, rast-search.rb: revise for UTF8. 2005-12-10 Kazuhiko * rast-register.rb: set 'diaries' for the 'my-ex' plugin. * rast-register.rb: revise attributes of the 'date' property. rebuilding indices is necessary. * rast-search.rb: revise for mod_ruby. 2005-12-06 Kazuhiko * rast.rhtml: remove a dummy link. 2005-12-05 Kazuhiko * rast-register.rb: revise attributes of the 'date' property. remove indices before rebuilding. 2005-12-04 Kazuhiko * rast-register.rb: support tDiary-2.0.x. * en/rast-register.rb, ja/rast-register.rb: add resources. 2005-11-24 Kazuhiko * rast-register.rb: fix a bug in command-line mode (reported by YAA). set 'cache_path' for the 'tlink' plugin (reported by YAA). * rast-register.rb: support rebuilding index by conf mode. abolish 'CGI' mode. 2005-11-23 Kazuhiko * rast-register.rb: use 'require' instead of 'autoload'. 2005-11-21 Kazuhiko * rast-register.rb: add a plugin file. * rast-search.rb, rast.rxml: support opensearch rss. * rast.rhtml: revise for more valid HTML output. 2005-05-11 Kazuhiko * rast.rhtml, i.rast.rhtml: use @num instead of 10. 2005-05-11 TADA Tadashi * rast.rhtml, i.rast.rhtml: set title to h2 element, and copy format_links plugin on top of results. 2005-05-10 TADA Tadashi * README.ja: fix typo. 2005-04-16 Kazuhiko * rast.rhtml: convert the encoding of @query. 2005-04-15 Kazuhiko * rast-search.rb: never use Rast::LocalDB. fix a bug in running from a shell. 2005-04-14 Kazuhiko * initial release of rast-search. tdiary-contrib-3.2.2/util/rast-search/README.ja000066400000000000000000000072261213632744000211230ustar00rootroot00000000000000rast-search README =================== Rast を用いた tDiary 検索環境です。 特徴 ---------- 日記の更新と連動して自動的にインデックスを更新するので、いつでも最新の 情報で検索することができます。日記を HTML 化した後に必要な部分だけを取 り出してインデックスを作成するので、ヘッダやフッタなどによる検索ノイズ がなく、また、プラグインの出力が検索対象になるという特徴があります。 必要なもの ---------- * tDiary 1.5 以降 * Ruby 1.8.2 以降 * Rast 0.3.1 以降 セットアップ ------------ 1. rast-register.rb を tDiary の プラグインディレクトリにコピーします。 2. rast-search.rb を tDiary の index.rb があるディレクトリにコピーしま す。必要なら index.rb と同じようにシンボリックリンクを張ったり名前を 変えたりしてください。 3. CGI として実行可能にします。 $ chmod a+x rast-search.rb 4. 必要なら #! のパスを変更します。 5. rast.rhtml と rast.rxml と i.rast.rhtml を tDiary の skel/ ディレク トリにコピーします。 6. rast-register.rb プラグインを有効にします。(tDiary の plugin/ ディレ クトリにコピーするか、プラグイン選択のディレクトリにコピーしてブラウ ザから有効に設定します。言語リソースファイルの en/rast-register.rb と ja/rast-register.rb も、プラグインディレクトリの en/ 以下および ja/ 以下にコピーしてください。) 7. (オプション) tdiary.conf で以下のように encoding の設定をできます。 Rast の encoding module の名前で設定してください。デフォルトは 'utf8' です。encoding の設定を変更する場合は、Rast のインデックス があるディレクトリ (cache ディレクトリの下の /rast) を消して、再度イ ンデックスを作りなおしてください。 @options['rast.index'] = 'utf8' 8. 既存の日記コンテンツに対して検索インデックスを作成します。tDiary の 設定画面から「Rast検索」を選び、「Rast検索のインデックスを再構築する 場合は、チェックボックスをチェックしてOKを押してください」というメッ セージに従ってチェックしてOKを押すと、 インデックスの作成は、tDiary の CGI の実行権限で以下のように実行する ことでも可能です。 ruby rast-register.rb [-p tdiary.rbのあるディレクトリ] [-c tdiary.confのあるディレクトリ] 9. 自分の tDiary の好きな場所 (例えばヘッダ) に以下のようなフォームを加 えてください。 search-form.rb プラグインを有効にしている場合は、以下のように書くこ ともできます。 <%= search_form('rast-search.rb', 'query') %> 以上です。 検索のしかた ------------ rast-search の検索対象は、日記本文、ツッコミ、TrackBack です。 検索方法については、 http://projects.netlab.jp/rast/query.html.ja をご覧くだ さい。 連絡先 ------ かずひこ http://www.fdiary.net/ バグ報告は以下のどこかにお願いします。 * tdiary-devel ML * 直接メール tdiary-contrib-3.2.2/util/rast-search/en/000077500000000000000000000000001213632744000202455ustar00rootroot00000000000000tdiary-contrib-3.2.2/util/rast-search/en/rast-register.rb000066400000000000000000000003061213632744000233640ustar00rootroot00000000000000@rast_register_conf_label = 'Rast Search' @rast_register_conf_header = 'Rebuild Rast search index' @rast_register_conf_description = 'To rebuild Rast search index, check the box and submit \'OK\'.' tdiary-contrib-3.2.2/util/rast-search/i.rast.rhtml000066400000000000000000000017171213632744000221210ustar00rootroot00000000000000<%# i.rast.rhtml $Revision: 1.5.2.1 $ %>

        <%= CGI::escapeHTML( @conf.html_title ) %> [全文検索]

        検索方法

        並べ替え: 表示件数:

        <% if @msg %>

        <%= @msg %>

        <% else %>

        <%= @result.hit_count %>件中<%= @start + 1 %>-<%= @start + @result.items.length %>件目

        <% for item in @result.items %><% format_result_item(item) %>

        <%= _(@conf.to_native(@title)) %>(スコア:<%= item.score %>)

        <% end %> <% if @result.hit_count > @num %> <%= format_links(@result) %> <% end %> <% end %> tdiary-contrib-3.2.2/util/rast-search/ja/000077500000000000000000000000001213632744000202355ustar00rootroot00000000000000tdiary-contrib-3.2.2/util/rast-search/ja/rast-register.rb000066400000000000000000000004351213632744000233570ustar00rootroot00000000000000@rast_register_conf_label = 'Rast検索' @rast_register_conf_header = 'Rast検索インデックスの再構築' @rast_register_conf_description = 'Rast検索のインデックスを再構築する場合は、チェックボックスをチェックしてOKを押してください。' tdiary-contrib-3.2.2/util/rast-search/rast-register.rb000077500000000000000000000171631213632744000227760ustar00rootroot00000000000000#!/usr/bin/env ruby # # Copyright (C) 2005 Kazuhiko # You can redistribute it and/or modify it under GPL2. # mode = "" if $0 == __FILE__ require 'cgi' ARGV << '' # dummy argument against cgi.rb offline mode. @cgi = CGI::new mode = "CMD" else mode = "PLUGIN" end if mode == "CMD" tdiary_path = "." tdiary_conf = "." $stdout.sync = true def usage puts "rast-register.rb $Revision: 1.10.2.2 $" puts " register to rast index files from tDiary's database." puts " usage: ruby rast-regiser.rb [-p ] [-c ]" exit end require 'getoptlong' parser = GetoptLong::new parser.set_options(['--path', '-p', GetoptLong::REQUIRED_ARGUMENT], ['--conf', '-c', GetoptLong::REQUIRED_ARGUMENT]) begin parser.each do |opt, arg| case opt when '--path' tdiary_path = arg when '--conf' tdiary_conf = arg end end rescue usage exit( 1 ) end tdiary_conf = tdiary_path unless tdiary_conf Dir::chdir( tdiary_conf ) begin $:.unshift tdiary_path require "#{tdiary_path}/tdiary" rescue LoadError $stderr.puts "rast-register.rb: cannot load tdiary.rb. <#{tdiary_path}/tdiary>\n" $stderr.puts " usage: ruby rast-regiser.rb [-p ] [-c ]" exit( 1 ) end end require 'rast' module ::TDiary # # Database # class RastDB DB_OPTIONS = { "preserve_text" => true, "properties" => [ { "name" => "title", "type" => Rast::PROPERTY_TYPE_STRING, "search" => false, "text_search" => true, "full_text_search" => true, "unique" => false, }, { "name" => "user", "type" => Rast::PROPERTY_TYPE_STRING, "search" => true, "text_search" => false, "full_text_search" => false, "unique" => false, }, { "name" => "date", "type" => Rast::PROPERTY_TYPE_STRING, "search" => true, "text_search" => true, "full_text_search" => false, "unique" => false, }, { "name" => "last_modified", "type" => Rast::PROPERTY_TYPE_DATE, "search" => true, "text_search" => false, "full_text_search" => false, "unique" => false, } ] } attr_accessor :db attr_reader :conf, :encoding def initialize(conf, encoding) @conf = conf @encoding = encoding @db_options = {'encoding' => @encoding}.update(DB_OPTIONS) @db_options['properties'].delete_if{|i| i['name'] == 'user'} unless @conf['rast.with_user_name'] end def transaction if !File.exist?(db_path) Rast::DB.create(db_path, @db_options) end Rast::DB.open(db_path, Rast::DB::RDWR, "sync_threshold_chars" => 500000) { |@db| yield self } end def cache_path @conf.cache_path || "#{@conf.data_path}cache" end def db_path @conf['rast.db_path'] || "#{cache_path}/rast".untaint end end # # Register # class RastRegister < TDiaryBase def initialize(rast_db, diary) @db = rast_db.db super(CGI::new, 'day.rhtml', rast_db.conf) @diary = diary @encoding = rast_db.encoding @date = diary.date @diaries = {@date.strftime('%Y%m%d') => @diary} if @diaries.empty? @plugin = ::TDiary::Plugin::new( 'conf' => @conf, 'cgi' => @cgi, 'cache_path' => @io.cache_path, 'diaries' => @diaries ) def @plugin.apply_plugin_alt( str, remove_tag = false ) apply_plugin( str, remove_tag ) end end def execute(force = false) date = @date.strftime('%Y%m%d') last_modified = @diary.last_modified.strftime("%FT%T") options = {"properties" => ['last_modified']} if @conf['rast.with_user_name'] result = @db.search("date : #{date} & user = #{@conf.user_name}", options) else result = @db.search("date : #{date}", options) end for item in result.items if force || item.properties[0] < last_modified @db.delete(item.doc_id) else return end end return unless @diary.visible? # body index = 0 anchor = '' @diary.each_section do |section| index += 1 @conf['apply_plugin'] = true anchor = "#{date}p%02d" % index title = CGI.unescapeHTML( @plugin.apply_plugin_alt( section.subtitle_to_html, true ).strip ) if title.empty? title = @plugin.apply_plugin_alt( section.body_to_html, true ).strip title = @conf.shorten( CGI.unescapeHTML( title ), 20 ) end body = CGI.unescapeHTML( @plugin.apply_plugin_alt( section.body_to_html, true ).strip ) properties = { "title" => title, "date" => anchor, "last_modified" => last_modified, } properties["user"] = @conf.user_name if @conf['rast.with_user_name'] @db.register(body, properties) end # comment @diary.each_visible_comment( 100 ) do |comment, index| if /^(TrackBack|Pingback)$/i =~ comment.name anchor = "#{date}t%02d" % index title = "TrackBack (#{comment.name})" else anchor = "#{date}c%02d" % index title = "#{@plugin.comment_description_short} (#{comment.name})" end body = comment.body properties = { "title" => title, "date" => anchor, "last_modified" => comment.date.strftime("%FT%T"), } properties["user"] = @conf.user_name if @conf['rast.with_user_name'] @db.register(body, properties) end end protected def mode; 'day'; end def cookie_name; ''; end def cookie_mail; ''; end def convert(str) str end end # # Main # class RastRegisterMain < TDiaryBase def initialize(conf) super(CGI::new, 'day.rhtml', conf) end def execute(encoding, out = $stdout) require 'fileutils' calendar db = RastDB.new(conf, encoding) FileUtils.rm_rf(db.db_path) db.transaction do |rast_db| @years.keys.sort.each do |year| out << "(#{year.to_s}/) " @years[year.to_s].sort.each do |month| @io.transaction(Time::local(year.to_i, month.to_i)) do |diaries| diaries.sort.each do |day, diary| RastRegister.new(rast_db, diary).execute out << diary.date.strftime('%m%d ') end false end end end end end end end if mode == "CMD" begin require 'cgi' if TDiary::Config.instance_method(:initialize).arity != 0 # for tDiary 2.1 or later cgi = CGI.new conf = TDiary::Config::new(cgi) else # for tDiary 2.0 or earlier conf = TDiary::Config::new end conf.header = '' conf.footer = '' conf.show_comment = true conf.hide_comment_form = true conf.show_nyear = false def conf.bot?; true; end encoding = 'utf8' TDiary::RastRegisterMain.new(conf).execute(encoding) rescue print $!, "\n" $@.each do |v| print v, "\n" end exit( 1 ) end puts else add_update_proc do conf = @conf.clone conf.header = '' conf.footer = '' conf.show_comment = true conf.hide_comment_form = true conf.show_nyear = false def conf.bot?; true; end diary = @diaries[@date.strftime('%Y%m%d')] encoding = 'utf8' TDiary::RastDB.new(conf, encoding).transaction do |rast_db| TDiary::RastRegister.new(rast_db, diary).execute(true) end end if !@conf['rast_register.hideconf'] && (@mode == 'conf' || @mode == 'saveconf') args = ['rast_register', @rast_register_conf_label] args << 'update' if TDIARY_VERSION > '2.1.3' add_conf_proc(*args) do str = <<-HTML

        #{@rast_register_conf_header}

        HTML if @mode == 'saveconf' if @cgi.valid?( 'rast_register_rebuild' ) encoding = 'utf8' str << '

        The following diaries were registered.

        ' out = '' TDiary::RastRegisterMain.new(@conf).execute(encoding, out) str << "

        #{out}

        " end end str end end end tdiary-contrib-3.2.2/util/rast-search/rast-search.rb000077500000000000000000000141371213632744000224150ustar00rootroot00000000000000#!/usr/bin/env ruby # -*- coding: utf-8 -*- # rast-search.rb $Revision: 1.6.2.2 $ # # Copyright (C) 2005 Kazuhiko # You can redistribute it and/or modify it under GPL2. # $KCODE= 'u' BEGIN { $stdout.binmode } if FileTest::symlink?( __FILE__ ) then org_path = File::dirname( File::readlink( __FILE__ ) ) else org_path = File::dirname( __FILE__ ) end $:.unshift( org_path.untaint ) require 'tdiary' require 'rast' # # class TDiaryRast # module TDiary class TDiaryRast < ::TDiary::TDiaryBase MAX_PAGES = 20 SORT_OPTIONS = [ ["score", "スコア順"], ["date", "日付順"], ] SORT_PROPERTIES = ["date"] ORDER_OPTIONS = [ ["asc", "昇順"], ["desc", "降順"], ] NUM_OPTIONS = [10, 20, 30, 50, 100] def initialize( cgi, rhtml, conf ) super @db_path = conf.options['rast.db_path'] || "#{cache_path}/rast" @encoding = 'utf8' # conf.options['sp.selected'] = '' parse_args format_form if @query.empty? @msg = '検索条件を入力して、「検索」ボタンを押してください' else search end end def load_plugins super # add a opensearch rss link @plugin.instance_variable_get('@header_procs').unshift Proc.new { cgi_url = @conf.base_url.sub(%r|/[^/]*$|, '/') + (@cgi.script_name ? _(File.basename(@cgi.script_name)) : '') %Q|\t\n| } # override some plugins def @plugin.sn(number = nil); ''; end end def eval_rxml require 'time' load_plugins ERB::new( File::open( "#{PATH}/skel/rast.rxml" ){|f| f.read }.untaint ).result( binding ) end private def parse_args @query = @cgi["query"].strip @start = @cgi["start"].to_i @num = @cgi["num"].to_i if @num < 1 @num = 10 elsif @num > 100 @num = 100 end @sort = @cgi["sort"].empty? ? "score" : @cgi["sort"] @order = @cgi["order"].empty? ? "desc" : @cgi["order"] end def search db = Rast::DB.open(@db_path, Rast::DB::RDONLY) begin options = create_search_options t = Time.now @result = db.search(convert(@query), options) @secs = Time.now - t rescue @msg = "エラー: #{_($!.to_s)}

        " ensure db.close end end def format_result_item(item) if @conf['rast.with_user_name'] @title, @user, @date, @last_modified = *item.properties else @title, @date, @last_modified = *item.properties end @summary = _(item.summary) || '' for term in @result.terms @summary.gsub!(Regexp.new(Regexp.quote(CGI.escapeHTML(term.term)), true, @encoding), "\\&") end end def format_links(result) page_count = (result.hit_count - 1) / @num + 1 current_page = @start / @num + 1 first_page = current_page - (MAX_PAGES / 2 - 1) if first_page < 1 first_page = 1 end last_page = first_page + MAX_PAGES - 1 if last_page > page_count last_page = page_count end buf = "

        \n" if current_page > 1 buf.concat(format_link("前へ", @start - @num, @num)) end if first_page > 1 buf.concat("... ") end for i in first_page..last_page if i == current_page buf.concat("#{i} ") else buf.concat(format_link(i.to_s, (i - 1) * @num, @num)) end end if last_page < page_count buf.concat("... ") end if current_page < page_count buf.concat(format_link("次へ", @start + @num, @num)) end buf.concat("

        \n") return buf end def format_anchor(start, num) return format('?query=%s;start=%d;num=%d;sort=%s;order=%s', CGI::escape(@query), start, num, _(@sort), _(@order)) end def format_link(label, start, num) return format('%s ', _(@cgi.script_name ? @cgi.script_name : ""), format_anchor(start, num), _(label)) end def create_search_options options = { "properties" => [ "title", "date", 'last_modified' ], "need_summary" => true, "summary_nchars" => 150, "start_no" => @start, "num_items" => @num } options['properties'] << 'user' if @conf['rast.with_user_name'] if SORT_PROPERTIES.include?(@sort) options["sort_method"] = Rast::SORT_METHOD_PROPERTY options["sort_property"] = @sort end if @order == "asc" options["sort_order"] = Rast::SORT_ORDER_ASCENDING else options["sort_order"] = Rast::SORT_ORDER_DESCENDING end return options end def format_options(options, value) return options.collect { |val, label| if val == value "" else "" end }.join("\n") end def format_form @num_options = NUM_OPTIONS.collect { |n| if n == @num "" else "" end }.join("\n") @sort_options = format_options(SORT_OPTIONS, @sort) @order_options = format_options(ORDER_OPTIONS, @order) end def _(str) CGI::escapeHTML(str) end def convert(str) @conf.to_native(str) end end end begin @cgi = CGI::new if ::TDiary::Config.instance_method(:initialize).arity != 0 # for tDiary 2.1 or later conf = ::TDiary::Config::new(@cgi) else # for tDiary 2.0 or earlier conf = ::TDiary::Config::new end tdiary = TDiary::TDiaryRast::new( @cgi, 'rast.rhtml', conf ) head = { 'type' => 'text/html', 'Vary' => 'User-Agent' } if @cgi.mobile_agent? then body = conf.to_mobile( tdiary.eval_rhtml( 'i.' ) ) head['charset'] = conf.mobile_encoding head['Content-Length'] = body.size.to_s else if @cgi['type'] == 'rss' head['type'] = "application/xml; charset=#{conf.encoding}" body = tdiary.eval_rxml else body = tdiary.eval_rhtml end head['charset'] = conf.encoding head['Content-Length'] = body.size.to_s head['Pragma'] = 'no-cache' head['Cache-Control'] = 'no-cache' end print @cgi.header( head ) print body rescue Exception if @cgi then print @cgi.header( 'type' => 'text/plain' ) else print "Content-Type: text/plain\n\n" end puts "#$! (#{$!.class})" puts "" puts $@.join( "\n" ) end tdiary-contrib-3.2.2/util/rast-search/rast.rhtml000066400000000000000000000032501213632744000216640ustar00rootroot00000000000000<%# rast.rhtml $Revision: 1.7.2.1 $ %>
        <%%=navi_user%>

        <%= CGI::escapeHTML( @conf.html_title ) %> [全文検索]

        検索方法

        並べ替え: 表示件数:

        <% if @msg %>

        <%= @msg %>

        <% else %>

        <%= _(@conf.to_native(@query)) %> の検索結果 <%= @result.hit_count %> 件中 <%= @start + 1 %> - <%= @start + @result.items.length %> 件目 (<%= @secs %> 秒)

        <% if @result.hit_count > @num %> <%= format_links(@result) %> <% end %> <% for item in @result.items %> <% format_result_item(item) %>

        <%= _(@conf.to_native(@title)) %>

        <%= @conf.to_native(@summary) %>

        <%= @conf.comment_anchor %>  (スコア:<%= item.score %>)

        <% end %> <% if @result.hit_count > @num %> <%= format_links(@result) %> <% end %> <% end %> tdiary-contrib-3.2.2/util/rast-search/rast.rxml000066400000000000000000000021051213632744000215160ustar00rootroot00000000000000"?> <%= _( @conf.html_title ) %> [全文検索]: <%= _(@query) %> <%= @conf.base_url.sub(%r|/[^/]*$|, '/') %><%= _(@cgi.script_name ? File.basename(@cgi.script_name) : "") %><%= format_anchor(@start, @num) %> Rast 検索: <%= _(@query) %> ja-JP <%= @result.hit_count %> <%= @start + 1 %> <%= @num %> <% for item in @result.items %> <% format_result_item(item) %> <%= _(@conf.to_native(@title)) %> <%= @conf.base_url %><%= @plugin.anchor(@date) %> <%= _(CGI.rfc1123_date(Time.parse(@last_modified))) %> <%= @conf.to_native(@summary) %> <% end %> tdiary-contrib-3.2.2/util/section_link/000077500000000000000000000000001213632744000201105ustar00rootroot00000000000000tdiary-contrib-3.2.2/util/section_link/README000066400000000000000000000013011213632744000207630ustar00rootroot00000000000000はてなダイアリーの「日記モード・見出し別ページ」のように、「1見出しが1ページになる日記形式、日付ごとにコメント・トラックバックを表示」になるようにします。 * tdiary以下のファイル3つ:tdiary以下に入れます(wikiとtdiary記法に対応しています) * misc/plugin/section_link.rb を設定画面から有効にします * mod_rewriteを使って拡張子を書き換えているひとは、misc/plugin/section_link_anchor.rbも有効にします ** mod_rewriteを書き換えます RewriteEngine on RewriteRule ^([0-9\-]+)p?([0-9]*)\.html$ ?date=$1§ion=$2 [L] tdiary-contrib-3.2.2/util/section_link/misc/000077500000000000000000000000001213632744000210435ustar00rootroot00000000000000tdiary-contrib-3.2.2/util/section_link/misc/plugin/000077500000000000000000000000001213632744000223415ustar00rootroot00000000000000tdiary-contrib-3.2.2/util/section_link/misc/plugin/section_link.rb000066400000000000000000000032131213632744000253460ustar00rootroot00000000000000# Copyright (C) 2011, KADO Masanori # You can redistribute it and/or modify it under GPL. # # section_link.rb # - enables section link and shows section title # - depends on: # - tdiary/tdiary_day_ext.rb # - tdiary/tdiaryext_style.rb # - tdiary/wikiext_style.rb alias :_orig_subtitle_link :subtitle_link def subtitle_link( date, index, subtitle ) if @cgi.params['section'].join('') != '' index = @cgi.params['section'][0] end r = _orig_subtitle_link( date, index, subtitle ) r.gsub(/#p(\d+)/){"§ion=#{$1}"} end alias :_orig_title_tag :title_tag def title_tag if @cgi.params['section'].join('') != '' and @mode == 'day' and diary = @diaries[@date.strftime('%Y%m%d')] sec = [] diary.each_section do |s| sec << s end site_title = " - #{_orig_title_tag.gsub( /<.*?>/, '')}" title = sec[@cgi.params['section'][0].to_i - 1].stripped_subtitle_to_html return "#{apply_plugin(title, true).gsub(/[\r\n]/, '')}#{h site_title }" else _orig_title_tag end end if @cgi.params["section"].join('') != "" add_section_leave_proc do diary = @diaries[@date.strftime("%Y%m%d")] i = 1 sections = [] diary.each_section do |s| unless i == @cgi.params["section"][0].to_i sections << [i, s] end i += 1 end unless sections.empty? "
        \n
          \n" + sections.map{|i, s| [i, my(@date.strftime("%Y%m%d") + "p" + sprintf("%02d", i), apply_plugin(s.stripped_subtitle_to_html, true))] }.map{|i, s| "
        1. #{s}
        2. " }.join("\n") + "\n
        \n" end end end # Local Variables: # mode: ruby # indent-tabs-mode: t # tab-width: 3 # ruby-indent-level: 3 # End: # vim: ts=3 tdiary-contrib-3.2.2/util/section_link/misc/plugin/section_link_anchor.rb000066400000000000000000000013041213632744000266770ustar00rootroot00000000000000# Copyright (C) 2011, KADO Masanori # You can redistribute it and/or modify it under GPL. # # section_link_anchor.rb # - enables section link with mod_rewrite # - depends on section_link.rb # # sample .htaccess: # # RewriteEngine on # RewriteRule ^([0-9\-]+)p?([0-9]*)\.html$ ?date=$1§ion=$2 [L] # def anchor( s ) if /^([\-\d]+)#?([pct]\d*)?$/ =~ s then if $2 then s1 = $1 s2 = $2 if $2 =~ /^p/ "#{s1}p#{s2.gsub(/p/, '')}.html" else "#{s1}.html##{s2}" end else "#$1.html" end else "" end end # Local Variables: # mode: ruby # indent-tabs-mode: t # tab-width: 3 # ruby-indent-level: 3 # End: # vim: ts=3 tdiary-contrib-3.2.2/util/section_link/tdiary/000077500000000000000000000000001213632744000214045ustar00rootroot00000000000000tdiary-contrib-3.2.2/util/section_link/tdiary/tdiary_day_ext.rb000066400000000000000000000006731213632744000247500ustar00rootroot00000000000000# Copyright (C) 2011, KADO Masanori # You can redistribute it and/or modify it under GPL. module TDiary class TDiaryDay alias :_orig_eval_rhtml :eval_rhtml def eval_rhtml if @cgi.params['section'].join('') != "" @diary.section_no = @cgi.params['section'][0] end _orig_eval_rhtml end end end # Local Variables: # mode: ruby # indent-tabs-mode: t # tab-width: 3 # ruby-indent-level: 3 # End: # vim: ts=3 tdiary-contrib-3.2.2/util/section_link/tdiary/tdiaryext_style.rb000066400000000000000000000012731213632744000251710ustar00rootroot00000000000000# Copyright (C) 2011, KADO Masanori # You can redistribute it and/or modify it under GPL. require 'tdiary/tdiary_day_ext' module TDiary class TdiaryextDiary; end class TdiaryDiary attr_accessor :section_no alias :_orig_to_html4 :to_html4 def to_html4( opt ) if @section_no idx = @section_no.to_i @sections = [@sections[idx - 1]] end _orig_to_html4 opt end alias :_orig_to_chtml :to_chtml def to_chtml( opt ) if @section_no idx = @section_no.to_i @sections = [@sections[idx - 1]] end _orig_to_chtml opt end end end # Local Variables: # mode: ruby # indent-tabs-mode: t # tab-width: 3 # ruby-indent-level: 3 # End: # vim: ts=3 tdiary-contrib-3.2.2/util/section_link/tdiary/wikiext_style.rb000066400000000000000000000013311213632744000246330ustar00rootroot00000000000000# Copyright (C) 2011, KADO Masanori # You can redistribute it and/or modify it under GPL. require 'tdiary/tdiary_day_ext' module TDiary class WikiextDiary; end class WikiDiary attr_accessor :section_no alias :_orig_to_html4 :to_html4 def to_html4( opt ) if @section_no idx = @section_no.to_i return @sections[idx - 1].html4( date, idx, opt ) end _orig_to_html4 opt end alias :_orig_to_chtml :to_chtml def to_chtml( opt ) if @section_no idx = @section_no.to_i return @sections[idx - 1].html4( date, idx, opt ) end _orig_to_chtml opt end end end # Local Variables: # mode: ruby # indent-tabs-mode: t # tab-width: 3 # ruby-indent-level: 3 # End: # vim: ts=3 tdiary-contrib-3.2.2/util/tdiary-for-ruby1.9/000077500000000000000000000000001213632744000207165ustar00rootroot00000000000000tdiary-contrib-3.2.2/util/tdiary-for-ruby1.9/compatible.rb000066400000000000000000000036331213632744000233670ustar00rootroot00000000000000# = for Ruby1.9.0 compatible = # # == 前提条件 == # # * Ruby1.9 の場合は --encoding=Binary オプションで動作させること # -------------------------------------------------------- # 汎用的な設定 # -------------------------------------------------------- # for Ruby1.9.0 unless "".respond_to?('to_a') class String def to_a [ self ] end end end unless "".respond_to?('each') class String alias each each_line end end # Ruby1.9では String が Enumerable ではなくなった class String def method_missing(name, *args, &block) each_line.__send__(name, *args, &block) end end # for Ruby1.8.X unless "".respond_to?('force_encoding') class String def force_encoding(encoding) self end end end unless "".respond_to?('bytesize') class String alias bytesize size end end unless "".respond_to?('ord') class String def ord self[0] end end class Integer def ord self end end end # -------------------------------------------------------- # tDiary 用の設定 # -------------------------------------------------------- # Ruby1.9でNKF::nkfを呼ぶと文字列のencodingが変わってしまう。 # そのため、encodingがBinaryの環境で動かすと # "character encodings differ" エラーとなる。 begin require 'nkf' module NKF alias :_nkf :nkf def nkf(option, src) r = _nkf(option, src) r.force_encoding('Binary') end module_function :nkf, :_nkf end rescue end # 日本語を含むツッコミを入れると diary.last_modified が String になる (原因不明) # (PStore 保存前は Time だが, 保存後に String となる) # 暫定的に String だったら Time へ変換する module TDiary class WikiDiary def last_modified if @last_modified.instance_of? String @last_modified = Time.at(0) end @last_modified end end end tdiary-contrib-3.2.2/util/tdiary-for-ruby1.9/tdiary-2.2.0.patch000066400000000000000000000075351213632744000237020ustar00rootroot00000000000000Index: update.rb =================================================================== --- update.rb (revision 97) +++ update.rb (working copy) @@ -5,7 +5,7 @@ # Copyright (C) 2001-2003, TADA Tadashi # You can redistribute it and/or modify it under GPL2. # -BEGIN { $defout.binmode } +BEGIN { $stdout.binmode } $KCODE = 'n' begin Index: misc/lib/hikidoc.rb =================================================================== --- misc/lib/hikidoc.rb (revision 97) +++ misc/lib/hikidoc.rb (working copy) @@ -476,7 +476,7 @@ def escape_meta_char( text ) text.gsub( META_CHAR_RE ) do |s| - '&#x%x;' % s[1] + '&#x%x;' % s[1].ord end end Index: misc/plugin/amazon.rb =================================================================== --- misc/plugin/amazon.rb (revision 97) +++ misc/plugin/amazon.rb (working copy) @@ -205,6 +205,7 @@ xml = amazon_call_ecs( asin, id_type ) File::open( "#{cache}/#{asin}.xml", 'wb' ) {|f| f.write( xml )} end + xml.force_encoding('UTF-8') doc = REXML::Document::new( xml ).root item = doc.elements.to_a( '*/Item' )[0] if pos == 'detail' then Index: tdiary.rb =================================================================== --- tdiary.rb (revision 97) +++ tdiary.rb (working copy) @@ -11,6 +11,7 @@ $:.insert( 1, File::dirname( __FILE__ ) + '/misc/lib' ) +require 'compatible' require 'cgi' require 'uri' begin @@ -466,6 +467,7 @@ load instance_variables.each do |v| + v = v.to_s v.sub!( /@/, '' ) instance_eval( <<-SRC def #{v} @@ -631,11 +633,10 @@ cgi_conf.untaint unless @secure def_vars = "" variables.each do |var| def_vars << "#{var} = nil\n" end - eval( def_vars ) + extend_vars = 'variables.each do |var| eval "@#{var} = #{var} if #{var} != nil" end' Safe::safe( @secure ? 4 : 1 ) do - eval( cgi_conf, binding, "(TDiary::Config#cgi_conf)", 1 ) + eval( def_vars + cgi_conf + extend_vars, binding, "(TDiary::Config#cgi_conf)", 1 ) end - variables.each do |var| eval "@#{var} = #{var} if #{var} != nil" end rescue IOError, Errno::ENOENT end end Index: plugin/ja/05referer.rb =================================================================== --- plugin/ja/05referer.rb (revision 97) +++ plugin/ja/05referer.rb (working copy) @@ -31,7 +31,7 @@

        既存設定はこちら

        #{label_referer_table}

        - #{"

        リンク元リストのURLを、特定の文字列に変換する対応表を指定できます。1件につき、URLと表示文字列を空白で区切って指定します。正規表現が使えるので、URL中に現れた「(~)」は、置換文字列中で「\\1」のような「\数字」で利用できます。

        " unless @conf.mobile_agent?} + #{"

        リンク元リストのURLを、特定の文字列に変換する対応表を指定できます。1件につき、URLと表示文字列を空白で区切って指定します。正規表現が使えるので、URL中に現れた「(~)」は、置換文字列中で「\\\\1」のような「\\数字」で利用できます。

        " unless @conf.mobile_agent?}

        既存設定はこちら

        HTML Index: index.rb =================================================================== --- index.rb (revision 97) +++ index.rb (working copy) @@ -5,7 +5,7 @@ # Copyright (C) 2001-2006, TADA Tadashi # You can redistribute it and/or modify it under GPL2. # -BEGIN { $defout.binmode } +BEGIN { $stdout.binmode } $KCODE = 'n' begin tdiary-contrib-3.2.2/util/tdiary-for-ruby1.9/tdiary-2.3.1.patch000066400000000000000000000173611213632744000237020ustar00rootroot00000000000000=== index.rb ================================================================== --- index.rb (revision 27329) +++ index.rb (local) @@ -1,11 +1,11 @@ #!/usr/bin/env ruby # -# index.rb $Revision: 1.35 $ +# index.rb # -# Copyright (C) 2001-2006, TADA Tadashi +# Copyright (C) 2001-2008, TADA Tadashi # You can redistribute it and/or modify it under GPL2. # -BEGIN { $defout.binmode } +BEGIN { $stdout.binmode } $KCODE = 'n' begin @@ -70,7 +70,7 @@ if @cgi.mobile_agent? then body = conf.to_mobile( tdiary.eval_rhtml( 'i.' ) ) head['charset'] = conf.mobile_encoding - head['Content-Length'] = body.size.to_s + head['Content-Length'] = body.bytesize.to_s else require 'digest/md5' body = tdiary.eval_rhtml @@ -80,7 +80,7 @@ body = '' else head['charset'] = conf.encoding - head['Content-Length'] = body.size.to_s + head['Content-Length'] = body.bytesize.to_s end head['Pragma'] = 'no-cache' head['Cache-Control'] = 'no-cache' === plugin/00default.rb ================================================================== --- plugin/00default.rb (revision 27329) +++ plugin/00default.rb (local) @@ -697,7 +697,7 @@ mail_header = (@conf['comment_mail.header'] || '').dup mail_header << ":#{@conf.date_format}" unless /%[a-zA-Z%]/ =~ mail_header mail_header = @date.strftime( mail_header ) - mail_header = comment_mail_mime( @conf.to_mail( mail_header ) ).join( "\n " ) if /[\x80-\xff]/ =~ mail_header + mail_header = comment_mail_mime( @conf.to_mail( mail_header ) ).join( "\n " ) rmail = '' begin === plugin/05referer.rb ================================================================== --- plugin/05referer.rb (revision 27329) +++ plugin/05referer.rb (local) @@ -159,7 +159,7 @@ def referer_add_to_diary( diary, body ) return unless body - body.each do |r| + body.each_line do |r| count, ref = r.chomp.split( / /, 2 ) next unless ref diary.add_referer( ref.chomp, count.to_i ) === plugin/ja/05referer.rb ================================================================== --- plugin/ja/05referer.rb (revision 27329) +++ plugin/ja/05referer.rb (local) @@ -31,7 +31,7 @@

        既存設定はこちら

        #{label_referer_table}

        - #{"

        リンク元リストのURLを、特定の文字列に変換する対応表を指定できます。1件につき、URLと表示文字列を空白で区切って指定します。正規表現が使えるので、URL中に現れた「(〜)」は、置換文字列中で「\\1」のような「\数字」で利用できます。

        " unless @conf.mobile_agent?} + #{"

        リンク元リストのURLを、特定の文字列に変換する対応表を指定できます。1件につき、URLと表示文字列を空白で区切って指定します。正規表現が使えるので、URL中に現れた「(〜)」は、置換文字列中で「\\\\1」のような「\\数字」で利用できます。

        " unless @conf.mobile_agent?}

        既存設定はこちら

        HTML === tdiary/defaultio.rb ================================================================== --- tdiary/defaultio.rb (revision 27329) +++ tdiary/defaultio.rb (local) @@ -13,7 +13,7 @@ header, body = data.split( /\r?\n\r?\n/, 2 ) headers = {} if header then - header.each do |l| + header.each_line do |l| l.chomp! key, val = l.scan( /([^:]*):\s*(.*)/ )[0] headers[key] = val ? val.chomp : nil === tdiary/tdiary_style.rb ================================================================== --- tdiary/tdiary_style.rb (revision 27329) +++ tdiary/tdiary_style.rb (local) @@ -22,7 +22,7 @@ if lines.size > 1 then if /^<#{section.body.collect{|l|l.chomp.sub( /^[  ]/u, '')}.join( "

        \n

        " )}

        \n] + r << %Q[

        #{section.body.collect{|l|l.chomp.sub( /^[ ]/u, '')}.join( "

        \n

        " )}

        \n] else r << %Q[

        <%= subtitle_proc( Time::at( #{date.to_i} ), nil ) %>] - r << %Q[#{section.body.collect{|l|l.chomp.sub( /^[  ]/u, '' )}.join( "

        \n

        " )}

        ] + r << %Q[#{section.body.collect{|l|l.chomp.sub( /^[ ]/u, '' )}.join( "

        \n

        " )}

        ] end r << %Q[<%= section_leave_proc( Time::at( #{date.to_i} ) ) %>\n] r << %Q[
        ] @@ -211,10 +211,10 @@ if /^#{section.body.collect{|l|l.chomp.sub( /^[  ]/u, '' )}.join( "

        \n

        " )}

        \n] + r << %Q[

        #{section.body.collect{|l|l.chomp.sub( /^[ ]/u, '' )}.join( "

        \n

        " )}

        \n] else r << %Q[

        <%= subtitle_proc( Time::at( #{date.to_i} ), nil ) %>] - r << %Q[#{section.body.collect{|l|l.chomp.sub( /^[  ]/u, '' )}.join( "

        \n

        " )}

        \n] + r << %Q[#{section.body.collect{|l|l.chomp.sub( /^[ ]/u, '' )}.join( "

        \n

        " )}

        \n] end r << %Q[<%= section_leave_proc( Time::at( #{date.to_i} ) ) %>\n] end === tdiary.rb ================================================================== --- tdiary.rb (revision 27329) +++ tdiary.rb (local) @@ -6,10 +6,11 @@ You can redistribute it and/or modify it under GPL2. =end -TDIARY_VERSION = '2.3.1' +TDIARY_VERSION = '2.3.1.20081115' $:.insert( 1, File::dirname( __FILE__ ) + '/misc/lib' ) +require 'compatible' require 'cgi' require 'uri' begin @@ -460,6 +461,7 @@ load instance_variables.each do |v| + v = v.to_s v.sub!( /@/, '' ) instance_eval( <<-SRC def #{v} @@ -660,11 +662,10 @@ cgi_conf.untaint unless @secure def_vars = "" variables.each do |var| def_vars << "#{var} = nil\n" end - eval( def_vars ) + extend_vars = 'variables.each do |var| eval "@#{ var} = #{var} if #{var} != nil" end' Safe::safe( @secure ? 4 : 1 ) do - eval( cgi_conf, binding, "(TDiary::Config#cgi_conf)", 1 ) + eval( def_vars + cgi_conf + extend_vars, binding, "(TDiary::Config#cgi_conf)", 1 ) end - variables.each do |var| eval "@#{var} = #{var} if #{var} != nil" end rescue IOError, Errno::ENOENT end end @@ -776,6 +777,7 @@ @subtitle_procs.taint @section_leave_procs.taint return Safe::safe( secure ? 4 : 1 ) do + src.force_encoding('UTF-8') eval( src, binding, "(TDiary::Plugin#eval_src)", 1 ) end end === update.rb ================================================================== --- update.rb (revision 27329) +++ update.rb (local) @@ -1,11 +1,11 @@ #!/usr/bin/env ruby # -# update.rb $Revision: 1.22 $ +# update.rb # -# Copyright (C) 2001-2003, TADA Tadashi +# Copyright (C) 2001-2008, TADA Tadashi # You can redistribute it and/or modify it under GPL2. # -BEGIN { $defout.binmode } +BEGIN { $stdout.binmode } $KCODE = 'n' begin @@ -55,7 +55,7 @@ 'status' => '200 OK', 'type' => 'text/html', 'charset' => conf.mobile_encoding, - 'Content-Length' => body.size.to_s, + 'Content-Length' => body.bytesize.to_s, 'Vary' => 'User-Agent' ) else @@ -64,7 +64,7 @@ 'status' => '200 OK', 'type' => 'text/html', 'charset' => conf.encoding, - 'Content-Length' => body.size.to_s, + 'Content-Length' => body.bytesize.to_s, 'Vary' => 'User-Agent' ) end tdiary-contrib-3.2.2/util/tdiary-grep/000077500000000000000000000000001213632744000176565ustar00rootroot00000000000000tdiary-contrib-3.2.2/util/tdiary-grep/README000066400000000000000000000004441213632744000205400ustar00rootroot00000000000000■■このツールは最新のtDiaryに追従していません。 ■■検索機能はプラグインとして実装されるようになったため、 ■■同等の機能はplugin/search-default.rbで実現しています。 ■■このツールは近々削除する予定です。 tdiary-contrib-3.2.2/util/tdiary-grep/grep.rb000066400000000000000000000227671213632744000211560ustar00rootroot00000000000000#!/usr/bin/env ruby # -*- coding: utf-8 -*- # # $Id$ # # Copyright (C) 2003,2004 Minero Aoki # # This program is free software. # You can distribute/modify this program under the terms of # the GNU LGPL, Lesser General Public License version 2.1. # TDIARY_DATA_PATH = nil CGI_URL = './' LOGGING = true DEBUG = $DEBUG # # HTML Templates # def unindent(str, n) str.gsub(/^ {0,#{n}}/, '') end HEADER = unindent(<<-'EOS', 2) tDiary Grep EOS FOOTER = unindent(<<'EOS', 2) EOS SEARCH_FORM = unindent(<<"EOS", 2)

        % fgrep -i '' */*.td2

        EOS SEARCH_RESULT = unindent(<<-'EOS', 2) + SEARCH_FORM
          % fgrep -i '<%= patterns.map {|re| escape(re.source) }.join(' ') %>' */*.td2
          <%
              toomanyhits = match_sections(patterns) {|section|
          %><%= format_date(section.date)
          %>: <%= escape(section.short_text) %>
          <%
              }
          %><%= toomanyhits ? 'too many hits.' : ''
          %>
        EOS SEARCH_ERROR = unindent(<<'EOS', 2) + SEARCH_FORM
          % fgrep -i '<%= escape(query) %>' */*.td2
          <%= escape(reason) %>.
          
        EOS HISTORY = unindent(<<"EOS", 2)
          <%
              cmd = ['ls', 'cd .', 'cvsdiffl', 'ps -ef', 'w', './configure --help',
                     'date', 'make', 'echo $?', 'vi log', 'jobs', 'cvs up', 'who']
              recent_queries.sort_by {|t,q| t }.each do |time, query|
                n = rand(100)
                if n < cmd.size
          %><%= time.to_i - 10 %>: <%= cmd[n] %>
          <%    end
          %><%= time.to_i %>: fgrep -i '<%= escape(query) %>' */*.td2
          <%
              end
          %>
        #{SEARCH_FORM} EOS # # Load Libraries # require 'cgi' class CGI def valid?(name) self.params[name] and self.params[name][0] end end require 'erb' require 'uri' # borrowed from tdiary require 'nkf' begin require 'uconv' def Uconv.unknown_unicode_handler(unicode) if unicode == 0xff5e "~" else raise Uconv::Error end end def to_euc(str) begin Uconv.u8toeuc(str) rescue Uconv::Error NKF::nkf('-w -m0', str) end end rescue LoadError def to_euc(str) NKF::nkf('-w -m0', str) end end # # Main # class TDiaryGrepError < StandardError; end class WrongQuery < TDiaryGrepError; end class InvalidTDiaryFormat < TDiaryGrepError; end class ConfigError < TDiaryGrepError; end Z_SPACE = " " # zen-kaku space BEGIN { $stdout.binmode } def main cgi = CGI.new html = '

        error

        ' begin html = generate_page(cgi) ensure send_html cgi, html end exit 0 end def generate_page(cgi) query = nil begin begin if LOGGING and File.file?(query_log()) and cgi.valid?('history') return history_page() elsif not cgi.valid?('q') return search_form_page() else query = [cgi.params['q']].compact.flatten.join(' ') html = search_result_page(setup_patterns(query)) save_query(query, query_log()) if LOGGING return html end rescue WrongQuery => err return search_error_page(query, err.message) end rescue Exception => err html = '' html << HEADER html << "
        \n"
            html << 'q=' << escape(query) << "\n" if query
            html << escape(err.class.name) << "\n" if DEBUG
            html << escape(err.message) << "\n"
            html << err.backtrace.map {|i| escape(i) }.join("\n") if DEBUG
            html << "
        \n" html << FOOTER return html end end def send_html(cgi, html) print cgi.header('status' => '200 OK', 'type' => 'text/html', 'charset' => 'UTF-8', 'Content-Length' => html.length.to_s, 'Cache-Control' => 'no-cache', 'Pragma' => 'no-cache') print html unless cgi.request_method == 'HEAD' end def setup_patterns(query) patterns = split_string(query).map {|pat| check_pattern pat /#{Regexp.quote(pat)}/iu } raise WrongQuery, 'no pattern' if patterns.empty? raise WrongQuery, 'too many sub patterns' if patterns.length > 8 patterns end def check_pattern(pat) raise WrongQuery, 'no pattern' unless pat raise WrongQuery, 'empty pattern' if pat.empty? raise WrongQuery, "pattern too short: #{pat}" if pat.length < 2 raise WrongQuery, 'pattern too long' if pat.length > 128 end def split_string(str) str.split(/[\s#{Z_SPACE}]+/ou).reject {|w| w.empty? } end def save_query(query, file) File.open(file, 'a') {|f| begin f.flock(File::LOCK_EX) f.puts "#{Time.now.to_i}: #{query.dump}" ensure f.flock(File::LOCK_UN) end } end def read_query_logs(file) File.open(file) {|f| begin f.flock(File::LOCK_SH) return f.readlines ensure f.flock(File::LOCK_UN) end } end def query_log "#{tdiary_data_path()}/grep.log" end # # eRuby Dispatchers and Helper Routines # def search_form_page patterns = [] ERB.new(HEADER + SEARCH_FORM + FOOTER).result(binding()) end def search_result_page(patterns) ERB.new(HEADER + SEARCH_RESULT + FOOTER).result(binding()) end def search_error_page(query, reason) ERB.new(HEADER + SEARCH_ERROR + FOOTER).result(binding()) end def history_page patterns = [] ERB.new(HEADER + HISTORY + FOOTER).result(binding()) end N_SHOW_QUERY_MAX = 20 def recent_queries return unless File.file?(query_log()) read_query_logs(query_log()).reverse[0, N_SHOW_QUERY_MAX].map {|line| time, q = *line.split(/:/, 2) [Time.at(time.to_i), eval(q)] } end def format_time(time) sprintf('%04d-%02d-%02d %02d:%02d:%02d', time.year, time.month, time.day, time.hour, time.min, time.sec) end def format_date(ymd) y, m, d = /\A(\d{4})(\d{2})(\d{2})/.match(ymd).captures "#{y}-#{m}-#{d}" end TOO_MANY_HITS = 50 def match_sections(patterns) hit = 0 match_sections0(patterns) do |section| yield section hit += 1 return true if hit > TOO_MANY_HITS end false end def match_sections0(patterns) foreach_data_file(tdiary_data_path()) do |path| read_diaries(path).sort_by {|diary| diary.date }.reverse_each do |diary| diary.each_section do |section| yield section if patterns.all? {|re| re =~ section.source } end end end end # # tDiary Implementation Dependent # def foreach_data_file(data_path, &block) Dir.glob("#{data_path}/[0-9]*/*.td2").sort.reverse_each(&block) end def read_diaries(path) diaries = [] File.open(path, :encoding => 'UTF-8') {|f| f.each('') do |header| diaries.push Diary.parse(header, f.gets("\n.\n").chomp(".\n")) end } diaries end class Diary def Diary.parse(header, body) ymd = header.slice(/^Date:\s*(\d{4}\d{2}\d{2})/, 1) or raise "unexpected tdiary format: Date=nil:\n#{header.strip}" format = header.slice(/^Format:\s*(\S+)/, 1) or raise "unexpected tdiary format: Format=nil:\n#{header.strip}" visible = case header.slice(/^Visible:\s*(\S+)/, 1) when 'true' then true when 'false' then false when nil then true else raise 'must not happen (parsing Visible:)' end new(ymd, visible, split_sections(body, format)) end SPLITTER = { 'tdiary' => /\n\n/, 'rd' => /^=(?!=)/, 'wiki' => /^!/, 'blog' => /\n\n/, 'blogrd' => /^=(?!=)/, 'blogwiki' => /^!/ } def Diary.split_sections(diary, format) re = SPLITTER[format.downcase] or raise ArgumentError, "unknown diary format: #{format}" diary.strip.split(re) end private_class_method :split_sections def initialize(ymd, visible, section_texts) @date = ymd @visible = visible @sections = [] section_texts.each_with_index do |src, idx| @sections.push DiarySection.new(self, idx + 1, src) end end attr_reader :date def each_section(&block) return unless @visible @sections.each(&block) end end class DiarySection def initialize(day, num, src) @day = day @number = num @source = src end def inspect "\#<#{self.class} #{@day.date}.#{@number}>" end def date @day.date end def format @day.format end attr_reader :source def url "#{CGI_URL}?date=#{@day.date}\#p#{sprintf('%02d', @number)}" end def short_text title, body = @source.split(/\n/, 2) sprintf('%-30s | %s', title.to_s.strip, remove_tags(body.to_s).gsub(/[\s#{Z_SPACE}]+/ou, ' ').slice(/\A.{0,60}/mu)) end private def remove_tags(str) str.gsub(/<.*?>|\(\([{|'<]|[>}|']\)\)|\(\(-(?m).*?(?-m)-\)\)/, '') end end @tdiary_data_path = nil def tdiary_data_path @tdiary_data_path ||= (TDIARY_DATA_PATH || data_path_config()) end def data_path_config tdiary_conf().slice(/^\s*@data_path\s*=\s*(['"])(.*?)\1/, 2) or raise ConfigError, 'cannot get tDiary @data_path' end @tdiary_conf = nil def tdiary_conf @tdiary_conf ||= File.read("#{File.dirname(__FILE__)}/tdiary.conf", :encoding => 'UTF-8') end # # Utils # ESC = { '&' => '&', '<' => '<', '>' => '>', '"' => '"' } def escape(str) str.gsub(/[&"<>]/) {|s| ESC[s] } end def escape_url(u) escape(URI.encode(u)) end main tdiary-contrib-3.2.2/util/tdiary-mode/000077500000000000000000000000001213632744000176455ustar00rootroot00000000000000tdiary-contrib-3.2.2/util/tdiary-mode/http.el000066400000000000000000000114111213632744000211440ustar00rootroot00000000000000;;; http.el -- utils for HTTP ;; Copyright (C) 2002 Junichiro Kita ;; Author: Junichiro Kita ;; $Id: http.el,v 1.3 2005/07/20 08:39:56 tadatadashi Exp $ ;; ;; This program is free software; you can redistribute it and/or ;; modify it under the terms of the GNU General Public License as ;; published by the Free Software Foundation; either version 2, or (at ;; your option) any later version. ;; This program is distributed in the hope that it will be useful, but ;; WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;; General Public License for more details. ;; You should have received a copy of the GNU General Public License ;; along with this program; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, ;; Boston, MA 02111-1307, USA. ;;; Commentary: ;;; Code: (require 'pces) (defvar http-proxy-server nil "Proxy server for HTTP.") (defvar http-proxy-port nil "Proxy port for HTTP.") (defvar http-timeout 10 "Timeout for HTTP.") ;; derived from url.el (defconst http-url-unreserved-chars '( ?a ?b ?c ?d ?e ?f ?g ?h ?i ?j ?k ?l ?m ?n ?o ?p ?q ?r ?s ?t ?u ?v ?w ?x ?y ?z ?A ?B ?C ?D ?E ?F ?G ?H ?I ?J ?K ?L ?M ?N ?O ?P ?Q ?R ?S ?T ?U ?V ?W ?X ?Y ?Z ?0 ?1 ?2 ?3 ?4 ?5 ?6 ?7 ?8 ?9 ?$ ?- ?_ ?. ?! ?~ ?* ?' ?\( ?\) ?,) "A list of characters that are _NOT_ reserve in the URL spec. This is taken from draft-fielding-url-syntax-02.txt - check your local internet drafts directory for a copy.") ;; derived from url.el (defun http-url-hexify-string (str coding) "Escape characters in a string. At first, encode STR using CODING, then url-hexify." (mapconcat (function (lambda (char) (if (not (memq char http-url-unreserved-chars)) (if (< char 16) (upcase (format "%%0%x" char)) (upcase (format "%%%x" char))) (char-to-string char)))) (encode-coding-string str coding) "")) (defvar http-fetch-terminator "" "content body end mark.") (defun http-fetch (url method &optional user pass data) "Fetch via HTTP. URL is a url to be POSTed. METHOD is 'get or 'post. USER and PASS must be a valid username and password, if required. DATA is an alist, each element is in the form of (FIELD . DATA). If no error, return a buffer which contains output from the web server. If error, return a cons cell (ERRCODE . DESCRIPTION)." (let (connection server port path buf str len) (string-match "^http://\\([^/:]+\\)\\(:\\([0-9]+\\)\\)?\\(/.*$\\)" url) (setq server (match-string 1 url) port (string-to-int (or (match-string 3 url) "80")) path (if http-proxy-server url (match-string 4 url))) (setq str (mapconcat '(lambda (x) (concat (car x) "=" (cdr x))) data "&")) (setq len (length str)) (save-excursion (setq buf (get-buffer-create (concat "*result from " server "*"))) (set-buffer buf) (erase-buffer) (setq connection (as-binary-process (open-network-stream (concat "*request to " server "*") buf (or http-proxy-server server) (or http-proxy-port port)))) (process-send-string connection (concat (if (eq method 'post) (concat "POST " path) (concat "GET " path (if (> len 0) (concat "?" str)))) " HTTP/1.0\r\n" (concat "Host: " server "\r\n") "Connection: close\r\n" "Referer: " url "\r\n" "Content-type: application/x-www-form-urlencoded\r\n" (if (and user pass) (concat "Authorization: Basic " (base64-encode-string (concat user ":" pass)) "\r\n")) (if (eq method 'post) (concat "Content-length: " (int-to-string len) "\r\n" "\r\n" str)) "\r\n")) (goto-char (point-min)) (while (not (search-forward http-fetch-terminator nil t)) (unless (accept-process-output connection http-timeout) (error "HTTP fetch: Connection timeout!")) (goto-char (point-min))) (goto-char (point-min)) (save-excursion (if (re-search-forward "HTTP/1.[01] \\([0-9][0-9][0-9]\\) \\(.*\\)" nil t) (let ((code (match-string 1)) (desc (match-string 2))) (cond ((equal code "200") buf) (t (cons code desc))))))))) (provide 'http) ;;; http.el ends here tdiary-contrib-3.2.2/util/tdiary-mode/tdiary-mode.el000066400000000000000000000467041213632744000224200ustar00rootroot00000000000000;;; tdiary-mode.el -- Major mode for tDiary editing -*- coding: utf-8 -*- ;; Copyright (C) 2002 Junichiro Kita ;; Author: Junichiro Kita ;; $Id: tdiary-mode.el,v 1.4 2005/08/19 08:36:43 tadatadashi Exp $ ;; ;; This program is free software; you can redistribute it and/or ;; modify it under the terms of the GNU General Public License as ;; published by the Free Software Foundation; either version 2, or (at ;; your option) any later version. ;; This program is distributed in the hope that it will be useful, but ;; WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;; General Public License for more details. ;; You should have received a copy of the GNU General Public License ;; along with this program; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, ;; Boston, MA 02111-1307, USA. ;;; Commentary: ;; usage: ;; ;; Put the following in your .emacs file: ;; ;; (setq tdiary-diary-list '(("my 1st diary" "http://example.com/tdiary/") ;; ("my 2nd diary" "http://example.com/tdiary2/"))) ;; (setq tdiary-text-directory (expand-file-name "~/path-to-saved-diary")) ;; (setq tdiary-browser-function 'browse-url) ;; (autoload 'tdiary-mode "tdiary-mode" nil t) ;; (autoload 'tdiary-new "tdiary-mode" nil t) ;; (autoload 'tdiary-new-diary "tdiary-mode" nil t) ;; (autoload 'tdiary-replace "tdiary-mode" nil t) ;; (add-to-list 'auto-mode-alist ;; '("\\.td$" . tdiary-mode)) ;; ;; You can use your own plugin completion, keybindings: ;; ;; (setq tdiary-plugin-definition ;; '( ;; ("STRONG" ("<%=STRONG %Q|" (p "str: ") "| %>")) ;; ("PRE" ("<%=PRE %Q|" (p "str: ") "| %>")) ;; ("CITE" ("<%=CITE %Q|" (p "str: ") "| %>")) ;; )) ;; ;; (add-hook 'tdiary-mode-hook ;; '(lambda () ;; (local-set-key "\C-i" 'tdiary-complete-plugin))) ;; ;; If you want to save username and password cache to file: ;; ;; (setq tdiary-passwd-file (expand-file-name "~/.tdiary-pass")) ;; ;; then, M-x tdiary-passwd-cache-save. !!DANGEROUS!! ;; ;; see http://kitaj.no-ip.com/rw-cgi.rb?cmd=view;name=tdiary-mode ;; ;; ToDo: ;; - find plugin definition automatically(needs modification for plugin) ;; - bug fix ;; ;;; Variable: (require 'http) (require 'poe) (require 'tempo) (defvar tdiary-diary-list nil "List of diary list. Each element looks like (NAME URL) or (NAME URL INDEX-RB UPDATE-RB).") (defvar tdiary-diary-name nil "Identifier for diary to be updated.") (defvar tdiary-diary-url nil "tDiary-mode updates this URL. URL should end with '/'.") (defvar tdiary-index-rb nil "Name of the 'index.rb'.") (defvar tdiary-update-rb "update.rb" "Name of the 'update.rb'.") (defvar tdiary-csrf-key nil "CSRF protection key.") (defvar tdiary-coding-system 'utf-8-dos) (defvar tdiary-title nil "Title of diary") (defvar tdiary-style-mode 'html-mode "Major mode to be used for tDiary editing.") (defvar tdiary-date nil "Date to be updated.") (defvar tdiary-edit-mode nil) (defvar tdiary-plugin-list nil "A List of pairs of a plugin name and its completing command. It is used in `tdiary-complete-plugin'.") (defvar tdiary-tempo-tags nil "Tempo tags for tDiary mode") (defvar tdiary-completion-finder "\\(\\(<\\|&\\|<%=\\).*\\)\\=" "Regexp used to find tags to complete.") (defvar tdiary-plugin-initial-definition '( ("my" ("<%=my %Q|" (p "a: ") "|, %Q|" (p "str: ") "| %>")) ("fn" ("<%=fn %Q|" (p "footnote: ") "| %>")) ) "Initial definition for tDiary tempo." ) (defvar tdiary-edit-mode-list '(("append") ("replace"))) (defvar tdiary-plugin-definition nil "A List of definitions for tDiary tempo. Each element looks like (NAME ELEMENTS). NAME is a string that contains the name of plugin, and ELEMENTS is a list of elements in the template. See tempo.info for details.") (defvar tdiary-complete-plugin-history nil "Minibuffer history list for `tdiary-complete-plugin'.") (defvar tdiary-passwd-file nil) (defvar tdiary-passwd-file-mode 384) ;; == 0600 (defvar tdiary-text-directory-mode 448) ;; == 0700 (defvar tdiary-passwd-cache nil "Cache for username and password.") (defvar tdiary-hour-offset 0 "Offset to current-time. `tdiary-today' returns (current-time + tdiary-hour-offset).") (defvar tdiary-text-suffix ".td") (defvar tdiary-text-directory nil "Directory where diary is stored.") (defvar tdiary-text-save-p nil "Flag for saving text. If non-nil, tdiary buffer is associated to a real file, named `tdiary-date' + `tdiary-text-suffix'.") (defvar tdiary-browser-function nil "Function to call browser. If non-nil, `tdiary-update' calls this function. The function is expected to accept only one argument(URL).") (defvar tdiary-mode-hook nil "Hook run when entering tDiary mode.") (defvar tdiary-init-file "~/.tdiary" "Init file for tDiary-mode.") ;(defvar tdiary-plugin-dir nil ; "Path to plugins. It must be a mounted file system.") ;(defvar tdiary-plugin-definition-regexp "^[ \t]*def[ \t]+\\(.+?\\)[ \t]*\\(?:$\\|;\\|([ \t]*\\(.*?\\)[ \t]*)\\)") ;;; Code: (defun tdiary-tempo-add-tag (def) (let* ((plugin (car def)) (element (cadr def)) (name (concat "tdiary-" plugin)) (completer (concat "<%=" plugin)) (doc (concat "Insert `" plugin "'")) (command (tempo-define-template name element completer doc 'tdiary-tempo-tags))) (add-to-list 'tdiary-plugin-list (list plugin command)))) (defun tdiary-tempo-define (l) (mapcar 'tdiary-tempo-add-tag l)) ;(defun tdiary-parse-plugin-args (args) ; (if (null args) ; nil ; (mapcar '(lambda (x) ; (let ((l (split-string x "[ \t]*=[ \t]*"))) ; (if (eq (length l) 1) ; (car l) ; l))) ; (split-string args "[ \t]*,[ \t]*")))) ;(defun tdiary-update-plugin-definition () ; (interactive) ; (let ((files (directory-files tdiary-plugin-dir t ".*\\.rb$" nil t)) ; (buf (generate-new-buffer "*update plugin*"))) ; (save-excursion ; (save-window-excursion ; (switch-to-buffer buf) ; (mapc 'insert-file-contents files) ; (setq tdiary-plugin-definition nil) ; (while (re-search-forward tdiary-plugin-definition-regexp nil t) ; (add-to-list 'tdiary-plugin-definition ; (list (match-string 1) ; (tdiary-parse-plugin-args (match-string 2))))) ; (kill-buffer buf))))) (defun tdiary-do-complete-plugin (&optional name) "Complete function for plugin." (let (command) (when (null name) (setq name (completing-read "plugin: " tdiary-plugin-list nil nil nil 'tdiary-complete-plugin-history))) (setq command (cadr (assoc name tdiary-plugin-list))) (when command (funcall command)))) ;; derived from tempo.el (defun tdiary-complete-plugin (&optional silent) "Look for a HTML tag or plugin and expand it. If there are no completable text, call `tdiary-do-complete-plugin'." (interactive "*") (let* ((collection (tempo-build-collection)) (match-info (tempo-find-match-string tempo-match-finder)) (match-string (car match-info)) (match-start (cdr match-info)) (exact (assoc match-string collection)) (compl (or (car exact) (and match-info (try-completion match-string collection))))) (if compl (delete-region match-start (point))) (cond ((or (null match-info) (null compl)) (tdiary-do-complete-plugin)) ((eq compl t) (tempo-insert-template (cdr (assoc match-string collection)) nil)) (t (if (setq exact (assoc compl collection)) (tempo-insert-template (cdr exact) nil) (insert compl) (or silent (ding)) (if tempo-show-completion-buffer (tempo-display-completions match-string collection))))))) (defun tdiary-today () (let* ((offset-second (* tdiary-hour-offset 60 60)) (now (current-time)) (high (nth 0 now)) (low (+ (nth 1 now) offset-second)) (micro (nth 2 now))) (setq high (+ high (/ low 65536)) low (% low 65536)) (when (< low 0) (setq high (1- high) low (+ low 65536))) (list high low micro))) (defun tdiary-read-username (url name) (let ((username (tdiary-passwd-cache-read-username url))) (or username (read-string (concat "User Name for '" name "': "))))) (defun tdiary-read-password (url name) (let ((password (tdiary-passwd-cache-read-password url))) (or password (read-passwd (concat "Password for '" name "': "))))) (defun tdiary-read-date (date) (while (not (string-match "[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]" (setq date (read-string "Date: " (or date (format-time-string "%Y%m%d" (tdiary-today))))))) nil) date) (defun tdiary-read-title (date) (read-string (concat "Title for " date ": ") tdiary-title)) (defun tdiary-read-mode (mode) (let ((default (caar tdiary-edit-mode-list))) (completing-read "Editing mode: " tdiary-edit-mode-list nil t (or mode default) nil default))) (defun tdiary-passwd-file-load () "Load password alist." (save-excursion (let ((buf (get-buffer-create "*tdiary-passwd-cache*"))) (when (and tdiary-passwd-file (file-readable-p tdiary-passwd-file)) (set-buffer buf) (insert-file-contents tdiary-passwd-file) (setq tdiary-passwd-cache (read buf))) (kill-buffer buf)))) (defun tdiary-passwd-file-save () "Save password alist. Dangerous!!!" (interactive) (save-excursion (let ((buf (get-buffer-create "*tdiary-passwd-cache*"))) (set-buffer buf) (erase-buffer) (prin1 tdiary-passwd-cache buf) (terpri buf) (when (and tdiary-passwd-file (file-writable-p tdiary-passwd-file)) (write-region (point-min) (point-max) tdiary-passwd-file) (set-file-modes tdiary-passwd-file tdiary-passwd-file-mode)) (kill-buffer buf)))) (defun tdiary-passwd-cache-clear (url) (setq tdiary-passwd-cache (remassoc url tdiary-passwd-cache))) (defun tdiary-passwd-cache-save (url user pass) (tdiary-passwd-cache-clear url) (add-to-list 'tdiary-passwd-cache (cons url (cons user (base64-encode-string pass))))) (defun tdiary-passwd-cache-read-username (url) (cadr (assoc url tdiary-passwd-cache))) (defun tdiary-passwd-cache-read-password (url) (let ((password (cddr (assoc url tdiary-passwd-cache)))) (and password (base64-decode-string password)))) (defun tdiary-post (mode date data) (let ((url (concat tdiary-diary-url tdiary-update-rb)) buf title user pass year month day post-data) (when (not (equal mode "edit")) (setq tdiary-edit-mode (setq mode (tdiary-read-mode mode))) (setq tdiary-date (setq date (tdiary-read-date date))) (setq tdiary-title (setq title (tdiary-read-title date)))) (setq user (tdiary-read-username url tdiary-diary-name)) (setq pass (tdiary-read-password url tdiary-diary-name)) (string-match "\\([0-9][0-9][0-9][0-9]\\)\\([0-9][0-9]\\)\\([0-9][0-9]\\)" date) (setq year (match-string 1 date) month (match-string 2 date) day (match-string 3 date)) (add-to-list 'post-data (cons "old" date)) (add-to-list 'post-data (cons "year" year)) (add-to-list 'post-data (cons "month" month)) (add-to-list 'post-data (cons "day" day)) (if tdiary-csrf-key (add-to-list 'post-data (cons "csrf_protection_key" tdiary-csrf-key))) (or (equal mode "edit") (add-to-list 'post-data (cons "title" (http-url-hexify-string title tdiary-coding-system)))) (add-to-list 'post-data (cons mode mode)) (and data (add-to-list 'post-data (cons "body" (http-url-hexify-string data tdiary-coding-system)))) (setq buf (http-fetch url 'post user pass post-data)) (if (bufferp buf) (save-excursion (tdiary-passwd-cache-save url user pass) (set-buffer buf) (decode-coding-region (point-min) (point-max) tdiary-coding-system) (goto-char (point-min)) buf) (tdiary-passwd-cache-clear url) (error "tDiary POST: %s - %s" (car buf) (cdr buf))))) (defun tdiary-post-text () (let* ((dirname (expand-file-name tdiary-diary-name (or tdiary-text-directory (expand-file-name "~/")))) (filename (expand-file-name (concat tdiary-date tdiary-text-suffix) dirname))) (unless (file-directory-p dirname) (make-directory dirname t) (set-file-modes dirname tdiary-text-directory-mode)) ;; If buffer-file-name is tdiary-text-directory/tdiary-diary-name/yyyymmdd.td ;; do nothing. (unless (equal filename buffer-file-name) (cond ((equal tdiary-edit-mode "replace") (write-region (point-min) (point-max) filename)) ((equal tdiary-edit-mode "append") (write-region (point-min) (point-max) filename t)))))) (defun tdiary-update () "Update diary." (interactive) (unless (and (eq (char-before (point-max)) ?\n) (eq (char-before (1- (point-max))) ?\n)) (save-excursion (goto-char (point-max)) (insert "\n"))) (tdiary-post tdiary-edit-mode tdiary-date (buffer-substring (point-min) (point-max))) (when tdiary-text-save-p (tdiary-post-text)) (if buffer-file-name (save-buffer) (set-buffer-modified-p nil)) (message "SUCCESS") (and (functionp tdiary-browser-function) (funcall tdiary-browser-function (concat tdiary-diary-url tdiary-index-rb "?date=" tdiary-date)))) (defun tdiary-do-replace-entity-ref (from to &optional str) (save-excursion (goto-char (point-min)) (if (stringp str) (progn (while (string-match from str) (setq str (replace-match to nil nil str))) str) (while (search-forward from nil t) (replace-match to nil nil))))) (defun tdiary-replace-entity-refs (&optional str) "Replace entity references. If STR is a string, replace entity references within the string. Otherwise replace all entity references within current buffer." (tdiary-do-replace-entity-ref "&" "&" (tdiary-do-replace-entity-ref "<" "<" (tdiary-do-replace-entity-ref ">" ">" (tdiary-do-replace-entity-ref """ "\"" str))))) ;(defun tdiary-read-mode (mode) ; (let ((default (caar tdiary-edit-mode-list))) ; (completing-read "Editing mode: " tdiary-edit-mode-list ; nil t (or mode default) nil default))) (defun tdiary-obsolete-check () ;; setting tdiary-diary-url in tdiary-init-file is obsolete. (when tdiary-diary-url (message "tdiary-diary-url is OBSOLETE. Use tdiary-diary-list instead of tdiary-diary-url.") (sit-for 5))) ;(defun tdiary-setup-diary-url (select-url) ; (interactive) ; (if (interactive-p) ; (setq select-url t)) (defun tdiary-setup-diary-url (select-url) ;; setting tdiary-diary-url in tdiary-init-file is obsolete. (tdiary-obsolete-check) (unless tdiary-diary-url (let* ((selected (car tdiary-diary-list)) (default (car selected))) (when select-url (setq selected (assoc (completing-read "Select SITE: " tdiary-diary-list nil t default nil default) tdiary-diary-list))) (setq tdiary-diary-name (nth 0 selected) tdiary-diary-url (nth 1 selected)) (and (eq (length selected) 4) (setq tdiary-index-rb (nth 2 selected) tdiary-update-rb (nth 3 selected)))))) (defun tdiary-new-or-replace (replacep select-url) (let (buf) (setq buf (generate-new-buffer "*tdiary tmp*")) (switch-to-buffer buf) (tdiary-mode) (setq tdiary-edit-mode "append") (let (start end body title csrf-key) (save-excursion (setq buf (tdiary-post "edit" tdiary-date nil)) (when (bufferp buf) (save-excursion (set-buffer buf) (if (re-search-forward "]+name=\"csrf_protection_key\" [^>]*value=\"\\([^>\"]*\\)\">" nil t nil) (setq csrf-key (match-string 1))) (re-search-forward "]+name=\"title\" [^>]+value=\"\\([^>\"]*\\)\">" nil t nil) (setq title (match-string 1)) (re-search-forward "" nil t nil) (setq end (match-beginning 0)) (setq body (buffer-substring start end)) ) (setq tdiary-csrf-key (and csrf-key (tdiary-replace-entity-refs csrf-key))) (when replacep (insert body) (setq tdiary-edit-mode "replace") (setq tdiary-title (tdiary-replace-entity-refs title)) (goto-char (point-min)) (tdiary-replace-entity-refs) (set-buffer-modified-p nil))))))) (defun tdiary-new (&optional select-url) (interactive "P") (tdiary-new-or-replace nil select-url)) (defun tdiary-replace (&optional select-url) (interactive "P") (tdiary-new-or-replace t select-url)) (defvar tdiary-mode-map (make-sparse-keymap) "Set up keymap for tdiary-mode. If you want to set up your own key bindings, use `tdiary-mode-hook'.") (define-key tdiary-mode-map [(control return)] 'tdiary-complete-plugin) (define-key tdiary-mode-map "\C-c\C-c" 'tdiary-update) (push (cons 'tdiary-date tdiary-mode-map) minor-mode-map-alist) (if (boundp 'minor-mode-list) (push 'tdiary-mode minor-mode-list)) (push '(tdiary-date " tDiary") minor-mode-alist) (defun tdiary-load-init-file () "Load init file." (let ((init-file (expand-file-name tdiary-init-file))) (when (file-readable-p init-file) (load init-file t t)))) (defun tdiary-make-temp-file-name () (let ((tmpdir (expand-file-name tdiary-diary-name (expand-file-name (user-login-name) temporary-file-directory)))) (unless (file-directory-p tmpdir) (make-directory tmpdir t) (set-file-modes tmpdir tdiary-text-directory-mode)) (expand-file-name tdiary-date tmpdir))) (defun tdiary-html-mode-init () "Initialize tDiary for default style" (tdiary-tempo-define (append tdiary-plugin-initial-definition tdiary-plugin-definition)) (tempo-use-tag-list 'tdiary-tempo-tags tdiary-completion-finder)) (defun tdiary-rd-mode-init () "Initialize tDiary for RD style" ) (defun tdiary-mode () "tDiary editing mode. The value of `tdiary-style-mode' will be used as actual major mode. \\{tdiary-mode-map}" (interactive) (funcall tdiary-style-mode) (and (featurep 'font-lock) (font-lock-set-defaults)) (tdiary-mode-setup)) (defun tdiary-mode-setup () "Set tDiary mode up." (interactive) (make-local-variable 'require-final-newline) (make-local-variable 'tdiary-date) (make-local-variable 'tdiary-title) (make-local-variable 'tdiary-edit-mode) (make-local-variable 'tdiary-diary-url) (make-local-variable 'tdiary-index-rb) (make-local-variable 'tdiary-update-rb) (make-local-variable 'tdiary-csrf-key) (setq require-final-newline t indent-tabs-mode nil tdiary-edit-mode "replace" tdiary-date (format-time-string "%Y%m%d" (tdiary-today))) (tdiary-load-init-file) (tdiary-setup-diary-url (if (boundp 'select-url) select-url t)) (set-buffer-file-coding-system tdiary-coding-system) (or tdiary-passwd-cache (tdiary-passwd-file-load)) (if buffer-file-name (let ((buf-name (file-name-nondirectory buffer-file-name))) (when (string-match "\\([0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]\\)" buf-name) (setq tdiary-date (match-string 1 buf-name)))) (setq tdiary-date (tdiary-read-date nil)) (if tdiary-text-save-p (set-visited-file-name (tdiary-make-temp-file-name)) (unless (string= (buffer-name) tdiary-date) (rename-buffer tdiary-date t)))) (let ((init (intern (concat "tdiary-" (symbol-name tdiary-style-mode) "-init")))) (if (fboundp init) (funcall init))) (run-hooks 'tdiary-mode-hook)) (defun tdiary-mode-toggle (&optional arg) (interactive "P") (let ((in-tdiary (and (boundp 'tdiary-date) tdiary-date))) (cond ((not arg) (setq arg (not in-tdiary))) ((or (eq arg '-) (and (numberp arg) (< arg 0))) (setq arg nil))) (cond (arg (tdiary-mode-setup)) (in-tdiary (setq tdiary-date nil))))) (provide 'tdiary-mode) ;;; tdiary-mode.el ends here tdiary-contrib-3.2.2/util/tdiary-vim/000077500000000000000000000000001213632744000175145ustar00rootroot00000000000000tdiary-contrib-3.2.2/util/tdiary-vim/ChangeLog000066400000000000000000000015171213632744000212720ustar00rootroot000000000000002005-07-29 Fri UECHI Yasumasa * echo site name and url when select a diary site. * allow to set update script each diary. * use CSRF protection key if exits. 2005-07-28 Thu UECHI Yasumasa * send referer when update a diary. 2004-11-08 Mon UECHI Yasumasa * change substitution order of character entity in TdiaryReplace(). thanx やえもん. 2004-02-25 Wed UECHI Yasumasa * support TrackBack 2004-02-19 Thu UECHI Yasumasa * quote argument of curl's -u option. 2004-02-17 Tue UECHI Yasumasa * use .netrc when g:tdiary_use_netrc = 1 2004-02-16 Mon UECHI Yasumasa * change editing mode, date, title in diary buffer. 2004-02-13 Fri UECHI Yasumasa * commit to CVS repository tdiary-contrib-3.2.2/util/tdiary-vim/README000066400000000000000000000055321213632744000204010ustar00rootroot00000000000000= tdiary.vim tdiary.vim は vim から日記を更新するための vimスクリプトです。 == 必要なもの tdiary.vim を使用するには以下のものが必要です。 * cURL - コマンドラインから http や ftp で通信するためのツール * iconv ライブラリ * vim (+iconv でコンパイルしたもの) cURL は (()) から入手できます。 == インストール tdiary.vim を $HOME/.vim/plugin ディレクトリにコピーするだけです。 == 設定 $HOME/.vimrc で次のように tDiary サイトの URL を設定します。 let tdiary_site1_url = "http://www.example.com/tdiary/" 最低限必要な設定はこれだけですが、複数の日記を更新するなら以下のような設定を追加してください。 let tdiary_site1_name = "ほげほげ日記" let tdiary_site2_url = "http://www.example.net/tdiary/" let tdiary_site2_name = "foobar日記" tDiary を設置するときに update.rb を update.cgi 等に変更している場合は以下も追加してください。 let tdiary_site1_updatescript = "update.cgi" let tdiary_site2_updatescript = "update.cgi" == パスワードの保存 cURL は $HOME/.netrc を読めるので、パスワードの保存にその機能を使います。ユーザ名とパスワードを .netrc に保存し、$HOME/.vimrc に let tdiary_use_netrc = 1 と設定すると有効になります。 == 使い方 tdiary.vim では次のコマンドが使えます。 * :TDiaryNew - 日記を書くための空のバッファを開きます * :TDiaryReplace - 指定した日付の日記を読み込んだバッファを開きます * :TDiaryUpdate - 日記を更新します * :TDiarySelect - 更新する tDiary サイトを選択するためのバッファを開きます * :TDiaryTrackback - TrackBack の excerpt を編修するためのバッファを開きます === 日記に追記 :TDiaryNew すると日付が YYYYMMDD 形式で表示されますので、適宜修正してリターンキーを押してください。日記を書いたら :TDiaryUpdate で更新してください。 === 日記を修正 :TDiaryReplace すると日付が YYYYMMDD 形式で表示されますので、修正したい日付に直してリターンキーを押してください。指定した日の日記が読み込まれます。修正後に :TDiaryUpdate で更新してください。 === tDiary サイトの選択 :TDiarySelect すると日記の一覧が表示されます。日記にカーソルを合わせてリターンキーを押すことで書き込み先が切り替わります。 === TrackBack 日記の編修バッファに表示されている TrackBackURL: に TrackBack 先の URL を記 入することで TrackBack が送られます。excerpt を編修する場合は :TDiaryTrackback することで編修用のバッファが開きます。 tdiary-contrib-3.2.2/util/tdiary-vim/tdiary.vim000066400000000000000000000174321213632744000215340ustar00rootroot00000000000000" Copyright (C) 2004 UECHI Yasumasa " Author: UECHI Yasumasa " $Revision: 1.8 $ " This program is free software; you can redistribute it and/or " modify it under the terms of the GNU General Public License as " published by the Free Software Foundation; either version 2, or (at " your option) any later version. " This program is distributed in the hope that it will be useful, but " WITHOUT ANY WARRANTY; without even the implied warranty of " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU " General Public License for more details. " You should have received a copy of the GNU General Public License " along with this program; see the file COPYING. If not, write to the " Free Software Foundation, Inc., 59 Temple Place - Suite 330, " Boston, MA 02111-1307, USA. if !exists("g:tdiary_site1_url") finish endif command! -nargs=0 TDiaryNew call TDiaryNew() command! -nargs=0 TDiaryReplace call TDiaryReplace() command! -nargs=0 TDiaryUpdate call TDiaryUpdate() command! -nargs=0 TDiarySelect call TDiarySelect() command! -nargs=0 TDiaryTrackback call EditTrackBackExcerpt() let s:curl_cmd = "curl" let s:user = '' function! s:TDiaryNew() call s:CreateBuffer("append") execute ":" . (s:body_start + 1) normal dG redraw! endfunction function! s:TDiaryReplace() call s:CreateBuffer("replace") let save_pat = @/ let @/ = 'input.\+name="title"[^>]\+>' normal ggn let title = substitute(getline("."), '.\+value="\(.*\)".\+', '\1', '') let @/ = 'textarea \+name="body"[^>]\+>' execute ":" . s:body_start normal dndf> let @/ = '/g silent! %s/</" normal G redraw! let @/ = save_pat endfunction function! s:TDiaryUpdate() " move to _tdiary_ buffer let n = bufwinnr(substitute(bufname("%"), "_.\\+_", "_tdiary_", "")) execute "normal " . n . "\w" " set parameters let data = s:SetParams() " set body & csrf protection key let data = data . "&body=" . s:MultiLineURLencode(s:body_start) let data = data . s:csrf_protection_key " debug mode if exists("g:tdiary_vim_debug") && g:tdiary_vim_debug call append("$", data) return endif " redirect data to tmpfile let tmpfile = tempname() execute "redir! > " . tmpfile silent echo data redir END " update diary let result = system(s:curl_cmd . s:user . " -d @" . tmpfile . " -e ". s:tdiary_update_url . " " . s:tdiary_update_url) call delete(tmpfile) redraw! if match(result, 'Wait or.\+Click here') != -1 echo "SUCCESS" else echo result endif endfunction function! s:TDiarySelect() split tDiary_select set buftype=nofile set nobuflisted set noswapfile let i = 1 while exists("g:tdiary_site{i}_url") let site_name = '' if exists("g:tdiary_site{i}_name") let site_name = g:tdiary_site{i}_name . " " endif call append(i - 1, site_name . g:tdiary_site{i}_url) let i = i + 1 endwhile normal gg nnoremap :call SetURL() endfunction function! s:EditTrackBackExcerpt() let save_line = line(".") normal gg call search("^TrackBackURL:") let tb_url = s:ParamValue(getline(".")) let tb_url = input("TrackBackURL: ", tb_url) delete call append(line(".") - 1, "TrackBackURL: " . tb_url) execute ":" . save_line let tb_bufname = substitute(bufname("%"), "_tdiary_", "_trackback_", "") split execute "normal \w" execute "edit " . tb_bufname set buftype=nofile set noswapfile set bufhidden=hide endfunction function! s:SetParams() let data = '' let i = 1 while i < s:body_start let l = getline(i) let r = s:ParamValue(l) if l =~ "^Editing mode" let mode = r let data = data . "&" . r . "=" . r elseif l =~ "^Date:" let data = data . s:Date2PostDate(r, mode) elseif l =~ "^Title:" let data = data . "&title=" . s:URLencode(r) elseif l =~ "^TrackBackURL:" if r != "" let data = data . "&plugin_tb_url=" . s:URLencode(r) let data = data . s:TrackBackExcerpt() endif endif let i = i + 1 endwhile return data endfunction function! s:ParamValue(str) let r = substitute(a:str, '^[^:]\+ *: *\(.*\)', '\1', '') let r = substitute(r, ' *$', '', '') return r endfunction function! s:TrackBackExcerpt() let data = "&plugin_tb_excerpt=" let n = bufwinnr(substitute(bufname("%"), "_.\\+_", "_trackback_", "")) if n > 0 execute "normal " . n . "\w" let data = data . s:MultiLineURLencode(1) execute "normal \p" endif return data endfunction function! s:MultiLineURLencode(start_line) let i = a:start_line let lastline = line("$") let data = "" while i <= lastline let data = data . s:URLencode(getline(i) . "\r\n") let i = i + 1 endwhile return data endfunction function! s:SetURL(...) if a:0 == 0 let i = line(".") else let i = a:1 endif let s:tdiary_url = substitute(g:tdiary_site{i}_url, "/\\+$", "", "") . "/" if exists("g:tdiary_site{i}_updatescript") let update_script = g:tdiary_site{i}_updatescript elseif exists("g:tdiary_update_script_name") let update_script = g:tdiary_update_script_name else let update_script = "update.rb" endif let s:tdiary_update_url = s:tdiary_url . update_script let s:user = "" call s:SetUser() "echo selected site let site_name = "" if exists("g:tdiary_site{i}_name") let site_name = g:tdiary_site{i}_name endif echo site_name s:tdiary_url if a:0 == 0 close endif endfunction function! s:SetUser() if exists("g:tdiary_use_netrc") && g:tdiary_use_netrc let s:user = " --netrc " elseif s:user == '' let s:user = input("User Name: ") let password = inputsecret("Password: ") if s:user != '' let s:user = " -u '" . s:user . ":" . password . "' " endif endif endfunction function! s:CreateBuffer(mode) if !exists("s:tdiary_update_url") call s:SetURL(1) endif let date = input("Date: ", strftime("%Y%m%d", localtime())) execute "edit _tdiary_" . date set buftype=nofile set noswapfile set bufhidden=hide "set fileformat=dos let s:body_start = 0 call append(s:body_start, "Editing mode (append or replace): " . a:mode) let s:body_start = s:body_start + 1 call append(s:body_start, "TrackBackURL: ") let s:body_start = s:body_start + 1 call append(s:body_start, "Date: " . date) let s:body_start = s:body_start + 1 call append(s:body_start, "Title: ") let s:body_start = s:body_start + 1 let s:body_start = s:body_start + 1 let data = "" if a:mode == "replace" let data = ' -d "' let data = data . s:Date2PostDate(date, a:mode) let data = data . '&edit=edit" ' endif execute 'r !' . s:curl_cmd . ' -s ' . s:user . data . s:tdiary_update_url normal gg let s:csrf_protection_key = "" if search('input.\+name="csrf_protection_key"') > 0 silent! s/"/\"/g silent! s/>/>/g silent! s/</ 6. Done. License ------- GNU GPL, General Public License version 2. Contact ------- Minero Aoki http://i.loveruby.net/en/ tdiary-contrib-3.2.2/util/tdiarysearch/README.ja000066400000000000000000000065071213632744000213720ustar00rootroot00000000000000■■このツールは最新のtDiaryに追従していません。 ■■検索機能はプラグインとして実装されるようになったため、 ■■同等の機能はplugin/search-default.rbで実現しています。 ■■このツールは近々削除する予定です。 tdiarysearch README =================== tDiary簡単検索CGIです。 あらかじめインデックスを作る必要がないので、 一般的な検索エンジンに比べてインストールが 圧倒的に簡単です。また、書いた直後の日記も 検索対象になるという長所があります。 必要環境 -------- * テキスト形式のデータベースを使っていること (tDiary 1.5 以降) * tDiary が動いているサーバに独自の CGI を追加する権限があること セットアップ ------------ 1. search.rb を tDiary の index.rb の隣にコピーします。 必要なら index.rb と同じようにシンボリックリンクを 張ったり名前を変えたりしてください。 2. CGI として実行可能にします。 $ chmod a+x search.rb 3. 必要なら #! のパスを合わせます。 4. (オプション) search.rb 先頭のパラメータを変更して クエリーログを有効にしてください。 ※ クエリーログの詳細については後述 5. 自分の tDiary の好きな場所 (例えばヘッダ) に以下の フォームを加えてください。
        以上です。 検索のしかた ------------ tdiarysearch はトピックごとに AND 検索を行います。 指定した語は空白で分割され、全単語がトピック内のテキストに 全て含まれる場合にそのトピックを検索結果にリストします。 AND 以外の演算はサポートしません。 また rev 1.8 の段階ではまだツッコミが検索できません。 近いうちに追加します。 クエリーログ ------------ クエリーログ (query log) というのは、検索語のログの ことです。このログが存在すると他の人が何を検索したのか 見られるようになります。クエリーログを有効にするには、 search.rb 内の定数 LOGGING を true にしてください。 CGI からログを見られるようにするには、search.rb に パラメータ history=on を付けて呼びます。例えば 次のリンクを日記に入れておくと、リンクをたどるだけで 日記から最近の検索ログが見られます。 [検索ログ] なお、クエリーログは tDiary のデータディレクトリに search.log という名前で作成されます。特にローテーション処理はしていないので、 適当な間隔でローテートしてください。 連絡先 ------ 青木峰郎 (あおき・みねろう) Minero Aoki http://i.loveruby.net/w/tdiarysearch.html バグ報告は以下のどこかにお願いします。 * Wiki 上のバグ報告ページ http://i.loveruby.net/w/tdiarysearchBugs.html * tdiary-devel ML * 直接メール tdiary-contrib-3.2.2/util/tdiarysearch/search.rb000077500000000000000000000263151213632744000217150ustar00rootroot00000000000000#!/usr/bin/env ruby # # tdiarysearch # # Copyright (C) 2003-2005 Minero Aoki # # This program is free software. # You can distribute/modify this program under the terms of # the GNU GPL, General Public License version 2. # # $originalId: search.rb,v 1.14 2005/07/27 07:16:07 aamine Exp $ # # Project home page: http://i.loveruby.net/w/tdiarysearch.html # # # Static Configurations # LOGGING = false LOGFILE_NAME = 'search.log' DEBUG = $DEBUG # # HTML Templates # def unindent(str) str.gsub(/^#{str[/\A(?:\t+| +)/]}/, '') end HEADER = unindent <<'EOS' tDiary Search
        EOS FOOTER = unindent <<'EOS'
        EOS SEARCH_FORM = unindent <<"EOS"
        <% if theme %><% end %>
        EOS SEARCH_PAGE = unindent <<"EOS"

        tDiary Search

        #{SEARCH_FORM} EOS TOO_MANY_HITS = 50 SEARCH_RESULT = unindent <<"EOS"

        tDiary Search: Search Result

        #{SEARCH_FORM} <% nhits = 0 toomanyhits = false match_components(patterns) {|diary, fragment, component| nhits += 1 if nhits > TOO_MANY_HITS toomanyhits = true break end %>

        <%= diary.y_m_d %>

        <%= short_html(component) %>

        <% } %>

        <%= toomanyhits ? 'too many hits.' : nhits.to_s+' hits.' %>

        #{SEARCH_FORM} EOS SEARCH_ERROR = unindent <<"EOS" #{SEARCH_FORM} <%= escape(reason) %>. EOS HISTORY = unindent <<"EOS"

        tDiary Search: Search History

        #{SEARCH_FORM}
          <% recent_queries.sort_by {|t,q| -t.to_i }.each do |time, query| %>
        • <%= time.strftime('%Y-%m-%d %H:%M:%S') %> | <%= escape(query) %>
        • <% end %>
        #{SEARCH_FORM} EOS # # Main # if File.symlink?(__FILE__) tdiarylib = File.dirname(File.readlink(__FILE__)) else tdiarylib = File.dirname(__FILE__) end $:.unshift tdiarylib require 'tdiary' require 'tdiary/io/default' require 'erb' TDIARY_ENCODING = (TDIARY_VERSION >= '2.3.0') ? 'utf-8' : 'euc-jp' class WrongQuery < StandardError; end Z_SPACE = "\241\241" # zen-kaku space BEGIN { $stdout.binmode } def main $KCODE = TDIARY_ENCODING cgi = CGI.new @config = TDiary::Config.new(cgi) @config.options['apply_plugin'] = true html = '

        error

        ' begin html = generate_page(cgi) ensure send_html cgi, html end exit 0 end def generate_page(cgi) query = nil begin theme = @config.theme if LOGGING and File.file?(query_log()) and cgi.valid?('history') return history_page(theme) end begin return search_form_page(theme) unless cgi.valid?('q') initialize_tdiary_plugins cgi query = @config.to_native([cgi.params['q']].flatten.compact.join(' ')) patterns = setup_patterns(query) html = search_result_page(theme, patterns) save_query(query, query_log()) if LOGGING return html rescue WrongQuery => err return search_error_page(theme, (patterns || []), err.message) end rescue Exception => err html = '' html << HEADER html << "
        \n"
            html << 'q=' << escape(query) << "\n" if query
            html << escape(err.class.name) << "\n" if DEBUG
            html << escape(err.message) << "\n"
            html << err.backtrace.map {|i| escape(i) }.join("\n") if DEBUG
            html << "
        \n" html << FOOTER return html end end def send_html(cgi, html) print cgi.header('status' => '200 OK', 'type' => 'text/html', 'charset' => TDIARY_ENCODING, 'Content-Length' => html.length.to_s, 'Cache-Control' => 'no-cache', 'Pragma' => 'no-cache') print html unless cgi.request_method == 'HEAD' end def setup_patterns(query) patterns = split_string(query).map {|pat| check_pattern pat Regexp.new( Regexp.quote(pat), Regexp::IGNORECASE, TDIARY_ENCODING ) } raise WrongQuery, 'no pattern' if patterns.empty? raise WrongQuery, 'too many sub patterns' if patterns.length > 8 patterns end def check_pattern(pat) raise WrongQuery, 'no pattern' unless pat raise WrongQuery, 'empty pattern' if pat.empty? raise WrongQuery, "pattern too short: #{pat}" if pat.length < 2 raise WrongQuery, 'pattern too long' if pat.length > 128 end def split_string(str) str.split(/[\s#{Z_SPACE}]+/ou).reject {|w| w.empty? } end def save_query(query, file) File.open(file, 'a') {|f| begin f.flock(File::LOCK_EX) f.puts "#{Time.now.to_i}: #{query.dump}" ensure f.flock(File::LOCK_UN) end } end # # eRuby Dispatchers and Helper Routines # def search_form_page(theme) patterns = [] ERB.new(HEADER + SEARCH_FORM + FOOTER).result(binding()) end def search_result_page(theme, patterns) ERB.new(HEADER + SEARCH_RESULT + FOOTER).result(binding()) end def search_error_page(theme, patterns, reason) ERB.new(HEADER + SEARCH_ERROR + FOOTER).result(binding()) end def history_page(theme) patterns = [] ERB.new(HEADER + HISTORY + FOOTER).result(binding()) end def query_log "#{@config.data_path}#{LOGFILE_NAME}" end N_SHOW_QUERY_MAX = 20 def recent_queries return unless File.file?(query_log()) File.readlines(query_log()).reverse[0, N_SHOW_QUERY_MAX].map {|line| time, q = *line.split(/:/, 2) [Time.at(time.to_i), eval(q)] } end INF = 1 / 0.0 def match_components(patterns) foreach_diary_from_latest do |diary| next unless diary.visible? num = 1 diary.each_section do |sec| if patterns.all? {|re| re =~ sec.to_src } yield diary, fragment('p', num), sec end num += 1 end diary.each_visible_comment(INF) do |cmt, num| if patterns.all? {|re| re =~ cmt.body } yield diary, fragment('c', num), cmt end end end end def fragment(type, num) sprintf('%s%02d', type, num) end # # tDiary Implementation Dependent # def foreach_diary_from_latest(&block) foreach_data_file(@config.data_path.sub(%r, '')) do |path| read_diaries(path).sort_by {|diary| diary.date }.reverse_each(&block) end end def foreach_data_file(data_path, &block) Dir.glob("#{data_path}/[0-9]*/*.td2").sort.reverse_each do |path| yield path.untaint end end def read_diaries(path) d = nil diaries = {} load_tdiary_textdb(path) do |header, body| d = diary_class(header['Format']).new(header['Date'], '', body) d.show(header['Visible'] != 'false') diaries[d.ymd] = d end (Years[d.y] ||= []).push(d.m) if d load_comments diaries, path diaries.values end DIARY_CLASS_CACHE = {} def diary_class(style) c = DIARY_CLASS_CACHE[style] return c if c require "tdiary/style/#{style.downcase}_style.rb" c = eval("TDiary::#{style.capitalize}Diary") c.__send__(:include, DiaryClassDelta) DIARY_CLASS_CACHE[style] = c c end module DiaryClassDelta def ymd date().strftime('%Y%m%d') end def y_m_d date().strftime('%Y-%m-%d') end def y '%04d' % date().year end def m '%02d' % date().month end end def load_comments(diaries, path) cmtfile = path.sub(/2\z/, 'c') return unless File.file?(cmtfile) load_tdiary_textdb(cmtfile) do |header, body| c = TDiary::Comment.new(header['Name'], header['Mail'], body, Time.at(header['Last-Modified'].to_i)) c.show = (header['Visible'] != 'false') d = diaries[header['Date']] d.add_comment c if d end end def load_tdiary_textdb(path) File.open(path) {|f| ver = f.gets.strip raise "unkwnown format: #{ver}" unless ver == 'TDIARY2.00.00' or ver == 'TDIARY2.01.00' f.each('') do |header| h = {} header.untaint.strip.each do |line| n, v = *line.split(':', 2) h[n.strip] = v.strip end yield h, f.gets("\n.\n").chomp(".\n").untaint end } end def short_html(component) # Section classes do not have common superclass, we can't use class here. case component.class.name when /Section/ section = component if section.subtitle sprintf('%s
        %s', tdiary2text(section.subtitle_to_html), tdiary2text(section.body_to_html)) else tdiary2text(section.body_to_html) end when /Comment/ cmt = component shorten(escape((cmt.name + ': ' + cmt.body))) else raise "must not happen: #{component.class}" end end def tdiary2text(html) re = Regexp.new('<[^>]*>', Regexp::EXTENDED, TDIARY_ENCODING) shorten(apply_tdiary_plugins(html).gsub(re, '')) end Years = {} TDiary::Plugin.__send__(:public, :apply_plugin) def apply_tdiary_plugins(html) @plugin.apply_plugin(html, false) end @plugin = nil def initialize_tdiary_plugins(cgi) @plugin = TDiary::Plugin.new('conf' => @config, 'secure' => false, 'diaries' => {}, 'cgi' => cgi, 'index' => @config.index, 'years' => Years, 'cache_path' => @config.cache_path || @config.data_path) end # # Utils # HTML_ESCAPE_TABLE = { '&' => '&', '<' => '<', '>' => '>', '"' => '"' } def escape(str) tbl = HTML_ESCAPE_TABLE str.gsub(/[&"<>]/) {|ch| tbl[ch] } end def escape_url(u) escape(urlencode(u)) end def urlencode(str) str.gsub(/[^\w-]/n) {|ch| sprintf('%%%02x', ch[0]) } end def shorten(str) re = Regexp.new('\A.{0,120}', Regexp::MULTILINE, TDIARY_ENCODING) str.slice(re) end def url(diary, fragment) if ( html_anchor_enabled? ) "#{@config.index}#{diary.ymd}.html\##{fragment}" else "#{@config.index}?date=#{diary.ymd}\##{fragment}" end end def html_anchor_enabled? if ( @html_anchor.nil? ) @html_anchor = @config.options2['sp.selected'].include?( 'html_anchor.rb' ) end return @html_anchor end # # Old Ruby Compatibility # if RUBY_VERSION < '1.8.0' class String remove_method :slice def slice(re, n = 0) m = re.match(self) or return nil m[n] end end end unless Array.method_defined?(:all?) module Enumerable def all? each do |i| return false unless yield(i) end true end end end unless Array.method_defined?(:sort_by) module Enumerable def sort_by map {|i| [yield(i), i] }.sort.map {|val, i| i } end end end unless MatchData.method_defined?(:captures) class MatchData def captures to_a()[1..-1] end end end main