« [iPod touch]iPod touch (iPhone)用にGNUツールをクロスコンパイルする | Main | [iPod touch]オカエリナサλ »

2007.11.02

[iPod touch]iPhone由来のメモ(MobileNotes.app)からsqlite3でデータを出し入れする

iPod touch素晴らしいです。本当に。
モバイル機器としては、通信手段が無線LAN Onlyというディスアドバンテージを抱え、個々の機能性を見ていくと欠点が目立ちながら、ためつすがめつ、これほどまでにほれぼれとできるのはなぜなんでしょうか。
iPod touchをいじり倒して、来るのかどうか分かりませんがiPhoneの上陸を待つとしましょう。

今回もJailbrokenなiPod touchの話題です。

iPod touch上で日本語入りのテキストファイルを作成できるソフトウェアが欲しいのですが、唯一のテキストエディタであるmobiletexteditがASCII決め打ちで処理しているので、しばし待たなくてはならないでしょう。
ファイルの入出力に渡されているエンコーディング指定をUTF8にでも書き換えればいんじゃね? ということで書き換えてみたものの、parse errorやらググっても見つからないヘッダを参照しているやらでコンパイル通せてません。

さて、iPhone搭載のアプリのうち、メール(MobileMail.app)、連絡先(MobileAddressBook.app)、カレンダー(MobileCal.app)、そしてメモ(MobileNotes.app)はバックエンドとしてSQLiteを使っているようで、それらから書き出されたデータはSQLiteで読めるということは広く知られてます。

sqlite3はErica's Ported Utillitiesに収録されてますので、Installer.appからインストールでき、iPod touch上でいじくることができます。
もちろん、データをコピーしてきて母艦でsqlite3を使っていじくることもできますし、各種処理系のSQLiteバインドを使うと、もう無茶苦茶いじくり倒せます。とても汎用性の高いフォーマットが採用されているのですね。

sqlite3でメモ(MobileNotes.app)のデータベースを読み出すことができたら、メモ(MobileNotes.app)をテキストエディタ代わりに使えそうです。
sqlite3はコマンドラインインターフェイスなので、Terminalから使います。

sqlite3 /var/root/Library/Notes/notes.db

これでインタラクティブモードが起動します。どんなtableが定義されているか見てみます。

sqlite> .table

<結果>

Note note_bodies
_SqliteDatabaseProperties

Note、note_bodies、_SqliteDatabasePropertiesと三つのtableがあることが分かります。
Noteがヘッダ情報、note_bodiesが本文を収めています。続いてスキーマを見てみます。

sqlite> .schema

<結果>

CREATE TABLE Note (creation_date INTEGER, title TEXT, summary TEXT);
CREATE TABLE _SqliteDatabaseProperties (key TEXT, value TEXT, UNIQUE(key));
CREATE TABLE note_bodies (note_id INTEGER, data, UNIQUE(note_id));
CREATE TRIGGER delete_note_bodies AFTER DELETE ON Note
BEGIN
DELETE FROM note_bodies WHERE note_id = OLD.ROWID;
END;

なーるほど、Noteのレコードを消すと、自動的にそれに対応したnote_bodiesの方も消えるよう、トリガがかかっているんですね。こういう仕組みがあるとは知りませんでした。メモを1件読み出してみます。
見やすくヘッダを付けてみます。

sqlite> .header on
sqlite> select * from Note limit 1;

<結果>

creation_date|title|summary
215507891|iPod touchのSafariで今見ているページを文字化けを直しつつ保存し、オフラインで見る方法|iPod touchのSafariは、機能こそ少ないですが、無理矢理実用してやりたくなる憎めない奴で

creation_date、title、summaryの順で表示されています。creation_dateは日付のはずですが、整数ですね。どこかの時点を起点とした経過秒数なのでしょう。試しに、これを0にしてみます。

sqlite> update Note set creation_date=0 where creation_date=215507891;

Notesを起動してみると、「2496 days ago 2001年1月1日 9:00」となっています。

dateコマンドで取得できるUNIX timeはUTCの1970年1月1日00:00:00(UNIX epoch)を起点とした経過秒数なので、Notesが起点としているものとの差は、UTCで978339600秒ということになります。
ここから日本のローカルタイムとの時差9時間(32400秒)を引くと、dateコマンドで求めたUNIX time表現の現在時刻からNotesのcreation_dateが求まります。

UNIX time - (978339600 - 32400)

unixtime=`date +%s`
creationdate=`expr $unixtime - \( 978339600 - 32400 \)`

新しいレコードを挿入してみます。シェルスクリプトを書きます。

#!/bin/sh

unixtime=`date +%s`
creationdate=`expr $unixtime - \( 978339600 - 32400 \)`
title=`date`
uname=`uname -a`

body=`sed -e 's/^\(.*\)$/<div>\1<\/div>/g'<<EOT
${uname}
1 long long body
2 long long body
3 long long body
4 long long body
5 long long body
EOT`

summary=`echo ${body} | head -1`

sql="insert into Note values( ${creationdate}, '${title}', '${summary}' );"
sqlite3 /var/root/Library/Notes/notes.db "$sql"

sql="insert into note_bodies values( (select max(note_id) + 1 from note_bodies), '${body}' );"
sqlite3 /var/root/Library/Notes/notes.db "$sql"

↓実行前

↓実行後

↓中身

うまく入りました。メモ(MobileNotes.app)からホーム画面に戻り、再度メモ(MobileNotes.app)を起動すると反映されます。bodyの部分はdivでくくって行を表現するようです。

レコードを消す場合は、Noteの方のレコードを消します。トリガによってnote_bodiesの方も消えてくれます。

sqlite> delete from Note where creation_date=215642040;

両方のtableのレコード数を確認します。

sqlite> select count(*) from Note;
5
sqlite> select count(*) from note_bodies;
5

Noteの方しか消していないのに、note_bodiesの方のレコードも消えています。

実用例としては、titleが@@で始まるレコードをテキストに書き出す、などがあります。

#!/bin/sh

notesdb=/var/root/Library/Notes/notes.db
ebooksdir=/var/root/Media/EBooks

sqlite3 $notesdb "select data from note_bodies where data like \"@@%\";" |
sed -e 's/<div>//g'\
-e 's/<br>//g'\
-e 's/<br class="webkit-block-placeholder">//g'\
-e 's/<\/div>/\
/g' > ${ebooksdir}/dump`date +%Y%m%d-%H%M%S`.txt

後で、これをシェルスクリプトアプリケーションにしてみます。

ちなみに、実際にはErica's Ported Utilitiesのsqlite3は残念ながらGNU readlineのサポートがONになっていないので、インタラクティブモードが使いにくいです。シェルスクリプトを書いて試す方がいいでしょう。


ちゃんと母艦と同期して使いたいんだ、という人向けにはThe Missing Sync for iPhoneというものが控えています。Yojimbo、Microsoft Entourage、Mark/Space Notebookとメモ(MobileNotes.app)が同期できるようです。
iPod touchで使えるかどうか分かりませんが。

|

« [iPod touch]iPod touch (iPhone)用にGNUツールをクロスコンパイルする | Main | [iPod touch]オカエリナサλ »