Webアプリを立てて外部から作業しやすくする

WX310K、いわゆる京ポン2を持って以降、出先でのWeb閲覧がお手軽にできるようになってからNexus5を持つ現在へと至っていますが、スマホ・タブレット時代になって相当リッチなWebアプリも動かせるようになりました。昔から現在に至るまで利用しているWebアプリケーションについて書いてみようと思います。 ソースコード閲覧 GNU Global このソフトはctagsの強化版といった感じのソフトウェアですが、ハイパーリンクでのクロスリファレンスを実現した静的HTMLも出力することができます。JavaScriptなどを使わないシンプルな出力なので、非力なWX310Kでもそれなりに利用できていました。今でも使っています。 gonzui 主にRubyで書かれたソースコード特化型検索エンジンです。残念ながら2005年を最後に更新がありません。かつては利用していました。 milkode 同じくRubyで書かれたソースコード検索エンジンです。開発は活発で、対応している言語もgonzuiより多いので、現在はこちらを使っています。gonzuiが独自データベースであったのに対し、milkodeはバックエンドにGroongaを使っています。 Pootle(翻訳) Pythonで書かれたWebアプリとして動作する翻訳ツールです。かなりモダンな造りでJavaScriptをガッツリ使っています。スタンダードなpo形式も扱えるので、役に立っています。 ownCloud(オンラインストレージ) PHPで書かれたオンラインストレージです。Linux, Windows, Android, iOS等のクライアントが用意されていますが、WebDAVとしても動作します。Webアプリとしても動きます。 サーバーサイドでAESを使った暗号化ができたり、サードパーティWebアプリがいろいろとあったりします。RSSリーダーもあるので、もしFeedlyがなくなってしまったらそれを使ってみようと考えています。 その他 gitlabやredmineも用意したのですが、これらはいまいち活用できていません。以前はWebでIMAPを扱えるIrohaMailも入れていたのですが、使い勝手がいまいちで消してしまいました。今時であればスマートフォンのIMAPクライアントで十分でしょう。

GData ClientのSpreadsheet ListFeed

個人的にはまったので記録に残しておこうと思います。 GoogleのAPIには2つの種類があります。一つはGoogle APIと呼ばれるもので、APIs Explorerにて確認できるものです。もう一つ、微妙に違うGoogle Data APIsというものがあります。GoogleはこれらのAPIを操作するためのライブラリを各種言語向け(Java, .NET, Python, ruby, PHP等)に用意しています。前者はgoogle-api-clientというような名前、後者はgdataというような名前を付けています。 この2つは微妙にセマンティックが違うのですが、OAuth2で認証できる点は同じで、認証ポイントも同一です。しかしそれぞれ個別にOAuth2認証クラスを持っていたりして、両方をまたいで(たとえばgmailとcalenderの組み合わせ等)使おうとするときは結構面倒です。両方をカバーするscopeでどちらかのライブラリで認証し、もう片方のOAuth2認証クラスに各種情報をコピーする必要があります。 それはともかく、今回はまったのは以前くらった「GData.SpreadsheetsライブラリのListFeedに潜む罠」の続きです。一行目に書かれた文字列がフィールドのキーとなるわけですが、さらにこの値は「API上は小文字しか受け付けない」という罠です。 たとえばA1に「Firstname」という値があったとして、ListEntry.CustomのLocalNameプロパティに”Firstname”としているとAPIレベルでエラーが帰ってきます。ここは”firstname”としなければなりません。 StackOverflowの“Cannot add a row to Google Spreadsheet”という記事でこのことが説明されていました。Google Sheets API version 3.0にはそのことは触れられていません… 毎度StackOverflowにはお世話になりっぱなしです。

Windows版puttyのビルド

puttyのビルドに関する情報、特にWindows向けが少ないのでメモとして記録しておきます。 必要なもの Perl (ActivePerl, Strawberry, cygwinなんでも良い) puttyのソース スクリプトの実行 perl mkfiles.plを実行 出力結果 windows/MSVC ディレクトリの下にVisual C++ 6向けのputty.dswファイルとサブディレクトリ以下に各種コマンド(putty, puttygen等)のサブディレクトリとプロジェクトファイル(dsp)が生成されます。 新しいVisual Studioで開く エクスプローラーからputty.dswを右クリックし、「プログラムから開く」で利用したいバージョンのVisual Studioを選択します。Expressでも使えます。 開いたあとはVisual Studioがslnファイルに変換してくれます。コマンドラインからmsbuildなども使えるようになります。 注意点 SSPIと呼ばれる機構を利用しているので、マクロSECURITY_WIN32を定義する必要があります。プロジェクトのプロパティからプリプロセッサの設定でこのマクロ定義を追加するなどの処置をすると良いでしょう。

mikutter-perlの公開

マルチプラットフォームで動作する、Rubyで書かれたTwitterクライアントmikutterのプラグイン、mikutter-perlを書きました。 動機: RubyからPerlを呼びたい 前々からNamazuのRuby実装を作りたい、ということを考えていました。現状のNamazuは独自のデータ形式を持っていますが、新しい実装ではバックエンドをGroongaにしたいと思っています。現状、Groongaのperl bindingはこれといった定番がないのに対し、RubyにはRroongaがあるので、作るならRubyだろうと考えています。 ただ、これまでPerlで書かれたフィルター群をどうにか継承できないか、とも考えていました。Namazuのフィルターはさまざまな形式のファイルからテキストを抽出するもので、今となっては結構な種類の数があります。 フィルター部分のみを呼び出すために、RubyからPerlのコードを呼び出したいという考えを実現する最初の一歩として、mikutter-perlを書いてみたというわけです。なお、Perl側には逆のことをするInline::Rubyというものがあります。 libperl呼び出し部分 最初に書いておきますが、やっていることは大したことありません。perlembedのサンプルとそう大きくは変わりません。 当初は直接libperl.soをDL::Importで読み込んで実行することを考えていたのですが、その手法には問題がありました。構造体へのアクセスができず、初期化に必要な作業が実行できません。以下にperlembedでも出てくるコード例を示します。 肝となるのはPL_exit_flagsです。perl_alloc, perl_constructで作成したperlインタプリタのインスタンス的なものに対し、終了時の挙動をフラグとして設定する箇所です。 gcc -Eオプションを使ってこの部分がどのような内容に展開されるかを確認すると、以下のようになります(on Debian wheezy)。 Perlinterpreterはstruct interpreterをtypedefしたもので、my_perlのIexit_flagsに値を代入するようなコードに展開されます。 デバッグ情報、シンボル情報などをstripした状態で、dlopen(2)だけでこれらにアクセスすることはできません。そもそもPerl周りはたくさんのマクロを使っているので、そこをクリアしたとしても汎用性が担保できません。 結局、そのあたりを全部担当するためのコードをCで書き、シンプルなインターフェースだけにまとめてDL::Import(dlopen)で呼び出せるようなコードを書きました(perlstub.c)。 RubyとPerlの間のやりとりも単純な文字列だけなので、割とシンプルに書きあがりました(mikutter-perl.c)。DL::Importはchar *を自動的にRubyの文字列に変換してくれるので楽です。 PL_exit_flagsさえ気にしなければ、DL::Importだけでコードを完結させることはできます。実際に書いたコードをgistにおいてあります。 mikutterプラグインの開発にあたって 今回初めてmikutterのプラグインを作成しました。参考にした資料は以下の通りです。 Writing mikutter plugin (http://toshia.github.io/writing-mikutter-plugin/) 基本的な書き方とイベントフィルタ、アクティビティの扱いについての情報 Event and Filters (http://toshia.github.io/writing-mikutter-plugin/event.html) 利用可能なイベントの一覧。今回は自分の実際のポストのみを対象とするためpostedイベントを監視 mikutter-shell-post (https://github.com/penguin2716/mikutter_shell_post) 似たようなことを実現している先行例として大いに参考になりました mikutter pluigin特有だと思われる、自分がはまった点についても列挙しておきます。 プラグイン内部で発生した例外は自力で受けないとスルーされる。ちょっとしたエラーがあっても止まらないのでわからない mypostイベントは、mikutter起動時に取得される過去の自身のツイートを受け取った時にも発生する。今まさにポストしたツイートに対応するイベントはpostedになる

ownCloudのDBマイグレーション失敗とリカバー

ふとしたことから、手元のsid環境を更新したのですが、その時にownCloudが5.0.25から7.0.2へと大きく変わってしまいました。ownCloudはアップブレード機能を持っている(web, occコマンド)のですが、それが途中でこけてしまったので、対処方法をblogに残しておきます。 5.0.25から7.0.2へ移行 自分はsid環境を、lxcコンテナの一つに持っています。その中でownCloudも運用しています。最初に導入したときのバージョンは5.0.25だったのですが、この記事を書いている辞典では7.0.2が最新です。5->6のメジャーアップグレードをはさめばうまくいったのかもしれませんが、自分のケースではデータベースの移行がうまくゆきませんでした。バックエンドにはSQLite3を使っています。 oc_lucene_statusでのエラー アップグレード時に発生したエラーログの一部を以下に示します。 oc_lucene_statusというテーブルの移行に失敗しています。このテーブルはLuceneによる全文検索用のものと思われますが、自分自身が全文検索を使ったことがこれまでなかったので、単純にテーブルの削除と再作成をすればよいだろうと推測し、まずはバックアップを取ったうえでdropしてみました。 単純にdropをしただけでは、当然テーブルがなくなるだけなので、やはりアップグレードに失敗します。その時のエラーは以下の通りです。 データベースのテーブルの定義はXMLで書かれています。ソースコードのapps/search_lucene/appinfo/database.xmlが該当するファイルです。これを見て適当に見よう見まねでテーブルを作ってみたところ、うまくゆきませんでした。 これはまずいと思い、バックアップしておいた方のデータベース上でのテーブル構造を参照してみました。 この結果を参考に、新しい方のデータベースで同じテーブルを作成し(表示されているSQLをそのまま実行する)、再度アップグレードを試みたところ成功しました。 無事アップグレードに成功し、今では普通に利用できています。

caffから受け取った署名を自分の鍵へ取り込む(gpg import)

ずいぶん間が開いてしまいましたが、GnuPG key signの作業をする(signing-party/caff)の続きです。前回は自分が相手に対して署名を行い、その結果を送るための手続きについて説明しました。今回はその逆、自分が受け取った相手からの署名を自分の鍵に追加する方法について説明します。 メールをファイルに保存 相手がcaffを使っている場合、pgp鍵のおそらくは各IDごとに1通のメールが届きます。 私の鍵の場合だと、IDとしているメールアドレスは4つあるので、一人当たり4通メールが送られてきます。それらを1つづつファイルとして保存します。 メールの内容は、それぞれのIDに対応する、自身の公開鍵で暗号化されたpgp asciiメッセージです。 メールの復号化 このメールをpgpコマンドで復号化します。 上記コマンド例では、入力されたファイルをmsgというファイル名で復号化しています。復号化した内容は、caffの標準テンプレートであれば以下のようになります。 署名の取り込み この復号化されたファイルには、添付ファイルとして鍵への署名があります。本文中にも説明がありますが、gpg –importコマンドを実行することで署名を自分の鍵に取り込むことができます。 これを、届いたメールの数だけ実施します。さすがに毎回passphreaseを入力するのはしんどいので、gpg-agent等を使うと楽になります。gpg-agentはバージョン2系からついてきます。1.4系にはありません。エージェントの使い方はssh-agentとよく似ているので、そちらに慣れている人であれば楽に使えるでしょう。 私は以下のようなワンライナーで一括処理をするようにしています。 公開キーサーバー上の鍵の更新 最後に、公開キーサーバーへ新しい(電子署名の増えた)鍵を送信して更新します。これは普段から公開キーサーバーに鍵を登録している人だけがすればよい作業なので、運用によっては不要な作業です。 以上で作業は終わりです。

GData.SpreadsheetsライブラリのListFeedに潜む罠

ほぼ1日ぐらいはまっていたのでメモ代わりに記録しておきます。 Googleの各種サービスはWeb APIを持っているだけでなく、.NET, Ruby, Python, Java等の各種言語向けSDKを用意しています。これを使ってGoogle Spreadsheetsを操作しようとして、ちょっとはまりました。 Spreadsheet APIのリファレンスには、spreadsheetを操作する2種類の方法を提供しています。ListFeed型(行単位処理)とCellFeed型(セル単位処理)です。 CellFeedは割と簡単で、指定した矩形範囲のセルを逐次処理させるのに向いている手段です。ただし、こちらにも若干の罠があって、デフォルトでは値の入っているセルのみしか操作できません。APIリファレンスのサンプルの書き方もそのようになっています。値の入っていないセルも捜査対象にするためには、CellQueryのReturnEmptyプロパティにReturnEmptyCells.yesを代入しておく必要があります。 上記のコードは、5×3のセルすべてにアクセスするためのコード例です。ReturnEmptyを指定しないと、値の入っていないセルはとばして結果を返してきます。 本題のListFeedの罠についてですが、まずAPIガイドのサンプルの一部を見てみます。 このコードをまっさらなシートに対して実行をすると、API側がHTTPステータス400を返すので、GDataRequestExceptionが発生します。 何が問題なのかというと、ListEntry.CustomのプロパティであるLocalNameは「1行目のカラムの値」との対応付けがなされている前提のAPIだからです。上記の例だと、1行目に”firstname, lastname, age, height”という値が入ったセルが必要だということです。このことについて気付いたのは、値の入ったシートに対してListFeedで読み出しをしてみたら、1行分だけ少ない結果が返ってきたからです。CellFeedはそういう制約がないため、1行目を含めて内容の取得、変更等ができます。 あとになってガイドを読み返したら、以下のような説明がありました。 list row Row of cells in a worksheet, represented as a key-value pair, where each key is a column name, and each value is the cell value. The first row of a worksheet is always considered the… Continue reading GData.SpreadsheetsライブラリのListFeedに潜む罠

KAKASIのコードについて

ここしばらくKAKASIのソースをいじっています。いい加減あたらしいバージョンをリリースして、しばらくは他のことをやりたいのですが、次に戻ってきたときいろいろと忘れそうなので、記録として残しておこうと思います。 そもそもKAKASIとは何か オリジナルのKAKASIはたかはしもとのぶさんによって作成されたソフトウェアです。漢字、カタカナ、ひらがな、ローマ字を相互に変換する機能をもっています。SKKの辞書を用いて、 オリジナルのKAKASIに、単語を分割する「分かち書き」機能をパッチとして作成したのが、馬場さんです。馬場さんはこの機能を利用して、freeWAISやNamazuなどの全文検索ソフトウェアで日本語を扱えるようにしました。 自分もNamazuの開発にかかわる中で、パッチとしてKAKASIの機能をメンテナンスするのはしんどい、KAKASIのリリース自体長らく行われていない、といった理由で、Namazuの開発の一環としてKAKASIの開発を継承することをたかはしさんに打診し、受け入れられて今に至ります。 最近の作業 KAKASIのバージョンは長いこと2.3.4でリリースが止まっていました。2006年ごろ自分がリリースをしようとした痕跡があるのですが、その後Debian方面でlibtext-kakasi-perlのテストが通らなくなった等いろいろな要因で「これはリリースしないといけない」と思い、ようやく出せたのが2014/1/18です。このリリースで一番大きい変化はUTF-8のサポートです。といっても、iconvに依存しています。KAKASI本体がISO-2022-JP, EUC-JP, SJIS(cp932)の変換機能を持っているのですが、UTF-8対応のためにテーブルを持つのもどうかな、と思いiconvを使うようにして実装しました。 これでひとまず解決か、と思いきやperlモジュールでテストが通らない問題が直っていませんでした。何が起きていたかというと、分かち書きオプション-wを付加したときに、先頭に余計な空白を出力するために、期待されていた出力とは異なっていたのです。 このバグはDebianパッケージの自動ビルドで発覚しました。開発者がアップロードしたアーキテクチャ以外(mips, arm等)のパッケージは、自動的にビルドサーバーによってパッケージが作成されます。その時make testまで実行するので、ライブラリの変化によってバグが顕著化されました。 これを直すために作業を進めていたところ、さらに複数のバグが発覚し、それらの対応も必要になり、今に至ります。 KAKASIの基本データ構造Character kakasi.hで様々なデータ構造が定義されていますが、文字を格納する基本となる型Character(実体はstruct character)が入出力の基本となります。 typedef struct character { char type; unsigned char c1, c2; } Character; typeは文字の種別を表し、0~5, 127の値をとります。値の定義は同様にkakasi.hで行われています /* character set */ #define ASCII 0 #define JISROMAN 1 #define GRAPHIC 2 #define KATAKANA 3 #define JIS78 4 #define JIS83 5 #define OTHER… Continue reading KAKASIのコードについて

KAKASI 2.3.5をリリース

KAKASI 2.3.5をリリースしました。 実は2006年にリリースしようとしていたのですが、途中で頓挫してしまい実に10年超えのリリース周期となってしまいました。 結構前からCVS版がDebianには入っているのですが、libkakasiが壊れているという問題があるので、このタイミングでのリリースとなりました。あと、 NipponというRのKAKASIバインディングが出来たのが、新しいニュースです。 kanwadictの一新をやりたいところです。辞書は昔からほとんど変わっていないので…

HTMLタグを含むpoファイルからプレーンテキストにまで加工して形態素解析にかけてみてtypo等を見つける (Doc-ja Advent Calendar 2013)

これはDoc-ja Advent Calendar 2013 5日目の記事です。 www.gnu.orgでは、現在GNU website Japanese Translation Teamにてチーム体制でwebの翻訳を進めています。実態はほとんどgniibeさん一人で、私は今のところ翻訳チェックぐらいしかできていませんが… gnu.orgのwebはメッセージの中にHTMLタグも含んだ状態で、poファイルによって管理されています。レビューをする上では、なかなか扱いにくい形式です。 そこで、私は一度poから日本語訳文のテキストを生成し、もう少し見やすくした状態でレビューをしています。この記事では、その方法を紹介します さらに、結果を形態素解析にかければ、若干typo等が見つけやすくなります 今時の形態素解析器はできるだけ細かく分解する方向の実装・辞書が多いので、KAKASIなどを使った方がよいかもしれません。