読者です 読者をやめる 読者になる 読者になる

パスワードをそのままメールで送らないでください。

GPG

 FTPサーバーなどを使うとき、パスワードなどのログイン情報がメールで送られてきたりしますよね。あれ、あまり感心できることじゃないんです。メールって「はがき」みたいなものだから、配達してる人たちには読めてしまうシステムなんです。そしてメールを配達してる人は郵便とちがって公務員に準じた身分ではありませんし、(すべての配達員に)秘守義務もありません。重要なビジネスメールがこっそり覗き見られて、2chなどに書き込まれてしまうことも(原理上)あり得るんです。
 じゃあ、どうしたら通信の秘密を守れるの? パスワードをメールで安全に伝える方法はあるの? という疑問が浮かびますよね。もちろんあります。公開鍵暗号と呼ばれる暗号方式で、メールの内容を暗号化しちゃえばいいのです。


 前段はこれぐらいにして、いきなり本題に移ります。
 今年の年始にマシンをリプレイスしまして、以前から使っていたGPG*1を再導入するのに「GPGTools」を使いました。GPGToolsの「GPG Suite」はMac OS X上でGPG環境を整備するパッケージになっています。

 ぼくが知らなかっただけなのかもしれませんが、これがもうめちゃくちゃ簡単なんです。ビックリしました。GPGってターミナル上でコマンドを使った操作が多かった(それゆえに敬遠されていた)んですが、ターミナルもコマンドも一切使いません。普通のアプリケーションのように「GPG Suite」をダウンロードしてインストールするだけです。導入から普段使いまですべてGUIで操作できます。「GPGってムツカシイ(めんどくさい)んでしょ」って言葉はもう過去の言い訳になっています。簡単な導入方法と使い方は下記のページを参照してください。

 パッケージのインストールが完了すると、いきなり鍵生成が始まりますが、ここでひとつ設定しておきたい箇所があります。新しい鍵を作るダイアログの下に「▶Advanced options」の「▶」部分をクリックして「Length:」を「4096」にしておきましょう*2。また、公開鍵をキーサーバーに登録して検索して使ってほしいひとは「Uplode public key after generation」にチェックを入れておきましょう*3


 GPGToolsがすごいのは、導入が簡単なだけじゃありません。Mac OS標準のMail.appにプラグインがインストールされて、メッセージの暗号化がクリックひとつでできます。

 暗号化されたメッセージを受け取ると、パスフレーズを入力ダイアログが開いて復号化します。

 Mail.appだけじゃなく、Gmailなどでもメッセージを選択してコンテキストメニューから暗号化/復号化ができます。


 システム環境設定には「GPGPreferences」があり、ツールのアップデートも自動的に行えるようになっています。
 このように導入・運用・保守が簡単に行える「GPGTools」を導入しない理由はありません。もしむりむり問題を見つけるとするなら、「秘密のメッセージ」をやりとりできる友達がいないということだけでしょう。
 …ということで、ぼくの新しい公開鍵はこちらになります。

fingerprint(指紋) = E000 1AC4 AD58 34C6 6C8F B1E1 999D 20A7 2B4A D3C9


キーサインパーティ

 GPG/PGPには公的な認証局がないので、キーサーバーで検索した公開鍵をそのまま信用できるとは言えません。もちろん、身内でよく知ってる人同士でやり取りする分には差し支えないのですが、ネット上では「顔も見たことがない人」とビジネスすることもあり得ます。そこでオフラインで(リアルに会って)鍵交換を行う「キーサインパーティ」が開かれ、信頼のチェーンをたくさんつないでいく「Web of Trust」が広がっています。

 キーサインパーティの流儀として、印刷されたfingerprintや、政府が発行する顔写真入りの運転免許証(またはパスポートなど)が必要になります。事前によく確かめて、機会があればいってみたいと思っています。

*1:公開鍵暗号方式PGPやGPGといった実装で呼ばれています

*2:鍵の長さが暗号の強さを表します。以前は1024が主流でしたが、キーサインパーティなどでは2048以上が推奨されており、現在は4096が主流のようです。

*3:キーサーバーへの登録はあとからでもできます

xreaサーバーでrubyのTwitterライブラリを使ってSSLエラーの対処メモ

xrea ruby Twitter

 昨日、xreaのサーバーにruby1.9.3をインストールしたのは、Twitter API 1.1対応のTwitterライブラリを使いたかったからなんです。で、ふつーにgem install twitterで入れて、さあここからつぶやき放題だぜ...と思ったらこんなエラーにお出迎えされました。じぇじぇじぇ。

SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed (Twitter::Error::ClientError)

 で、ふつーの対処法ならこれだと思います。

 xreaのサーバーですと...

ruby19 -ropenssl -e 'p OpenSSL::X509::DEFAULT_CERT_FILE'
"/usr/local/openssl/cert.pem"

ってことになってます。ちなみに指し示されたファイルはありません。うちは間借りしてるだけのユーザーなので、この場所になにかを入れたり出したりできません!
 以下、苦し紛れの対処法です。流儀としてすごく間違ってるかもしれません。net/httpsでちゃんと書くべきなのかも。

~/.bashrcに書き込む

 TwitterのCA証明書ファイルの取得方法は以下を参考にしました。

 この証明書ファイルを~/.bashrcに環境変数SSL_CERT_FILEとして書き込むことでエラーを回避できました。下記の1行を~/.bashrcに追加します。

export SSL_CERT_FILE=/virtual/ユーザー名/パス/twitter.pem

 参考にしたのはこちら

 だが、しかし...

cronを使う時は

 cronを使う時は~/.bashrcを読みません。定期的に何度も犯している間違いでデジャヴ感まんさい。
 なのでcrontabで指定しているshell script内で

env SSL_CERT_FILE=/virtual/ユーザー名/パス/twitter.pem スクリプトの呼び出し

としてみました。やれやれ。

xreaのサーバーにruby1.9.3をインストールしたメモ

xrea ruby

 xreaさんのrubyのバージョンは1.8.5ですね。使いたいライブラリ関係もあってちょっと窮屈に思っていました。もしかしてコンパイルできる? と思ってやってみたらできちゃったコンみたいなのでメモしておきます。CORESERVERでもないし、たぶん推奨されていないことだと思うので自己責任でお願いします。*1
 インストール場所は~/local/bin/ruby19みたいな感じになるようにします。

yamlをインストール

 まず、 LibYAMLをインストールします。

mkdir ~/src
cd ~/src #ソースをダウンロードしたりコンパイルしたりする場所
wget http://pyyaml.org/download/libyaml/yaml-0.1.4.tar.gz
tar zxf yaml-0.1.4.tar.gz
cd yaml-0.1.4
./configure --prefix=$HOME/local/yaml/ #./configureやmakeの途中でKilledされることがあります。挫けずにぶつかっていきまっしょい。
make
make install

 yamlが未インストールのままrubyコンパイルをしてしまうと、のちのち

It seems your ruby installation is missing psych (for YAML output).
To eliminate this warning, please install libyaml and reinstall your ruby.

と怒られてしまうので、先にインストールしました。

rubyのインストール
cd ~/src
wget ftp://ftp.ruby-lang.org/pub/ruby/1.9/ruby-1.9.3-p429.tar.gz
tar zxf ruby-1.9.3-p429.tar.gz
cd ruby-1.9.3-p429
./configure -prefix=$HOME/local --program-suffix=19 --disable-install-rdoc --with-opt-dir=$HOME/local/yaml/
make
make install

 --disable-install-rdocとしないと、

Directory .ext/rdoc already exists, but it looks like it isn't an RDoc directory.

Because RDoc doesn't want to risk destroying any of your existing files,
you'll need to specify a different output directory name (using the --op

option)

と怒られてしまいましたので、断念しました。
 --program-suffix=19 としているので、今回インストールしたrubyは「ruby19」「gem19」などとなります。

パスを通す

 ~/.bashrcを編集してパスを通しておきます。実際にはviでやってますが下記のように追記してもかまいません。

echo "PATH=$HOME/local/bin:$HOME/local/lib/ruby/1.9.1" >> ~/.bashrc
source ~/.bashrc #更新

 下記のようにバージョンが返ればインストール完了です。

xxxxx~> ruby19 -v
ruby 1.9.3p429 (2013-05-15 revision 40747) [i686-linux]
xxxxx~> gem19 -v
2.0.3

*1:ちょっと前だと60秒以上のプロセスはkillされてたような気が...

rubyの正規表現の複数行モード

ruby regex

 きょうふと、自分がへんな思い込みをしていることに気がつきました。
 恥ずかしいったらないんだけど、もしかして同じことを思ってる人がいるかもしれないので書いておきます。


 どんな思い込みかというと...
改行を含む複数行の文字列に対してruby正規表現で検索置換をする時、改行文字で区切られた行の行頭「^」や行末「$」を使うには、m修飾子が必要だという誤解です。ワンライナーで書くと

ruby -e 'puts "aa\nbb\ncc\n".gsub(/^/, "M")'

の結果が

Maa
bb
cc

だと思ってた。

Maa
Mbb
Mcc

という結果を得るには

ruby -e 'puts "aa\nbb\ncc\n".gsub(/^/m, "M")'

と書かないといけないと思っていたんです。まじすいません。
 そういう誤解を醸成したのは、perlの複数行モードをイメージしていたからでしょう。perlでは文字列に含まれる改行文字の直前の行頭にマッチさせるにはm修飾子が必要なんだよね。上記の例でいうと

perl -e '$_ = "aa\nbb\ncc\n";s/^/M/mg; print $_;'

と書かなければいけません。と、とりあえず他人のせいにしておくモード^^


 じゃあ、rubyのm修飾子ってなんなの? と思う方もおられるでしょう。
 リファレンスマニュアルに書かれている通りですが、rubyのm修飾子は正規表現で「.」が改行を含むようになるオプションです。*1

ruby -e 'puts "<p>\nhogehoge\n</p>\n".sub(/^<p>(.+)<\/p>/m){$1}'

 つまり、行頭「^」や行末「$」の位置とはまるで関係ないんですな。m修飾子とは関係なく、文字列全体の先頭にマッチさせたければ「\A」を、最終にマッチさせたければ「\z」または「\Z」(文字列が改行で終っていればその改行の直前)を使います。


 もうひとつ生き恥を晒しておきますと、この思い込みに気がついたきっかけは、下記のようなスクリプトを書いてる途中に、なぜか2行目(あとで消そうと思ってた)がマッチしてしまっていたからです。じぇじぇ!

$_.sub!(/^(<h\d)/){"<!-- 見出し -->\n#{$1}"}
$_.sub!(/^<h1.*?>(.+)<\/h1>$/){"= #{$1}"}

 いままで、なぜ気がつかなかったのか、つくづく情けないことだなあ(詠嘆)。


参照

詳説 正規表現 第3版 p107「3.3.4.3 ドット全マッチモード(単一行モード)」、p.108 「3.3.4.4 拡張行アンカーマッチモード(複数行モード)」
Rubyist Magazine - 標準添付ライブラリ紹介 【第 14 回】 正規表現 (3)

*1:ちなみに(混乱するかもしれませんが)、同じ結果を得るためにはperlだとs修飾子(単一行モード)を使います。perl -e '$_ = "

\nhogehoge\n

\n";s/^

(.+)<\/p>/$1/s; print $_;'

正規表現スタイル由来の文字スタイルをリアル文字スタイルとして適用する

eBook InDesign CS5 JavaScript

 緊デジ対応の電子書籍(データ有)を作成する時、IDML経由にしろ、タグマッピングでXML経由にしろ、InDesign上の正規表現スタイルは全無視されてしまいます。そこで、段落スタイルで設定されている正規表現スタイルを順番に検索置換し、リアル文字スタイルを適用します。
 コードを見ればわかるとおり、段落スタイルの中の正規表現スタイルだけを見ます(段落スタイルに書かれていない正規表現スタイルは無視します)。オーバーライドされた文字スタイルは考慮しません。正規表現スタイルが重複している場合は、最後のスタイルだけを適用します。なお、このスクリプトはドキュメントを破壊的に変更しますので、適用後のドキュメントは保存しないようにしてください。

/*
    Apply_CharStyle_of_RegexStyle_origin.jsx
    段落スタイルに設定されている正規表現スタイル由来の文字スタイルをリアル文字列に適用します。
    段落スタイルに書かれていない正規表現スタイルは無視します(段落スタイルの中の正規表現スタイルだけを見ます)。オーバーライドされた文字スタイルは考慮しません。
    正規表現スタイルが重複している場合は、最後のスタイルだけを適用します。
    いうまでもなく、このスクリプトはドキュメントを破壊的に変更します。
    
   
    2012-06-24  とりあえず
*/

#target "InDesign"

////////////////////////////////////////////エラー処理 
function myerror(mess) { 
  if (arguments.length > 0) { alert(mess); }
  exit();
}

////////////////////////////////////////////正規表現検索置換
/*
my_range	検索置換の範囲
my_find	検索オブジェクト ex.) {findWhat:"(わたく?し|私)"}
my_change	置換オブジェクト ex.)  {changeTo:"ぼく"}

my_changeが渡されない時は検索のみ、マッチしたオブジェクトを返す。
my_changeが渡されると置換が実行されて、返値はなし。
*/
function my_RegexFindChange(my_range, my_find, my_change) {
    //検索の初期化
    app.findGrepPreferences = NothingEnum.nothing;
    app.changeGrepPreferences = NothingEnum.nothing;
    //検索オプション
    app.findChangeGrepOptions.includeLockedLayersForFind = false;//ロックされたレイヤーをふくめるかどうか
    app.findChangeGrepOptions.includeLockedStoriesForFind = false;//ロックされたストーリーを含めるかどうか
    app.findChangeGrepOptions.includeHiddenLayers = false;//非表示レイヤーを含めるかどうか
    app.findChangeGrepOptions.includeMasterPages = false;//マスターページを含めるかどうか
    app.findChangeGrepOptions.includeFootnotes = false;//脚注を含めるかどうか
    app.findChangeGrepOptions.kanaSensitive = true;//カナを区別するかどうか
    app.findChangeGrepOptions.widthSensitive = true;//全角半角を区別するかどうか

    app.findGrepPreferences.properties = my_find;//検索の設定
    if (my_change == null) {
        return my_range.findGrep();//検索のみの場合:マッチしたオブジェクトを返す
    } else {
        app.changeGrepPreferences.properties = my_change;//置換の設定
        my_range.changeGrep();//検索と置換の実行
    }
}



/////実行
    var my_attention = confirm("Apply_CharStyle_of_RegexStyle_origin.jsx\r    段落スタイルに設定されている正規表現スタイル由来の文字スタイルをリアル文字列に適用します。\r    段落スタイルに書かれていない正規表現スタイルは無視します(段落スタイルの中の正規表現スタイルだけを見ます)。オーバーライドされた文字スタイルは考慮しません。\r    正規表現スタイルが重複している場合は、最後のスタイルだけを適用します。\r    いうまでもなく、このスクリプトはドキュメントを破壊的に変更します。");
    if (my_attention === false){exit()};//「いいえ」ボタンで終了

if (app.documents.length === 0) {myerror("ドキュメントが開かれていません")}
var my_doc = app.documents[0];

var my_paragraph_styles = my_doc.allParagraphStyles;
for (var i = 1; i< my_paragraph_styles.length; i++) {//0番地は、「[段落スタイルなし]」
    if (my_paragraph_styles[i].nestedGrepStyles.length >0) {
        for (var ii =0; ii < my_paragraph_styles[i].nestedGrepStyles.length; ii++) {
            var my_regex_style = my_paragraph_styles[i].nestedGrepStyles[ii];//正規表現スタイル
            var my_regex = my_regex_style.grepExpression;//正規表現
            var my_char_style = my_regex_style.appliedCharacterStyle//文字スタイル
            my_RegexFindChange(my_doc, {findWhat:my_regex, appliedParagraphStyle:my_paragraph_styles[i]},{appliedCharacterStyle:my_char_style});
        }
    }
}

先頭文字スタイル*1とか、先頭行スタイルとか、どうするんだ... って思いません? ぼくも思います。「繰り返し」がなかったらできると思います*2。思うだけ。

*1:(追記:2012-07-09T11:38:52+0900)先頭文字スタイルについては、スタイルをタグにマップでタグづけできるようす。see also. http://densyodamasii.com/先頭文字/先頭行/正規表現スタイルの処理を考/

*2:あ、先頭文字スタイルは(テキスト検索の)ワイルドカード表現互換だからそれも痛いです

ImageMagickで-trimして、長辺が最大ピクセル値を超えたら-resizeするドロップレット

AppleScript ImageMagick
(*
convert-trim-resize.app
ImageMagickで
convert -trim orginal-file new-file
を実行する。
ピクセル数の最大値my_maxpixelを書き換えると、長辺がこの値を超えた時だけresizeします。
オプション変えたい人は ドロップレットのdo shell scriptの部分を直接書き換えてくだしあ。


2012-06-10	とりあえず
*)


--ドラッグ&ドロップで実行
on open of drop_files
	--設定
	set my_maxpixel to 1536 --長辺のピクセル最大値
	
	--ファイルのフィルタリング
	set my_files to my file_kind({"jpg", "jpeg", "png", "gif", "tif", "tiff", "bmp"}, {""}, drop_files) --拡張子のリスト、ファイルタイプのリスト、処理ファイル	
	
	repeat with i in my_files
		my violation_name(i as alias)
		set path_info to my split_path(i as alias)
		set org_path to POSIX path of (i as alias)
		set new_path to (dir of path_info) & (f_name of path_info) & "_new" & (ext of path_info)
		my alert_same_name(new_path)
		try
			do shell script "/usr/local/bin/convert -trim " & (quoted form of org_path) & " " & (quoted form of new_path) --空白除去
			set new_w to (do shell script "/usr/local/bin/identify -format '%w' " & (quoted form of new_path)) as integer
			set new_h to (do shell script "/usr/local/bin/identify -format '%h' " & (quoted form of new_path)) as integer
			if (new_w > my_maxpixel) or (new_h > my_maxpixel) then --幅または高さがピクセル最大値を超えていた
				do shell script "/usr/local/bin/mogrify -resize " & my_maxpixel & "x" & my_maxpixel & " " & (quoted form of new_path) --上書きでリサイズ
			end if
		on error errMsg number errNo
			display dialog "実行エラーです" & return & errMsg & return & errNo buttons {"Cancel"} default button 1 with icon 1 --キャンセルで終了
		end try
	end repeat
end open


----------------------------------------------●必要なファイルだけをフィルタして返します
to file_kind(extention_list, type_list, theFiles)
	set my_files to {}
	
	ignoring case
		tell application "Finder"
			repeat with i in theFiles
				if extention_list contains ((name extension of i) as Unicode text) then
					set end of my_files to contents of i
				else if (kind of i) is "フォルダ" as Unicode text then
					--activate
					--display dialog "フォルダ「" & (name of i) & "」の中の全ファイルを処理します" buttons {"キャンセル", "OK"} default button 2 with icon 0
					set my_files to my_files & my file_kind(extention_list, type_list, every file in folder i)
				else if type_list contains ((file type of i) as Unicode text) then
					set end of my_files to contents of i
				else
					--activate
					--display dialog "ファイル「" & (name of i) & "」は処理ファイルとして不適当です" buttons {"キャンセル", "OK"} default button 2 with icon 0
				end if
			end repeat
		end tell
	end ignoring
	return my_files
end file_kind

----------------------------------------------●
--フルパス名を、コンテナディレクトリ・ファイル名+拡張子・ファイル名・拡張子に分割する
--返値はPOSIX pathのレコード {dir:"", name_ext:"", f_name:"", ext:""}
to split_path(f)
	set f to quoted form of ((POSIX path of f) as Unicode text) --まずPOSIX pathにする
	set d to do shell script "echo " & f & " | perl -pe 's/^(.+\\/).+$/$1/;'" --コンテナディレクトリ
	set ne to do shell script "echo " & f & " | perl -pe 's/^.+\\/(.)/$1/;'" --ファイル名+拡張子
	if f ends with "/'" then --フォルダの場合
		set n to text 1 thru -2 of ne
		set e to ""
	else
		set e to do shell script "echo '" & ne & "' | perl -pe 's/^.+(\\..+)$/$1/;'"
		if e is not "" then
			set n to do shell script "echo '" & ne & "' | perl -pe 's/" & e & "$//;'"
		end if
	end if
	
	return {dir:d, name_ext:ne, f_name:n, ext:e}
end split_path

----------------------------------------------●
--同名ファイルの警告
to alert_same_name(file_path)
	tell application "Finder"
		if (exists (file_path as POSIX file)) then
			display dialog file_path & " は同名のファイルがあります" & return & "上書きしますか?" buttons {"Cancel", "上書き"} default button 1 with icon 1 --キャンセルで終了
		end if
	end tell
end alert_same_name

----------------------------------------------●
--ファイル名の警告
to violation_name(file_path)
	set file_path to quoted form of ((POSIX path of file_path) as Unicode text) --まずPOSIX pathにする
	set file_path_test to do shell script "echo " & file_path & " | perl -pe 's/[\\/\\.0-9A-Za-z _-]+//;'"
	if (file_path_test is not "") then
		display dialog file_path & " のファイル名には英数字以外の文字が使われています。" & return & "処理トラブルになるかもしれません。続行しますか?" buttons {"Cancel", "続行"} default button 1 with icon 1 --キャンセルで終了
	end if
end violation_name

キャプション付き図版や表組みの余白をImageMagickでトリミングする

ImageMagick InDesign eBook

 InDesignに配置された図版や表組みを電子書籍用に落とし込む時、いくつかの課題があります。

  • 印刷用データとしてCMYKカラースペースがベースになっている
  • Illustratorの図版ドキュメントに、システムにないフォントが含まれている可能性
  • キャプションを分離させたくない

 電書魂さんの下記記事にもコメントさせていただいたんですが...
「フォントを含む画像」の変換テスト | 電書魂
InDesignはフォントラスタライザを含んでいるので、ドキュメントにフォントが含まれていれば(システムにフォントがなくても)、「表示が質」-「高品質表示」で画面上のフォントが正しく表示されます。
f:id:seuzo:20120609130220p:image
f:id:seuzo:20120609130505p:image

作戦A)スクリーンキャプチャで撮る

 (品質上)可能性の話をすればキリがありませんが、高品質表示でスクリーンキャプチャを取るのは、悪い方法ではないと考えます。少なくとも刷本からスキャニングするよりきれいでしょう*1。CMYKベース→RGBは手間ひまをかけて調整すれば、若干マシにはなるでしょうが原理的にオリジナルカラーに戻るわけではありません。今どき市井の人がデスクトップ上でどれくらいの解像度にしているのかわかりませんが、ウチでは1920×1200pxです。Retinaディスプレイが2048×1536なので、まずまずな大きさを得られるんじゃないでしょうか。
f:id:seuzo:20120609132541j:image
 こんな感じで画面全体に広げて、スクリーンキャプチャを撮りました。*2撮った画像がこちらです。
f:id:seuzo:20120609133230p:image

作戦B)JPEG書出し

 InDesignのJPEG書出しを使えば、選択したオブジェクトだけをJPEG書出しできます。しかも解像度指定もできます。やり方としてはこっちの方が断然ラクですね。
f:id:seuzo:20120609173555p:image

残った余白をどうするか?

 でだ、スクリーンキャプチャを撮る時にどうしても余白が入ってしまいます。これはInDesignドキュメントからJPEG書出しした時も、オブジェクトサイズで書き出されるので余白が残ります。Photoshopで行うとすると、ピクセルが見えるくらい大きくしないとうまくトリミングできません。
 そこでImageMagickを使って、余白をトリミングしましょう。ImageMagickXcodeでもデフォルトインストールではありません。Homebrewなどからインストールするとラクです。
 ImageMagickをインストールしたら、ターミナルからconvertコマンドが実行できるようになります。

$ convert -trim original.png new.png

f:id:seuzo:20120609141319p:image
 余白を取り除くためのトリミングツールは他にもたくさんあるかと思います。今回、ImageMagickを試してみたのは、CLTなので他のスクリプトなどにも組み込みやすいからです。


*1:いうまでもありませんが、解像度が高いことと画質がよいことは必ずしも一致しません

*2:ここで使用しているのはSnapz Pro X http://www.ambrosiasw.com/utilities/snapzprox です。もちろん、これくらい簡単なスクリーンキャプチャを撮るだけなら、command + shift + 4でもかまいません。