daemonfreaks.com

mtimeをメタデータから取る

posted by jun-g at Sun, 06 Feb 2022 23:40 JST

PyBlosxomは記事の作成日時を各エントリーファイルの修正日時(mtime)から取得します。投稿後に過去記事を修正した場合に作成日付が変わってしまうのが気に入らなかったので、entrycacheというプラグインを使用して初回に記事が読み込まれた際のmtimeがキャッシュされるようにしていましたが、キャッシュファイルがサーバー側で生成・更新され続けるため、キャッシュファイルを紛失してしまうと作成日時が再現できなくなる脆弱な仕組みが気になっていたので、 entrymtime というプラグインを自作し、各エントリーファイルのmetadataに作成日時を書いておけるようにしました。

移行の為にentrycacheのキャッシュファイルから作成日時を抽出して各エントリーファイルのmetadataに追記。

import os, time

with open('.entrycache') as c:
    data = c.read()

caches = eval(data)

for item in caches.items():
    fname = os.path.basename(item[0])
    if not os.path.exists(fname):
        continue
    t = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(item[1]))
    with open(fname) as r:
        lines = r.readlines()
    lines.insert(1, "#entrymtime %s\n" % t)
    with open(os.path.join("new", fname), 'w') as w:
        w.writelines(lines)

ついでに拡張子がtxtのエントリーファイルの拡張子を blx に変更しました。

さらについでに、エントリーファイルもgithubで管理するようにしました。ついでというよりこれが本当のやりたかったこと。

うーん、2022年の記事とは思えないですね…w

PyBlosxomのプラグイン

posted by jun-g at Mon, 23 Sep 2013 22:28 JST

バージョン1.5から標準でプラグインが同梱されるようになったので、同梱されてるものはなるべくそれを使うように設定を変更しました。

ついでに自作のプラグインはコードを整理してちょっとづつbitbucketに登録していってます。

daemonfreaks / pyblosxom-plugins

自分のブログをちょこちょこカスタマイズするのは箱庭的な趣があって、何年経っても楽しいものですね。

wbgpagerを使うようにした

posted by jun-g at Sun, 06 Jul 2008 03:24 JST

前からこのブログにページャが付いていない事が気になっていたので、今更ながらページャのプラグインを使うようにした。追加したプラグインはwbgpager

最初、エラーも出ないのにページャが全然表示されず、ちょっとハマった。使用しているPyBlosxomのバージョンが古いせいかな、と思い、一つ前のバージョン(2007-11-30)のwbgpagerを使ってみると、ようやく動くようになった。

最近ブログを放置しすぎている気がするので、久々に色々手入れしようかな。

PyBlosxomではてなスターを使うプラグイン

posted by jun-g at Tue, 11 Dec 2007 06:52 JST

超今更って感じやけど、PyBlosxomではてなスターを使う為のプラグインを作った。

ダウンロードはこちらからどうぞ。→ hatenastar.py

使い方。

まずはてなスターに自分のブログを登録してトークンを入手する。必要なのはトークンの文字列だけで、JavaScriptタグは不要。

次にconfig.pyでプラグインをロードするように設定し、

py["hatenastar_token"] = "入手したトークン"

の設定を追加する。

次にFlavourの編集。head.htmlのHEADタグ内に「$hatenastar_header」を追加し、story.htmlの星を表示したい部分に「$hatenastar_star」を、コメントアイコンを表示したい部分に「$hatenastar_comment」を追加する。

以上。

次に既知の問題。表示するエントリの内容を自前でゴリゴリJSONに変換してJavaScriptタグ内に吐き出しているだけなので、エントリ名にシングルクォーテーションが入ってるとJavaScriptでエラーになるはず。でもって、ほとんどテストしてないので他にも不具合あるかも。需要ないから誰も使わないし誰も直してくれないと思ってるので、そのうち自分で直したりキレイにしたりする予定。

需要ないけど一応「その他の参考情報 - はてなスター日記」に載せて欲しいのでトラックバック送っとくか。

PyBlosxom用vim plugin - pyblosxom.vim

posted by jun-g at Mon, 23 Apr 2007 21:59 JST

~/.vimrc がごちゃごちゃしてきたので、以前書いたPyBlosxom用のvimスクリプトを整理してvim pluginにしてみた。

ダウンロード

こちらからどうぞ

インストール

アーカイブを展開すると、pyblosxom.pyとpyblosxom.vimが出てくるので、それらを~/.vim/pluginに入れてインストール完了。

他に必要なもの

  • config.py … PyBlosxomの設定ファイル。
  • py-mixi … mixi日記に投稿する際に必要。(無くてもOK)

~/.vimrcの設定

~/.vimrcに以下の設定が必要。

  • g:pbconfigfile … config.pyファイルのパス
  • g:pbftpserver … FTPサーバ名
  • g:pbftpuser … FTPユーザー
  • g:pbftppassword … FTPパスワード
  • g:pbworkdir … ローカルの作業ディレクトリ
  • g:pbremotedir … アップロード先のディレクトリ
  • g:pbpingservers … 更新PINGを送信するPingサーバ
  • g:pbmixiid … mixiにログインするメールアドレス
  • g:pbmixipassword … mixiのパスワード

~/.vimrcには以下のように書けば良い。

:let g:pbconfigfile = "/home/jun-g/pyblosxom/config.py"
:let g:pbftpserver = "daemonfreaks.com"
:let g:pbftpuser = "user"
:let g:pbftppassword = "password"
:let g:pbworkdir = "/tmp"
:let g:pbremotedir = "/pyblosxom/entries"
:let g:pbmixiid = "mixi@loginid.com"
:let g:pbmixipassword = "mixipassword"
:let g:pbpingservers = "['http://pingoo.jp/ping/', 'http://api.my.yahoo.co.jp/RPC2', 'http://blogsearch.google.co.jp/ping/RPC2']"

使い方

  • 新規エントリ作成 -> 新しいエントリ(バッファ)にテンプレートを表示

    :PBCreateEntry
  • エントリのアップロード -> 現在編集中のエントリ(バッファ)を保存してアップロード

    :PBUploadEntry
  • トラックバック送信 -> 現在編集中のエントリから指定したURLへトラックバックを送信

    :PBTrackback [trackback url]
  • 更新PING送信

    :PBSendUpdatePing
  • 日記の抜粋をmixi日記に投稿 -> 現在編集中のエントリの抜粋を投稿

    :PBPost2Mixi

備考・ToDoなど

  • トラックバックで送信する本文は、エントリの先頭行に「...」を加えた文字列。
  • mixi日記に投稿する日記の抜粋は、エントリの先頭行に「...」を加えた文字列とエントリのURL。
  • Windows版vimには未対応。
  • カテゴリ(サブディレクトリ)には対応していない。なぜなら自分が使っていないから。次のバージョンで対応予定。
  • 更新PING送信機能は、以前どなたかのBlogで見かけたコードをほぼそのまま使用している。
  • mixi日記投稿機能は、以前実装したものを外部の関数として書き直したもの。

ご意見、ご要望、バグレポート、パッチなどなど、お待ちしています。

PyBlosxomでGoogle Sitemapを生成

posted by jun-g at Sun, 08 Apr 2007 19:13 JST

プラグインを探したけど見つからなかったので自分で作ってみた。sitemaps.orgプロトコルに準拠。

ダウンロードはこちらからどうぞ。

インストールは、sitemap.pyをプラグインディレクトリに入れて、config.pyのプラグイン設定に"sitemap"を追加するだけ。$base_url/sitemap.xmlにアクセスして表示されればOK。

アクセスがある度に生成するので、エントリが大量にあるblogではちょっと重いかも…。

entrycache導入

posted by jun-g at Mon, 02 Apr 2007 13:39 JST

PyBlosxomはファイルの更新日時がそのままエントリの投稿日時になるので、過去のエントリに追記しちゃうとそのエントリの日付が変わってしまって困るなー、って思ってたら、投稿日時を記憶するプラグインがあったことに今頃気づいた…。

ということで、ファイル名やエントリの配置などの細工なしで導入できそうなentrycacheをプラグインに追加。初回起動時に過去エントリのキャッシュを一気に作成するので、少し重かった。

あと、mod_wsgi環境ではキャッシュファイルに投稿日時が保存されなくて少しハマッた。mtimeが取得できてない?でも投稿日時の表示はできてるしなぁ。今度デバッグしてみよう。

comments, trackback, check_javascript, tb_spamプラグイン導入

posted by jun-g at Mon, 18 Dec 2006 03:24 JST

ようやく導入してみた。わくわく。trackbackプラグインの修正に合わせて、tb_spamプラグインも以下の通り修正してから導入した。

--- tb_spam.py.orig	Mon Dec 18 02:59:37 2006
+++ tb_spam.py	Mon Dec 18 03:09:12 2006
@@ -11,25 +11,20 @@
 __VERSION__ = '0.1'
 __LICENSE__ = 'BSD license'
 
-def cb_comment_reject(args):
+def cb_trackback_reject(args):
     request = args['request']
     comment = args['comment']
-    if comment.has_key('trackback'):
-        import urllib
-
-        config = request.getConfiguration()
-        my_url = config['base_url']
-        if (comment.has_key('link')):
-            f = urllib.urlopen(comment['link'])
-            content = f.read()
-            f.close()
-
-            if content.find(my_url) == -1:
-                return True
-            else:
-                return False
-        else:
+    import urllib
+    config = request.getConfiguration()
+    my_url = config['base_url']
+    if comment.has_key('link'):
+        f = urllib.urlopen(comment['link'])
+        content = f.read()
+        f.close()
+        if content.find(my_url) == -1:
             return True
-
+        else:
+            return False
     else:
         return False

上手く動きますように!!

コメントスパム対策系プラグインでトラックバックまでrejectされる問題

posted by jun-g at Mon, 18 Dec 2006 02:37 JST

こないだ書いたcheck_javascriptプラグインを使えばtrackbackプラグインへの修正は不要、っていうのは嘘でした。すみません。check_javascriptプラグインを導入すると、トラックバック受信時にエラーが発生するようになります。

どうもこの辺り、設計がいけてない気がする。ちゃんと仕組みを整理した上で修正したいので、ちょっとまとめてみる。

まず、そもそも「trackbackプラグインがcommentsプラグインの機能を使用する事を前提に実装されている」という事が問題だと考えられる。しかし、これを言い出すと、trackbackプラグインをスクラッチから書き直す事になってしまう。本来はその方が良いのかもしれないけど、ちょっと大変そうなので今回はパス。

次に、shunuhsさんがsh1.2 pyblosxom : 続: MagicWord/comments/trackback pluginで取った「トラックバック経由で受け取ったデータにtrackbackプラグイン内部で判定用パラメータを追加し、コメントスパム対策系プラグイン内でトラックバックか判定する」という対策の場合、使用するコメントスパム対策プラグイン全てに「受け取ったデータはトラックバックか?」という判定処理を加える必要があるし、既にPyblosxom Plugin Registryに登録されているコメントスパム対策系プラグインは、やはりそのままでは使えない事になる。できればこれらのプラグインを修正無しで使用できるようにしたい。

以上の事を(ほんのちょっとだけ)考えた結果、「cb_comment_reject関数はwriteComment()を呼び出す前、しかもtrackbackプラグインでは実行されない関数内で実行するようにすればいいのでは?」という結論に至った。

ということでcomments.pyを早速修正。svn diffの結果は以下の通り。

Index: comments.py
===================================================================
--- comments.py	(リビジョン 954)
+++ comments.py	(作業コピー)
@@ -359,19 +359,6 @@
         os.makedirs(cdir)
 
     cfn = os.path.join(cdir,entry['fn']+"-"+comment['pubDate']+"."+config['comment_draft_ext'])
-     
-    argdict = { "request": request, "comment": comment }
-    reject = tools.run_callback("comment_reject",
-                                argdict,
-                                donefunc=lambda x:x != 0)
-
-    if (isinstance(reject, tuple) or isinstance(reject, list)) and len(reject) == 2:
-        reject_code, reject_message = reject
-    else:
-        reject_code, reject_message = reject, "Comment rejected."
-
-    if reject_code == 1:
-        return reject_message
    
     def makeXMLField(name, field):
         return "<"+name+">" + cgi.escape(field.get(name, "")) + "</"+name+">\n";
@@ -475,13 +462,9 @@
         comment_dir = os.path.join(config['comment_dir'], entry['absolute_path'])
 
         # create the message
+        from email.Header import Header
         from email.MIMEText import MIMEText
         message = []
-        message.append("From: %s" % email)
-        message.append("To: %s" % config["comment_smtp_to"])
-        message.append("Date: %s" % formatdate(float(comment['pubDate'])))
-        message.append("Subject: comment by %s" % author)
-        message.append("")
         message.append("Name: %s" % author)
         if comment.has_key('email'):
             message.append("Email: %s" % comment['email'])
@@ -498,7 +481,13 @@
 
         body = '\n'.join(message)
         body = MIMEText(body.encode('utf-8'), 'plain', 'utf-8')
- 
+        subj = "comment by %s" % author
+        subj = Header(subj.encode("utf-8"), "utf-8")
+        body["Subject"] = subj
+        body["From"] = config["comment_smtp_from"]
+        body["To"] = config["comment_smtp_to"]
+        body["Date"] = formatdate(float(comment['pubDate']))
+
         if (config.has_key('comment_mta_cmd')):
             argv = [config['comment_mta_cmd'],
                     '-s',
@@ -506,7 +495,7 @@
                     config['comment_smtp_to']]
             # TODO: switch to subprocess when we can require python 2.4
             process = popen2.Popen3(argv, capturestderr=True)
-            process.tochild.write(body)
+            process.tochild.write(body.as_string())
             process.tochild.close()
             process.wait()
             stdout = process.fromchild.read()
@@ -521,7 +510,7 @@
             server = smtplib.SMTP(config['comment_smtp_server'])
             server.sendmail(from_addr=email,
                             to_addrs=config['comment_smtp_to'], 
-                            msg=body)
+                            msg=body.as_string())
             server.quit()
 
     except Exception, e:
@@ -714,9 +703,22 @@
             cdict['email'] = form['email'].value
 
         cdict['ipaddress'] = pyhttp.get('REMOTE_ADDR', '')
-        data["comment_message"] = writeComment(request, config, data, \
-                                                cdict, encoding)
 
+        argdict = { "request": request, "comment": cdict }
+        reject = tools.run_callback("comment_reject",
+                                    argdict,
+                                    donefunc=lambda x:x != 0)
+        if (isinstance(reject, tuple) or isinstance(reject, list)) and len(reject) == 2:
+            reject_code, reject_message = reject
+        else:
+            reject_code, reject_message = reject, "Comment rejected."
+        if reject_code == 1:
+            data["comment_message"] = reject_message
+        else:
+            data["comment_message"] = writeComment(request, config, data, \
+                                                   cdict, encoding)
+
+
 def massage_link(linkstring):
     """Don't allow html in the link string. Prepend http:// if there isn't
     already a protocol."""

こないだの修正分も含まれているのでちょっと紛らわしいかも。この差分の内容には以下の修正が含まれている。

  • cb_comment_rejectをwriteComments()実行前に処理するように変更
  • コメント/トラックバック内容に非ASCII文字が含まれていた場合にメール送信時にエラーになる問題を修正
  • 「From」「To」「Subject」「Date」がメールヘッダではなくメール本文に設定されてしまう不具合を修正

これで、スパム対策プラグインを導入しても、修正無しにトラックバックの受信が行えるようになるはず。

しかし、上記の修正を適用するとトラックバック受信時にcb_comment_reject関数が実行されなくなってしまう為、トラックバックスパム対策を行うフックが無くなってしまう。これは、trackbackプラグイン側にフックを用意すれば良いと思う。trackback.pyを以下のように修正してみた。

Index: trackback.py
===================================================================
--- trackback.py	(リビジョン 954)
+++ trackback.py	(作業コピー)
@@ -96,6 +96,19 @@
                       'link' : form['url'].value, \
                       'source' : form.getvalue('blog_name', ''), \
                       'description' : form.getvalue('excerpt', '') }
+
+            argdict = { "request": request, "comment": cdict }
+            reject = tools.run_callback("trackback_reject",
+                                        argdict,
+                                        donefunc=lambda x:x != 0)
+            if (isinstance(reject, tuple) or isinstance(reject, list)) and len(reject) == 2:
+                reject_code, reject_message = reject
+            else:
+                reject_code, reject_message = reject, "Trackback rejected."
+            if reject_code == 1:
+                print >> response, tb_bad_response % reject_message
+                return 1
+
             from Pyblosxom.entries.fileentry import FileEntry
             from Pyblosxom.pyblosxom import Request
             from Pyblosxom.pyblosxom import PyBlosxom

この修正を適用すると、トラックバック処理時にcb_trackback_reject関数が実行されるようになる。トラックバックスパム対策には、この関数を持つプラグインを実装すれば良い。

コメントとトラックバックのスパム対策に同じ処理(IPアドレスチェックとかNGワードチェックとか)を使用したい場合は、

def cb_comment_reject():
    spam_check()

def cb_trackback_reject():
    spam_check()

def spam_check():
    (処理)

みたいなプラグインの実装にすれば良いと思う。どうせこれまでに存在したコメントスパム対策プラグインはトラックバックに対しては機能しなかったはずなので、この仕組みで問題ないはず。

と、まぁ自分なりの修正案をガーっと書いてみた訳やけど、実はあんまり動作確認もしてないし、Pyblosxom自体の仕組みもソースを斜め読みした程度しか理解してないので、もしかしたらデタラメな事書いてるかも。ツッコミ等ありましたらよろしくお願いします。> pyblosxomユーザーの皆様

とりあえず自分のところには、上記修正を適用したcommentsプラグインを導入してみて、問題無さそうならパッチをMLに投げてみる事にしよう。trackbackプラグインの修正は…もうちょっと考えてみよう。

pyblosxomのSVN trunkにcheck_javascriptプラグインが追加されてた!

posted by jun-g at Fri, 15 Dec 2006 03:30 JST

昨日、pyblosxomのSVN trunkにcheck_javascriptプラグインが新たに登録されてた。どうもJavaScriptを利用したコメントスパム対策用のプラグインみたい。という事は、こいつを利用すればMagicWordプラグインは不要、さらにtrackbackプラグインへの修正も不要って事かー!ムホムホ!!という事で早速試してみた。

まずはいつも通りcheck_javascript.pyをpluginsディレクトリにコピーして、config.pyを編集してプラグインがロードされるように設定。そして、コメントフォーム用のflavourであるcomment-form.htmlを、trunkの雛型を参考にして以下の通り修正。

--- comment-form.html.orig	Sun Oct 15 02:59:40 2006
+++ comment-form.html	Fri Dec 15 03:00:11 2006
@@ -3,7 +3,7 @@
 <div class="blosxomCommentForm">
 <form method="post" action="$base_url/$file_path.html#commentMessage" id="comments_form">
 <fieldset>
-<input type="hidden" name="secretToken" value="pleaseDontSpam" />
+<input type="hidden" name="secretToken" id="secretTokenInput" value="pleaseDontSpam" />
 <input name="parent" type="hidden" value="$file_path" />
 <input name="title" type="hidden" value="$title" />
 <label class="commentForm">Name</label><br />
@@ -21,6 +21,11 @@
 <input name="submit" type="submit" value="Post" />
 </fieldset>
 </form>
+<script type="text/javascript"><!--
+// used by check_javascript.py. this is almost entirely backwards compatible,
+// back to 4.x browsers.
+document.getElementById("secretTokenInput").value = "$blog_title";
+//--></script>
 </div> <!-- ends blosxomCommentForm div -->
 </div>
 </div> <!-- ends blosxomComments div -->

パラメータ「secretTokenInput」の値にJavaScriptで$blog_titleの値を設定し、プラグイン側のcb_comment_reject()で値をチェックする、という仕組みらしい。お手軽やね。あ、でもJavaScript使うって事は、テキストブラウザや古いブラウザからはコメント投稿できないって事かー!ま、いいか。

という事で、簡単さに惹かれてこいつを導入する事に決定。効果の程はこれいかに。

trunkのcomments plugin

posted by jun-g at Tue, 12 Dec 2006 03:00 JST

先日のtrackback pluginのパッチは無事に取り込まれた模様。よかった。

そのパッチを作る際、trunkのcomments.pyを軽く見たんやけど、なんかメール送信時の非ASCII文字を受け付けない問題とか色々修正されてるっぽかったので、近々試してみないとなぁと思ってたら、shunuhsさんがtrunkに入れ替えた上にパッチを書いて、しかもtb spam用のプラグインまで作ってた。素晴らしいっす。仕事早いっす。動作実績があると心強いので、早速僕もtrunkのcomments/trackback pluginに入れ替える事にした。最近コメントスパムに悩まされていたので、ついでにMagicWord pluginも導入することに。

が、その前にshunuhsさんが「メールが飛ばない」と言われている問題を調べてみる事にした。テスト環境のcomments.pyをtrunkのものに入れ替えて試してみると、pyblosxomのエラーログに

2006-12-12 00:07:34,909 [ERROR] comments: error sending email: ['Traceback (most recent call last):\n', '  File "/pub/www/pyblosxom/plugins/comments.py", line 524, in send_email\n    msg=body)\n', '  File "/usr/local/lib/python2.4/smtplib.py", line 692, in sendmail\n    (code,resp) = self.data(msg)\n', '  File "/usr/local/lib/python2.4/smtplib.py", line 485, in data\n    q = quotedata(msg)\n', '  File "/usr/local/lib/python2.4/smtplib.py", line 193, in quotedata\n    re.sub(r\'(?:\\r\\n|\\n|\\r(?!\\n))\', CRLF, data))\n', '  File "/usr/local/lib/python2.4/sre.py", line 142, in sub\n    return _compile(pattern, 0).sub(repl, string, count)\n', 'TypeError: expected string or buffer\n']

というのが出てた。どうもメール送信時にエラーになってるっぽい。で、なんとなくピンときて入れた修正が以下。

--- comments.py.orig	Tue Dec 12 01:52:47 2006
+++ comments.py	Tue Dec 12 02:36:47 2006
@@ -521,7 +521,7 @@
             server = smtplib.SMTP(config['comment_smtp_server'])
             server.sendmail(from_addr=email,
                             to_addrs=config['comment_smtp_to'], 
-                            msg=body)
+                            msg=body.as_string())
             server.quit()
 
     except Exception, e:

予想適中、無事にメール送信できるようになった。しかーし!現状のcomments.pyの作りだと、メールヘッダに設定されるべき「From」「To」「Subject」がメール本文に記載されるという超手抜き仕様。現状だとこんな本文のメールが来る。

From: from_at_aemonfreaks.com
To: to_at_daemonfreaks.com
Date: Mon, 11 Dec 2006 16:20:32 -0000
Subject: comment by TEST

Name: TEST
URL: 
Hostname: localhost.daemonfreaks.local (192.168.0.21)
Entry URL: http://localhost/blog/200611060000
Comment location: /pub/www/pyblosxom/entries/comments/200611060000-1165854032.63.cmt


Hello, world.

しかも件名が空。イケてない。先頭の4行は明らかにメールヘッダにあるべき。なので、以前自分で修正したやつと同様の修正を今回も入れる事にした。修正内容は以下のとおり。

--- comments.py.orig	Tue Dec 12 01:52:47 2006
+++ comments.py	Tue Dec 12 01:48:48 2006
@@ -475,13 +475,9 @@
         comment_dir = os.path.join(config['comment_dir'], entry['absolute_path'])
 
         # create the message
+        from email.Header import Header
         from email.MIMEText import MIMEText
         message = []
-        message.append("From: %s" % email)
-        message.append("To: %s" % config["comment_smtp_to"])
-        message.append("Date: %s" % formatdate(float(comment['pubDate'])))
-        message.append("Subject: comment by %s" % author)
-        message.append("")
         message.append("Name: %s" % author)
         if comment.has_key('email'):
             message.append("Email: %s" % comment['email'])
@@ -498,7 +494,13 @@
 
         body = '\n'.join(message)
         body = MIMEText(body.encode('utf-8'), 'plain', 'utf-8')
- 
+        subj = "comment by %s" % author
+        subj = Header(subj.encode("utf-8"), "utf-8")
+        body["Subject"] = subj
+        body["From"] = config["comment_smtp_from"]
+        body["To"] = config["comment_smtp_to"]
+        body["Date"] = formatdate(float(comment['pubDate']))
+
         if (config.has_key('comment_mta_cmd')):
             argv = [config['comment_mta_cmd'],
                     '-s',
@@ -506,7 +508,7 @@
                     config['comment_smtp_to']]
             # TODO: switch to subprocess when we can require python 2.4
             process = popen2.Popen3(argv, capturestderr=True)
-            process.tochild.write(body)
+            process.tochild.write(body.as_string())
             process.tochild.close()
             process.wait()
             stdout = process.fromchild.read()
@@ -521,7 +523,7 @@
             server = smtplib.SMTP(config['comment_smtp_server'])
             server.sendmail(from_addr=email,
                             to_addrs=config['comment_smtp_to'], 
-                            msg=body)
+                            msg=body.as_string())
             server.quit()
 
     except Exception, e:

これで「Subject」「From」「To」(「Date」はオマケ)が正しくメールヘッダに設定されるようになった。ちなみに「comment_mta_cmd」を使用してメール送信を行う場合の動作は未確認なので、どなたか試してみてください…。

と、ここまで調べたところで時間切れになってしまった。続きは明日以降で。Magic Wordとtb_spam.pyの動作確認をしてから全部導入することにしよう。

trackbackプラグインのパッチ

posted by jun-g at Sun, 26 Nov 2006 21:29 JST

shunuhsさんに勧められたので、以前作ったtrackbackプラグインのパッチを本家に取り込んでもらうべくpyblosxom-develのMLに投げてみたよ。

英語書くっていうレベルじゃねぇぞ的な拙い英文は相変わらず。割と適当な英文でも結構伝わるものなので大丈夫なはず。根拠は無いけど。

トラックバックスパムが

posted by jun-g at Wed, 15 Nov 2006 20:49 JST

昨日、一昨日と大量のトラックバックスパムを喰らってしまった。昨日は仕事が終わって家に帰ってきたのがAM2:30頃で、それから大量のスパムに気付いて、慌てて削除したんだけど、このまま放置してたら今日も喰らっちゃうだろうなぁ、と思ったので、眠かったけどとりあえず急いでtrackback.pyを修正してスパム避けを実装しておいた。

--- trackback.py.orig	Wed Nov 15 02:58:41 2006
+++ trackback.py	Wed Nov 15 03:12:36 2006
@@ -87,6 +87,16 @@
         message = "A trackback must have at least a URL field (see http://www.sixapart.com/pronet/docs/trackback_spec )"
 
         if form.has_key("url"):
+            try:
+                import urllib
+                ret = urllib.urlopen(form['url'].value)
+                target = ret.read()
+                ret.close()
+            except:
+                target = ""
+            if not config['base_url'] in target:
+                print >> response, tb_bad_response % "Please paste any links to your blog."
+                return 1
             from comments import decode_form
             decode_form(form, config['blog_encoding'])
             import time

いわゆる言及リンクのないトラックバックは受け付けないようにしたかったんだけど、trackback.py内で当該エントリのURLを取得する方法を調べる余裕がなかったので、結局ここのサイトのURLがあればオッケーという適当な作りに。送信元ページ内のチェックもかなり適当。週末時間が取れたらもうちょっとちゃんと書き直す。つもり。

trackbackプラグイン導入 その2

posted by jun-g at Sun, 15 Oct 2006 03:53 JST

はてなダイアリーからTrackBackを送信してみたところ、レスポンスは正常に返ってきたのに、コメント欄表示でエラーが出るようになった。TrackBackを受信して出来たコメントファイルも空だったので調べてみると、ここのコメント欄に書いてあるとおり、trackback.py内で文字が適切にエンコードされていない、という事らしい。

というわけで、trackback.pyを以下の通り修正した。

--- trackback.py.orig   Sun Oct 15 03:24:03 2006
+++ trackback.py        Sun Oct 15 03:26:32 2006
@@ -87,6 +87,8 @@
         message = "A trackback must have at least a URL field (see http://www.sixapart.com/pronet/docs/trackback_spec )"

         if form.has_key("url"):
+            from comments import decode_form
+            decode_form(form, config['blog_encoding'])
             import time
             cdict = { 'title': form.getvalue('title', ''), \
                       'author': 'Trackback from %s' % form.getvalue('blog_name', ''), \

もう一度はてなダイアリーからTrackBackを送信すると、無事に受信・表示できるようになった

それにしても、今回の件だけでなく、pyblosxomを設置するにあたって、SH1.2 PYBLOSXOMpyblosxom関連のエントリをとても参考にさせてもらった。これらのエントリがなかったらpyblosxomの導入を途中で挫折してたかも。ありがとうございます。

trackbackプラグイン導入

posted by jun-g at Sun, 15 Oct 2006 03:05 JST

commentsプラグインに続いてtrackbackプラグインを導入してみた。

commentsプラグインでメール送信 導入

posted by jun-g at Sat, 14 Oct 2006 06:48 JST

メール送信部分の修正、スタイルシートの調整が完了したので、commentsプラグインを導入してみた。

comments.pyの修正箇所はこんな感じ。

--- comments.py.orig	Thu Oct 12 23:07:08 2006
+++ comments.py	Sat Oct 14 06:39:54 2006
@@ -450,26 +450,21 @@
         from rfc822 import formatdate
     from socket import gethostbyaddr
 
+    from email.Header import Header
+    from email.MIMENonMultipart import MIMENonMultipart
+
     author = escape_SMTP_commands(clean_author(comment['author']))
     description = escape_SMTP_commands(comment['description'])
     ipaddress = escape_SMTP_commands(comment.get('ipaddress', '?'))
 
-    if comment.has_key('email'):
-        email = escape_SMTP_commands(clean_author(comment['email']))
-    else:
-        email = config['comment_smtp_from']
-
     try:
         server = smtplib.SMTP(config['comment_smtp_server'])
         curl = config['base_url']+'/'+entry['file_path']
-        comment_dir = os.path.join(config['comment_dir'], entry['absolute_path'])
-
+        from_addr = config['comment_smtp_from']
+        to_addr = config['comment_smtp_to']
+        subject = "comment by %s" % author
+        enc = config["blog_encoding"]
         message = []
-        message.append("From: %s" % email)
-        message.append("To: %s" % config["comment_smtp_to"])
-        message.append("Date: %s" % formatdate(float(comment['pubDate'])))
-        message.append("Subject: comment by %s" % author)
-        message.append("")
         message.append("Name: %s" % author)
         if comment.has_key('email'):
             message.append("Email: %s" % comment['email'])
@@ -479,12 +474,19 @@
             message.append("Hostname: %s (%s)" % (gethostbyaddr(ipaddress)[0], ipaddress))
         except:
             message.append("IP: %s" % ipaddress)
-        message.append("Entry URL: %s" % curl)
+        message.append("Entry URL: %s.html" % curl)
         message.append("Comment location: %s" % comment_filename)
         message.append("\n\n%s" % description)
-        server.sendmail(from_addr=email,
-                        to_addrs=config['comment_smtp_to'], 
-                        msg="\n".join(message))
+        msg = "\n".join(message)
+        part = MIMENonMultipart("text", "plain")
+        subj = Header(subject.encode(enc), enc)
+        part["Subject"] = subj
+        part["From"] = from_addr
+        part["To"] = to_addr
+        part.set_payload(msg.encode(enc), enc) 
+        server.sendmail(from_addr=from_addr,
+                        to_addrs=to_addr,
+                        msg=part.as_string())
         server.quit()
     except Exception, e:
         logger = tools.getLogger()

ついでにエントリの固定リンクに拡張子を付けるようにしたり、Recent Entriesを最大10件までの表示に変更したりした。

commentsプラグインでメール送信

posted by jun-g at Fri, 13 Oct 2006 01:05 JST

ローカルのテスト環境ではとりあえずメール送信できるようになった。まだ気に入らない部分があるので、もうちょっと修正してから週末に導入する。

commentプラグイン

posted by jun-g at Thu, 12 Oct 2006 01:19 JST

commentsプラグインを導入しようとしたけど、メール送信部分が日本語を受け付けない仕組みになっていたので導入延期。修正して送信できるようになってから導入しようっと。