TopMovable Type > バージョン別 > 3.121-ja > 2005年1月
2005年1月31日

コメントスパム対策(その5)

January 31,2005 1:15 AM
Tag:[]
Permalink

約5ヶ月ぶりの対策です。
これまでの経緯は、コメントスパム対策(その3)で特定の文字列をエラーとする対処を行った後、コメントスパム対策(その4)を実施したのですが、通常のコメントでエラーが発生するようになってしまい、一旦全て元に戻しておりました。その後、大量のコメントスパムを頂く度に削除するという原始的な手法に陥ってましたがさすがにみっともないので今回、下記のプラグインを使わせて頂きました。

Ogawa::MemorandaQuasi-Spam Filter Plugin

個人的にコメントスパム対策は特定の文字列のみをエラーとするのが望ましいと思ってましたので、まさにうってつけのプラグインです。ありがとうございました。
使い方は簡単です。以下、引用です。

quasi-spamfilter.zipをダウンロードし、展開してください。次に中に含まれるquasi-spamfilter.plをMovable Typeのpluginsディレクトリーにアップロードしてください。以上です。

また、デフォルト状態では

# Set your spam pattern
our $PATTERN = '<h1>|<a\s'; # H1 or A elements

と h1 タグおよび a タグを対象とする設定となってますので、私は下記のように変更しています。

# Set your spam pattern
our $PATTERN = 'hoge1|hoge2|hoge3';

hogen が対象文字列です。文字列を"|"で区切ることで何文字でも設定できます。

このように特定かつ複数文字列を含んだコメントをフィルタリングすることができる他、その後のリアクションを変更することもできます。エラーにすることもできますし、特定のURLにリダイレクトさせることもできます。私はデフォルト状態で利用させていただいてますので、フィルタリングされたコメントはあたかも正常に受け付けられたかのように振る舞います。

ということで、もしコメント投稿後の個別エントリーアーカイブにコメントが反映されていなければフィルタリングされたと解釈ください(普段使われることのない文字列しかフィルタの対象にしてませんので大丈夫とは思いますが)。

Comments [10] | Trackbacks [9]
2005年1月29日

RSSリーダーの本文表示の違いを探る(その3:NoCDATAの利用)

January 29,2005 10:00 PM
Tag:[, ]
Permalink

Movable Typeには NoCDATA というオプションが用意されています。これを用いれば RSSフィードのデータの特殊文字をエンコードする設定も可能です。ユーザーズマニュアルに下記の説明があります。

デフォルトでMovable Typeは、データをXMLにエンコードしているとき、あなたのデータにHTMLタグや、XMLに対し安全でないデータが含まれていないかどうかをチェックし、検出した場合は、データをCDATAタグで囲みます。 ただし、ニュース・アグリゲータの中には、CDATAを他のデータと一緒にすると、問題が生じることがあります。こうした問題がある場合は、NoCDATAを使って特殊文字をエンティティにエンコードすることができます。

具体的には設定ファイル mt.cfg の250行目にある

# NoCDATA 1

という行の先頭の#とブランクを削除することで有効になります。
実験として、

本文に<a href="hogehoge">HTMLタグ</a>を含んでいます。

という本文を例に変換してみました。

NoCDATA 0 の場合

<description><![CDATA[<p>本文に<a href="hogehoge">HTMLタグ</a>を含んでいます。</p>]]></description>

NoCDATA 1 の場合

<description>&lt;p&gt;本文に&lt;a href=&quot;hogehoge&quot;&gt;HTMLタグ&lt;/a&gt;を含んでいます。&lt;/p&gt;</description>

これまでのまとめです。

  • HTMLタグや特殊文字を存在する場合、CDATAセクションとなる
  • NoCDATAオプションを利用することでHTMLタグや特殊文字のエンコード(つまりCDATAセクションとならない)が可能
  • MTEntryBody を使用し Convert Line Breaks が有効の場合、改行用のHTMLタグが付与されるため常にCDATAセクションとなる。MTEntryExcerpt を使用するとHTMLタグは全て除去されるため、CDATAセクションとなるのはHTMLエンティティが存在する場合のみ
  • Movable Type3.0 と 3.1x では description のテキスト部分に用いられているMTタグが異なる

ということで、一番最初の index.rdf のサンプルはHTMLタグを用いてCDATAセクションの有無を説明したかったのですが、CDATAセクション有無がMTタグに依存してしまうため、description には MTEntryExcerpt を適用した状態でHTMLエンティティを用いました。

しかしよく考えてみると、その状態で本文とは別に「概要(excerpt)」を記述すればHTMLタグを利用できた訳です。つまりCDATAセクション化やエンコードはそもそも「概要」を対象とした機能であり、そうすることで機能は本来の役割を自然に振る舞うのではないでしょうか。

Comments [9] | Trackbacks [0]
2005年1月28日

RSSリーダーの本文表示の違いを探る(その2)

January 28,2005 5:05 PM
Tag:[, ]
Permalink

RSSフィード本文のエンコードの仕組みについては前回の通りですが、ここでひとつ疑問がわきました。それはサイトによってHTMLタグがあるものとないものが混在するのはなぜか?という点についてです。これはMyBlogListリーダーをご覧になったことのある方ならご存知と思います。
本テンプレートユーザの方は Movable Type をお使いなので一律同じ結果、つまりHTMLタグが常に表示されるか、あるいは常に表示されないか、のどちらか一方になるだろうと思って見比べてみたところ、それでもタグありとタグなしの表示が混在していました。
今回はこの原因について探ってみました。たいした結果ではありません。

実は最初、私が試したサンプルは本文に

本文にHTMLタグを含んでいません。本文にHTMLタグを含んでいません。
本文にHTMLタグを含んでいません。

と書いて、これをRSSフィードにすると

<description>本文にHTMLタグを含んでいません。本文にHTMLタグを含んでいません。本文にHTMLタグを...</description>

という結果になることを期待しました。ところが実際に生成してみると、

<description><![CDATA[<p>本文にHTMLタグを含んでいません。本文にHTMLタグを含んでいません。<br />
本文にHTMLタグを含んでいません。</p>]]></description>

となりました。これは明らかに Mobable Type の Convert Line Breaks 機能により <p> や <br> タグが付与されたもので、たしかにMyBlogListリーダーではここから "<![CDATA]" と "]]>" を除いた部分が表示されていた記憶があります。
ではタグが付与されないパターンはどうやって生成されているのでしょうか?

ここで小粋空間の index.rdf(抜粋) を見てみると

              :
<item rdf:about="http://www.koikikukan.com/archives/2005/01/25-233913.php">
<title>Movable Typeの脆弱性と対策</title>
<link>http://www.koikikukan.com/archives/2005/01/25-233913.php</link>
<description>ほぼ引用ですいません(+出遅れてます)。 【重要】 Movable Typeの脆...</description>
<dc:subject>3.121-ja</dc:subject>
<dc:creator>yujiro</dc:creator>
<dc:date>2005-01-25T23:39:13+09:00</dc:date>
</item>
              :

と、HTMLタグは付与されていませんでした(他のエントリーについても同様です)。私は index.rdf のテンプレートをカスタマイズしていませんし、そもそも積極的にカスタマイズするページでもありません。

両者の違いについて内部処理で表示が切り替わる仕組みがあるのか?とも考えましたが、答えは簡単でした。
小粋空間で用いているindex.rdf テンプレート(抜粋)では該当部分に

<description><$MTEntryExcerpt encode_xml="1"$></description>

と MTEntryExcerpt が設定されており、実験で用いた Movable Type 3.121(新規インストールで利用)の index.rdf テンプレートには

<description><$MTEntryBody encode_xml="1"$></description>

と、MTEntryBodyが設定されていました。

つまり、Movable Type3.1x で index.rdf テンプレートの description タグのテキスト部分に MTEntryBody が用いられるようになったことが、表示に違いが生じていた原因と考えられます。小粋空間は3.01からのアップデートだったため、旧テンプレートの設定である MTEntryExcerpt が引き継がれていた、という訳です。

Comments [0] | Trackbacks [2]
2005年1月27日

RSSリーダーの本文表示の違いを探る(その1)

January 27,2005 7:30 PM
Tag:[, ]
Permalink

昨年末、「MyBlogListリーダー等のRSSリーダーの本文表示でHTMLタグが表示される場合があります(注:現在は改善されているようです)がどうしてですか?」という質問の回答です。色々調べてみたとろ結構面白い結果となりましたので連載ものでいってみます。

MyBlogListリーダーで本文にHTMLタグが含まれるのはその仕様に依存すると思われますが、HTMLタグが本文に付与されることについては、少なくとも Movable Typeについてはその機能によるものです。
具体的には、本文中にHTMLタグまたはHTMLエンティティ(らしきもの)が存在する場合、文章全体がCDATAセクションという

<![CDATA[ ~ ]]>

というもので括られます("~"に本文が入ります)。これで括ることによって文章にどのような文字が含まれていても適正なXMLデータとして扱われますので、一切加工されずそのまま保存されるという仕組みになっています。

RSSリーダーはRSSフィード(index.rdf/index.xml等)を参照します。下記に Movable Type でひとつだけエントリーしたRSS1.0フィードの index.rdf を示します。上は本文にHTMLエンティティを含まないもの、下は含んだ(ここでは"&lt;"と"&gt;")ものです。青字部分と赤字部分がそれぞれ対象となる部分です。

index.rdf(本文にHTMLエンティティを含まない)

<?xml version="1.0" encoding="utf-8"?>
 
<rdf:RDF
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
xmlns:admin="http://webns.net/mvcb/"
xmlns:cc="http://web.resource.org/cc/"
xmlns="http://purl.org/rss/1.0/">
 
<channel rdf:about="http://~/">
<title>First Weblog</title>
<link>http://~/</link>
<description></description>
<dc:language>ja</dc:language>
<dc:creator></dc:creator>
<dc:date>2005-01-27T17:39:25+09:00</dc:date>
<admin:generatorAgent rdf:resource="http://www.movabletype.org/?v=3.121-ja" />
 
 
<items>
<rdf:Seq><rdf:li rdf:resource="http://~/archives/2005/01/post.html" />
</rdf:Seq>
</items>
 
</channel>
 
<item rdf:about="http://~/archives/2005/01/post.html">
<title>てすと</title>
<link>http://~/archives/2005/01/post.html</link>
<description>本文にHTMLエンティティを含んでいません。本文にHTMLエンティティを含んでい...</description>
<dc:subject></dc:subject>
<dc:creator>Melody</dc:creator>
<dc:date>2005-01-27T17:39:25+09:00</dc:date>
</item>
 
 
</rdf:RDF>

index.rdf(本文にHTMLエンティティを含む)

<?xml version="1.0" encoding="utf-8"?>
 
<rdf:RDF
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
xmlns:admin="http://webns.net/mvcb/"
xmlns:cc="http://web.resource.org/cc/"
xmlns="http://purl.org/rss/1.0/">
 
<channel rdf:about="http://~/">
<title>First Weblog</title>
<link>http://~/</link>
<description></description>
<dc:language>ja</dc:language>
<dc:creator></dc:creator>
<dc:date>2005-01-27T17:39:25+09:00</dc:date>
<admin:generatorAgent rdf:resource="http://www.movabletype.org/?v=3.121-ja" />
 
 
<items>
<rdf:Seq><rdf:li rdf:resource="http://~/archives/2005/01/post.html" />
</rdf:Seq>
</items>
 
</channel>
 
<item rdf:about="http://~/archives/2005/01/post.html">
<title>てすと</title>
<link>http://~/archives/2005/01/post.html</link>
<description><![CDATA[本文に&lt;b&gt;HTMLエンティティ&lt;/b&gt;を含んでいます。...]]></description>
<dc:subject></dc:subject>
<dc:creator>Melody</dc:creator>
<dc:date>2005-01-27T17:39:25+09:00</dc:date>
</item>
 
 
</rdf:RDF>

仮にHTMLタグが含まれていれば、

<description><![CDATA[本文に<b>HTMLエンティティ</b>を含んでいます。...]]></description>

となります。最初からHTMLタグを例に扱った方がわかりやすいのですが、扱えない理由があります。これについては後ほど明らかにしたいと思います。

参考までに、変換処理を実際に行っている

lib/MT/Util.pm

のソース(抜粋)を掲載しておきます。

my %Map = ('&' => '&amp;', '"' => '&quot;', '&lt;' => '<', '&gt;' => '>', '\'' => '&apos;');
my $RE = join '|', keys %Map;
 
sub encode_xml {
    my($str, $nocdata) = @_;
    $nocdata ||= MT::ConfigMgr->instance->NoCDATA;
    if (!$nocdata && $str =~ m/
        <[^>]+>  ## HTML markup
        |        ## or
        &(?:(?!(\#([0-9]+)|\#x([0-9a-fA-F]+))).*?);
                 ## something that looks like an HTML entity.
    /x) {
        ## If ]]> exists in the string, encode the > to >.
        $str =~ s/]]>/]]>/g;
        $str = '<![CDATA[' . $str . ']]>';
    } else {
        $str =~ s!($RE)!$Map{$1}!g;
    }
    $str;
}
Comments [3] | Trackbacks [0]
2005年1月26日

ポップアップ画面を用いたコメント投稿(その5:その4の補足)

January 26,2005 3:00 PM
Tag:[]
Permalink

その4:コメントフォームのカスタマイズ」で、コメント・プレビュー/コメント・エラー時のサイン・インおよびサイン・アウトについては、

<$MTRemoteSignInLink static="<$MTCommentPreviewIsStatic$>"$>

という記述がサポートされていないため「画面を誘導できません」と書きましたが、Ogawaさんのパッチを流用させて頂くという案がありましたので追記致します。

lib/MT/Context.pm

の1110?1140行目辺りにあるサイン・イン/サイン・アウト用リンクをハンドリングするプログラムに対して下記の通り、赤字を削除して青字を追加します。

sub _hdlr_remote_sign_in_link {
    my ($ctx, $args) = @_;
    my $cfg = MT::ConfigMgr->instance;
       :
    my $comment_script = $cfg->CommentScript;
    my $static_arg = $args->{static} ? "static=1" : "static=0";
    my $static_arg;
    if (defined($args->{static})) {
        $static_arg = $args->{static} ? "static=1" : "static=0";
    } else {
        $static_arg = $ctx->stash('comment_is_static') ? "static=1" : "static=0";
    }
    my $e = $_[0]->stash('entry');
       :
}
 
sub _hdlr_remote_sign_out_link {
    my ($ctx, $args) = @_;
    my $cfg = MT::ConfigMgr->instance;
       :
    my $static_arg = $args->{static} ? "static=1" : "static=0";
    my $static_arg;
    if (defined($args->{static})) {
        $static_arg = $args->{static} ? "static=1" : "static=0";
    } else {
        $static_arg = $ctx->stash('comment_is_static') ? "static=1" : "static=0";
    }
    my $e = $_[0]->stash('entry')
       :
}

これでコメント・プレビューおよびコメント・エラーテンプレートの MTRemoteSignInLink および MTRemoteSignOutLink を

<$MTRemoteSignInLink$>
<$MTRemoteSignOutLink$>

と static属性を省略して記述することで、コメント・リストまたは個別エントリーアーカイブの MTRemoteSignInLink または MTRemoteSignOutLink で設定された static値を引き継ぎます。具体的には、例えば <$MTRemoteSignOutLink$> がHTMLソースに展開されると

<a href="http://~/mt-comments.cgi?__mode=handle_sign_in&static=0&entry_id=3&logout=1">サイン・アウト</a>

のように static値(0はポップアップ画面への誘導を示します)が query string に設定されます。またこれ以降の画面遷移にも引き継がれます。
誤りがありましたらご指摘よろしくお願い致します。

Comments [7] | Trackbacks [0]
2005年1月25日

Movable Typeの脆弱性と対策

January 25,2005 11:39 PM
Tag:[]
Permalink

ほぼ引用ですいません(+出遅れてます)。

【重要】 Movable Typeの脆弱性と対策について

Movable Typeの脆弱性により、スパムメールの送信を幇助してしまう現象が発生することが分かりました。出荷済みのすべてのMovable Type日本語版に、この脆弱性があることが確認されました。

旧バージョンに対して、この脆弱性を回避するためのプラグインが公開されています。なお日本語版サイトではダウンロード可能なMovable Typeが、脆弱性の問題に対策済みのバージョン3.122に更新されています。
詳細は上記ページを参照ください。

Comments [0] | Trackbacks [1]
2005年1月14日

テンプレートのアンカー修正

January 14,2005 3:50 PM
Tag:[]
Permalink

昨年からの宿題となっていた、個別エントリーアーカイブのコメント、コメント投稿、およびトラックバックにあるアンカータグの id 属性および name 属性の指定を修正しました。修正対象のテンプレートは

Movable Type 3.11-ja/3.121-ja 3カラム テンプレート(サイズ可変)
Movable Type 3.11-ja/3.121-ja 3カラム テンプレート(サイズ固定)

です。修正内容は下記の通りです。

<MTEntryIfAllowPings>
<a id="trackbacks" name="trackbacks"></a>
<div id="trackbacks" class="comments-head">トラックバックURL</div>
        :
        :
<a id="comments" name="comments"></a>
<div id="comments" class="comments-head"><a name="comments"></a>コメント</div>
 
<MTComments>
<a id="c<$MTCommentID$>" name="c<$MTCommentID$>"></a>
<div id="c<$MTCommentID$>" class="comments-body">
        :

修正の動機は、「テンプレートから生成されたページで、コメントやトラックバックのアンカー指定が Another HTML-lint gateway の文法チェックにひっかかる」というご指摘を頂いたのが発端で、とりあえず分散していた id 属性と name 属性をアンカータグにまとめました。
またコメント用の name 属性値の先頭に"c"を付与しました。理由は id 属性との属性値が異なっていることによる文法エラーを避けるためと、デフォルトテンプレートの記述("c+MTCommentID")に従いました。
2つの属性を同一のタグに移動したことで、リンクを示す a タグとスタイルを決定する div タグが意味的に理解しやすくなるという効果もあったようです。なお現状の設定でも動作上問題ありません。

また、個別エントリーアーカイブ(3カラム用)/コメント・プレビュー(3カラム用)/コメント・エラー(3カラム用)の各テンプレートのサイドメニューにあるコメント投稿者のリンクも併せて修正致しました。修正内容は下記の通りです。こちらは"c"の追加およびアンカー名にバグがありましたので、その対処です。

<div class="side">
<MTEntries recently_commented_on="5">
<a href="<$MTEntryLink$>"><MTEntryTitle></a>
<br/>
<MTComments lastn="5">
└ <a href="<$MTEntryLink$>#c<$MTCommentID$><MTEntryID pad="1"$>">
<MTCommentAuthor></a> <$MTCommentDate format="%m/%d"$><br />
</MTComments>
</MTEntries>
</div>

個別エントリーアーカイブのサイドメニューにあるコメント投稿者欄をクリックして、該当の投稿者位置にページがスクロールされない場合は上記の対処を行ってください。"#"の後ろにある"c"は付与しない方が修正が楽です。

Comments [10] | Trackbacks [3]
2005年1月13日

ポップアップ画面を用いたコメント投稿(その4:コメントフォームのカスタマイズ)

January 13,2005 11:58 PM
Tag:[]
Permalink

3回で終わらせるつもりでしたが追加内容がありましたので。
コメント・リスト/コメント・プレビュー/コメント・エラーのテンプレートに MTCommentFields を用いない、つまり個別エントリーアーカイブのフォーム部分を利用する場合の修正方法です。

具体的な作業としては、コメント・リストテンプレートの

<MTCommentFields static="1">

およびコメント・プレビュー/コメント・エラーテンプレートの

<MTCommentFields preview="1">

の部分を下記のソースにそれぞれ入れ替えます。ソースは個別アーカイブテンプレートから該当部分を切り出したもので、赤色および青色部分の修正を行います。赤色は本来の修正箇所、青色はフォーム情報を前ページから引き継ぐための修正です(Ogawa::memorandaさんからのアドバイスによるものです)。
繰り返しになりますが投稿されたコメントがポップアップ画面からのものか、非ポップアップ画面からのものかを次の画面に知らせる必要があります。それを引継ぐ情報としてstatic属性が使われています。赤色の

<$MTRemoteSignOutLink static="n"$>

または

<input type="hidden" name="static" value="n" />

の部分を適宜修正してください。n の意味は下記の通りです。必要な値を適宜設定してください。

0:サイン・イン/サイン・アウト/コメント投稿後、ポップアップ画面へ誘導
1:サイン・イン/サイン・アウト/コメント投稿後、非ポップアップ画面へ誘導
<$MTCommentPreviewIsStatic$>:前画面のstatic値を引き継ぐ

ただし、コメント・プレビュー/コメント・エラーで

<$MTRemoteSignOutLink static="<$MTCommentPreviewIsStatic$>"$>

という記述はサポートされていないようです。→ 2005.01.27追記その5に対処方法を記しました。

コメント・リストテンプレート

<h2>コメントしてください</h2>
 
<MTIfRegistrationRequired>
 
<MTIfNonEmpty tag="MTTypeKeyToken">
<div id="thanks">
<p>サイン・インを確認しました、
<script type="text/javascript" src="<MTCGIPath><MTCommentScript>?__mode=cmtr_name_js"></script><script>document.write(commenter_name);</script>
さん。コメントしてください。 (<a href="<$MTRemoteSignOutLink static="1"$>">サイン・アウト</a>)</p>
 
(いままで、ここでコメントしたとがないときは、コメントを表示する前にこのウェブログのオーナーの承認が必要になることがあります。承認されるまではコメントは表示されません。そのときはしばらく待ってください。)
 
<form method="post" action="<$MTCGIPath$><$MTCommentScript$>" name="comments_form" onsubmit="if (this.bakecookie[0].checked) rememberMe(this)">
<input type="hidden" name="static" value="1" />
<input type="hidden" name="entry_id" value="<$MTEntryID$>" />
 
<p><label for="url">URL:</label><br />
<input tabindex="1" type="text" name="url" id="url" />
情報を登録する?
<input type="radio" id="remember" name="bakecookie" onclick="rememberMe(this.form)" /><label for="remember">はい</label><input type="radio" id="forget" name="bakecookie" onclick="forgetMe(this.form)" value="Forget Info" style="margin-left: 15px;" /><label for="forget">いいえ</label><br style="clear: both;" />
 
</p>
 
<p><label for="text">コメント:</label><br />
<textarea tabindex="2" id="text" name="text" rows="10" cols="50"></textarea></p>
 
<div align="center">
<input type="submit" tabindex="3" name="preview" value=" 確認 " />
<input style="font-weight: bold;" tabindex="4" type="submit" name="post" value=" 投稿 " />
</div>
</form>
 
</div>
 
<script language="javascript" type="text/javascript">
<!--
if (commenter_name) {
document.getElementById('thanks').style.display = 'block';
} else {
document.write('サイン・インしていません。このサイトにコメントをする前に登録してください。 <a href="<$MTRemoteSignInLink static="1"$>"> サイン・イン</a>');
document.getElementById('thanks').style.display = 'none';
}
// -->
</script>
 
<MTElse>
コメント登録機能が設定されていますが、TypeKey トークンが設定されていません。
</MTElse>
</MTIfNonEmpty>
 
<MTElse>
<MTIfNonEmpty tag="MTTypeKeyToken">
<script type="text/javascript" src="<MTCGIPath><MTCommentScript>?__mode=cmtr_name_js"></script>
<script language="javascript" type="text/javascript">
<!--
if (commenter_name) {
document.write('サイン・インを確認しました、', commenter_name, '. さん。コメントしてください。 (<a href="<$MTRemoteSignOutLink static="1"$>">サイン・アウト</a>)');
} else {
document.write('TypeKey ID を使って <a href="<$MTRemoteSignInLink static="1"$>"> サイン・イン</a> してください。');
}
// -->
</script>
</MTIfNonEmpty>
 
<form method="post" action="<$MTCGIPath$><$MTCommentScript$>" name="comments_form" onsubmit="if (this.bakecookie[0].checked) rememberMe(this)">
<input type="hidden" name="static" value="1" />
<input type="hidden" name="entry_id" value="<$MTEntryID$>" />
 
<div id="name_email">
<p><label for="author">名前:</label><br />
<input tabindex="1" id="author" name="author" /></p>
 
<p><label for="email">メールアドレス:</label><br />
<input tabindex="2" id="email" name="email" /></p>
</div>
 
<MTIfNonEmpty tag="MTTypeKeyToken">
<script language="javascript" type="text/javascript">
<!--
if (commenter_name) {
document.getElementById('name_email').style.display = 'none';
}
// -->
</script>
</MTIfNonEmpty>
 
<p><label for="url">URL:</label><br />
<input tabindex="3" type="text" name="url" id="url" />
保存しますか?
<input type="radio" id="remember" onClick="rememberMe(this.form)" name="bakecookie" /><label for="remember">はい</label><input type="radio" id="forget" name="bakecookie" onclick="forgetMe(this.form)" value="Forget Info" style="margin-left: 15px;" /><label for="forget">いいえ</label><br style="clear: both;" />
</p>
 
<p><label for="text">コメント:</label> <MTIfAllowCommentHTML>
(書式を変更するような一部のHTMLタグを使うことができます)</MTIfAllowCommentHTML><br/>
<textarea tabindex="4" id="text" name="text" rows="10" cols="50"></textarea></p>
 
<div align="center">
<input type="submit" name="preview" tabindex="5" 
value=" 確認 " />
<input style="font-weight: bold;" type="submit" name="post" 
tabindex="6" value=" 投稿 " />
</div>
</form>
 
</MTElse>
</MTIfRegistrationRequired>

コメント・プレビュー/コメント・エラーテンプレート

<h2>コメントしてください</h2>
 
<MTIfRegistrationRequired>
 
<MTIfNonEmpty tag="MTTypeKeyToken">
<div id="thanks">
<p>サイン・インを確認しました、
<script type="text/javascript" src="<MTCGIPath><MTCommentScript>?__mode=cmtr_name_js"></script><script>document.write(commenter_name);</script>
さん。コメントしてください。 (<a href="<$MTRemoteSignOutLink static="1"$>">サイン・アウト</a>)</p>
 
(いままで、ここでコメントしたとがないときは、コメントを表示する前にこのウェブログのオーナーの承認が必要になることがあります。承認されるまではコメントは表示されません。そのときはしばらく待ってください。)
 
<form method="post" action="<$MTCGIPath$><$MTCommentScript$>" name="comments_form" onsubmit="if (this.bakecookie[0].checked) rememberMe(this)">
<input type="hidden" name="static" value="<$MTCommentPreviewIsStatic$>" />
<input type="hidden" name="entry_id" value="<$MTEntryID$>" />
 
<p><label for="url">URL:</label><br />
<input tabindex="1" type="text" name="url" id="url" />
情報を登録する?
<input type="radio" id="remember" name="bakecookie" onclick="rememberMe(this.form)" /><label for="remember">はい</label><input type="radio" id="forget" name="bakecookie" onclick="forgetMe(this.form)" value="Forget Info" style="margin-left: 15px;" /><label for="forget">いいえ</label><br style="clear: both;" />
 
</p>
 
<p><label for="text">コメント:</label><br />
<textarea tabindex="2" id="text" name="text" rows="10" cols="50"></textarea></p>
 
<div align="center">
<input type="submit" tabindex="3" name="preview" value=" 確認 " />
<input style="font-weight: bold;" tabindex="4" type="submit" name="post" value=" 投稿 " />
</div>
</form>
 
</div>
 
<script language="javascript" type="text/javascript">
<!--
if (commenter_name) {
document.getElementById('thanks').style.display = 'block';
} else {
document.write('サイン・インしていません。このサイトにコメントをする前に登録してください。 <a href="<$MTRemoteSignInLink static="1"$>"> サイン・イン</a>');
document.getElementById('thanks').style.display = 'none';
}
// -->
</script>
 
<MTElse>
コメント登録機能が設定されていますが、TypeKey トークンが設定されていません。
</MTElse>
</MTIfNonEmpty>
 
<MTElse>
<MTIfNonEmpty tag="MTTypeKeyToken">
<script type="text/javascript" src="<MTCGIPath><MTCommentScript>?__mode=cmtr_name_js"></script>
<script language="javascript" type="text/javascript">
<!--
if (commenter_name) {
document.write('サイン・インを確認しました、', commenter_name, '. さん。コメントしてください。 (<a href="<$MTRemoteSignOutLink static="1"$>">サイン・アウト</a>)');
} else {
document.write('TypeKey ID を使って <a href="<$MTRemoteSignInLink static="1"$>"> サイン・イン</a> してください。');
}
// -->
</script>
</MTIfNonEmpty>
 
<form method="post" action="<$MTCGIPath$><$MTCommentScript$>" name="comments_form" onsubmit="if (this.bakecookie[0].checked) rememberMe(this)">
<input type="hidden" name="static" value="<$MTCommentPreviewIsStatic$>" />
<input type="hidden" name="entry_id" value="<$MTEntryID$>" />
 
<div id="name_email">
<p><label for="author">名前:</label><br />
<input tabindex="1" id="author" name="author" value="<$MTCommentPreviewAuthor encode_html="1"$>" /></p>
 
<p><label for="email">メールアドレス:</label><br />
<input tabindex="2" id="email" name="email" value="<$MTCommentPreviewEmail encode_html="1"$>" /></p>
</div>
 
<MTIfNonEmpty tag="MTTypeKeyToken">
<script language="javascript" type="text/javascript">
<!--
if (commenter_name) {
document.getElementById('name_email').style.display = 'none';
}
// -->
</script>
</MTIfNonEmpty>
 
<p><label for="url">URL:</label><br />
<input tabindex="3" type="text" name="url" id="url" value="<$MTCommentPreviewURL encode_html="1"$>" />
保存しますか?
<input type="radio" id="remember" onClick="rememberMe(this.form)" name="bakecookie" /><label for="remember">はい</label><input type="radio" id="forget" name="bakecookie" onclick="forgetMe(this.form)" value="Forget Info" style="margin-left: 15px;" /><label for="forget">いいえ</label><br style="clear: both;" />
</p>
 
<p><label for="text">コメント:</label> <MTIfAllowCommentHTML>
(書式を変更するような一部のHTMLタグを使うことができます)</MTIfAllowCommentHTML><br/>
<textarea tabindex="4" id="text" name="text" rows="10" cols="50"><$MTCommentPreviewBody convert_breaks="0" encode_html="1"$></textarea></p>
 
<div align="center">
<input type="submit" name="preview" tabindex="5" 
value=" 確認 " />
<input style="font-weight: bold;" type="submit" name="post" 
tabindex="6" value=" 投稿 " />
</div>
</form>
 
</MTElse>
</MTIfRegistrationRequired>
Comments [3] | Trackbacks [1]
2005年1月11日

選択されたアーカイブリンクを強調表示する

January 11,2005 5:10 PM
Tag:[]
Permalink

サイドメニューにある Monthly Archives および Categories のリンクをクリックした時に該当のリンクを強調表示させるカスタマイズです。
本カスタマイズは下記の記事を参考にさせて頂きました。ありがとうございました。

nlog(n)月別アーカイブ一覧で表示月を強調したい

ここではカスタマイズ方法のみ記しておりますので機能の詳細につきましては参照元の記事をご覧ください。

以下カスタマイズ方法です。なおオリジナルは PerlScript プラグインを利用されていますがここでは php を使ってみました。したがって利用するアーカイブファイルの拡張子が .php になっていることが前提となります。またモジュール化されている場合は正常に動作しませんので予めご了承ください。PerlScriptプラグインを利用される場合は拡張子の制約はありませんので必要な箇所を適宜修正ください。

1.MTTagInvoke のダウンロード

MTExtensions のページより MTTagInvoke をダウンロードしてください(ページ左上に「Download」のリンクがあります)。ダウンロードしたファイルを解凍して MTTagInvoke.pl を plugins フォルダに配置(FTP等によるアップロードを含む)します。

2.Monthly Archives を変更する場合

日付アーカイブテンプレートにあるサイドメニューの Monthly Archives のタグ(下のリスト)の下線部分を削除して、青色のタグを追加してください。例は公開テンプレートのものを利用しています。

<div class="sidetitle">
Monthly Archives
</div>
 
<MTTagInvoke tag_name="MTSetVar" name="thismonth">
<MTTagAttribute name="value"><$MTArchiveDate format="%Y%m"$></MTTagAttribute>
</MTTagInvoke>
 
<div class="side">
<MTArchiveList archive_type="Monthly">
<a href="<$MTArchiveLink$>">
<a href="<$MTArchiveLink$>"<?php $a ="<$MTGetVar name="thismonth"$>"; $b = "<$MTArchiveDate format="%Y%m"$>"; if ($a == $b) print " style=\"font-weight:bold;\""; ?>>
<$MTArchiveTitle$></a> [<$MTArchiveCount$>]<br/>
</MTArchiveList>
</div>

本設定は日別アーカイブページにも適用されます。例えば月別アーカイブと日別アーカイブが同じ「日付アーカイブテンプレート」を利用する設定になっていて(デフォルトではそのようになっています)、カレンダーのリンクが日別アーカイブページになっている場合、カレンダーのリンクをクリックした先のページで該当月が強調表示されます。

3.Categories を変更する場合

カテゴリー・アーカイブテンプレートにあるサイドメニューの Categories のタグ(下のリスト)の下線部分を削除して、青色のタグを追加してください。同じく公開テンプレートのものを例にしています。

3.1 一括表示

<div class="sidetitle">
Categories
</div>
 
<MTTagInvoke tag_name="MTSetVar" name="thiscategory">
<MTTagAttribute name="value"><$MTArchiveTitle$></MTTagAttribute>
</MTTagInvoke>
 
<div class="side">
<MTCategories>
<a href="<$MTCategoryArchiveLink$>">
<a href="<$MTCategoryArchiveLink$>" <?php $a ="<$MTGetVar name="thiscategory"$>"; $b = "<$MTArchiveTitle$>"; if ($a == $b) print "style=\"font-weight:bold;\""; ?>>
<$MTCategoryLabel$></a> [<$MTCategoryCount$>]<br />
</MTCategories>
</div>

3.2 サブカテゴリー表示

<div class="sidetitle">
Categories
</div>
 
<MTTagInvoke tag_name="MTSetVar" name="thiscategory">
<MTTagAttribute name="value"><$MTArchiveTitle$></MTTagAttribute>
</MTTagInvoke>
 
<div class="side">
<div id="categories">
<MTTopLevelCategories>
<MTSubCatIsFirst><ul></MTSubCatIsFirst>
<MTIfNonZero tag="MTCategoryCount">
<li><a href="<$MTCategoryArchiveLink$>" title="<$MTCategoryDescription$>">
<a href="<$MTCategoryArchiveLink$>" <?php $a ="<$MTGetVar name="thiscategory"$>"; $b = "<$MTArchiveTitle$>"; if ($a == $b) print "style=\"font-weight:bold;\""; ?> title="<$MTCategoryDescription$>">
<MTCategoryLabel></a> [<$MTCategoryCount$>]
<MTElse>
<li><MTCategoryLabel>
</MTElse>
</MTIfNonZero>
<MTSubCatsRecurse max_depth="3">
</li>
<MTSubCatIsLast></ul></MTSubCatIsLast>
</MTTopLevelCategories>
</div>
</div>

サブカテゴリーについては MTTopLevelCategories で括られているか、モジュール化されていないとクリックしたカテゴリー自体が表示されませんのでご注意ください。

いずれも表示部分を、

style=\"font-weight:bold;\"

に統一していますが、

class=\"hogehoge\"

に変更し、スタイルシートへ

.hogehoge {
    font-weight:bold;
}

と設定することも可能です。

2005.01.11 追記
モジュール化されている場合は正常に動作しない旨を追記しました。

2005.01.12 追記
モジュール化対応版を公開しました。

Comments [3] | Trackbacks [2]
2005年1月 4日

リアルタイムカレンダー(改)

January 4,2005 6:10 PM
Tag:[, , ]
Permalink

Movable Type がサポートするカレンダーでは、エントリー投稿やコメント投稿が行われないとカレンダー(のリンク)は更新されません。したがって MTCalendarIfToday タグを利用して本日の日付を装飾するカスタマイズを行っている場合も、先の動作がない限りカレンダーの本日表示は更新されません。
本カスタマイズは仕様に依存せず、リアルタイムに日付を更新させます(ブラウザの更新等は必要です)。本日の日付がリアルタイムに更新されることを指して「リアルタイムカレンダー」と(勝手に)命名しました。なおカレンダー自体が存在しない月跨りについては機能の対象外ですので予めご了承ください。

注:本エントリーではPHP化が必要なため、現在は JavaScript によるカスタマイズを推奨しています。詳細は下記のエントリーまたはカレンダーアーカイブをご覧ください。


このカスタマイズを行う前提条件はPHPが利用可能なこと、つまりカレンダータグを利用するテンプレートのファイル名の拡張子が .php になっていることです(詳細は後述)。
オリジナルサイトは下記です。ありがとうございました。

kamishiro.netphpを使って今日の日付部分を動的にハイライトする方法

また記事のURLは以前よりこのカスタマイズを利用されていた Magic White さんより教えて頂きました(自力で発見できず…)。併せてありがとうございました。

タイトルの「改」は下記を指しています。

  • 文字自体のスタイル設定だったオリジナルからテーブルのカラムにスタイルを与えられるように変更
  • 本日であることを日でしか判定していなかったので年月日判定を追加(月送りカレンダー用)

ここでは拡張子がすでに .php になっている場合とそうでない場合、および月送りカレンダー利用の場合の3つのケースについて説明しています。それぞれに必要な項目は下記の通りです。

拡張子が .php になっている場合:1、2.1(または2.3)
拡張子が .php になっていない場合:1、3、4
月送りカレンダーの場合:1、2.2

月送りカレンダーの場合の注意事項

  • 本エントリーとは別に月送りカレンダーでのカスタマイズが必要です。
  • カレンダー用テンプレートのファイル名の拡張子は .php に変更してください。
  • 月送りカレンダーを引き込むタグ(iframe)は .html ファイルを呼び出すようになってますので、下記のように .php ファイルを引き込むように変更してください。
<div align="center" class="side">
<iframe name="cal-iframe" src="<MTBlogURL>archives/calendar/<MTDate format="%Y/%m/index">.html.php" width="150" height="115" scrolling="NO" frameborder="0" marginwidth="0" marginheight="0">
</iframe>
</div>
  • 横型カレンダーご利用で拡張子が .php になっていない場合は、本エントリー3項のリストの下半分(空行から下の部分)を2.3項のリストに置き換える形で行ってください。
  • 月送りカレンダー用ファイルの拡張子を「.html」から「.php」に変更した際、.html ファイルが残っているとカレンダーが正常に表示されない場合があります。 .html ファイルは必ず削除してください。

1.スタイルシートにカレンダー用スタイルの追加(共通)

スタイルシートのcalendar設定の下辺りに下記の青色部分を追加します。リストは公開テンプレートを例にしています。設定部分は2パターン掲載していますので不要な部分を削除して設定内容を適宜修正してください。

.calendar table {
    padding: 0px;
    border-collapse: collapse;
}
 
.today {
    background : #000000; /* 背景色をつける設定 */
    border : 1px solid #000000; /* 枠線をつける設定 */
}

注:月送りカレンダーの方は、上記の設定をカレンダー用スタイルシート(calendar.css)の一番下に追加してください。

2.カレンダー関連タグの変更(拡張子が .php になっている場合/月送りカレンダーの場合)

カレンダーの設定がされている各テンプレートの <MTCalendar>~</MTCalendar> の部分を下記のスクリプトに変更します。利用中のカレンダーによって2種類のテンプレートを用意していますので該当する方をお使いください。

2.1 通常の1ヶ月表示の場合

<?php $day = date("j");?>
<MTCalendar>
<MTCalendarWeekHeader><tr></MTCalendarWeekHeader>
<MTCalendarIfEntries><?php $d="<$MTCalendarDay$>"; if($day == $d) { $style = " class=\"today\""; } else { $style = ""; } ?><td align="center"<?php print "$style"; ?>><span class="calendar"><MTEntries lastn="1"><a href="<$MTEntryLink archive_type="Daily"$>"><$MTCalendarDay$></a></MTEntries></span></td></MTCalendarIfEntries>
<MTCalendarIfNoEntries><?php $d="<$MTCalendarDay$>"; if($day == $d) { $style = " class=\"today\""; } else { $style = ""; } ?><td align="center"<?php print "$style"; ?>><span class="calendar"><$MTCalendarDay$></span></td></MTCalendarIfNoEntries>
<MTCalendarIfBlank><td>&nbsp;</td></MTCalendarIfBlank>
<MTCalendarWeekFooter></tr></MTCalendarWeekFooter>
</MTCalendar>

2.2 月送りカレンダーの場合

月送りカレンダーご利用の方は「アーカイブ・テンプレート」の「カレンダー」に設定されている該当部分を下記に変更してください。

<?php $day = date("j"); $year = date("Y"); $month = date("m"); ?>
<MTCalendar month="this">
<MTCalendarWeekHeader><tr></MTCalendarWeekHeader>
<MTCalendarIfEntries>
<?php $y="<$MTCalendarDate format='%Y'$>"; $m="<$MTCalendarDate format='%m'$>"; $d="<$MTCalendarDay$>"; if($year == $y && $month == $m && $day == $d) { $style = " class=\"today\""; } else { $style = ""; } ?>
<td align="center"<?php print "$style"; ?>><span class="calendar"><MTEntries lastn="1"><a href="<$MTEntryLink archive_type="Daily"$>"   target="_top"><$MTCalendarDay$></a></MTEntries></span></td>
</MTCalendarIfEntries>
<MTCalendarIfNoEntries>
<?php $y="<$MTCalendarDate format='%Y'$>"; $m="<$MTCalendarDate format='%m'$>"; $d="<$MTCalendarDay$>"; if($year == $y && $month == $m && $day == $d) { $style = " class=\"today\""; } else { $style = ""; } ?>
<td align="center"<?php print "$style"; ?>><span class="calendar"><$MTCalendarDay$></span></td>
</MTCalendarIfNoEntries>
<MTCalendarIfBlank><td>&nbsp;</td></MTCalendarIfBlank>
<MTCalendarWeekFooter></tr></MTCalendarWeekFooter>
</MTCalendar>

ちなみに両者の違いですが、月送りカレンダー/複数月表示の場合は本日の判定に年月日を取得しています。1ヶ月表示の場合は日のみの判定なので若干軽いです。月送りカレンダーで1ヶ月用のタグを使うと毎月同じ日に印がつきますのでご注意ください。

2.3 横型カレンダーの場合

このカレンダーは table タグを用いてないパターンです。1項のスタイルシートは .today があれば大丈夫です(table のスタイル設定は不要)が、若干スタイルの指定が必要かもしれませんので適宜行ってください。

<?php $day = date("j");?>
<MTCalendar> 
<MTCalendarIfEntries> 
<?php $d="<$MTCalendarDay$>"; if($day == $d) { $style = "today"; } else { $style = "calendar"; } ?>
<span class="<?php print "$style"; ?>"> 
<MTEntries lastn="1"> 
<a href="<$MTEntryLink archive_type="Daily"$>"> <$MTCalendarDay$></a>
</MTEntries> 
</MTCalendarIfEntries> 
<MTCalendarIfNoEntries>
<?php $d="<$MTCalendarDay$>"; if($day == $d) { $style = "today"; } else { $style = "calendar"; } ?>
<span class="<?php print "$style"; ?>"> 
<$MTCalendarDay$>
</MTCalendarIfNoEntries> 
<MTCalendarIfBlank><MTElse></span></MTElse></MTCalendarIfBlank>
</MTCalendar>

3.カレンダー用インデックステンプレートの作成(拡張子が .php になっていない場合)

「管理メニュー」の「テンプレート」をクリック→次ページ右上の「新しいインデックス・テンプレートを作る」をクリック(3.2-ja 以降の場合は左上の「インデックス」→右上の「テンプレートを新規作成」をクリック)し、下記を設定してください。

テンプレート名:カレンダー(何でも良い)
出力ファイル名:calendar.php
インデックス?自動的に再構築する:チェック
テンプレートの内容:下記リストをコピー&ペースト(公開テンプレート用に合わせてますのでそれ以外の方はクラス名等を適宜修正してください)
<div class="side">
<div class="calendar">
<div class="sidetitle">
Calendar of <$MTDate format="%B %Y"$>
</div>
<table border="0" cellspacing="4" cellpadding="0" align="center" summary="投稿した日にリンクする月別のカレンダー">
<tr>
<th abbr="Sunday"><span class="calendar"><font color="#e50003">Sun</font></span></th>
<th abbr="Monday"><span class="calendar">Mon</span></th>
<th abbr="Tuesday"><span class="calendar">Tue</span></th>
<th abbr="Wednesday"><span class="calendar">Wed</span></th>
<th abbr="Thursday"><span class="calendar">Thu</span></th>
<th abbr="Friday"><span class="calendar">Fri</span></th>
<th abbr="Saturday"><span class="calendar"><font color="blue">Sat</font></span></th>
</tr>
 
<?php $day = date("j");?>
<MTCalendar>
<MTCalendarWeekHeader><tr></MTCalendarWeekHeader>
<MTCalendarIfEntries><?php $d="<$MTCalendarDay$>"; if($day == $d) { $style = " class=\"today\""; } else { $style = ""; } ?><td align="center"<?php print "$style"; ?>><span class="calendar"><MTEntries lastn="1"><a href="<$MTEntryLink archive_type="Daily"$>"><$MTCalendarDay$></a></MTEntries></span></td></MTCalendarIfEntries>
<MTCalendarIfNoEntries><?php $d="<$MTCalendarDay$>"; if($day == $d) { $style = " class=\"today\""; } else { $style = ""; } ?><td align="center"<?php print "$style"; ?>><span class="calendar"><$MTCalendarDay$></span></td></MTCalendarIfNoEntries>
<MTCalendarIfBlank><td>&nbsp;</td></MTCalendarIfBlank>
<MTCalendarWeekFooter></tr></MTCalendarWeekFooter>
</MTCalendar>
</table>
</div>
</div>

設定終了後、保存・再構築してください。

4.calendar.phpのインクルード(拡張子が .php になっていない場合)

各テンプレートの カレンダー設定部分(赤色)をごっそり削除して青色のタグに置き換えてください。

<div class="side">
<div class="calendar">
<table border="0" cellspacing="4" cellpadding="0" align="center" summary="投稿した日にリンクする月別のカレンダー">
<caption class="calendarhead"><$MTDate format="%B %Y"$></caption>
<tr>
<th abbr="Sunday"><span class="calendar"><font color="#e50003">Sun</font></span></th>
<th abbr="Monday"><span class="calendar">Mon</span></th>
<th abbr="Tuesday"><span class="calendar">Tue</span></th>
<th abbr="Wednesday"><span class="calendar">Wed</span></th>
<th abbr="Thursday"><span class="calendar">Thu</span></th>
<th abbr="Friday"><span class="calendar">Fri</span></th>
<th abbr="Saturday"><span class="calendar"><font color="blue">Sat</font></span></th>
</tr>
 
<MTCalendar>
<MTCalendarWeekHeader><tr></MTCalendarWeekHeader>
<td align="center" <MTCalendarIfToday>bgcolor="#ffffe0"</MTCalendarIfToday>><span class="calendar">
<MTCalendarIfEntries>
<MTEntries lastn="1"><a href="<$MTEntryLink archive_type="Daily"$>"><$MTCalendarDay$></a></MTEntries>
</MTCalendarIfEntries><MTCalendarIfNoEntries><$MTCalendarDay$></MTCalendarIfNoEntries><MTCalendarIfBlank> </MTCalendarIfBlank>
</span></td><MTCalendarWeekFooter></tr></MTCalendarWeekFooter></MTCalendar>
</table>
</div>
</div>
<$MTInclude file="calendar.php"$>

設定終了後、保存・再構築してください。

2005.01.05 追記
月送りカレンダー用のタグにtypoがありましたので修正しました。また同タグのリンクにターゲット指定を追加しました。

2005.02.02 追記
月送りカレンダーのエントリーへのリンクおよび説明を本文に追加しました。

2005.03.11 追記
横型カレンダーの説明を本文に追加しました。

2005.03.21 追記
横型カレンダーの </span> の制御が誤っていましたので修正しました。

2005.07.31 追記
月送りカレンダーの場合、 iframe タグを修正する説明が不足していましたので追記しました。

2005.08.07 追記
Apache のログにPHPエラーが出ていたためスクリプトを一部修正しました。

2005.10.31 追記
3.2-ja 用の記述を追加しました。

Comments [71] | Trackbacks [32]
Now loading...
ギターに入った猫
掲載広告募集
Styles
Font Size
Default
For defective color vision
Gray Scale
RGB Color
Search this site

このブログをメールで購読する by:FeedBurner

AMN
Categories
Monthly Archives
2020年
2019年
2018年
2017年
2016年
2015年
2014年
2013年
2012年
2011年
2010年
2009年
2008年
2007年
2006年
2005年
2004年
2003年
BlogPeople
Syndicate this site
FeedBurner(RSS1.0/RSS2.0/Atom)
Counter
これまでのアクセス
Powered by
Movable Type 6.0.3