Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Mkphotohtml Ver.2.0 (ANN)

2 views
Skip to first unread message

YAMADA Kunihiro

unread,
Nov 11, 2003, 11:05:33 AM11/11/03
to
山田邦博です。

Mkphothhtml Version 2 の投稿です。

ディジタルカメラ(Digital Camera)で多量に撮った写真を簡単に整理し、
Netscape や Mozilla 等の一般的なブラウザ(Web browser) で見れるようにする
ものです。
今回の目玉は、サブテーマとして URL を指定できるようになったことです。
これによって、アルバムをネットワークの中で分割できるようになりました。
他人様の mkphotohtml(ver.2) によるアルバムに リンクが張れると言い替え
てもいいでしょう。

Unix ユーザ(Unix user)向けです。

詳細は別投稿(DOC)中のドキュメント README.jp.txt を参照して下さい。

-...-

本投稿は 4部に分けて投稿します。
ANN (Announce: この投稿)
DOC (Document: README)(1000行弱)
BIN (Binaries: shar のため長大です)(約2400行)
ETC (Etc: 日本語と英語のメッセージファイル)

-...-

Mkphotohtml Ver.2.0 の全てのファイルは

ftp://ftp.tksa.gr.jp/king/image/Mkphotohtml_2.0.tgz

にあります。
これには本投稿にはない、インストーラ、小さな関連プログラム(便利グッズ)、
設定例、細かいドキュメントが含まれています。

最新の Mkphotohtml (ドキュメントを含む)については

http://www.tksa.gr.jp/king/Software/Mkphotohtml/index.html

を参照して下さい。
そこに実例も示しておきました。

-...-

インストール方法は別投稿(BIN)の shar より、mkphotohtml を取り出し、以
下の PATHの通っている所にコピーして下さい。
/usr/local/bin/, /usr/bin/ あるいは $HOME/bin/ 等

さらに、別投稿(ETC)の shar より message.english と message.japanese を
取り出し、/etc/mkphotohtml/ あるいは ~/etc/mkphotohtml/ ディレクトリに
コピーして下さい。


あるいは、上記 FTP より Mkphotohtml_2.0.tgz を取って来て、展開、その中
の installer を以下のように実行して下さい。

# Mkphotohtml_2.0/bin/install.sh local
## local は usr あるいは home も可。

詳細は同アーカイブ中のドキュメント(Mkphotohtml_2.0/doc/INSTALL.jp.txt)
を参照して下さい。

.-.-.

YAMADA Kunihiro

unread,
Nov 11, 2003, 11:09:52 AM11/11/03
to
山田邦博です。

Mkphothhtml Version 2 の投稿です。

-...-

本投稿は 4部に分けて投稿します。
ANN (Announce)
DOC (Document: この投稿)


BIN (Binaries: shar のため長大です)(約2400行)
ETC (Etc: 日本語と英語のメッセージファイル)

-...-

Mkphotohtml Ver.2.0 の全てのファイルは
ftp://ftp.tksa.gr.jp/king/image/Mkphotohtml_2.0.tgz
にあります。
これには本投稿にはない、インストーラ、小さな関連プログラム(便利グッズ)、
設定例、細かいドキュメントが含まれています。

最新の Mkphotohtml (ドキュメントを含む)については
http://www.tksa.gr.jp/king/Software/Mkphotohtml/index.html
を参照して下さい。
そこに実例も示しておきました。


=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
README.jp.txt
-------------

Mkphotohtml - Make photo.html

山田邦博
YAMADA Kunihiro <ki...@tksa.gr.jp>
11 Nov.2003 (Release 2.0)
Copyright policy: GNU GPL Ver.2


概要:
----


ディジタルカメラ(Digital Camera)で多量に撮った写真を簡単に整理し、
Netscape や Mozilla 等の一般的なブラウザ(Web browser) で見れるようにする
ものです。

一つのディレクトリ(Directory)で一つのテーマ(Theme)を表現する。 各テー
マはその下にサブディレクトリ(Sub-directory)を作る事でサブテーマ
(Sub-theme)を構成し、全体は木構造(Tree structure)となっている。
画像(Image)は各テーマ(各ディレクトリ)毎に管理する。
トップテーマ(Top-Theme,ディレクトリ)から全てのテーマを含む HTML ファイル
(HTML file)の一群を自動的に生成する。
また、サブテーマとしてリモート サーバ上にある URL を指定する事ができる。

各テーマ毎に、画像及びサブテーマの順序や、コメント等を設定するファイル
Contents.conf を置くことができる。 逆に、画像を適当に分割しておきさえす
れば、後は一切手間無しの手抜きモードもある(撮影日時だけで決める)。


各テーマにおける(photo.html の)表示はそのテーマの画像、およびその直
下のサブテーマの代表画像のサムネイル(Thumbnail)が縦一列に並びます。各
画像の右側に、拡大画像へのリンク、画像名、日時、コメントが付きます。
実際にどういう形で表示されるかは、以下の URL を参照して下さい。
http://www.tksa.gr.jp/cats/photo.html

最新の mkphotohtml は以下の URL に用意しておきます。 この文書に書か
れていない使用例等もあります。

http://www.tksa.gr.jp/king/Software/Mkphotohtml/index.html


動機:
----
いわゆるディジカメに限らず銀塩写真でも写真と言うものは整理が面倒です。
要はやたら数が多くなってしまう事に原因があるようです。 ディジタル画像な
ら、保持と検索が楽なはず。
世の中には、凝った GUI を駆使した画像のアルバム作成ソフトが沢山あるよ
うですが、どう見ても使いやすくはなさそう。 適当な設定ファイルとスクリプ
ト(script)で作成するものが欲しかった。

きちんと検索できるようにするのは面倒に見えるけれど、単純に日時だけで管
理してしまう手法がある。 こういう手抜き手法は長続きする。
大部分は手抜きモードで、ここはという特定のテーマだけ凝った事ができれば実
用性が高いはず。

個人的な使用だけでなく、Web での公開用にも使用できるものが良い。
それならば、一般的なブラウザ(Web browser)が使用できる。
画像(銀塩写真ならさしずめネガ)をちょっと探そうとする時、Netscape や
Mozilla のような機能満載のブラウザは起動が余りに遅すぎる。 Lynx のよう
な絵無しモードのブラウザでも、なんとなくテーマの構造と画像の概要が分か
る程度の HTML ファイルを生成したい。


こだわり:
--------
阿呆な GUI を避けよう。
徹底したスクリプト主義で。
Lynx でもテーマと画像の概要が理解できるような HTML ファイル生成。


Version 1.x から 2.x への主な変更点:
-----------------------------------
・サブテーマとして、"http://some.domain/some/theme/" という形式の URL
を指定する事ができるようになった。
・Contents.db と photo.html の文字コードを UTF-8 に統一した。
・Charset 設定は、ver.1.x では出力ファイル(Contents.db と photo,html)
の文字コードを指定したが、ver.2.0 からは記述ファイル自身(メッセージ
ファイルと Contents.conf)の文字コードを指定する。 (UTF-8 への変換は
自動的に行われる。)
・Message-File の形式が変わった。
また、Language 指定の段階で読み込まれる(まだ読み込まれていなければ)。

.... .-. .... .-. -...-


機能:
----

各テーマ(ディレクトリ)の HTML ファイルは全て同一の名前(photo.html) で
ある。 トップテーマ(トップディレクトリ)の photo.html から全てのテーマ、
及びそのテーマに属する画像へのアクセスを可能にする。
トップテーマをルートとする Tree 構造を扱う。 Leaf Node に対応するテーマ
には必ず画像があり、それ以外の node に対応するテーマが画像を持つかどう
かは任意である。


mkphotohtml の起動オプション:
----------------------------
mkphotohtml -h
mkphotohtml [-rv] -c [directories ...]
mkphotohtml [-b] [-e] [-f] [-m mailaddress] [-n]
[-o globaloption=directive,...]
[-r] [-s] [-t url] [-u username] [-v] [-w]
[directories ...]

-h : Help.
ヘルプ
-v 以外のオプションの併用は無効。
簡単な使用方法の他、テーマオプションのデフォールト設定値が表示
される。 このデフォールト値は mkphotohtml script 内部で保持され
ているものの他、/etc/mkphotohtml/option ファイルがあれば上書き
されたデフォールト値が表示される。 なお、上書きされたかどうかは
-v オプションを付ける事で確認できる。
-b : Back button added to photo.html
メッセージファイル中に "Back:" 項が指定してある時、この -b オプ
ションがあると、photo.html に 戻りボタン が付く。
デフォールトは 戻りボタン が付かない。
このオプションは "-o Back=Yes" と同一である。
-c : Clean bogus shrinked images.
指定されたディレクトリ(デフォールトはカーレントディレクトリ)の
テーマ内の縮小された画像の内、対応する生画像がない場合、その祝
処された画像を消去する。 -r を同時に指定すると、再帰的に下位の
ディレクトリについても同様の消去を行なう。
-v を同時にした場合、消去ファイルの詳細が表示される。
-c を指定した時、Contents.db と photo.html の更新を行なわなず、
縮小ファイルの作成も行なわない。
-C characterset :
Contents.conf を記述した文字コードのデフォールトを
characterset とする。
このオプションは "-o Charset=characterset" と同一である。
-D : Debug.
-e string :
文字列 "string" を photo.html の終りに付け加える。(Epilogue)
これは典型的には Copyright の表示に使用される。
このオプションは "-o Epilogue=string" と同一である。
-f : Force update.
本来なら Contents.db と photo.html の更新がされない場合でも、強
制的に更新する。
-l lang :
Photo.html で使用するメッセージの言語を lang に指定する。
このオプションは "-o Language=lang" と同一である。
-m mailaddress :
Mail address.
mailto: として photo.html に書き込まれるメイルアドレス。
デフォールトは $userid@$domain である。 $userid は環境変数
$USER で置き換えられる。 また $domain は FQDN からホスト名を
取り除いたものに置き換えられる。 さらに $fqdn は FQDN で置き
換えられる(`hostname -d` を使用)。
このオプションは "-o Mail-Address=mailaddress" と同一である。
-o : Default options for Contents.conf
基本的には Contents.conf のオプション部(Option:)のデフォールト
をあらかじめ指定するために使用される。
本オプション群は環境変数 MKPHOTOHTML でも設定でき、もしこの環境
変数が設定されていれば、シェルコマンドラインに先だって設定され
る。
詳細に付いてはテーマ オプションの項で解説する。
-p string :
文字列 "string" を photo.html の初めに付け加える。(Prologue)
これは典型的には Copyright の表示に使用される。
このオプションは "-o Prologue=string" と同一である。
-r : Recursive.
指定した directories (デフォールトはカーレントディレクトリ)の下
位のディレクトリに関しても再帰的に実行する。
-s : Suppress start page infomation in HTML header
photo.html の header 部内に <link rel="start" ...> を付加しな
い。
このオプションは "-o Start=No" と同一である。
-t url :
address or URL of Top page for start
Start オプションで付加する時の address または URL を指 定する。
デフォールト値は "/index.html" である。
このオプションは "-o Top=url" と同一である。
-u username :
Full name of user like as "Firstname Lastname".
mailto: として photo.html に書き込まれる名前。
デフォールトは $passwd である。 この $passwd は/etc/passwd ファ
イルから userid に対応するユーザ名が抽出され、置き換えられる。
このオプションは -o "User-Name=Firstname Lastname" と同一である。
注意:Full Name を書く際、空白が入るので、上記のように qoute す
る必要がある。
-v : Verbose messages.
処理の詳細が表示される。
-w : check web page
このオプションは "-o Check-Web=Yes" と同一である。

directories ... :
テーマに相当するディレクトリのリストを指定する。
デフォールトはカーレントディレクトリ。


テーマ設定ファイル(Contents.conf):
---------------------------------

各テーマ毎にそのテーマの構成等を設定するファイル(Contents.conf)を置
く事ができる。 各テーマのディレクトリに Contents.conf があれば、その設
定に従った HTML ファイル photo.html がそのディレクトリに作られる。
詳細に付いては、"Contents.conf と Contents.db の構成" の項で説明する。

この Contents.conf は必須ではない。 もしなければ、全てがデフォールト
設定と解釈されるだけである。
後述の "テーマ キャッシュ ファイル (Contents.db)" の項で説明するように、
(存在しない場合を含め) Contents.conf の解釈が全て Contents.db ファイル
に書き込まれる。

手軽に Contents.conf を作る方法は、とりあえず一度 mkphotohtml で
Contents.db と photo.html を作らせ、Contents.db を Contents.conf にコ
ピーし(あるいはリネームし)、(web browser で photo.html を表示させなが
ら、) 適当に編集して行けば良い。

Contents.conf は、後述する "Charset=" オプションを適切に設定する事で、
任意の文字コードで記述することができる。(内部処理のために UTF-8 に変換
される。)

文字ストリングを " はそのまま " として扱われる。(Ver.2)
注: Ver.1 では文字ストリングの各行の 最初と最後の " は取り除
かれていた。
ナル ストリングを指定する時は
item=
のように = の後を空文にすること。 文字ストリングの各行の前後の空白は除
去される。

photo.html に挿入される文字ストリング中の HTML メタ文字 (&"<>) は文
字実体参照 (&amp;&quot;&lt;%gt;) に変換されます。 従って、それらの文字
ストリングから photo.html に HTML タグの類を挿入することはできません。
photo.html に挿入される文字ストリングで、継続行が許されている項目(
prologue,epilogue,comment)については、行の終りに <br> をつけ、改行しま
す。


テーマ キャッシュ ファイル(Contents.db):
---------------------------------------

mkphotohtml コマンドで HTML ファイル(photo.html)を作ると、その内容を反
映したデータファイル Contents.db が作られる。
Contents.conf と Contents.db とは同一と見倣せる。 (Contents.conf で指定
されていない デフォールト 設定が Contents.db に反映される。) 従って、
Contents.db の内容をそっくり Contents.conf にコピーし、そのまま使用する
事ができる。

この Contents.db はそのテーマの photo.html を作る際のデータベースとなっ
ていて、サブテーマや画像の順序が保存されている。
従って、各種オプションや Contents.conf の指示がどのように解釈されたか調
べるのに役立つ。
また、Contents.db 中の Option: 部と Theme: 部は一つ上位のテーマから参
照され、さらに Version がチェックされる。 場合によっては、リモートサイ
トの mkphotohtml が Contents.db を参照する事もある。("ウェブテーマ" の
項参照)

詳細に付いては、"テーマ設定ファイル(Contents.conf) および テーマ キャッ
シュ ファイル(Contents.db)" の項で説明する。

Contents.db を消去する事は差し支えないが、編集すべきでない。 それは
Contents.db の日時(mtime)を調べ、それが以下の日時
そのテーマ内の Contents.conf の日時
そのテーマ内の画像を収容するディレクトリの日時
そのテーマの直下のサブテーマのディレクトリの日時
より新しければ Contents.db と photo.html の更新をしないからである。
(例外 -f オプション)

Contents.db は UTF-8 で記述される。


Contents.conf と Contents.db の構成 :
------------------------------------

各テーマ毎にそのテーマの構成等を設定するファイル(Contents.conf)を置
く事ができる。 各テーマのディレクトリに Contents.conf があれば、その設
定に従った HTML ファイル photo.html がそのディレクトリに作られる。

Contents.conf のデフォールトを含む全解釈が同じディレクトリ中の
Contents.db に作られる。
Contents.db ファイルは上位のテーマから参照される。 また、リモートのサー
バ上で実行された mkphotohtml (ver.2) から参照されることもある。
Contents.db ファイルはそのテーマ情報のキャッシュとして機能しているため、
編集すべきではない。


Contents.conf および Contents.db の構成は以下の通りである。
=========================================================

Version:
プログラム名 バージョン
# プログラム名は "mkphothtml"
# バージョンは mmm.nnn または mmm.nnn-string
# ここで mmm nnn は数字。 string は英数字、"_" および
# "." だが、最初の一文字は英数字に制限される。
# プログラム mkphotohtml のバージョンの mmm と一致しな
# いと、あるいは .nnn の値が実行プログラムのそれより
# 大きい時、処理が中断される。

Option: # オプション部に関してはテーマオプション
Charset=... # の項で解説する。
Language=...
Order=...
Image=...
Theme=...
Config=...
Mail=...
User-Name=...
Scale-Directory=...
Size-of-Picture=...
Back=...
Start=...
Top=...
Check-Web=...
Refer=...
Prologue=...
Epilogue=...

Theme:
Theme=テーマ名
# HTML で使用できる任意の文字列。
# HTMLメタ文字があれば文字実体参照に変換される。
# ここで指定した文字列は photo.html に挿入される。
# Default: ディレクトリ名
Image=代表画像 [(N=dir,scale,wxh)(H=dir,scale,wxh)(I=dir,scale,wxh)]
# そのテーマを代表する画像を指定する。
# この項は継続行が可能。
# Default: 当テーマで最初に配置されるインデックス(サム
# ネイル)画像に対応する画像
代表画像 :
# そのテーマ内の原(raw)画像のファイル名(xxxx.jpeg)、
# 下位のサブテーマの原画像のファイル名(subdir/..../xxxx.jpeg)、
# サブテーマのディレクトリ名(subdir/..../)、
# または、リモート サーバ上の(Makephtohtml ver.2 で既
# に作成された)テーマの url (http::/some.domain/some/theme/)
# を 指定できる。
# サブディレクトリ名 または url を指定した場合は、それ
# らのテーマの代表画像が使用される。
# Contents.conf で url を指定する場合、対応する
# web-theme section (http://..../..../) がなければなら
# ない。
# なお、画像ファイル名を指定する際、画像収納サブディレ
# クトリ(":raw" 等)は付けてはいけない。
(N=dir,scale,wxh)(H=dir,scale,wxh)(I=dir,scale,wxh) :
# Contents.conf では無視される。(表記を省略すべきである)
# ヘッダ、インデックス画像の収納ディレクトリ(dir)、縮
# 小スケール(scale)、画像の大きさ(横x高さ、wxh)。
Comment=テーマの概要を示すコメント
# HTML で使用できる任意の文字列。
# HTMLメタ文字があれば文字実体参照に変換される。
# この項は継続行が可能。 各行は <br> で改行される。
# ここで指定した文字列は photo.html に挿入される。
# default: なし
Latest=unix-epoch (日時)
# default: そのテーマ及びそれ以下のサブテーマ内の最新
# 画像の時間そのテーマ及びそれ以下のサブテーマ内の最新
# 画像の Unix epoch と (日時)。
# 日時は Local Time で、英語表記。
unix-epoch : Unix epoch による時間(秒)である。
# Contents.conf では、この値は無視される。
# Contents.conf では省略すべきである。(実際の最新画像
# の Unix epoch で置き換えられる。)
(日時) : 通常 locale に従った日時を記述する。
# 括弧"()"以外の任意の文字列が使用できる。 英語以外の
# 日時を表現するための他、ファイルのタイムスタンプとは
# 異なる日時を記述するために使用できる。
# 日時は 括弧 "()" で囲われていなければならない。
# HTMLメタ文字があれば文字実体参照に変換される。

http://www.a.some.domain/some/path-x/theme/
# リモート サーバ上の mkphotohtml (ver.2) で既に作成さ
# れたテーマの url (ウェブテーマ web-theme)。
Theme=テーマ名
# "Theme:" 部の "Theme=" 項に同じ。
# Default: そのウェブテーマの Contents.db ファイルの
# Theme: 部から取られる。
Image=url/img_nnnn.jpeg (N=dir,scale,wxh)(H=dir,scale,wxh)(I=dir,scale,wxh)
# この "Image=" 項は、Contents.conf では無視される。
# Default: そのウェブテーマの Contents.db ファイルの
# Theme: 部から取られる。
url/img_nnnn.jpeg :
# このテーマの画像の url に 原画像名を連結したもの
((N=dir,scale,wxh)H=dir,scale,wxh)(I=dir,scale,wxh) :
# ヘッダ、インデックス画像の収納ディレクトリ(dir)、縮
# 小スケール(scale)、画像の大きさ(横x高さ、wxh)。
Comment=ウェブテーマの概要を示すコメント
# "Theme:" 部の "Comment=" 項に同じ。
# Default: そのウェブテーマの Contents.db ファイルの
# Theme: 部から取られる。
Latest=unix-epoch (日時)
# "Theme:" 部の "Latest=" 項に同じ。
# Default: そのウェブテーマの Contents.db ファイルの
# Theme: 部から取られる。

http://www.b.some.domain/some/path-y/theme/
....
....

directory-a/
# サブテーマのディレクトリ名
Theme=サブテーマ名
# "Theme:" 部の "Theme=" 項に同じ。
# Default: そのサブテーマの Contents.db ファイルの
# Theme: 部から取られる。
Image=サブテーマを代表する画像 [(N=dir,scale,wxh)(H=dir,scale,wxh)(I=dir,scale,wxh)]
# そのサブテーマ内の原(raw)画像のファイル名(xxxx.jpeg)、
# そのサブテーマの下位のサブサブテーマの原画像のファイル名
# (subsubdir/..../xxxx.jpeg)、
# サブサブテーマのディレクトリ名(subsubdir/..../)、
# または、リモート サーバ上の(Makephtohtml ver.2 で既
# に作成された)テーマの url (http::/some.domain/some/theme/)
# を 指定できる。
# サブサブディレクトリ名 または url を指定した場合は、
# それらのテーマの代表画像が使用される。
# Contents.conf で url を指定する場合、対応する
# web-theme section (http://..../..../) がなければなら
# ない。
# なお、画像ファイル名を指定する際、画像収納サブディレ
# クトリ(":raw" 等)は付けてはいけない。
# Default: そのサブテーマの Contents.db ファイルの
# Theme: 部から取られる。
(N=dir,scale,wxh)(H=dir,scale,wxh)(I=dir,scale,wxh) :
# Contents.conf では無視される。(表記を省略すべきである)
# ヘッダ、インデックス画像の収納ディレクトリ(dir)、縮
# 小スケール(scale)、画像の大きさ(横x高さ、wxh)。
# Default: そのサブテーマの Contents.db ファイルの
# Theme: 部から取られる。
Comment=サブテーマの概要を示すコメント
# "Theme:" 部の "Comment=" 項に同じ。
# Default: そのサブテーマの Contents.conf ファイルの
# Theme: 部から取られる。
Latest=unix-epoch (日時)
# "Theme:" 部の "Latest=" 項に同じ。
# Default: そのサブテーマの Contents.db ファイルの
# Theme: 部から取られる。

directory-b/
....
....

img_xxxx.jpeg
# :raw/ ディレクトリ以下に収納されている原画像のファイ
# ル名。
# 注: Makephotohtml ver.1 ではファイル名の直後に ":"
# が必要でしたが、ver.2 では付けてはいけません。
Name=画像名
# HTML で使用できる任意の文字列。
# HTMLメタ文字があれば文字実体参照に変換される。
# ここで指定した文字列は photo.html に挿入される。
# Default: ファイル名 (img_xxxx.jpeg)
Date=日時
# HTML で使用できる任意の文字列。
# HTMLメタ文字があれば文字実体参照に変換される。
# ここで指定した文字列は photo.html に挿入される。
# Default: オリジナル画像ファイルのタイムスタンプ(mtime)
# 例: Sat Dec 9 19:19:56 2000
Comment=画像のコメント
# "Theme:" 部の "Comment=" 項に同じ。
# Default: なし
img_yyyy.jpeg
....
....

=========================================================

Contents.conf 内の各項目は全て省略可能である。 これらを記述するのは、
そのテーマ内でデフォールトと異なる設定をしたい時である。


テーマ オプション:
-----------------

テーマ オプションは各テーマ毎に設定可能なオプションである。 ただし、
以下のデフォールト オプションはテーマ オプションに先だって設定される。
(1) /etc/mkphotohtml/option
(2) $HOME/etc/mkphotohtml/
(3) 環境変数 MKPHOTOHTHL
(4) シェルコマンドの -o オプション
(1)から(4)へと順に設定が上書きされる。

各テーマにおけるオプションは上記デフォールト オプションをベースとし
て、各テーマにおける設定ファイル(Contents.conf)中のオプション部で上書
き設定される。
注:上位テーマのオプションが下位テーマのオプションに影響する事
はなく、互いに独立である。

テーマ オプションの項目キーワード(....=)は最初の 3文字だけに省略可能
である。 キーワード値も Mail,User-Name,Message-File を除き、最初の 3文
字に省略可能なものが多く(複合語は各々の最初の 3文字)、理解しやすいと思
われる省略形を用意した。
また、Mail,User-Name,Scale-Directory および Top の値を除き、大文字小文
字の区別はない。

キーワード値が複合語の場合、語間をハイフン(-)でつなぐ事を基本としている
が、アンダーライン(_)で代用でき、さらに省略できる。 例えば、New-First,
New_First,NewFirst は同一と見倣される。 さらにこれの変化形として
New-Fir,New-1st (当然 "-" を "_" で代用したり省略できる)も認めている。

Charset=文字コードセット
Charset : (Cha)
Contents.conf で使用する文字コードセットを指定する。
文字コードセット : ascii,utf8,jis,sjis,euc-jp,ISO-2022-JP,
ISO-8859-1 ... などなど
(Default : iso-2022-jp)

Language=使用言語
Language : (Lang,Lan)
使用言語を指定する。
photo.html 内のメッセージで使用する言語を規定する。
使用言語 : Japanese (Japan,JP) ... Default
English (注:Japanese 以外の短縮形はなし)
その他の言語も後述する Message-File を用意する事で可能。

Order=順序
Order : (省略形:Ord)
テーマと画像の配置戦略を決める。
順序 : New-First (New-Fir,New-1st) ... Default
最新の画像、テーマを最初に配置する。
逆時間順である。
Old-Last も同一。
New-Last (New-Las)
最新の画像、テーマを最後に配置する。
時間順である。
Old-First も同一。
Theme-First (The-Fir,The-1st,Directory-First,Dir-Fir,Dir-1st)
テーマ(ディレクトリ)を最初に配置する。
Image-Last も同一。
Image-First (Ima-Fir,Ima-1st)
画像を最初に配置する。
Theme-Last,Directory-Last も同一。

Image=順序
Image : (Ima)
Order=Theme-First または Image-First の時のみ有効である。
順序 : Reverse (Rev) ... Default
最新の画像を最初に配置する。
逆時間順である。
Normal (Nor)
最新の画像を最後に配置する。
時間順である。

Theme=順序
Theme : (The)
Order=Theme-First または Image-First の時のみ有効である。
順序 : Reverse (Rev) ... Default
最新のテーマを最初に配置する。
逆時間順である。
Normal (Nor)
最新のテーマを最後に配置する。
時間順である。

Config=順序
Config : (Con)
Contents.conf ファイルで記述された、サブテーマ及び画像
の順序を使用するかどうかを規定する。
順序 : Non (No) ... Default
使用しない。
First (Fir,1st)
使用し、かつ最初に配置する。
Last (Las)
使用し、かつ最後に配置する。


Mail-Address=メイルアドレス
Mail-Address : (Mail,Mai,Mail-Add,Mai-Address,Mai-Add)
メイルアドレスは photo.html の mailto: で使用される。
メイルアドレス :
you...@your.domain の形式を持つメイルアドレスで、デフォー
ルト値と異なるものに変更する場合に使用する。

デフォールト値は $userid@$domain である。

メイルアドレス中の $userid,$domain,$fqdn は以下のように
展開される。
$userid はログインした時の userid で、環境変数 USER
から取られる。
$domain は使用ホストの FQDN 名からホスト名を取り除いた
ものである。
$fqdn は FQDN で置き換えられる。
$userid,$domain,$fqdn はそれぞれ ${userid}, ${domain},
${fqdn} という形式で書いても良い。

メイルアドレス値が "" の場合、メイルアドレスがないもの
として、photo.html に mailto: を含めない。

User-Name=ユーザ名
User-Name : (User,Use,User-Nam,Use-Name,Use-Nam)
ユーザ名は photo.html の mailto: で使用される。
ユーザ名 :
通常 "FirstName SecondName" の形式を取るが、スペースを
含め自由である。 アルファベット以外にも数字、カンマ(,)、
空白も使用できる。
ユーザ名を日本語等で記述することが可能であるが、UTF-8
でない場合は "Charset=文字コードセット" をこのオプショ
ン以前に指定しておく必要がある。(環境変数 MKPHOTOHTML
での指定、シェル コマンドからのオプション指定の場合も、
このユーザ名だけはコード変換を例外的に行なえる。)

ユーザ名のデフォールトは、$passwd で、userid(環境変数
USER)を元に、パスワードファイル(/etc/passwd)から取っ
て来る。

ユーザ名が "" の場合、ユーザ不詳として、photo.html に
mailto: を含めない。

Scale-Directory=(スケール=ディレクトリ)リスト
Scale-Directory : (Scale,Sca,Scale-Dir,Sca-Dir,...)
画像の大きさ(スケール)と対応する画像を収納するディレク
トリを指定する。 本オプションを指定すると後述する
Size-of-Picture オプションの内容が消去される。
(スケール=ディレクトリ)リスト :
スケール :
0 より大、1 以下の整数、小数、整分数。
スケール値が 1、すなわち元画像、が必ず含まれていなけ
ればならない。
スケールの表記は photo.html の中で直接使用される。
ディレクトリ:
テーマディレクトリの中に収容する画像のサブディレクトリ
名。 このディレクトリ名の最初の一文字は全てのスケール
のディレクトリ名と一致していなければならない。
また、その最初の一文字で始まるディレクトリはテーマディ
レクトリとは見倣されない。 通常、この最初の一文字は特
殊文字で始まるのが良いと思われる。
縮小画像は(もしなければ)元画像から作成され、対応するディ
レクトリに収納される。
縮小画像のファイル名にはスケールから作られた
sub-extension が挿入されるため、スケール毎に異なるファ
イル名となる。 従って、このディレクトリ名を同一にする
事も可能であるが、元画像のディレクトリだけは独立にして
おく事を特に推奨する。
例:Scale=(1.0=%raw)(0.5=%half)(0.2=%fifth)(0.1=%tenth)
デフォールト: (1/1=:raw)(1/2=:shrink)(1/4=:shrink)(1/8=:shrink)

Size-of-Picture=(ディスプレイ=スケール)リスト
Size-of-Picture : (Size,Siz,Siz-of-Pic,Size-Picture,Size-Pic,...)
photo.html における画像表示の大きさを指定する。
Size-of-Picture オプションは Scale-Directory オプショ
ンの後に指定しなければならない。
ディスプレイ:
Normal : (Nor,N)
インデックス(サムネイル)画像をクリックして拡大
表示する時の画像を指示。
Header : (Hea,H)
テーマディレクトリの代表画像(photo.html の表示
で最上段に来る画像)を指示。
Index : (Ind,I,Indices)
インデックス(サムネイル)画像を指示。
インデックス画像は縦一列に左寄せで表示される。
各画像は小さいが、その右側にタイトル、日時、コ
メント等が表示される。
上記 Normal, Header および Index の全てがリストに含ま
れなければならない。
スケール:
Scale-Directory で指定したスケール表示のいずれか。
デフォールト: (Normal=1/2)(Header=1/4)(Index=1/8)

注: Scale-Directory と Size-of-Picture は他の -o オプション
とは違って少し特殊である。
これらは各テーマ毎に異なる事が可能であるが、そのテーマ
の Contents.db が有効(Contents.conf より新しいか、
Contents.conf がない)な場合、その Contents.db の内容か
ら Scale-Directory と Size-of-Picture を設定する。 この
場合デフォールトオプションの変更は反映されない。
従って、この二つのオプションに関してだけは、デフォール
トオプションを変更してテーマに反映するため、そのテーマ
の Contents.db を消去するか、touch Contents.conf を行な
うか、-f オプション(Force update) 付きで mkphotohtml を
起動する必要がある。

Back=有無
Back : (Bak)
photo.html に 戻りボタン を付けるかどうかを指定する。

有無 : No (Non,Not) ... Default
戻りボタン が付かない。
Yes (Use)
メッセージファイル中に "Back:" 項の指定があれ
ば、戻りボタンが付く。

Start=有無
Start : (Sta)
photo.html の header 部内に <link rel="start" ...> を
付加するかどうか指定する。

有無 : Yes (Use) ... Default
付加する。
No (Non,Not)
付加しない。

Top=url
Top : (省略形はない)
Start オプションで付加する時の address または URL を指
定する。

url : Web page 内の address または URL。
デフォールト値は "/index.html" である。

Check-Web=強制
Check-Web : (Che-Web,Check,Che)
Web-theme の Contents.db は URL を元にしたファイル名で
キャッシュされるが、リモート サーバと同期を強制的に取
るかどうかを指定する。
強制 : Yes (On)
同期を取る。
No (Off) ... Default
同期を取らず、キャッシュ ファイルを使用する。

Refer=認可
Refer : (Ref)
Network Photo Album として他サーバからリンクされること
を認めるかどうかを指定する。
認可 : Allow (All)
リンクを認める。
Deny (Den) ... Default
リンクを認めない。

Prologue=文字列
Prologue : (Prolog,Pro)
もし、ナル文字列以外が指定されていれば photo.html のテー
マ画像の後にその文字列を表示する。
Copyright の表示を想定しているが、それ以外の用途も可能。
文字列 :
任意の文字列。 オプションファイル中では継続行が可能。
(コマンドオプション、環境変数では一行のみ)
文字列はセンターリングされる。
文字列中に $copyright (または ${copyright}) があると、
言語指定に対応するメッセージファイルから "Copyright="
項目の文字列に置き換えられる。
文字列中に $uname (または ${uname}) があると、
"User-Name=" オプションの内容に置き換えられる。
さらに、文字列中に $mail または $Mail があると、
"Mail-Address=" オプションの内容に置き換えられる。 こ
の際、元の文字列が $Mail の場合は、Prologue 全体が
Mailto: となる。 (ただし、"Mail-Address=" オプション
の内容が "" の場合は Mailto: にならない。)
デフォールト値は "$copyright $uname <$Mail>" である。

Epilogue=文字列
Epilogue : (Epilog,Epi)
もし、ナル文字列以外が指定されていれば photo.html のサ
ムネイル画像の後にその文字列を表示する。
Copyright の表示を想定しているが、それ以外の用途も可能。
文字列 :
"Prologue=" に同じ。
デフォールト値は "" である。


メッセージファイル:
------------------

メッセージファイルの構成については ファイル message.english および
message.japanese を参照されたし。

設定項目の内、
"Language=","Album=","Comment=","Theme=","WebTheme=","Latest=",
"Arrow=" および "Copyright=" は必須ですが、"Back=" および
"Charset=" は任意である。

mkphotohtml コマンドに -b オプションの指定があり、かつ "Back=" が
設定されていると、photo.html に "戻り" ボタンが付く。

メッセージファイルに UTF-8 または ASCII 以外の文字コードを使用した
時には、"Charset=" を指定しなければならない。メッセージファイル中
の "Charset=" はその指定行以降で有効となるため、上記設定項目よりも
前に置かれるべきである。
注: Contents.conf のテーマオプションで書かれた "Charset=" と
は独立である。 "Charset=" はその記述ファイル自身が書かれた文字
コードを指定するものである。

メッセージファイルは言語別になっていて、言語名を "Lang" とすれば、その
ファイル名は、"message.lang"である。(言語名を小文字化したものが拡張子
として使用される。)
メッセージファイル中の設定項目 "Language=" の指定と、そのファイル名の
拡張子は一致していなければならない。

メッセージファイルは /etc/mkphotohtml/ または $HOME/etc/mkphotohtml/
の下に言語別のファイルとして置かれ、言語指定(Language=...)があった時に、
まだ読み込まれていなければ、読み込まれる。
メッセージファイルが /etc/mkphotohtml/ と $HOME/etc/mkphotohtml/ の両
方にあった場合は、この順序で読み込まれ、後者によって上書きされる。
後者の上書き設定の場合、必須設定項目であっても省略できる。

各言語の message.lang は、そのファイル中で指定された charset で書かれ
ていなければならない。

設定項目の文字列("=" の後ろ)は " で囲うことができる。 これによって、文
字列の最初、あるいは最後に空白を挿入する事ができる。
" で囲わない場合は、前後の空白が除去される。


サブテーマ:
----------
サブテーマのディレクトリ名の先頭一文字は、画像収容ディレクトリの先頭
一文字(デフォールトは ":")およびドット(".")であってはならない。 それら
の名前のディレクトリはサブテーマとして扱われない。
サブテーマディレクトリにある Contents.db ファイルは上位のテーマから参
照される。 下位のサブテーマディレクトリに Contents.db がない場合、その
サブテーマは内容が空として扱われ、無視される。
注: mkphotohtml コマンドで -r オプションを付けると、より下位のサ
ブテーマから Contents.db を作成する。


ウェブテーマ:
------------
ウェブテーマは "http://some.domain/some/theme/" の形式の URL を
Contents.conf ファイルの中で指定する。
上記の URL では "http://some.domain/some/theme/Contents.db" を取って来
て、".http:some.domain%some%theme%Contents.db" という名前のファイルと
してキャッシュする。 この際、リモートのファイルのタイムスタンプが再生
される。 一度このファイルが作成されると "Check-Web=Yes" (-w option) を
指定しない限り、更新されない。 また、リモートとローカルのそれぞれのタ
イムスタンプが同一の時も更新されない。
注: Contents.conf ファイル、サブテーマディレクトリ および 画像収
容ディレクトリのタイムスタンプが Contents.db より古いと、その
テーマの更新をスキップする。 この場合、同テーマ内で指定したウェ
ブテーマのキャッシュファイルの更新は、-w オプションがあっても
行われない。 (例外: -f -w オプションの同時指定)

ウェブテーマは、このキャッシュされた Contents.db すなわちリモートサー
バの Contents.db だけを使用し、それ以上立ち入った探索や検査を行わない。


画像:
----
画像は現在 jpeg 形式のみ扱える。
画像ファイルの拡張子は jpeg,JPEG,jpg,JPG のいずれかでなければならない。

各テーマの画像は各ディレクトリ毎に前述の特別のディレクトリ名の下に置
かれる。(オプション "Scale-Directory=" 参照)
デフォールト設定では、各テーマの原画像はそのテーマディレクトリのサブディ
レクトリ ":raw" に収納されていなければならない。
縮小画像はもしなければ自動的に作成され、縮小画像用のディレクトリに収納
される。(収納サブディレクトリがなければ作成される。)

上記拡張子を最後に持つ原画像ファイルに ".ORIG" なる拡張子を付けたファ
イルがあると、そのファイルのタイムスタンプ(mtime) が原画像のタイムスタ
ンプとして使用される。

デフォールト設定では、画像の大きさ(画素数)として 1600x1200 (pixels)
以上を想定しています。 これは、単純に 1/8 の大きさをインデックス画像
(サムネイル)の大きさとしていて、そのインデックスに付加されたメッセージ
(テーマ名または画像名、日時、コメント)をうまく納めるために必要とされま
す。 画像の大きさの範囲内に、web browser のフォントの大きさをうまく合わ
せる設定ができれば、小さい画像でも不都合はないでしょう。

1600x1200 (pixels) より小さい元画像や、それより遥かに大きな元画像の
場合はテーマオプション "Scale-Directory=" と "Size-of-Picture=" によっ
て適当な縮小率(Scale)を設定するのが良いでしょう。


シンボリック リンク:
-------------------
各テーマ内でディレクトリを別の(テーマの)ディレクトリに symlink するこ
とができる。 この場合、その symlink 直下の Contents.db を見に行くことは
あるが、その symlink 以降の修正をしない。
この動作は、mkphotohtml コマンドで -r (recursive) を指定した時に重要であ
る。 なぜなら、symlink を使うと、無限のサイクリックなディレクトリ構造を
作れてしまうからである。

また、縮小画像収容ディレクトリに symlink を使用した時は、そのディレク
トリに対して mkphotohtml -c (Clean up bogus shrinked images) が働かない。


タイムスタンプ:
--------------
本システムはタイムスタンプ(mtime)をフルに活用しています。
Contents.db は他のファイルやディレクトリのタイムスタンプに依存しています。
(この辺りの雰囲気は make コマンド(man make(1)) に似ています。)
さらに、画像やテーマの配列に画像のタイムスタンプを活用しています。 従っ
て、元画像のタイムスタンプの管理は重要です。 ディジタルカメラのクロック
を正確に合わせておきましょう。

古い写真をスキャナー等でディジタル画像化した場合、古い写真の撮影日では
なく、ディジタル画像化した日時がそのタイムスタンプになるでしょう。
これで具合が悪ければ、touch コマンドで日時を変更して下さい。 それでも
Unix epoch の都合で 1970年以前には設定できないでしょう。
古い、古い写真のタイムスタンプを復元する手段がありませんが、その日時を表
示する最後の手段は Contents.conf で "Date=" を設定する方法です。 また、
"Config=First" または "Config=Last" を指定して、画像の配列順序をタイムス
タンプに依らず Contents.conf で指定した画像の配列順序に強制することです。
なお、"Date=" の右側の日時のフォーマットは自由であり、日付以外の目的で
書くことができる。(継続行なし)


インストール環境と方法:
----------------------
別ドキュメント INSTALL.jp.txt を参照して下さい。


セキューリティ:
--------------
本システムはファイルの作成、削除、リネーム等を積極的に行なうため、絶対
安全とは言いかねます。 私の経験では、デバッグ中のトラブルはありましたが、
実使用中のトラブルはありませんでした。 ですが、特に危険と思われる、
root ユーザ、グループでの使用ができないようにしてあります。

他人の Contents.db を参照する時、この中の一部の文字列が photo.html
に挿入されます。 悪意のある毒の混入に対処するため、全ての HTML メタ文
字(&"<>)を文字実体参照(&amp;&quot;&lt;%gt;)に変換します。 すなわち、タ
グを使えないようにしてあります。
この変換は、Contents.db だけではなく、各言語(lang)のメッセージファイル
(message.lang) に関しても行われます。

Mkphotohtml version 2.0 からウェブテーマを URL で指定できるようにな
りました。 リモートの URL の Contents.db に悪意のある毒が混入されてい
た場合、最終的に作成される photo.html は安全でないかもしれません。
信用のできるリモートだけを相手にすべきです。
ファイル ".http:some.domain%some%theme%Contents.db" の内容をチェックし
ておくことを勧めます。


アルバム(photo.html)の著作権について:
------------------------------------
著作権(Copyright)表示ができるようにしてあります。 "Prologue=" と
"Epilogue=" オプションで書き込めます。
"Prologue=" のデフォールトでは
Copyright: Your Name <you...@your.domain>
の形で挿入されます。
"Epilogue=" はデフォールトでは "" ですが、詳細な許可条件等を挿入するこ
とを想定しています。

Mkphotohtml(ver.2) はリモートサイト上の Contents.db を参照し、そこに
許可(Refef=Allow)が明示してあれば、ウェブテーマとして取り込み、
photo.html 上でリンクする事ができます。 デフォールトは "Refer=Deny" と
してあります。 必要に応じて Refer=Allow を設定して下さい。

リモートのサイトから mkphotohtml によってリンクされたくない時は、ウェ
ブサーバが Contents.db をアクセスできないように owner と permission を
調整するのも良いでしょう。

リモートからあなたの Contents.db にアクセスでき、かつそこで
"Refer=Allow" を設定してあれば、この Mkphotohtml の性格上、リンクされ
る事を認めたものと解釈されます。

Mkphotohtml は許可された Contents.db から先の情報を探し回るような
はしたない事はしません。
アルバム作者の意図を壊すようなアクセスを極力排したつもりです。

あなたのアルバムのトップテーマにリンクするのは良いが、途中のサブテー
マにリンクするのを認めたくないなら、トップテーマの Contents.conf にの
み "Refer=Allow" を設定してください。


おまけ:
------
以下の二つのユーティリティ プログラムを付けておきます。

image-rotate : 画像の回転
getphotofromcard : カードから画像を incoming テーマとして取り
込み mkphotohtml を呼び出して photo.html ま
で作ります。
change_date.pl : Contents.db の日時部分を locale に準じた形式に
変換するフィルターです。
最新の GNU date コマンドが必要です。
UTF-8 に対応した nkf が必要です。
Debian の標準のインストールのままでは Sarge
以後でないと動作しません。
日本語 locale では日付部分が
"2003年 9月 17日 水曜日 16:29:58 JST" のよう
な形に入れ替わります。
is-utf8 : ファイル(STDIN を含む)の文字セットが UTF-8 かどうか
を調べる。

簡単なプログラムなので、コメントを見て詳細をハックして下さい。


その他:
------
著作権は GNU GPL Version 2 に準じます。(GPL-2 参照)
バグレポート、意見等は歓迎します。

.-.-.

YAMADA Kunihiro

unread,
Nov 11, 2003, 11:12:03 AM11/11/03
to
山田邦博です。

Mkphothhtml Version 2 の投稿です。

-...-

本投稿は 4部に分けて投稿します。
ANN (Announce)
DOC (Document: README)(1000行弱)
BIN (この投稿)
ETC (Etc: 日本語と英語のメッセージファイル)

-...-

Mkphotohtml Ver.2.0 の全てのファイルは
ftp://ftp.tksa.gr.jp/king/image/Mkphotohtml_2.0.tgz
にあります。
これには本投稿にはない、インストーラ、小さな関連プログラム(便利グッズ)、
設定例、細かいドキュメントが含まれています。

最新の Mkphotohtml (ドキュメントを含む)については
http://www.tksa.gr.jp/king/Software/Mkphotohtml/index.html
を参照して下さい。
そこに実例も示しておきました。


=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
#!/bin/sh
# This is a shell archive (produced by GNU sharutils 4.2.1).
# To extract the files from this archive, save it to some FILE, remove
# everything before the `!/bin/sh' line above, then type `sh FILE'.
#
# Made on 2003-11-11 17:48 JST by <king@owlin>.
# Source directory was `/home/king/src/image/Mkphotohtml_2.0/bin'.
#
# Existing files will *not* be overwritten unless `-c' is specified.
#
# This shar contains:
# length mode name
# ------ ---------- ------------------------------------------
# 68563 -rwxr-xr-x mkphotohtml
#
save_IFS="${IFS}"
IFS="${IFS}:"
gettext_dir=FAILED
locale_dir=FAILED
first_param="$1"
for dir in $PATH
do
if test "$gettext_dir" = FAILED && test -f $dir/gettext \
&& ($dir/gettext --version >/dev/null 2>&1)
then
set `$dir/gettext --version 2>&1`
if test "$3" = GNU
then
gettext_dir=$dir
fi
fi
if test "$locale_dir" = FAILED && test -f $dir/shar \
&& ($dir/shar --print-text-domain-dir >/dev/null 2>&1)
then
locale_dir=`$dir/shar --print-text-domain-dir`
fi
done
IFS="$save_IFS"
if test "$locale_dir" = FAILED || test "$gettext_dir" = FAILED
then
echo=echo
else
TEXTDOMAINDIR=$locale_dir
export TEXTDOMAINDIR
TEXTDOMAIN=sharutils
export TEXTDOMAIN
echo="$gettext_dir/gettext -s"
fi
if touch -am -t 200112312359.59 $$.touch >/dev/null 2>&1 && test ! -f 200112312359.59 -a -f $$.touch; then
shar_touch='touch -am -t $1$2$3$4$5$6.$7 "$8"'
elif touch -am 123123592001.59 $$.touch >/dev/null 2>&1 && test ! -f 123123592001.59 -a ! -f 123123592001.5 -a -f $$.touch; then
shar_touch='touch -am $3$4$5$6$1$2.$7 "$8"'
elif touch -am 1231235901 $$.touch >/dev/null 2>&1 && test ! -f 1231235901 -a -f $$.touch; then
shar_touch='touch -am $3$4$5$6$2 "$8"'
else
shar_touch=:
echo
$echo 'WARNING: not restoring timestamps. Consider getting and'
$echo "installing GNU \`touch', distributed in GNU File Utilities..."
echo
fi
rm -f 200112312359.59 123123592001.59 123123592001.5 1231235901 $$.touch
#
if mkdir _sh01288; then
$echo 'x -' 'creating lock directory'
else
$echo 'failed to create lock directory'
exit 1
fi
# ============= mkphotohtml ==============
if test -f 'mkphotohtml' && test "$first_param" != -c; then
$echo 'x -' SKIPPING 'mkphotohtml' '(file already exists)'
else
$echo 'x -' extracting 'mkphotohtml' '(text)'
sed 's/^X//' << 'SHAR_EOF' > 'mkphotohtml' &&
#! /usr/bin/perl -w
X
# mkphotohtml : Make photo.html
#
X
# Author:
# YAMADA Kunihiro <ki...@tksa.gr.jp>
# (http://www.tksa.gr.jp/king/)
#
# Copyright policy:
# GNU GPL Ver.2
#
X
# Usage:
# mkphtohtml [option] [directories ...]
# Options:
# -b : Back button added to photo.html (Default: Not added)
# -c : Clean bogus shrinked images
# -C characterset : Specify charset to characterset for Contents.conf
# -D : Debug
# -e string : add string as epilog to photo.html
# -f : Force update
# -h : Help
# -l lang : Set laguage to lang for messages of photo.html
# -m mailaddress :
# Mail address like as 'you...@your.domain'
# -o : Default theme options for Contents.conf:
# There are many sub options.
# The format is "Sub-Option=value,...."
# Type "mkphothtml -h: for detail theme options,
# or read README.jp.txt for more detail
# -p string : add string as prolog to photo.html
# -r : Recursive
# -s : Suppress start page infomation in HTML header
# -t url :
# address or URL of Top page for start
# -u Username :
# Full name of user like as "Firstname Lastname"
# -v : Verbose messages
# -w : check web page
#
# Directories:
# Directory list of the themes. (Default : current directory(.))
#
X
# Documents:
# Following documents are available;
# BUGS.jp.txt
# Change.log
# Format.txt
# INSTALL.jp.txt
# MUMBLE.jp.txt
# README.jp.txt (Japanese text only, sorry)
#
X
# Latest version:
# You can get the latest version and it's documents from
# my web page;
# http://www.tksa.gr.jp/king/Software/Mkphothtml/
#
X
# History:
# (Please see other document "Change.log" for detail.)
# 28 Dec.2000 starting Ver.0.0
# 11 Apr.2001 Ver.0.0
# 9 Jun.2003 starting Ver.1.0
# 21 Jun.2003 rewritten almost
# 22 Jul.2003 Ver.1.0-pre.1 : Released
# 29 Jul.2003 Ver.1.0 : Released
# 2 Aug.2003 Ver.1.0-patch.01 : Released
# 12 Sep.2003 Ver.1.1 : Released
# 8 Oct.2003 Ver.2.0-pre.02 : Released
# 11 Oct.2003 Ver.2.0-pre.03 : Released
# 18 Oct.2003 Ver.2.0-pre.04 : Released
# 11 Nov.2003 ver.2.0 : Released
#
X
no lib qw(:ALL .);
use strict qw(vars subs refs);
use Getopt::Std;
use Cwd;
use File::Basename;
use File::stat;
use Time::localtime;
use HTTP::Date;
use LWP::Simple;
use IPC::Open2;
use Net::Domain qw(hostfqdn hostdomain);
use Image::Size 'html_imgsize';
use Unicode::MapUTF8 qw(to_utf8 utf8_supported_charset);
use vars qw($opt_b $opt_c $opt_C $opt_D $opt_e $opt_f $opt_h $opt_l $opt_m
X $opt_o $opt_p $opt_r $opt_s $opt_t $opt_u $opt_v $opt_w);
X
die "$0 : \"Root user or group\" is prohibitted, sorry.\n"
X if $< == 0 or $> == 0 or $( == 0 or $) == 0; # uid,euid,gid,egid : root?
X
#######################################
### Please configure for your needs ###
#######################################
X
umask 022;
my $DMODE = 0755; # Permission for directory
my $CONFIG = "Contents.conf"; # Configure file for contents
my $CONTENT = "Contents.db"; # Contents file (generated)
my $HTML = "photo.html"; # HTML file (generated)
my $IMGEXT = "jpeg|JPEG|jpg|JPG"; # Extention of Image file
my $ORIG = "ORIG"; # Extention of Original image file
my $PREHTTP = ".http."; # Prefix of web theme file
my $SLASHHTTP = "%"; # Replace slashes of url for web theme file
X
## program path ##
my $DJPEG = "/usr/bin/djpeg"; # decompress a JPEG file to an image file
my $CJPEG = "/usr/bin/cjpeg"; # compress an image file to a JPEG file
my $JPEGTOPNM = "/usr/bin/jpegtopnm -quiet";
X # convert JFIF file to portable pixmap
my $PNMSCALE = "/usr/bin/pnmscale"; # scale a PNM image
my $PNMTOJPEG = "/usr/bin/pnmtojpeg"; # convert PNM image to a JFIF image
X
## Limit for web
my $MAXWEBDOCLENGTH = 1000000; # Maximum allowed size for web page
X
## default for option -o ##
## These options can be changed by option -o or system and user option file,
## and can be overlayed temporaly by $CONFIG file on each theme directory.
## Caution: These default options are not checked these validity,
## so take care when you change these default values!
## System wide options (/etc/mkphotohtml/option) are recommended.
##
$::opt_charset = "iso-2022-jp"; # charset for Contents.conf file
X # UTF-8 if ""
$::opt_lang = "Japanese"; # Language for message
$::opt_order = "New-First"; # , New-Last, Theme-First or Image-First
$::opt_image = "Reverse"; # or Normal
$::opt_theme = "Reverse"; # or Normal
$::opt_config = "Non"; # , First or Last
$::opt_mail = '$userid@$domain'; # your mail address
$::opt_uname = '$passwd'; # your name like as "First Middle Last"
$::opt_scale = "(1/1=:raw)(1/2=:shrink)(1/4=:shrink)(1/8=:shrink)";
X # Scale and Directory name for raw and shrinked pictures
$::opt_size = "(Normal=1/2)(Header=1/4)(Index=1/8)";
X # Size of Picture for Normal, Header and Indicies display
$::opt_back = "No"; # or Yes (Back button added to photo.html)
$::opt_start = "Yes"; # or No (start page added in HTML header)
$::opt_top = "/index.html"; # link to Top page or URL
$::opt_ckweb = "No"; # or Yes (Check Web theme page)
$::opt_refer = "Deny"; # or Allow (refer for photo album)
$::opt_prolog = '$copyright: $uname <$Mail>';
X # Any string for prolog clause
X # $copyrigh := $html_message{$::opt_lang}->{Copyright}
X # $uname := $::opt_uname
X # $Mail := $::opt_mail
$::opt_epilog = ""; # Any string for epilog clause
X
#############################
### End of Configuration ###
#############################
X
X
### Constants ###
my $VERSION = "2.0";
my $WEBINFO = "http://www.tksa.gr.jp/king/Software/Mkphothtml/";
X
my $PFIRST = "[-_]?(?:First|1st|Fir)";
my $PLAST = "[-_]?Last?";
my $PTHEME = "The(?:m[ea]?)?";
my $PDIR = "Dir(?:ectory)?";
my $PIMAGE = "Ima(?:ge)?";
my $PNAME = basename $0;
my $LPNAME = "\L$PNAME\E";
my $UPNAME = "\U$PNAME\E";
my $SYSCONFDIR = "/etc/$LPNAME";
my $USERCONFDIR = "$ENV{HOME}/etc/$LPNAME";
X
### Global valiables ###
my $picrawdir; # Directory name for raw images
my %scale_dir; # Scale-Directory
my %picheader; # Picture(Header,Index,Norml)-Scale
my %shrink_name; # shrink name(extention) inserted into image file name
my @sorted_scale; # Sorted scale of Pictures
my %version_checked;
my %html_message; # messages for html with multi lingual.
X # $html_message{$::opt_lang}->{Item}
X
my ($CLEAN,$DEBUG,$FORCEUPDATE,$HELP,$RECURSIVE,$VERBOSE);
X
getopts('bcC:De:fhl:m:op::rst:u:vw');
$CLEAN = $opt_c;
$DEBUG = $opt_D;
$FORCEUPDATE = $opt_f;
$HELP = $opt_h;
$RECURSIVE = $opt_r;
$VERBOSE = $opt_v;
X
sub set_option_from_file ( $;$ );
sub set_option ( $$;$ );
sub set_messages ( $ );
sub check_version ( $$;$ );
sub makephoto ( @ );
sub set_charset ( $ );
sub sanitize_meta ( $;$ );
X
X
if (-r "/etc/$PNAME/option") {
X set_option_from_file("/etc/$PNAME/option"); # System wide options
X warn <<EOF if $VERBOSE;
System wide option file "/etc/$PNAME/option" is read.
X Default theme-options are override.
EOF
}
X
if (-r "$USERCONFDIR/option") {
X set_option_from_file("$USERCONFDIR/option"); # User options
X warn <<EOF if $VERBOSE;
User theme options are set by "$USERCONFDIR/option".
X Default theme-options are override.
EOF
}
X
X
if ($HELP) {
X my @langs;
X foreach my $f (glob "/etc/$PNAME/message.* $USERCONFDIR/message.*") {
X next unless $f =~ m!/message\.(\w+)$!;
X next unless -r $f;
X my $lang = "\u$1";
X push @langs,$lang unless grep($_ eq $lang, @langs);
X }
X my $langs = join(',', sort(@langs));
X
X print <<EOF;
X
This is Mkphotohtml version $VERSION
X
Copyright 2001-2003, YAMADA Kunihiro <king\@tksa.gr.jp>
X
You can get the latest version from
\t$WEBINFO
X
X
Usage: $PNAME [option] [directories ...]
X
Options:
X -b : Back button added to photo.html
X (same as -o Back=Yes)
X -c : Clean up bogus shrinked images
X -C characterset :
X Specify charset to characterset for Contents.conf
X (same as -o Charset=characterset)
X -D : Debug
X -e string :
X add string as epilog to photo.html
X -f : Force update
X -h : Help
X -l lang :
X Set laguage to lang for messages of photo.html
X (same as -o Language=lang)
X -m mailaddress :
X Mail address like as 'yourid\@your.domain'
X (same as -o Mail-Address=yourid\@your.domain)
X -o : Default theme options for $CONFIG:
X Charset=characterset
X Language=any-language (Default : $::opt_lang)
X Note: You can specify any language if you prepared a proper
X message file.
X Order=New-First|New-Last|Theme-First|Image-First (Default : $::opt_order)
X Image=Reverse|Normal (Default : $::opt_image)
X Theme=Reverse|Normal (Default : $::opt_theme)
X Config=Non|First|Last (Default : $::opt_config)
X Mail-Address=yourid\@your.domain (Default : $::opt_mail)
X User-Name="FirstName LastName" (Default : $::opt_uname)
X Scale-Directory=(scale1=directory1)(scale2=directory2)....
X (Scale and Directory name for raw and shrinked pictures)
X Default : $::opt_scale
X Size-of-Picture=(display1=scale1)(display2=scale2)....
X (Size of Picture for Normal, Header and Indices display)
X Default : $::opt_size
X Back=No|Yes (Default : No)
X Start=Yes|No (Default : Yes)
X Top=url of top page (Default : /index.html)
X Check-Web=No|Yes (Default : No)
X Refer=Deny|Allow (Default : Deny)
X Prologue=any-string (Default : "$::opt_prolog")
X Epilogue=any-string (Defualt : "$::opt_epilog")
X -p string :
X add string as prolog to photo.html
X -r : Recursive
X -s : Suppress start page infomation in HTML header
X (Same as -o Start=No)
X -t url :
X address or URL of Top page for start
X (same as -o Top=url)
X -u username :
X Full name of user like as "Firstname Lastname"
X (same as -o "User-Name=Firstname Lastname")
X -v : Verbose messages
X -w : check web page
X (same as -o Check-Web=Yes)
X
Directories:
X Directory list of the themes. (Default : current directory(.))
X
Current usable languages by system and user defaults are
\t$langs.
X
EOF
X exit 0;
}
X
X
if (exists $ENV{$UPNAME}) {
X foreach (split m/,/,$ENV{$UPNAME}) {
X set_option("ENV",$_); # Options from Enviroment
X warn <<EOF if $VERBOSE;
Theme options are set by the environment "$UPNAME".
X Default theme-options are override.
EOF
X }
}
X
$::opt_charset = $opt_C if $opt_C;
{
X my $erm = set_charset($::opt_charset);
X if ($erm) {
X die <<EOF;
Bad command option: "-C $::opt_charset"
\t$erm
EOF
X }
}
X
set_option("sh","Language=$opt_l") if $opt_l; # Default language for message
$::opt_back = "Yes" if $opt_b; # Back button
$::opt_mail = $opt_m if $opt_m; # Mail address
if ($opt_m) {
X die <<EOF unless $opt_m =~ /\@/;
Bad command option: "-m $opt_m" : should be included "\@".
EOF
}
X
set_option("sh","Prolog=$opt_p") if $opt_p; # Add prolog clause to photo.html
set_option("sh","Epilog=$opt_e") if $opt_e; # Add epilog clause to photo.html
$::opt_start = "No" if $opt_s; # Start page info. into HTML header
$::opt_top = $opt_t if $opt_t; # address or URL of Top page
set_option("sh","User-Name=$opt_u") if $opt_u; #User Name
$::opt_ckweb = "Yes" if $opt_w; # check web theme page
if ($opt_o) { # Option -o (from sh command)
X foreach (split m/,/,$opt_o) {
X set_option("sh",$_);
X }
X warn <<EOF if $VERBOSE;
Theme options are set by the shell command option "-o".
X Default theme-options are override.
EOF
}
X
set_option("Default","Language=$::opt_lang"); # make sure while no option
X
unshift @ARGV, "." unless @ARGV; # add default directory to current
X
makephoto(@ARGV);
Xexit 0;
X
######################################################################
X
sub is_utf8 ( $ ) {
X my $s = shift;
X while ($s =~ s/^(.)//s) {
X return 0 if $1 eq "\e"; # JIS or other charset with ESC
X my $c = ord($1);
X next unless $c & 0x80; # ASCII
X my $n;
X if (($c & 0xe0) == 0xc0) {
X $n = 2;
X } elsif (($c & 0xf0) == 0xe0) {
X $n = 3;
X } elsif (($c & 0xf8) == 0xf0) {
X $n = 4;
X } elsif (($c & 0xfc) == 0xf8) {
X $n = 5;
X } elsif (($c & 0xfe) == 0xfc) {
X $n = 6;
X } else {
X return 0;
X }
X for (my $i=2; $i<=$n; ++$i) {
X $s =~ s/^(.)//s;
X return 0 unless (ord($1) & 0xc0) == 0x80;
X }
X }
X return 1;
}
X
sub get_config ( \*$ ) {
X my ($in,$f) = @_;
X local (*FH) = $$in;
X local ($_);
X return "" if eof(FH);
X while (<FH>) {
X $::ILN = $.;
X chomp;
# print "#",__LINE__,"# $.: \"$_\"\n" if $DEBUG;
X next if /^\s*$/; # Null line
X my $sv = $_;
X $_ = to_utf8({ -string => $_, -charset => $::opt_charset })
X if $::opt_charset;
X next if /^\s*\#/; # line with only comment
# print "#",__LINE__,"# ",($sv eq $_ ? "SAME" : "DIFF"),"\n" if $DEBUG;
X s/^\s+/\t/; # replace preceding spaces with single tab
X s/\s+$//; # remove trailing spaces
X s/\s+\#.*//; # remove comment part
# print "#",__LINE__,"# Charset=($::opt_charset) # $.: ($_)\n" if $DEBUG;
X if (is_utf8($_)) {
X return $_;
X } else {
X my $erm;
X if ($::opt_charset) {
X $erm = "Can't convert charset from $::opt_charset to UTF-8";
X } else {
X $erm = "Non UTF-8 character found";
X }
X $f = cwd() . "/$f" unless $f =~ m(^/);
X die "$erm\n\tat \"$f\" line $.\n";
X }
X }
X return "";
}
X
sub set_charset ( $ ) {
X $::opt_charset = shift;
X $::opt_charset = "" unless $::opt_charset;
X return undef unless $::opt_charset;
X if ($::opt_charset =~ /^utf[-_]?8$|^(us[-_]?)?ascii$/i) {
X $::opt_charset = ""; # Default setting
X return undef;
X }
X $::opt_charset = "jis" if $::opt_charset =~ /^iso-2022-jp$/i;
X # avoid bug?
X # to_utf can't convert properly from iso-2022-jp
X return undef if utf8_supported_charset($::opt_charset);
X return "Charset \"$::opt_charset\" is not supported.";
}
X
sub check_scale ( $ ) {
X my $scale = shift;
X my $v = 0;
X my $mes;
X if ($scale =~ /^(\d+)$/) {
X $v = $1;
X } elsif ($scale =~ /^(\d*)\.(\d*)$/) {
X $v = (($1 or $2) ? $scale + 0 : 0);
X } elsif ($scale =~ m!^(\d+)/(\d+)$!) {
X if ($2) {
X $v = $1 / $2;
X } else {
X $mes = "Bad scale value($scale) : cannot divide by 0.";
X }
X } else {
X $mes = "Bad scale format \"$scale\".";
X }
X if (not $mes and ($v > 1 or $v ==0)) {
X $mes = "Bad scale value($v): should be >0 and <=1.";
X }
X return ($v,$mes);
}
X
sub set_option_from_file ( $;$ ) {
X my $file = shift;
X my $only_scale_size = shift;
# my $save_ILN = $::ILN;
X local $::ILN;
X local $_;
X print "#",__LINE__,"# set_option_from_file, (",cwd,")($file) ",($only_scale_size?"ONLY":"ALL"),"\n" if $DEBUG;
X open(INF,"<$file") || die "Cannot open file $file : $!";
X my $from = "conf";
X $from = "db" if $file =~ /$CONTENT$/;
X $from = "$file" if $file =~ m!/!;
X OUTER:
X while ($_ = get_config(*INF,$file)) {
X if (/^Ver(sion)?:/i) {
X if ($_ = get_config(*INF,$file)) {
X check_version($file,$_);
X }
X } elsif (/^Opt(ion)?:$/i) {
X while ($_ = get_config(*INF,$file)) {
X last OUTER if /^\S/;
X unless ($only_scale_size) {
X if (s/^\s+(Pro|Epi)(?:log|logue)?\s*=\s*//i) {
X my $pt = ($1 =~ /Pro/i ? \$::opt_prolog : \$::opt_epilog);
X print "#",__LINE__,"# SETOPTF: ProEpi ($_)\n" if $DEBUG;
X $$pt = $_;
X while ($_ = get_config(*INF,$file)) {
X print "#",__LINE__,"# SETOPTF: ProEpi ($_)\n" if $DEBUG;
X last if /^\S|^\s+[\w\.-]+\s*=/;
X s/^\s+//;
X $$pt .= "\n\t\t $_";
X }
X redo;
X }
X }
X set_option($from,$_,$only_scale_size);
X }
X }
X }
X close(INF);
# $::ILN = $save_ILN;
}
X
sub set_option ( $$;$ ) {
X my $from = shift;
X local $_ = shift;
X my $only_scale_size = shift;
X print "#",__LINE__,"# set_option from='$from' \$_='$_'\n" if $DEBUG;
X s/^\s+//;
X s/\s+$//;
X my $errmes;
X if ($from eq "conf") {
X $errmes = "Error at " . cwd() . "/$CONFIG line $::ILN :";
X } elsif ($from eq "db") {
X $errmes = "Error at " . cwd() . "/$CONTENT line $::ILN :";
X } elsif ($from eq "sh") {
X $errmes = "Error in \"-o option\" on shell command:";
X } elsif ($from eq "ENV") {
X $errmes = "Error in Environment \"$UPNAME\":";
X } elsif ($from eq "Default") {
X $errmes = "Error while default setting:";
X } else { # Contents.db or mkphotohtml.conf
X $errmes = "Error at $from line $::ILN:";
X }
X
X if (s/Sca(le)?([-_]?($PDIR)?)?\s*=\s*//io) {
X s/\s+//g;
X $::opt_scale = $_;
X $::opt_size = ""; # option_size should be set later
X my %vlist;
X while (s/^\((.*?)\)//) {
X my $s = $1;
X unless ($s =~ /(.*)=(.*)/) {
X die <<EOF;
$errmes
\t"Scale-Directory=" should be formed as "(Scale=Directory)".
EOF
X }
X my ($scale,$dir) = ($1,$2);
X my ($v,$mes) = check_scale($1);
X die <<EOF if $mes;
$errmes
\t"Scale-Directory=" ($s)
\t\t$mes
EOF
X die <<EOF if exists $vlist{$v};
$errmes
\t"Scale-Directory=($s)" :
\t\tThe value($v) of the scale($scale) is doubly defined.
EOF
X $vlist{$v} = $dir;
X }
X die <<EOF if $_;
$errmes
\t"Scale-Directory=" : Bad format.
EOF
X die <<EOF unless exists $vlist{1};
$errmes
\t"Scale-Directory=" should be specified the raw image directory that
\t the value of scale is 1.
EOF
X my $c1 = substr($vlist{1},0,1); # 1st character of image directory name
X for my $v (keys %vlist) {
X my $cx = substr($vlist{$v},0,1);
X die <<EOF unless $c1 eq $cx;
$errmes
\t"Scale-Directory=$::opt_scale" :
\t First character of directory name should be same.
\t (First character of raw image directory is "$c1", but
\t the one of scale of $v is "$cx".)
EOF
X }
X } elsif (s/Size?([-_]?(of[-_]?)?Pic(ture)?)?\s*=\s*//i) {
X s/\s+//g;
X my ($h,$i,$n);
X while (s/^\(.+?\)//) {
X my $s = $&;
X if ($s =~ /\(\s*([^\s=]*)\s*=\s*([^\s\)]*)\s*\)/) {
X my $picture = $1;
X my $scale = $2;
X unless ($picture =~
X /^Nor(mal)?$|^N$|^Hea(der)?$|^H$|^Ind(ex)?$|^Indices$|^I$/i) {
X die <<EOF;
$errmes
\t"Size-of-Picture=" should be formed as "(Display=Scale)".
\t\t(Display=Scale)=($picture=$scale) : Bad Display specified.
\t\t\tDisplay is one of "Normal", "Header" and "Index".
EOF
X }
X die <<EOF unless $::opt_scale =~ /\($scale=/;
$errmes
\tOption: Size-of-Picture=($picture=$scale)
\t Scale($scale) not found on Scale-Directory.
EOF
X $h = $scale if $picture =~ /^H/i;
X $i = $scale if $picture =~ /^I/i;
X $n = $scale if $picture =~ /^N/i;
X }
X }
X die <<EOF if $_;
$errmes
\t"Size-of-Picture='$_'" : Bad format.
EOF
X die <<EOF unless $h and $i and $n;
$errmes
\t"Size-of-Picture=" should have Normal,Header and Index.
EOF
X $::opt_size = "(Normal=$n)(Header=$h)(Index=$i)";
# print "#",__LINE__,"# option_size='$::opt_size'\n" if $DEBUG;
X } elsif ($only_scale_size) { # truncate here if only scale size
X return;
X } elsif (s/^(Lan(guage)?|Lang)\s*=\s*//i) {
X $::opt_lang = "\L$_\E";
X unless (exists $html_message{$_}) {
X ### set default messages from files ###
X my $smfile = "$SYSCONFDIR/message.$::opt_lang";
X my $umfile = "$USERCONFDIR/message.$::opt_lang";
X set_messages($smfile) if -r $smfile;
X set_messages($umfile) if -r $umfile;
X die <<EOF unless -r $smfile or -r $umfile;
$errmes
\tLanguage "\u$::opt_lang" is not supported.
\tNo message file (message.$::opt_lang).
EOF
X }
X } elsif (s/^Ord(er)?\s*=\s*//i) {
X if (/^New$PFIRST$|^Old$PLAST$/io) {
X $::opt_order = "New-First";
X } elsif (/^New$PLAST$|^Old$PFIRST$/io) {
X $::opt_order = "New-Last";
X } elsif (/^$PTHEME$PFIRST$|^$PDIR$PFIRST$|^$PIMAGE$PLAST$/io) {
X $::opt_order = "Theme-First";
X } elsif (/^$PIMAGE$PFIRST$|^$PTHEME$PLAST$|^$PDIR$PLAST$/io) {
X $::opt_order = "Image-First";
X } else {
X die <<EOF;
$errmes
\t"Option: Order=" should be New-First (Old-Last)
\t or New_Last (New-First)
\t or Theme-First (Image-Last)
\t or Image-First (Theme-Last)
EOF
X }
X } elsif (s/$PIMAGE\s*=\s*//i) {
X if (/^Nor(mal)?$/i) {
X $::opt_image = "Normal";
X } elsif (/^Rev(erse)?$/i) {
X $::opt_image = "Reverse";
X } else {
X die <<EOF;
$errmes
\t"Option: Image=" should be "Normal" or "Reverse"
EOF
X }
X } elsif (s/($PTHEME|$PDIR)\s*=\s*//io) {
X if (/^Nor(mal)?$/i) {
X $::opt_theme = "Normal";
X } elsif (/^Rev(erse)?$/i) {
X $::opt_theme = "Reverse";
X } else {
X die <<EOF;
$errmes
\t"Option: Theme=" should be "Reverse" or "Normal"
EOF
X }
X } elsif (s/Con(fig)?\s*=\s*//i) {
X if (/^Non$/i) {
X $::opt_config = "Non";
X } elsif (/^(First|1st|Fir)$/i) {
X $::opt_config = "First";
X } elsif (/^Last?$/i) {
X $::opt_config = "Last";
X } else {
X die <<EOF;
$errmes
\t"Option: Config=" should be "Non" or "Normal" or "Reverse"
EOF
X }
X } elsif (s/^Cha(rset)?\s*=\s*//i) {
X my $erm = set_charset($_);
X die <<EOF if $erm;
$errmes
\t$erm
EOF
X } elsif (s/^Mail?([-_]?Add(ress)?)?\s*=\s*//i) {
X $::opt_mail = $_;
X die <<EOF unless not $_ or /\@/;
$errmes
\t"Option: Mail=$_" : should be included "\@".
EOF
X } elsif (s/^User?([-_]?Name?)?\s*=\s*//i) {
X $::opt_uname = $_; # Name of User
X } elsif (s/^Back?\s*=\s*//i) {
X if (/^Yes$|^Use$/i) {
X $::opt_back = "Yes";
X } elsif (/^No[nt]?$/i) {
X $::opt_back = "No";
X } else {
X die <<EOF;
$errmes
\t"Option: Back=" should be "Yes" or "No" ("Use" or "Non" can be used).
EOF
X }
X } elsif (s/^Sta(rt)?\s*=\s*//i) {
X if (/^Yes$|^Use$/i) {
X $::opt_start = "Yes";
X } elsif (/^No[nt]?$/i) {
X $::opt_start = "No";
X } else {
X die <<EOF;
$errmes
\t"Option: Start=" should be "Yes" or "No" ("Use" or "Non" can be used).
EOF
X }
X } elsif (s/^Top\s*=\s*//i) {
X $::opt_top = $_;
X } elsif (s/^Che(ck)?([-_]?Web)?\s*=\s*//i) {
X if (/^Yes$|^On$/i) {
X $::opt_ckweb = "Yes";
X } elsif (/^No$|^Off$/i) {
X $::opt_ckweb = "No";
X } else {
X die <<EOF
$errmes
\t"Option: Check-Web=" should be "Yes" or "No" ("On" or "Off" can be used).
EOF
X }
X } elsif (s/^Ref(er)?\s*=\s*//i) {
X if (/^All(ow)?$/i) {
X $::opt_refer = "Allow";
X } elsif (/^Deny?$/i) {
X $::opt_refer = "Deny";
X } else {
X die <<EOF;
$errmes
\t"Option: Refer=" should be "Allow" or "Deny".
EOF
X }
X } elsif (s/^(Pro|Epi)(?:log|logue)?\s*=\s*//i) {
X # from Command line option or Environment
X my $pe = $1;
X if ($pe =~ /Pro/i) {
X $::opt_prolog = $_;
X } else {
X $::opt_epilog = $_;
X }
X } elsif (/^$/) {
X # skip
X } else {
X die <<EOF;
$errmes
\tOption: "$_" is bad theme option.
EOF
X }
} # end of set_option
X
sub set_messages ( $ ) {
X my $msgfile = shift;
X $msgfile =~ s/^\s+//;
X $msgfile =~ s/\s+$//;
X return unless $msgfile;
X $msgfile =~ /\.([^.]+)$/;
X my $fext = $1;
# my $save_ILN = $::ILN;
X local $::ILN;
X local $::opt_charset = "";
X local $_;
X my ($lang,$album,$comment,$theme,$webtheme,$latest,$arrow);
X my $back = "";
X my $copyright = "";
X die "\"$msgfile\" : Bad message file name.\n" unless $msgfile =~ /^[\/.\w]/;
X $msgfile = cwd . "/$msgfile" unless $msgfile =~ m!^/!;
X open(INMES,"<$msgfile") || die "Cannot open Message-File \"$msgfile\" : $!";
X while ($_ = get_config(*INMES,$msgfile)) {
# print "#",__LINE__,"# title: \"$_\"\n" if $DEBUG;
X if (s/^\s*(\w+)\s*=\s*//i) {
X my $tl = $1;
X s/\"$// if s/^\"//; # remove quote
X my $item =$_;
X die <<EOF unless $item;
Error at $msgfile line $::ILN :
\tNo item for $tl found.
EOF
X if ($tl =~ /^Cha(rset)?$/i) {
X my $erm = set_charset($item);
X die <<EOF if $erm;
Error at $msgfile line $::ILN :
\t$erm
EOF
X } elsif ($tl =~ /^Lan(guage)?$/i) {
X $lang = "\L$item\E"; # lower case
X die <<EOF unless $lang eq $fext;
Specified language($lang) is not match with the file extension.
\tat message file ($msgfile) line $::ILN.
EOF
X } elsif ($tl =~ /^Alb(um)?$/i) {
X $album = sanitize_meta($item);
X } elsif ($tl =~ /^Com(ment)?$/i) {
X $comment = sanitize_meta($item);
X } elsif ($tl =~ /^The(me)?$/i) {
X $theme = sanitize_meta($item);
X } elsif ($tl =~ /^Web(Theme)?$/i) {
X $webtheme = sanitize_meta($item);
X } elsif ($tl =~ /^Lat(est)?$/i) {
X $latest = sanitize_meta($item);
X } elsif ($tl =~ /^Arr(ow)?$/i) {
X $arrow = sanitize_meta($item);
X } elsif ($tl =~ /^Back?$/i) {
X $back = sanitize_meta($item);
X } elsif ($tl =~ /^Cop(yright)?$/i) {
X $copyright = $item;
X } else {
X die <<EOF;
Bad message item ($tl) :
\tat message file \"$msgfile\" line $::ILN.
EOF
X }
# redo;
X } elsif (/^$/) {
X last;
X } else {
X die <<EOF;
No proper message item found ($_) :
\tat message file \"$msgfile\" line $::ILN.
EOF
X }
X }
X close(INMES);
# $::ILN = $save_ILN;
X die "Language should be defined in message file \"$msgfile\"\n"
X unless $lang;
X $html_message{$lang} = {} unless $html_message{$lang};
X my $hml = $html_message{$lang};
X $hml->{Album} = $album if $album;
X $hml->{Comment} = $comment if $comment;
X $hml->{Theme} = $theme if $theme;
X $hml->{WebTheme} = $webtheme if $webtheme;
X $hml->{Latest} = $latest if $latest;
X $hml->{Arrow} = $arrow if $arrow;
X $hml->{Back} = $back if $back;
X $hml->{Copyright} = $copyright if $copyright;
X die "Some title and item not defined in message file \"$msgfile\"\n"
X unless $hml->{Album} and $hml->{Comment} and $hml->{Theme}
X and $hml->{WebTheme} and $hml->{Latest} and $hml->{Arrow}
X and $hml->{Copyright};
} # end of set_messages
X
sub get_mtime_of_original_file ( $ ) {
X my $f = shift;
X unless ($f =~ /(.*\/)?(.+)\.($IMGEXT)/) {
X die "!!BUG!! \$f=($f) : Bad image extension : ";
X }
X my $path = ($1 ? "$1$picrawdir" : $picrawdir);
X my $fname = $2;
X my $ext = $3;
X unless (-r "$path/$f") {
X print "#",__LINE__,"# no file: \"$path/$f\" \n" if $DEBUG;
X return undef;
X }
X my $f_orig;
X if ( -r "$path/$fname.$ORIG.$ext") {
X $f_orig = "$fname.$ORIG.$ext";
X } elsif (-r "$path/$fname.$ext.$ORIG") {
X $f_orig = "$fname.$ext.$ORIG";
X } else {
X $f_orig = "$fname.$ext";
X }
X return stat("$path/$f_orig")->mtime;
}
X
sub get_default_theme ( ;$ ) {
X my $fullpath = shift;
X local ($_) = (defined $fullpath ? $fullpath : cwd);
X s!/$!!; # remove last "/"
X s!.*/!!; # remove leading path
X $_ = "root" unless $_;
X return $_;
}
X
sub n_version ( $ ) {
X my $ver = shift;
X unless ($ver =~ /^(\d+)\.(\d+)(-[a-z][.\w]*)?$/i) {
X die "!!BUG!! bad version format : $!";
X }
X return $1+$2/1000;
}
X
sub check_version ( $$;$ ) {
X my ($file,$pname_version,$http) = @_;
X print "#",__LINE__,"# check_version : file=($file)\n" if $DEBUG;
X $file = cwd . "/$file" unless $file =~ m!/!;
X my $db = ($file =~ /\.db$/ ? 1 : 0);
X my $recommended = ($db ? "\"$PNAME -fr\" is recommended."
X : "Config-file should be corrected.");
X my $version;
X if ($pname_version =~ /^\s+(\S+)\s+(\d+)\.(\d+)(-[a-z][.\w]*)?$/) {
X $version = "$2.$3";
X $version .= $4 if $4;
X die <<EOF unless $1 eq $PNAME;
X
Mismatched program!
X
X This program is "$PNAME".
X The specified program at $file line $::ILN
X is "$1".
$recommended
X
EOF
X my ($nV,$nv) = (n_version($VERSION),n_version($version));
X die <<EOF unless int($nV) == int($nv) and $nV >= $nv;
X
Mismatched version!
X
X The version of $PNAME
X is "$VERSION".
X The version at $file line $::ILN
X is "$version".
$recommended
X
EOF
X if ($VERSION ne $version and not exists $version_checked{$file}) {
X warn <<EOF;
X
Versions of $PNAME ($VERSION)
X and of $file line $::ILN ($version)
X are not exactly same, but accepted.
$recommended
X
EOF
X if ($version =~ /-pre/i) {
X warn <<EOF;
### Mismatched pre-released-version may cause curious phenomena. ###
### Please take care! ###
X
EOF
X }
X }
X } else {
X s/^\s+//;
X die <<EOF;
X
Improper version format ($_) is detected.
\tat $file line $::ILN.
X
$recommended
X
EOF
X }
X $version_checked{$file} = 1;
X return $version;
}
X
X
sub getTheme ( $;$ ) {
X my ($file,$http) = @_; # Contents-File, url
# my $save_ILN = $::ILN;
X local $::opt_charset = "";
X local $::ILN;
X local $_;
X my $dir = "";
X print "#",__LINE__,"# getTheme($file)\n" if $DEBUG;
X if ($file =~ m!/$!) {
X $dir = $file;
X $file .= $CONTENT;
X }
X my ($version,$theme,$image,$comment,$mtime);
X my $time_locale = "";
X open(CF,"$file") || die "Cannot open $file : $!";
X SECTION:
X while ($_ = get_config(*CF,$file)) {
X my $iln = $::ILN;
X if (/^Option:/) {
X while ($_ = get_config(*CF,$file)) {
X redo SECTION if /^\S/; # Skip Option: section
X }
X } elsif (/^Version:/) {
X if ($_ = get_config(*CF,$file)) {
X $version = check_version($file,$_,$http);
X }
X } elsif (/^Theme:/) {
# print "#",__LINE__,"# getTheme (Theme:)\n" if $DEBUG;
X while($_ = get_config(*CF,$file)) {
X print "#",__LINE__,"# getTheme \$_=($_)\n" if $DEBUG;
X if (s/^\s+Theme\s*=\s*//) {
X $theme = $_;
X } elsif (s/^\s+Image\s*=\s*//) {
X $image = $_;
X my $info = "";
X while ($_ = get_config(*CF,$file)) {
X last if /^\S|^\s+[\w\.-]+=/;
X s/\s//g;
X $info .= "\n\t $_";
X }
X $image = $dir . $image unless $image =~ m(^http://)i;
X $image .= $info;
X $info =~ s/\s+//g;
X $info =~ s/\)\(/ /g;
X $info =~ s/[()]//g;
X my $i = 0;
X foreach my $im (split ' ',$info) {
X $i += 1 if $im =~ /^N/i;
X $i += 10 if $im =~ /^H/i;
X $i += 100 if $im =~ /^I/i;
X }
X die <<EOF unless $i == 111;
Broken contents-file: (No info for image)
\tat $file line $iln.
EOF
X redo;
X } elsif (s/^\s+Comment\s*=\s*//) {
X $comment = "$_";
X while ($_ = get_config(*CF,$file)) {
X last if /^\S|^\s+[\w\.-]+\s*=/;
X s/^\s+//;
X $comment .= "\n\t\t$_";
X }
X redo;
X } elsif (/^\s+Latest\s*=(\d+)/) {
X $mtime = $1;
X $time_locale = $1 if /\((.+)\)/;
# } elsif (/^\s+Mtime=(\d+)/) {
# $w_mtime = $1;
X } elsif (/^\S|^$/) {
X last;
X } else {
X die <<EOF;
Broken contents-file:
\tat $file line $::ILN.
"$PNAME -fr" is recommended.
EOF
X }
X }
X }
X last if $version and $theme;
X }
X close(CF);
X print "#",__LINE__,"# getTheme result : $version,$theme,$image,$comment,$mtime\n" if $DEBUG;
X die <<EOF unless $version;
Version is not found in the contents-file. (It might be too old.):
\t$file
"$PNAME -fr" is recommended.
EOF
X die <<EOF unless $theme and $image and $mtime;
"Theme:" section on the contents-file (as following) is broken.
\t$file
"$PNAME -fr" is recommended.
EOF
# $::ILN = $save_ILN;
X return ($theme,$image,$comment,$mtime,$time_locale);
} # end of getTheme
X
sub get_theme_image ( $ ) {
X my $dbf = shift;
X print "#",__LINE__,"# get_theme_image: dbf=($dbf)\n" if $DEBUG;
X die "!!BUG!! \"$dbf\" : not found : " unless -r $dbf;
# my $save_ILN = $::ILN;
X local $::ILN;
X local $_;
X my ($theme,$image,$comment,$mtime,$time_locale) = getTheme($dbf);
# $::ILN = $save_ILN;
X return $image;
}
X
sub get_shrink_size () {
# print "#",__LINE__,"# get_shrink_size\n" if $DEBUG;
X local $_ = $::opt_scale;
X die "!!BUG!! \"Option: Scale-Directory=\" is not set.\n" unless $_;
X %scale_dir = ();
X while (s/^\((.*?)\)//) {
X my $s = $1;
X $s =~ s/^\s+//;
X $s =~ s/\s+$//;
X if ($s =~ /(\S*)\s*=\s*(.*)/) {
X my $scale = $1;
X my $dir = $2;
X $scale_dir{$scale} = $dir;
X } else {
X die <<EOF;
\t"Option: Scale-Directory=" should be formed as "(Scale=Directory)".
EOF
X }
X }
X die "Bad format." if $_;
X $_ = $::opt_size;
X die <<EOF unless $_;
"Option: Size-of-Picture=" is not set.
\tNote: "Size-of-Picture" should be placed after "Scale-Directory"
EOF
X %picheader = ();
X while (s/^\((.*?)\)//) {
X my $s = $1;
X if ($s =~ /(.*)=(.*)/) {
X my $picture = $1;
X my $scale = $2;
X if ($picture eq "Normal") {
X $picheader{Normal} = $scale;
X } elsif ($picture eq "Header") {
X $picheader{Header} = $scale;
X } elsif ($picture eq "Index") {
X $picheader{Index} = $scale;
X } else {
X die "!!BUG!! \"Bad Option: Size=\" should be Normal|Header|Index.";
X }
X } else {
X die <<EOF;
\t"Option: Size-of-Picture=" should be formed as "(Title=scale)".
\t\t(Title is one of "Normal", "Header" and "Index".)
EOF
X }
X }
X die "Bad format.\n" if $_;
X
X my %value;
X foreach my $scale (keys %scale_dir) {
X my ($v,$mes) = check_scale($scale);
X die "In Scale-Directory:\n$mes\n" if $mes;
X if (exists $value{$v}) {
X die "!!BUG!! Scale value($v) doubly defined in Scale-Dierectory.";
X }
X $value{$v} = $scale;
X my $sn;
X if ($scale =~ m!(.+)/(.+)!) {
X $sn = "$1_$2";
X } elsif ($scale =~ m/(.*)\.(.*)/) {
X $sn = "$2" if (not defined $1 or $1 == 0);
X }
X $shrink_name{$scale} = ($v == 1 ? "" : ".$sn.");
X }
X unless (exists $value{1}) {
X die "!!BUG!! Raw image file (Scale=1) is not found.";
X }
X @sorted_scale = ();
X foreach my $v (sort keys %value) {
X unshift @sorted_scale,$value{$v};
X }
X $picrawdir = $scale_dir{$sorted_scale[0]};
} # end of get_shrink_size
X
sub get_only_shrink_size_from_file () {
# print "#",__LINE__,"# get_only_shrink_size_from_file\n" if $DEBUG;
X local %::option_scale = %::option_scale;
X local %::option_size = %::option_size;
X my $only_scale_and_size = 1;
X my $file;
X if (-r $CONFIG and -r $CONTENT) {
X $file = (stat($CONFIG)->mtime > stat($CONTENT)->mtime ?
X $CONFIG : $CONTENT);
X } elsif (-r $CONFIG) {
X $file = $CONFIG;
X } elsif (-r $CONTENT) {
X $file = $CONTENT;
X }
X set_option_from_file($file,$only_scale_and_size) if $file;
X get_shrink_size();
}
X
sub image_path ( $$;$ ) {
X my ($header,$o_image,$require_size) = @_;
# print "#",__LINE__,"# image_path header='$header' image='$o_image'\n" if $DEBUG;
X $o_image =~ s(.+/http://)(http://);
X my $image = $o_image;
X my $info = "";
X if ($image =~ s/\s*(\(.*)//) {
# print "#",__LINE__,"# \$image=($image)\n" if $DEBUG;
X $info = ($1 ? $1 : "");
# print "#",__LINE__,"# \$info=($info)\n" if $DEBUG;
X $info =~ s/\s+//g;
X $info =~ s/\)\(/ /g;
X $info =~ s/[()]//g;
X }
X unless ($image =~ /(.*)\.($IMGEXT)$/) {
X die "Bad image file name ($image) : ";
X }
X my ($base,$ext) = ($1,$2);
X my $path = "./"; # for mozilla
X ($path,$base) = ($1,$2) if $base =~ m!(.*/)([^/]+)$!;
X my $sub_theme = ($path and $path ne "./"); # sub theme image
X my $html_image_size;
X my $im_info;
X if ($info) {
X foreach my $im (split ' ',$info) {
# print "#",__LINE__,"# \$im=($im)\n" if $DEBUG;
X unless ($im =~ /^(.+)=([^,]+),([^,]+),([^,]+)$/) {
X die <<EOF;
Bad info for image "$o_image".
EOF
X }
X my ($hd,$scale,$dir,$wxh) = ($1,$2,$3,$4);
X $wxh =~ /(\d+)x(\d+)/;
X my $hiz = "width=\"$1\" height=\"$2\"";
X my $sn;
X if ($scale =~ m!(.+)/(.+)!) {
X $sn = "$1_$2";
X } elsif ($scale =~ m/(.*)\.(.*)/) {
X $sn = "$2" if (not defined $1 or $1 == 0);
X }
X $shrink_name{$scale} = ".$sn.";
X if ($hd =~ /^N(ormal)?$/) {
X next unless $header eq "Normal";
X $picheader{Normal} = $scale;
X $im_info = "N=$dir,$scale,$wxh";
X $html_image_size = $hiz;
X last;
X } elsif ($hd =~ /^H(eader)?$/) {
X next unless $header eq "Header";
X $picheader{Header} = $scale;
X $im_info = "H=$dir,$scale,$wxh";
X $html_image_size = $hiz;
X last;
X } elsif ($hd =~ /^I(ndex)?$/) {
X next unless $header eq "Index";
X $picheader{Index} = $scale;
X $im_info = "I=$dir,$scale,$wxh";
X $html_image_size = $hiz;
X last;
X } else {
X die <<EOF;
Bad info for image "$o_image".
EOF
X }
X $scale_dir{$scale} = $dir;
X }
X } elsif ($sub_theme) { # theme image
X my $oldwd = cwd;
X chdir $path; # goto theme sub-directory
X get_only_shrink_size_from_file();
X chdir $oldwd;
X }
X my $scale;
X my $dir;
X if ($header eq "Header" or $header eq "Index" or $header eq "Normal") {
X $scale = $picheader{$header};
X $header =~ /^(.)/;
X my $hd = $1;
X foreach my $im (split ' ',$info) {
X $im =~ /^(.).*=(.+)/;
X if ($hd eq $1) {
X $im_info = "$hd=$2";
X last;
X }
X }
X $dir = $scale_dir{$scale};
X } elsif ($header eq "Raw") {
X $scale = $sorted_scale[0];
X } else {
X $scale = $header;
X }
X $path .= $scale_dir{$scale};
X my $real_image_path;
X if ($scale eq $sorted_scale[0]) {
X $real_image_path = "$path/$base.$ext";
X } else {
X $real_image_path = "$path/$base$shrink_name{$scale}$ext";
X }
X if ($require_size and not $html_image_size) {
X die <<EOF if $path =~ /^http:/;
No info of "$header" size of the image on http:
\t$o_image
The version of mkphotohtml on the remote site might be mismatch with local one.
Try "mkphotohtml -fw" once to renew the cache file.
EOF
X $html_image_size = html_imgsize($real_image_path);
X }
X if ($require_size and not $im_info) {
X $html_image_size =~ /width=\"(\d+)/i;
X my $width = $1;
X $html_image_size =~ /height=\"(\d+)/i;
X my $height = $1;
X $header =~ /^(.)/;
X my $hd = $1;
X $im_info = "$hd=$scale,$dir,${width}x${height}";
X }
# print "#",__LINE__,"# real_image_path=($real_image_path)\n\tHD=($header) size=($html_image_size) im_info=($im_info)\n" if $DEBUG;
X get_shrink_size() if $sub_theme; # restore variables for scale and dir.
X if ($require_size) {
X return $real_image_path,$html_image_size,$im_info;
X } else {
X return $real_image_path;
X }
} # end of image_path
X
X
sub sanitize_meta ( $;$ ) {
X local $_ = shift;
X my $no_br = shift;
X return "" unless $_;
X s/\\\#/\#/g;
X s/&/&amp;/g;
X s/\"/&quot;/g;
X s/</&lt;/g;
X s/>/&gt;/g;
X s/^\s+/\t/mg;
X s/\n$//;
X s/\n/<br>\n/g unless $no_br;
X return $_;
}
X
######################################################################
X
my $depth = 0;
X
sub makephoto (@) {
X print "#",__LINE__,"# MAKEPHOTO dirs=`@_'\n" if $DEBUG;
X my @ds = @_;
X my $oldpwd = cwd;
X ++$depth;
X
X SPECIFIED_DIRECTORY:
X foreach my $d (@ds) {
X chdir $oldpwd;
X $d =~ s!/$!!;
X if (-l $d) {
X warn "\"$oldpwd/$d\" is symbolic link, skipped.\n" if $VERBOSE;
X next SPECIFIED_DIRECTORY;
X }
X chdir $d || die "Cannot change directory to \"$d\".\n";
X my $pwd = cwd; # Full Path
X if ($FORCEUPDATE) {
X if (-r $CONTENT) {
X rename "$CONTENT", "$CONTENT.OLD";
X warn <<EOF if $VERBOSE;
Force-update:
\t$pwd/$CONTENT renamed to $CONTENT.OLD
EOF
X }
X }
X my @dirs = ();
X my @dirs_rec = ();
X {
X get_only_shrink_size_from_file();
X foreach my $f (glob("*")) {
X next if $f =~ /^$ORIG$|^$ORIG\.|\.$ORIG$|\.$ORIG\./o;
X next if substr($f,0,1) eq substr($picrawdir,0,1);
X push @dirs, $f if -d $f;
X push @dirs_rec, $f if (-d $f && ! -l $f);
X }
X }
X if (@dirs_rec && $RECURSIVE) {
X makephoto(@dirs_rec);
X print "#",__LINE__,"# Back from recursive call. Now pwd=",cwd,"\n" if $DEBUG;
X }
X undef @dirs_rec;
X warn <<EOF if $VERBOSE;
Now, theme directory "$pwd" is processed.
EOF
X
X if ($CLEAN) {
X print "#",__LINE__,"# CLEAN\n" if $DEBUG;
X get_only_shrink_size_from_file();
X foreach my $scale (@sorted_scale[1..$#sorted_scale]) {
X my $dir = $scale_dir{$scale};
X if (-l $dir) {
X warn "\"$pwd/$dir\" is symbolic link, skipped.\n" if $VERBOSE;
X next;
X }
X my $cleaned;
X foreach my $f (glob "$dir/*") {
X next unless $f =~ m!/(.+)\.([^.]+)\.($IMGEXT)$!o;
X my $rf = "$1.$3";
X my $shrinkname = ".$2.";
X next unless $shrinkname eq $shrink_name{$scale};
X unless (-f "$picrawdir/$rf") {
X unlink $f;
X warn "unlink $pwd/$f\n" if $VERBOSE;
X $cleaned = 1;
X }
X }
X warn "Cleaned up bogus images on $dir\n"
X if $cleaned and $VERBOSE;
X }
X next SPECIFIED_DIRECTORY;
X } # end of CLEAN
X
X print "#",__LINE__,"# Now dir: ",cwd,"\n" if $DEBUG;
X my @tmp = ();
X while (my $d = shift @dirs) {
X if (-r "$d/$CONTENT") {
X push @tmp,$d;
X } else {
X warn "No $CONTENT under \"$pwd/$d/\" ... skipped\n";
X }
X }
X @dirs = @tmp;
X print "#",__LINE__,"# \@dirs=(@dirs)\n" if $DEBUG;
X
X my @images = ();
X foreach my $f (glob("$picrawdir/*")) {
X next if $f =~ /\.$ORIG$|\.$ORIG\./o;
X $f =~ s!.+/!!; # remove directory part
X push @images, $f
X if -r "$picrawdir/$f" and $f =~ /\.($IMGEXT)$/o;
X }
X print "#",__LINE__,"# \@images=(@images)\n" if $DEBUG;
X
X my $should_be_updated = $FORCEUPDATE;
X
X my $mkshrink;
X foreach my $f (@images) {
X my ($base,$dir,$ext) = fileparse $f, '\.[^.]*';
X push @images, $f if -r $f;
X foreach my $scale (@sorted_scale[1..$#sorted_scale]) {
X my $rawfile = image_path("Raw", $f);
X my $shrinkfile = image_path($scale,$f);
X unless (-e "$shrinkfile" &&
X (stat($shrinkfile)->mtime > stat("$rawfile")->mtime)) {
X unless (-d $scale_dir{$scale}) {
X mkdir $scale_dir{$scale},$DMODE;
X warn "Directory \"$pwd/$scale_dir{$scale}\" is created\n"
X if $VERBOSE;
X }
X warn "Shrink image(s) for \"$pwd/$picrawdir\".\n"
X if $VERBOSE and not $mkshrink;
X $mkshrink = 1;
X if ($scale =~ m!^1/[248]$!) {
X die "$DJPEG : cannot be executed.\n" unless -x $DJPEG;
X die "$CJPEG : cannot be executed.\n" unless -x $CJPEG;
X system "$DJPEG -scale $scale $rawfile | $CJPEG >$shrinkfile";
X } else {
X my ($v,$mess) = check_scale($scale);
X die "!!BUG!! $mess : " if $mess;
X die "$JPEGTOPNM : cannot be executed.\n" unless -x $JPEGTOPNM;
X die "$PNMSCALE : cannot be executed.\n" unless -x $PNMSCALE;
X die "$PNMTOJPEG : cannot be executed.\n" unless -x $PNMTOJPEG;
X system
X "$JPEGTOPNM $rawfile | $PNMSCALE $v | $PNMTOJPEG >$shrinkfile";
X }
X die "Cannot shrink $pwd/$rawfile.\n" if $?;
X $should_be_updated = 1
X }
X }
X }
X
X if (not $should_be_updated and -f $CONFIG and -f $CONTENT) {
X $should_be_updated = 1
X if stat($CONFIG)->mtime > stat($CONTENT)->mtime ;
X }
X if (-f $CONTENT) {
X unless ($should_be_updated) {
X if (@images) {
X foreach my $d (values %scale_dir) {
X if (! -d $d or stat($CONTENT)->mtime < stat($d)->mtime) {
X $should_be_updated = 1;
X print "#",__LINE__,
X "# No $d, or \$CONTENT($CONTENT) is older than $d\n" if $DEBUG;
X last;
X }
X }
X } else {
X warn "No image on $pwd\n" if $VERBOSE;
X }
X if (@dirs) {
X foreach my $d (@dirs) {
X if (stat($CONTENT)->mtime < stat($d)->mtime) {
X $should_be_updated = 1;
X print "#",__LINE__,"# \$CONTENT($CONTENT) is older than $d\n" if $DEBUG;
X last;
X }
X }
X } else {
X warn "No sub-theme directory on $pwd\n" if $VERBOSE;
X }
X }
X } else {
X $should_be_updated = 1;
X warn "$pwd/$CONTENT is not found.\n" if $VERBOSE;
X }
X
X unless ($should_be_updated) {
X warn "No update for $CONTENT and $HTML on $pwd\n" if $VERBOSE;
X next SPECIFIED_DIRECTORY;
X }
X
X ### $CONENT and $HTML should be updated. ###
X
X my $option_on;
X local $::opt_lang = $::opt_lang;
X local $::opt_order = $::opt_order;
X local $::opt_image = $::opt_image;
X local $::opt_theme = $::opt_theme;
X local $::opt_config = $::opt_config;
X local $::opt_mail = $::opt_mail;
X local $::opt_uname = $::opt_uname;
X local $::opt_charset = $::opt_charset;
X local $::opt_scale = $::opt_scale;
X local $::opt_size = $::opt_size;
X local $::opt_back = $::opt_back;
X local $::opt_start = $::opt_start;
X local $::opt_top = $::opt_top;
X local $::opt_ckweb = $::opt_ckweb;
X local $::opt_refer = $::opt_refer;
X local $::opt_prolog = $::opt_prolog;
X local $::opt_epilog = $::opt_epilog;
X
X my $theTheme_on;
X my $theTheme_theme = get_default_theme();
X my $theTheme_image;
X my $theTheme_comment = "";
X my $theTheme_latest;
X my @contents;
X if (-r $CONTENT) {
X rename "$CONTENT", "$CONTENT.OLD";
X warn "$pwd/$CONTENT : renamed to $CONTENT.OLD\n" if $VERBOSE;
X }
X
X if (-r $CONFIG) {
X warn "$pwd/$CONFIG is found.\n" if $VERBOSE;
X open(INCONFIG,$CONFIG) || die "Cannot read $pwd/$CONFIG : $!";
X while ($_ = get_config(*INCONFIG,$CONFIG)) {
###
X sub get_theme_items ( * ) {
X my $section = shift;
X print "#",__LINE__,"# CONFIG: get_theme_item:($section)\n" if $DEBUG;
X my ($theme,$image,$comment,$latest) = ("","","","");
X my $pwd = cwd;
X while ($_ = get_config(*INCONFIG,$CONFIG)) {
X last if /^\S|^$/;
X if (s/^\s+$PTHEME\s*=\s*//io) {
X $theme = $_;
X } elsif (s/^\s+$PIMAGE\s*=\s*//io) {
X if ($section eq "http") {
X warn <<EOF;
Image item in http section is specified, but it is not allowed :
\tat $pwd/$CONFIG line $::ILN.
\t..... ignored.
EOF
X $image = "";
X } elsif (m!/$!) {
X $image = $_;
X unless (-d $image) {
X warn <<EOF;
Sub-theme($_) for theme image specified, but it is not found :
\tat $pwd/$CONFIG line $::ILN.
\t..... ignored.
EOF
X $image = "";
X }
X } else {
X s/\s+.*$//; # ignore (...) parts
X $image = $_;
X unless (/\.($IMGEXT)$/o) {
X warn <<EOF;
Bad theme image file name ($_):
\tat $pwd/$CONFIG line $::ILN.
\t..... ignored.
EOF
X $image = "";
X }
X }
X print "#",__LINE__,"# image:($image)\n" if $DEBUG;
X } elsif (s/^\s+Com(ment)?\s*=\s*//i) {
X s/^\s+//;
X $comment = $_;
X while ($_ = get_config(*INCONFIG,$CONFIG)) {
X last if /^\S|^\s+[\w\.-]+\s*=/;
X s/^\s+//;
X $comment .= "\n\t\t$_";
X }
X redo;
X } elsif (/^\s+Lat(est)?\s*=.*?\((.+)\)/) {
X $latest = $2;
X if ($section eq "Sub-Theme") {
X warn <<EOF;
Latest item in Sub-Theme section is specified, but it is not allowed :
\tat $pwd/$CONFIG line $::ILN.
\t..... ignored.
X
EOF
X $latest = "";
X }
X } else {
X die <<EOF;
Error at $pwd/$CONFIG line $::ILN :
\t"$_" is bad $section item.
EOF
X }
X }
X return ($theme,$image,$comment,$latest);
X } ### End of sub get_theme_items;
###
X if (/^Ver(sion)?:/i) {
X print "#",__LINE__,"# CONFIG: Version\n" if $DEBUG;
X while ($_ = get_config(*INCONFIG,$CONFIG)) {
X last if /^\S/; # version checked already
X }
X redo;
X } elsif (/^Opt(ion)?:$/i) { ### Option:
X print "#",__LINE__,"# CONFIG: Option\n" if $DEBUG;
X die "\"Option:\" doubly defined at $pwd/$CONFIG line $::ILN.\n"
X if $option_on;
X $option_on = 1;
X while ($_ = get_config(*INCONFIG,$CONFIG)) {
X last if /^\S/;
X if (s/^\s+(Pro|Epi)(?:log|logue)?\s*=\s*//i) {
X my $pt = ($1 =~ /Pro/i ? \$::opt_prolog : \$::opt_epilog);
X print "#",__LINE__,"# CONFIG: ProEpi ($_)\n" if $DEBUG;
X $$pt = $_;
X while ($_ = get_config(*INCONFIG,$CONFIG)) {
X print "#",__LINE__,"# CONFIG: ProEpi ($_)\n" if $DEBUG;
X last if /^\S|^\s+[\w\.-]+\s*=/;
X s/^\s+//;
X $$pt .= "\n\t\t $_";
X }
X redo;
X }
X set_option("conf",$_);
X }
X get_shrink_size();
X redo; ### End of Option:
X } elsif (/^$PTHEME:$/io) { ### Theme:
X print "#",__LINE__,"# CONFIG: Theme\n" if $DEBUG;
X die "\"Theme:\" doubly defined at $pwd/$CONFIG line $::ILN.\n"
X if $theTheme_on;
X $theTheme_on = 1;
X ($theTheme_theme,$theTheme_image,$theTheme_comment,$theTheme_latest)
X = get_theme_items("Theme");
X print "#",__LINE__,"# CONFIG: Theme image : ($theTheme_image)\n" if $DEBUG;
X if ($theTheme_image =~ m!/$!) {
X die <<EOF unless -d $theTheme_image;
Bad theme directory specified ($theTheme_image):
\tat $pwd/$CONFIG line $::ILN.
EOF
X if (-r "$theTheme_image$CONTENT") {
X $theTheme_image = get_theme_image($theTheme_image);
X die <<EOF unless $theTheme_image;
"$theTheme_image" : Bad theme specified.
\tat $pwd/$CONFIG line $::ILN.
EOF
X } else {
X die <<EOF;
"$theTheme_image/$CONTENT" : not found.
\tat $pwd/$CONFIG line $::ILN.
EOF
X }
X }
X if ($theTheme_image) {
X my $imp = (image_path("Header",$theTheme_image));
X print "#",__LINE__,"# imp=($imp)\n" if $DEBUG;
X unless ($imp and -r $imp) {
X warn <<EOF;
"$imp" is not found.
\t\t.... ignored it and took default theme image instead.
\t"$theTheme_image" is specified
\t\tat $pwd/$CONFIG line $::ILN.
EOF
X $theTheme_image = "";
X }
X }
X print "#",__LINE__,"# theTheme_image:($theTheme_image)\n" if $DEBUG;
X redo; ### End of Theme:
X } elsif (s!^http:?//(\S+)/($CONTENT)?$!http://$1/!i) { ### Web-theme
X print "#",__LINE__,"# CONFIG: http: ($_)\n" if $DEBUG;
X my $url = $_;
X $_ .= $CONTENT;
X my $http = $_;
X s(^http://)($PREHTTP)o;
X s(/)($SLASHHTTP)og;
X my $fhttp = $_;
X my ($theme,$image,$comment,$latest) = get_theme_items("http");
X print "#",__LINE__,"# CONFIG(http): theme=($theme) image=($image) comment=($comment) latest=($latest)\n" if $DEBUG;
X my $update_web;
X my $ignore;
X my ($w_theme,$w_image,$w_comment,$mtime,$time_locale,$w_mtime);
X if (-r "$fhttp") {
X $w_mtime = stat($fhttp)->mtime;
X print "#",__LINE__,"# CONFIG: w_mtime=($w_mtime)\n" if $DEBUG;
X if ($::opt_ckweb eq "Yes") {
X $update_web = 1;
X }
X } else {
X $update_web = 1;
X }
X if ($update_web) {
X print "#",__LINE__,"# CONFIG: update_web=($update_web)\n" if $DEBUG;
X my ($content_type, $document_length, $modified_time,
X $expires, $server) = head("$http");
X print "#",__LINE__,"# content_type=($content_type) document_length=($document_length) modified_time=($modified_time) expires=($expires) server=($server)\n" if $DEBUG;
X unless ($content_type and $modified_time) {
X warn "Cannot access to \"$http\" ... skipped.\n";
X $ignore = 1;
X }
X print "#",__LINE__,"# w_mtime=($w_mtime) modified_time=($modified_time)\n" if $DEBUG;
# if (defined $w_mtime and ($w_mtime == str2time($modified_time))) {
X if (defined $w_mtime and ($w_mtime == $modified_time)) {
X warn "Content of Web page ($http) is not changed.\n"
X if $VERBOSE;
X $update_web = 0;
X } else {
X if ($content_type and $content_type =~ m(text/plain)i) {
X $document_length = 0 unless defined $document_length;
X if ($document_length <= $MAXWEBDOCLENGTH) {
# $w_mtime = str2time($modified_time);
X $w_mtime = $modified_time;
X } else {
X warn "Document length on Web page ($http) is too long.\n";
X $ignore = 1;
X }
X } else {
X warn "Bad Content_type on Web page ($http).\n";
X $ignore = 1;
X }
X }
X }
X if ($ignore) {
X print "#",__LINE__,"# CONFIG: $url : ignored\n" if $DEBUG;
X } else {
X if ($update_web) {
X rename $fhttp,"$fhttp.OLD" if -r $fhttp;
X my $rc = getstore($http,$fhttp);
X if (is_error($rc)) {
X my $mes = status_message($rc);
X die "Error($mes) while accessed $http\n";
X }
X utime $w_mtime,$w_mtime,$fhttp;
X open(FHTTP,$fhttp) || die "Cannot read $pwd/$fhttp : $!";
X my $allowed;
X {
X local $::ILN;
X local $_;
X while ($_ = get_config(*FHTTP,$fhttp)) {
X if (s/^\s+Ref(er)?\s*=\s*//i) {
X $allowed = 1 if /^All(ow)?$/i;
X last;
X }
X }
X }
X close FHTTP;
X if ($allowed) {
X warn "$fhttp is updated\n" if $VERBOSE;
X } else {
X unlink $fhttp;
X $ignore = 1;
X warn <<EOF;
Web-theme ($url) is specified at
\t\t$pwd/$CONFIG line $::ILN.
\tBut denied to refer for Network Photo Album.
\t.... skipped.
EOF
X }
X }
X unless ($ignore) {
X my ($w_theme,$w_image,$w_comment,$mtime,$time_locale)
X = getTheme($fhttp,$http);
X $theme = $w_theme unless $theme;
X $image = $w_image; #unless $image;
X $comment = $w_comment unless $comment;
X $latest = $time_locale unless $latest;
X push @contents,{ "ThemeWeb" => $http,
X "Theme" => $theme,
X "Image" => $image,
X "Comment" => $comment,
X "Mtime" => $mtime,
X "Ltime" => $latest,
X "URL" => $url
X };
X }
X }
X redo; ### End of Web-theme
X } elsif (s!^(\S+)/$!!) { ### Sub-theme
X print "#",__LINE__,"# CONFIG: Sub-Theme: ($1)\n" if $DEBUG;
X my $theme_dir = $1;
X @dirs = grep {$_ ne $theme_dir} @dirs; # remove it from @dirs
X my ($theme,$image,$comment,$latest) = get_theme_items("Sub-Theme");
X my $im = "$theme_dir/$image";
X $im =~ s!/([^/]+)$!/$picrawdir/$1!;
X print "#",__LINE__,"# CONFIG: Sub-Theme image: ($im)\n" if $DEBUG;
X unless (-r $im) {
X $image = "";
X warn <<EOF;
Theme image($im) is not found
\tat $pwd/$CONFIG line $::ILN.
\t ... ignored it and took default theme image instead.
EOF
X }
X if ($latest) {
X warn <<EOF;
Bad "Latest:" item found
\tat $pwd/$CONFIG line $::ILN.
\t ... ignored it.
EOF
X }
X if (-r "$theme_dir/$CONTENT") {
X my ($d_theme,$d_image,$d_comment,$mtime,$time_locale)
X = getTheme("$theme_dir/$CONTENT");
X $theme = $d_theme unless $theme;
X $image = $d_image unless $image;
X $comment = $d_comment unless $comment;
X push @contents,{ "ThemeDir" => $theme_dir,
X "Theme" => $theme,
X "Image" => $image,
X "Comment" => $comment,
X "Mtime" => $mtime,
X "Ltime" => $time_locale
X };
X } else {
X warn <<EOF;
Sub theme "$theme_dir" is specified
\tat $pwd/$CONFIG line $::ILN,
\tbut "$theme_dir/$CONTENT" is not found.
\t ... ignored it.
EOF
X }
X redo; # end of sub theme
X } elsif (s/^([^\s:]+)$//) {
X print "#",__LINE__,"# CONFIG: Image\n" if $DEBUG;
X my $image_file = $1;
X die <<EOF unless $image_file =~ /\.($IMGEXT)$/o;
Error at $pwd/$CONFIG line $::ILN :
\tImage: "$image_file" does not have proper extension of image.
EOF
X @images = grep {$_ ne $image_file} @images; # remove it from @images
X my ($name,$date,$comment) = ("","","");
X while ($_ = get_config(*INCONFIG,$CONFIG)) {
X last if /^\S|^$/;
X if (s/^\s+Name?\s*=\s*//i) {
X $name = $_;
X } elsif (s/^\s+Date?\s*=\s*//i) {
X $date = $_;
X } elsif (s/^\s+Com(ment)?\s*=\s*//i) {
X s/^\s+//;
X $comment = "$_";
X while ($_ = get_config(*INCONFIG,$CONFIG)) {
X last if /^\S|^\s+[\w\.-]+\s*=/;
X s/^\s+//;
X $comment .= "\n\t\t$_";
X }
X redo;
X } else {
X die <<EOF;
Error at $pwd/$CONFIG line $::ILN :
\tImage: "$_" is bad theme option.
EOF
X }
X }
X my $mtime = get_mtime_of_original_file($image_file);
X if (defined $mtime) {
X $name = $image_file unless $name;
X $date = ctime($mtime) unless $date;
X push @contents,{ "ImageFile" => $image_file,
X "Name" => $name,
X "Date" => $date,
X "Comment" => $comment,
X "Mtime" => $mtime
X };
X } else {
X warn "$image_file: specified at $pwd/$CONFIG line $::ILN,",
X " but not found ... skipped.\n";
X }
X redo; # end of image
X } elsif (/^$/) {
X last;
X } else {
X die <<EOF;
Error at $pwd/$CONFIG line $::ILN :
\t"$_" is wrong section.
EOF
X }
X }
X close(INCONFIG);
X } # end of CONFIG
X
X print "#",__LINE__,"# Option: Language=$::opt_lang, Order=$::opt_order, Image=$::opt_image, Theme=$::opt_theme, Config=$::opt_config\n" if $DEBUG;
X
X get_shrink_size();
X
X my @here_d;
X while (my $d = shift @dirs) { # add new SubTheme entries to Contents
X if (-r "$pwd/$d/$CONTENT") {
X my ($theme,$image,$comment,$mtime,$time_locale)
X = getTheme("$pwd/$d/$CONTENT");
X push @here_d,{ "ThemeDir" => $d,
X "Theme" => $theme,
X "Image" => $image,
X "Comment" => $comment,
X "Mtime" => $mtime,
X "Ltime" => $time_locale
X }
X } else {
X die "!!BUG!! No $pwd/$d/$CONTENT found. : ";
X }
X }
X undef @dirs;
X
X my @here_f;
X while (my $f = shift @images) { # add new Image entries to here_f
X my $mtime = get_mtime_of_original_file($f);
X my $date = ctime($mtime);
X push @here_f,{ "ImageFile" => $f,
X "Name" => $f,
X "Date" => $date,
X "Comment" => "",
X "Mtime" => $mtime
X }
X }
X undef @images;
X
X print "#",__LINE__,"# opt_config=\"$::opt_config\"\n" if $DEBUG;
X if ($::opt_config eq "Non") {
X foreach (@contents) {
X if (exists $_->{ThemeDir}) {
X push @here_d,$_;
X } elsif (exists $_->{ThemeWeb}) {
X unless ($_->{Image} =~ m(^http://)) {
# print "### http=($_->{URL}) Image=($_->{Image})\n" if $DEBUG;
X $_->{Image} = $_->{URL} . $_->{Image};
X }
X push @here_d,$_;
X } else {
X $_->{Mtime} = get_mtime_of_original_file($_->{ImageFile});
X $_->{Date} = ctime($_->{Mtime}) unless $_->{Date};
X push @here_f, $_;
X }
X print "#",__LINE__,"# \@contents: Mtime=($_->{Mtime})\n" if $DEBUG;
X }
X }
X
X my @here;
X if ($::opt_order =~ /^New-|^Old-/) {
X print "#",__LINE__,"# opt_order=\"$::opt_order\"\n" if $DEBUG;
X @here = sort {$a->{Mtime} <=> $b->{Mtime}} (@here_d,@here_f);
X @here = reverse(@here)
X if $::opt_order eq "New-First" or $::opt_order eq "Old-Last";
X } else {
X @here_d = sort {$a->{Mtime} <=> $b->{Mtime}} @here_d;
X @here_f = sort {$a->{Mtime} <=> $b->{Mtime}} @here_f;
X
X @here_d = reverse(@here_d) if $::opt_theme eq "Reverse";
X @here_f = reverse(@here_f) if $::opt_image eq "Reverse";
X
X if ($::opt_order eq "Image-First") {
X @here = (@here_f,@here_d); # Order=Image-First
X } else {
X @here = (@here_d,@here_f); # Order=Directoy-First
X }
X }
X undef @here_d;
X undef @here_f;
X
X if ($::opt_config eq "Last") {
X @contents = (@here,@contents); # Config=Last
X } elsif ($::opt_config eq "First") {
X @contents = (@contents,@here); # Config=First
X } else {
X @contents = @here; # Config=Non
X }
X undef @here;
X
X rename "$CONTENT", "$CONTENT.OLD" if -r $CONTENT;
X unless (@contents) {
X if (-r $CONFIG) {
X warn "Configuration file($CONFIG) exists but no image found\n",
X " under $pwd ... ignored.\n";
X } else {
X warn "No image in \"$pwd/\" ... skipped.\n";
X }
X next SPECIFIED_DIRECTORY;
X }
X
X unless ($theTheme_image) {
X my $c = $contents[0];
X if (exists $c->{ImageFile}) {
X $theTheme_image = $c->{ImageFile};
X } elsif (exists $c->{ThemeDir}) {
X if ($c->{Image} =~ m(^http://)i) {
X $theTheme_image = "$c->{Image}";
X } else {
X $theTheme_image = "$c->{ThemeDir}/$c->{Image}";
X }
X } elsif (exists $c->{ThemeWeb}) {
X $theTheme_image = "$c->{Image}";
X } else {
X die "!!BUG!! Cannot get default theme image on $pwd : ";
X }
X $theTheme_comment = $c->{Comment} unless $theTheme_comment;
X }
# unless ($theTheme_image =~ /\S+\s+(.+)/) {
## if ($theTheme_image =~ m(http://)) {
## }
# }
X
X ### Generate Contents file ###
X print "#",__LINE__,"# Generate Contents: $pwd/$CONTENT\n" if $DEBUG;
X
X my $max_mtime = 0;
X foreach my $c (@contents) {
X $max_mtime = $c->{Mtime} if $max_mtime < $c->{Mtime};
X }
X my $ctime = ctime();
X my $latestdate = ($theTheme_latest ? $theTheme_latest : ctime($max_mtime));
X my ($titleimage_N,$size_titleimage_N,$t_info_N)
X = image_path("Normal",$theTheme_image,"size-required");
X my ($titleimage_H,$size_titleimage_H,$t_info_H)
X = image_path("Header",$theTheme_image,"size-required");
X my ($titleimage_I,$size_titleimage_I,$t_info_I)
X = image_path("Index",$theTheme_image,"size-required");
X $theTheme_image .= "\n\t ($t_info_N)($t_info_H)($t_info_I)"
X unless $theTheme_image =~ /\s/;
X
X my $content_db = <<EOF;
# $CONTENT: Do not edit this!
# This file was generated by $PNAME at $ctime
X
Version:
\t$PNAME $VERSION
X
Option:
\tCharset=utf8
\tLanguage=$::opt_lang
\tOrder=$::opt_order
\tImage=$::opt_image
\tTheme=$::opt_theme
\tConfig=$::opt_config
\tMail-Address=$::opt_mail
\tUser-Name=$::opt_uname
\tScale-Directory=$::opt_scale
\tSize-of-Picture=$::opt_size
\tBack=$::opt_back
\tStart=$::opt_start
\tTop=$::opt_top
\tCheck-Web=$::opt_ckweb
\tRefer=$::opt_refer
\tPrologue=$::opt_prolog
\tEpilogue=$::opt_epilog
X
Theme:
\tTheme=$theTheme_theme
\tImage=$theTheme_image
\tComment=$theTheme_comment
\tLatest=$max_mtime ($latestdate)
X
EOF
X foreach my $c (@contents) {
X if (exists $c->{ThemeDir}) {
X $content_db .= <<EOF;
$c->{ThemeDir}/
\tTheme=$c->{Theme}
\tImage=$c->{Image}
\tComment=$c->{Comment}
\tLatest=$c->{Mtime} ($c->{Ltime})
EOF
X } elsif (exists $c->{ThemeWeb}) {
X $content_db .= <<EOF;
$c->{ThemeWeb}
\tTheme=$c->{Theme}
\tImage=$c->{Image}
\tComment=$c->{Comment}
\tLatest=$c->{Mtime} ($c->{Ltime})
EOF
X } elsif (exists $c->{ImageFile}) {
X $content_db .= <<EOF;
$c->{ImageFile}
\tName=$c->{Name}
\tDate=$c->{Date}
\tComment=$c->{Comment}
EOF
X } else {
X die "!!BUG!! No theme nor Image found on \@contents : ";
X }
X }
X open(CFILE,">$CONTENT") || die "Cannot write on $pwd/$CONTENT : $!";
X print CFILE $content_db;
X close(CFILE);
X undef $content_db;
X warn "$pwd/$CONTENT is updated.\n" if $VERBOSE;
X
X ### Generate photo.html ###
X my $hml = $html_message{$::opt_lang};
X
X foreach my $c (@contents) {
X $c->{Comment} = sanitize_meta($c->{Comment})
X if exists $c->{Comment};
X foreach my $item (qw(ThemeWeb Theme Image URL Mtime Ltime
X theme_dir ImageFile Name Date)) {
X $c->{$item} = sanitize_meta($c->{$item},"No<br>")
X if exists $c->{$item};
X }
X }
X
X my $back;
X $back = 1 if $::opt_back eq "Yes"
X and $hml->{Back}
X and ($depth >= 2 or -r "../$HTML");
X
X $_ = $::opt_mail;
X if (/\$userid\b|\${userid}/i) {
X s/\$userid\b|\${userid}/$ENV{USER}/ig;
X }
X if (/\$fqdn\b|\${fqdn}/i) {
X my $m = $_; # save $_ for Net::Domain ver. 2.13
X my $f = hostfqdn();
X $_ = $m; # restore $_
X s/\$fqdn\b|\${fqdn}/$f/ig;
X }
X if (/\$domain\b|\${domain}/i) {
X my $m = $_; # save $_ for Net::Domain ver. 2.13
X my $d = hostdomain();
X $_ = $m; # restore $_
X s/\$domain\b|\${domain}/$d/ig;
X }
X $::opt_mail = $_;
X
X $_ = $::opt_uname;
X if (/^\$passwd$/i) {
X open(INP,"/etc/passwd") || die "Cannot read /etc/passwd : $!";
X while (<INP>) {
X next unless /^$ENV{USER}:/o;
X /[^:]*?:[^:]*?:[^:]*?:[^:]*?:([^:]*?)?:/;
X $_ = $1;
X s/,.*//s; # Full name of the user
X last;
X }
X close(INP);
X die "User name of \"$ENV{USER}\" is not found in /etc/passwd.\n"
X unless $_;
X }
X $_ = to_utf8({ -string => $_, -charset => $::opt_charset })
X if $::opt_charset;
X $::opt_uname = $_;
X
X
X for my $pe (\$::opt_prolog,\$::opt_epilog) {
X next unless $$pe;
X $$pe =~ s/\$uname\b|\${uname}/$::opt_uname/ig;
X $$pe =~ s/\$copyright\b|\${copyright}/$hml->{Copyright}/ig;
X if ($::opt_mail
X and $$pe =~ s(\$mail\b|\${mail})($::opt_mail)ig
X and $& eq '$Mail') {
X $$pe = sanitize_meta($$pe);
X $$pe =~ s/^\s+/\t /mg;
X $$pe = <<EOF;
X <address><a href="mailto:$::opt_mail">
\t<small>
\t$$pe
\t</small>
X </a></address>
EOF
X } else {
X $$pe =~ s/\s*<?\s*(\$Mail\b|\${Mail})\s*>?\s*/ /g;
X $$pe = sanitize_meta($$pe);
X $$pe = " <small>\n\t$$pe\n </small>";
X }
X }
X
X for my $p (\$theTheme_theme,\$theTheme_comment,\$theTheme_latest) {
X $$p = sanitize_meta($$p);
X }
X
X print "#",__LINE__,"# Generate $HTML\n" if $DEBUG;
X print "#",__LINE__,"# \$theTheme_image=`$theTheme_image'\n" if $DEBUG;
X $theTheme_image =~ s/\s.*//;
X my $html = "";
X $html = <<EOF;
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<!-- This is generated by $PNAME (version $VERSION).
\tYou can get the latest version of mkphotohtml and it\'s documents
\tfrom following web page;
\t\t$WEBINFO
X -->
<html>
X <head>
X <META HTTP-EQUIV="Content-Type"
X CONTENT="text/html; charset=utf-8">
X <META NAME="GENERATOR" CONTENT="mkphotohtml V$VERSION">
X <META NAME="Keyword" CONTENT="mkphotohtml,Network Photo Album">
X <META NAME="Networkphotoalbum" CONTENT="$::opt_refer">
EOF
X $html .= <<EOF if $::opt_start eq "Yes";
X <link rel="start" href="$::opt_top">
EOF
X $html .= <<EOF if -r "../$HTML";
X <link rel="previous" href="../$HTML">
EOF
X $html .= <<EOF if $::opt_mail;
X <link rev="made" href="mailto:$::opt_mail">
EOF
X $html .= <<EOF;
X <title>$theTheme_theme</title>
X </head>
X <body>
X <center>
X <h1>$theTheme_theme</h1>
X <a href="$titleimage_N">
X <img src="$titleimage_H"
X $size_titleimage_H
X alt="Theme-image: $theTheme_image">
X </a><br>
X $theTheme_comment
X </center><br>
EOF
X $html .= <<EOF if $back;
X <a href="../$HTML">$hml->{Back}</a>
EOF
X $html .= <<EOF if $::opt_prolog;
X <hr>
X <center>
$::opt_prolog
X </center>
EOF
X $html .= <<EOF;
X <hr>
X <h1>$hml->{Album}</h1>
X $hml->{Comment}
X <br><br>
EOF
X while (my $c = shift @contents) {
X if (exists $c->{ThemeDir}) { # SubThemeDir
X my ($subtheme_image,$size_image,$info_dummy)
X = image_path("Index","$c->{ThemeDir}/$c->{Image}","size_required");
X my $date = ($c->{Ltime} ? $c->{Ltime} : ctime($c->{Mtime}));
X print "#",__LINE__,"# \$subtheme_image=$subtheme_image\n" if $DEBUG;
X $html .= <<EOF;
X <a href="$c->{ThemeDir}/$HTML">
X <img src="$subtheme_image"
X $size_image
X alt="$c->{ThemeDir}" align="left"></a>
X <font size="+2">$hml->{Theme}$c->{Theme}</font><br>
X <font size="-1">$hml->{Latest} $date</font><br>
X $c->{Comment}<br clear="left">
EOF
X } elsif (exists $c->{ThemeWeb}) { # Web theme
X unless ($c->{Image} =~ m(http://)) {
X $c->{Image} = $c->{URL} . $c->{Image};
X }
X my ($web_image,$size_image)
X = image_path("Index",$c->{Image},"size-required");
X my $date = ($c->{Ltime} ? $c->{Ltime} : ctime($c->{Mtime}));
X $html .= <<EOF;
X <a href="$c->{URL}$HTML">
X <img src="$web_image"
X $size_image
X alt="$c->{URL}" align="left"></a>
X <font size="+2">$hml->{WebTheme}$c->{Theme}</font><br>
X <font size="-1">$hml->{Latest} $date</font><br>
X $c->{Comment}<br clear="left">
EOF
X
X } elsif (exists $c->{ImageFile}) { # Image file
X $c->{ImageFile} =~ /(.*)(\.[^.]+)/;
X my ($base,$ext) = ($1,$2);
X my $ifile = image_path("Raw",$c->{ImageFile});
X my $imagefiles = "<a href=\"$ifile\" "
X . "title=\"$c->{ImageFile}\">$sorted_scale[0]</a>";
X for my $scale (@sorted_scale[1..$#sorted_scale]) {
X my $ifile = image_path($scale,$c->{ImageFile});
X $imagefiles .= "\n\t, <a href=\"$ifile\" "
X . "title=\"$c->{ImageFile}\">$scale</a>";
X }
X my $image_normal = image_path("Normal",$c->{ImageFile});
X my $image_index = image_path("Index", $c->{ImageFile});
X my $size_index = html_imgsize($image_index);
X $html .= <<EOF;
X <a href="$image_normal">
X <img src="$image_index"
X $size_index
X alt="$c->{ImageFile}" align="left"></a>
X <font size="-1">
X $hml->{Arrow} $imagefiles
X </font><br>
X <strong><font size="+1">$c->{Name}</font></strong><br>
X <font size="-1">$c->{Date}</font><br>
X $c->{Comment}<br clear="left">
EOF
X } else {
X die "!!BUG!! Broken \@contents";
X }
X }
X
X my $time = ctime();
X
X $html .= <<EOF;
X <hr>
EOF
X $html .= <<EOF if $back;
X <a href="../$HTML">$hml->{Back}</a>
EOF
X $html .= <<EOF if $::opt_epilog;
X <center>
$::opt_epilog
X </center>
X <hr>
EOF
X if ($::opt_uname and $::opt_mail) {
X $html .= <<EOF;
X <address><a href="mailto:$::opt_mail">
X $::opt_uname
X </a></address>
EOF
X }
X $html .= <<EOF;
X Last modified: $time
X </body>
</html>
EOF
X rename "$HTML", "$HTML.OLD" if -r $HTML;
X open(HTML,">$HTML") || die "Cannot write on $pwd/$HTML : $!";
X print HTML $html;
X close(HTML);
X warn "$pwd/$HTML is updated.\n" if $VERBOSE;
X }
X chdir $oldpwd;
X --$depth;
}
SHAR_EOF
(set 20 03 11 11 15 49 09 'mkphotohtml'; eval "$shar_touch") &&
chmod 0755 'mkphotohtml' ||
$echo 'restore of' 'mkphotohtml' 'failed'
if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
&& ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
md5sum -c << SHAR_EOF >/dev/null 2>&1 \
|| $echo 'mkphotohtml:' 'MD5 check failed'
de71286a0b82221ce44879b1bc184660 mkphotohtml
SHAR_EOF
else
shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'mkphotohtml'`"
test 68563 -eq "$shar_count" ||
$echo 'mkphotohtml:' 'original size' '68563,' 'current size' "$shar_count!"
fi
fi
rm -fr _sh01288
exit 0

0 new messages