トップ 最新 追記

日々の破片

Subscribe with livedoor Reader
著作一覧

2018-04-11

_ 今日のバグ

あまりにもあほうなバグのために1~2時間ほど悩む。

最初、次のようなコードを書いていた。

class X
  def htov(a) #本当はjoinでは済まない程度に複雑
    s = "**begin**\n"
    a.each {|e| s << "#{e}\n" }
    s << "**end**\n"
  end
end

最初のと最後のマークを定数にしたほうが良いことに気づく(他のオブジェクトも利用するからだ)。

で、直す。

class X
  BEGIN_MARK = "**begin**\n"
  END_MARK = "**end**\n"
  def htov(a)
    s = BEGIN_MARK
    a.each {|e| s << "#{e}\n" }
    s << END_MARK
  end
end

で、1回動かして問題ないことを確認したわけだが、あとから動かしていると異常なデータが作られまくる。

4文字追加して修正。

追記:Stringを定数として扱いたければ積極的に例外にさせるためにfreezeしたものに定数名をつけるのが良いだろう。BEGIN_MARK = '**begin**¥n'.freeze


2018-04-12

_ ケビン・ミトニックの超監視社会で身をまもる方法を読了

なんとなくおもしろそうなので買って読んだ。

ら、想像よりも遥かにおもしろかった。

そりゃそうだと納得するのは、ケビン・ミトニックはハッカーはハッカーでもコンピュータハッカーというよりは、ソーシャルエンジニアリングのハッカーだった。この男は口車という車に乗って、世界中を飛び回る。まさに立て板に水のようにぺらぺらぺらぺらおもしろ話が出てくる出てくる(本人が執筆しているのではなく、ケビン・ミトニックの放談をロバート・バモシという人がまとめた本のようだ)。

パターンは決まっていて、大体以下のような組み立てになっている。

label:a

というわけで~すれば安全かというとそうではない。

~年、~のことだ。~という男が~から~した。彼は~することを忘れていたというわけだ。

すぐさまFBIが~へ急行したのは言うまでもない。

一体何がまずかったのか?

~には~という仕組みがあるため、~から居場所がわかってしまうのだ。

では、どうすれば良いか?

実は~には~というアクセス手段がある。

~年のことだが、わたしが~へ行ったときはこの方法を使った。

つまり最初に~してから~したというわけだ。

もちろん、なんの問題もない。

さて教訓だが、~のときに自分を秘匿するには~だけではだめだということだ。~の場合には~と~が欠かせない。

goto label:a

ためになるかどうかはともかく、おもしろい。

伝説のハッカーが教える超監視社会で身をまもる方法(ケビン・ミトニック/ロバート・バモシ/高取芳彦)

なお、内容紹介には

その中でミトニックが与えるヒントは、無法地帯とも言えるサイバー空間でプライバシーを守るための究極のサバイバルマニュアルとなっています。

と書いてあるが、相当違う。NSAやFBIやCIAが跋扈する無法地帯とも言える現実社会で自分自身のプライバシーを守りながらサバイバルする方法だ。

というわけで、ケビン・ミトニックのヒーローはスノーデンのようだ(スノーデンがリークするために行ったあれこれを相当細かく説明している)。というか、スノーデンが取った方法は公開されているからだろう。

なぜか読んでいる最中、なぜかビッグデータ・コネクトを思い出したりした。

ビッグデータ・コネクト (文春文庫)(藤井太洋)

これも、社会という無法地帯に跋扈する警察やらマスコミやらからプライバシーを守りながらサバイバルする話(でも)あった。


2018-04-14

_ セミラーミデ

子供と東劇にメトライブビューイングのセミラーミデ。

まず指揮者のマウリッツィオ・ベリーニが指揮棒を小刻みに振りながら、左腕で大きな流れを示す、どえらくわかりやすい指揮なのに目を見張る。序曲はロッシーニの序曲だ。つまり悪くない。

ロッシーニ:序曲集(ヨーロッパ室内管弦楽団/クラウディオ・アバド/ロッシーニ)

(アバードももちろん悪いはずがない)

全然内容を知らないのでオペラブッファかオペラセリアなのかもわからず観始めるわけだが、冒頭、諸国の皇子たちの到着です、となり、なんかトゥーランドットみたいなオペラか? と思うと、まったく違う。

古代バビロニアを舞台としていて、みんなでバール神を称えている。なんかウェルズのタイムマシーンの神みたいだけど、人食いなんだろうか? とか考えてみているが、あとになって考えるとあれはモロコ神だった。

インドの皇子がテノールで歌う。カマレナという人で佳い声。なんだが、いかにもテノールの役(ヴァグナーが完璧にルールを変えるまでは、テノールはタミーノとか音楽教師とか、色物でしかないのだが、これもそれっぽい)なので、ブッファかな? とか思いながら観続ける。

悪役登場し、セミラーミデが女王で、王様が死んだから(悪役が暗殺したことが暗に示される)新たな王を選ぶ必要があるという舞台設定が徐々にわかってくる。

若い軍人アルサーチェ登場。ズボン役だ。

人死にがからんでいるのだから、オペラセリアなのかなぁ。

ライオンキングのマンドリルの役回り(あとで文字通りとわかる)の高僧オローエ(いかにも高僧っぽい名前だ)が良い声で歌うのだが、やはり高僧ということはこいつが諸悪の根源か? と観ている(ドンカルロスにしても、アイーダにしても、魔笛にしても、高僧が出てくれば悪役というのがオペラだからだ)。

唐突に王様の幽霊が出て来て、お前が王様だと、若い軍人アルサーチェが指名される。そして通り過ぎていく。

みんなが混乱する。したがって、嵐がきて、ヘラジカヘラジカヘラジカッタラチャンチャカチャンと、いつものロッシーニ音楽が流れて、なんだこれ? となる。

幕間に、高僧が自伝を出版したことを宣伝。12歳のときは刑務所にいた。でも今はオペラ歌手をやっているんだ。みんなも希望をもって努力しよう。

2幕になって衝撃の事実がばんばんわかってくる。

死んだから次の王様を選ぶから諸国から皇子を呼んだというが、死んだのは15年前と、えらく悠長な話とわかる。

さらにボーマルシェもダポンテもはだしで逃げ出す衝撃的な事実の連続攻撃が起きる。でたらめ極まりない。

高僧は実は悪役ではなく、牛若丸に対する高野山の高僧の役回りということが明かされる。

そして真犯人と、若い軍人アルサーチェの出自が明らかになる。

暗闇の中でアルサーチェと悪役の殺し合いが起きる。手ごたえあり! なのだが、舞台の上は明るいからこれまた無茶苦茶だ。

女王セミラーミデの思い付きで結婚が決まって大喜びしていたインドの皇子の大喜びがぬか喜びに変わってしまい、哀切極まりない名曲を素晴らしい声で歌う。物語としては屁の突っ張りにもならない皇子だが、歌はばんばん飛び出してくるんだな。

みんなの頭が混乱して、ヘラジカヘラジカヘラジカッタラチャンチャカチャンとロッシーニ節でまとめる。

なんだかなぁ……

おもしろさは抜群だし、歌のサーカスみたいなおもしろさも抜群だし、ヘラジカヘラジカだし、嵐もあるが、おれがベートーヴェンなら、きみはブッファが良いねぇと言うところだ。

というわけで、ロッシーニをロッシーニとして存分に楽しめた。

それにしても、シェークスピアは偉大極まりない。ハムレット(1600年頃)のハムを台本作家に食わせたいところだった。セミラーミデは1823年の作品だから200年たって、大傑作の悲劇がロッシーニになったのだな。(なんと原作はヴォルテールなのか)


2018-04-17

_ ヘッドレスChromeでPDF

HTMLからPDFを生成する必要があって、以下の方法を考えた。

Edgeに該当URIを叩かせて、プリンタドライバにMS純正のPDF出力を設定しておいてJavaScriptでprintを呼び出す。

で、これが確実に動くのはわかっているのだが、実行環境がGNU/Linuxなのでどうにもならない。

Firefoxはapt-getで入れられるのでメンテナンスが楽そうだが、PDFに出力する簡単な方法が考え付かない。

しょうがないので、ヘッドレスChrome(頭があって手足がないが正解な気がするが本人がヘッドレスを名乗っているのだからまあ良いのだろう)を使うことにした。

Chromeはapt-getはできないが、debが用意されているから我慢する(のだが、今、あらためてみると、どうやってdebをダウンロードしたのかまったくわからない。どうあってもWindows版をダウンロードさせようとするのだが、キャンセルしまくると小さな文字のリンクがあって、Linuxを選択すると、またダイアログが出てくる……。しかし1週間くらい前にはまともなページにたどり着けて、そのURIをcurlしたんだよなぁ)。

説明を読もうとすると、なぜか頼みもしないのに日本語のページ(ヘッドレス Chrome ことはじめ)に飛ばされて、かつ情報が古い(Windowsでは待てとなっているが、Windowsでも--headlessで動作するので古い。書いてあるChromeは59についてだが、Windows版は65になっているし)が、まあ、このページからリンクされているところはそれっぽいから問題なかろう。

・このメモを書くためにあらためて「ヘッドレス Chrome ことはじめ」のページを眺めていたら、一番最後にドロップダウンリストで言語を選択できるようになっていて、US Englishにしたら、Windowsは60からのサポートとバージョン番号付きで書いてあった。なら65で動いて当然だ。というか、なんで先頭で言語を選択できるようにしていないのだろうか(または常に同期を取らないのだろうか)。なんか本当に面倒くさいベンダーだなぁ。

で、PDFの出力方法として chrome --headless --disable-gpu --print-to-pdf https://www.chromestatus.com/ というのが出ているのだが、これが全然だめだ。

コンテンツに重なって頼みもしないヘッダとフッタが出力される。どうしろと。

で、調べるとStack Overflowにやはり同じ問題で困った人たちが質問しているが、有効な解答が、マージンなしにして出力すればヘッダとフッタが下になって隠されるというやつで、なんだそれ。コンテンツとして印刷用のマージンを入れることになるわけだが、それだとWebとPDFでスタイルを変えなければならないし、しかも、PDF出力時のメディアタイプがわからないから話にならない(@media PDFかな? とか思ったがall、print、screen、speech以外に何が使えるか調べるのもあほらしくてやらなかった)。

が、DevTool(Chromeのデバッガインターフェイス)を眺めたら、Page#printToPDFというメソッドがあって、そのパラメータに、displayHeaderFooterというまさにおれが欲しいものがあるではないか。

この場合、Chromeを起動しておいて外部からWebSocketで操作することになる。WebSocketの口はhttpで/jsonから取得する、おお、こういうインターフェイスは大好きだ。こういうところは素晴らしい。

で、起動方法はリモートデバッグオプションを指定して、chrome --headless --disable-gpu --remote-debug-port=9222とすれば良いらしい(というか、これで動いた)。ポートの9222はデフォルトらしいので変えたければ別の値を指定すれば良いのだろうけど、いずれにしてもクライアントが最初にHTTPでアクセスするからウェルノウンにしておく必要はある。あと、disable-gpuは無くても動くようだが、バグを突くといやだから(バグ回避用の設定っぽい)指定する。これをnohupしておいて別口のクライアントからアクセスすることになる。

ぱっと見、DevToolを操作するためのnode用のライブラリがあるようだが、そんなもの使いたくないので、自分でopen-uriを使ってポート9222の/jsonを叩いてPageのURIを取ってWebSocketを使ってと書き始めたが、ふと、こんな程度の処理なら誰か作っているのではと気づいた。で、さらに探すと(しかしドキュメント性が低いのでやたらと時間が食われるのには閉口した)、chrome_remoteというGemがあることがわかったので、それを利用することした。

えらく簡単だ。

require 'chrome_remote'
require 'base64'
 
class PdfWriter
  def initialize()
    @chrome = ChromeRemote.client
    @chrome.send_cmd 'Network.enable'  # Navigateに必要
    @chrome.send_cmd 'Page.enable'     # Pageオブジェクトの操作に必要
    @chrome.send_cmd 'Runtime.enable'  # JavaScript実行に必要
  end
 
  def to_pdf(uri)
    @chrome.send_cmd 'Page.navigate', url:uri
    @chrome.wait_for 'Page.loadEventFired'
    # ロード後に数秒実行に必要なJavaScriptが動くとしたらここで待機するか、またはイベントをチェックする必要がある。
==begin
    JavaScriptの呼出しには、Runtime.evaluateを使う
    ret = @chrome.send_cmd 'Runtime.evaluate', expression: "document.getElementById("foobar').baz()"
==end
    ret = @chrome.send_cmd 'Page.printToPDF', 
                           dispalyHEaderFooter:false,  # これがやりたかったことだ
                           printBackground: false,
                           paperHeight: 11.7, paperWidth: 8.3 # A4: 11.7inch * 8.3inch
    ret['data']  # JSONが返されてdataプロパティにBase64エンコードされたPDFが格納されている
  end
 
  def to_pdf_file(file, uri)
    data = to_pdf(uri)
    File.open(file, 'wb') do |fout|
      fout.write(Base64.decode64(data))
    end
  end
end

実際は同じChromeのインスタンスを使いまわしたいので、Mutex使って排他制御したり他にもいろいろするが、単発ならこれでOK。


2003|06|07|08|09|10|11|12|
2004|01|02|03|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|09|10|11|12|
2011|01|02|03|04|05|06|07|08|09|10|11|12|
2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|04|05|06|07|08|09|10|11|12|
2016|01|02|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|

ジェズイットを見習え