おがさわらなるひこのオープンソースとかプログラミングとか印刷技術とか

おがさわらなるひこ @naru0ga が技術系で興味を持ったりなんだりしたことをたまーに書くブログです。最近はてなダイアリー放置しすぎて記事書くたびにはてな記法忘れるのではてなブログに移行しました。

クリエイティブ・コモンズ・ライセンス
特に断りがない場合は、本ブログの筆者によるコンテンツは クリエイティブ・コモンズ 表示 - 継承 4.0 国際 ライセンスの下に提供されています。

【私家訳】新しくモダンでセキュアなWindows向け印刷体験

このブログはMicrosoftJohnathan Norman氏による

techcommunity.microsoft.com

の非公式私家訳です。それとも誰か訳してるのかなあ。

The 機械翻訳をちょこちょこ手を入れた品質なので、まあそこのところは許してくだせえ。


過去1年間、MORSEチームはWindows Printチームと協力して、Windows Print Systemの近代化に取り組んできました。この新しいデザインは、Windows Printスタックに対する20年以上で最大の変更の1つです。目標は、互換性を最大化し、ユーザーを第一にする、より現代的で安全な印刷システムを構築することでした。私たちはこの新しいプラットフォームをWindows Protected Print Mode(WPP)と呼んでいます。ユーザーはSecure-by-Defaultであるべきだと考えています。これが、WPPが最終的にWindowsのデフォルトでオンになる理由です。

最近、Windowsでのサードパーティドライバのサービスを終了する計画を発表しました。ドライバから離れることで、印刷スタックを大幅に改善することができました。この記事では、ドライバレス印刷を採用する場合について説明し、互換性に関する洞察を提供し、Windows保護印刷モードによって提供されるセキュリティの改善をプレビューします。

この変更の背後にある最大の動機の1つはセキュリティです。Windowsの印刷システムは攻撃者の主要なターゲットでした。スプーラは高い特権で実行され、ネットワークからコードをロードする必要がありますが、これは低摩擦と高いセキュリティでは実現が困難です。Stuxnetと「印刷の悪夢」(Print Nightmare)では印刷バグが関与しており、MSRCに報告されたすべてのWindowsケースの9%を占めています。印刷スタックのセキュリティ保護は、主にサードパーティ製ドライバの使用が原因で困難です。WPPはすべてのサードパーティ製ドライバをブロックし、さまざまな新しいセキュリティ保護を実装しています。

これらの変更をある文脈に置くために、MORSEはWindows Printの過去のMSRCケースの分析を行い、これらの変更が役立つかどうかを評価しました。私たちが見つけたのは、Windows Protected Print Modeがこれらの脆弱性の半分以上を軽減したということです。

設定を変更すると不便に感じる人もいることはわかっていますが、全体的なユーザセキュリティにとってはそれが最善であると考えています。

ドライバー問題

印刷ドライバのセキュリティモデルは、共有責任アプローチに依存しており、Windows印刷スタックとサードパーティドライバはそれぞれ、脆弱性の導入を回避しながら、機能を提供し、セキュリティの約束を実施する役割を果たす必要があります。これはWindowsの他のサブシステムと同様ですが、印刷は特に困難なシナリオです。なぜなら、私たちとお客様の両方が、プロセスを可能な限り摩擦のないものにしたいと考えているからです。セキュリティ、利便性、および古いデバイスとの下位互換性のバランスをとることは困難です。ここにいくつかの例があります。

印刷の悪夢(Print Nightmare)

この脆弱性は、認証されたリモートユーザがRPCコールRpcAddPrinterDriverを使用して印刷ドライバをインストールし、リモートロケーションにあるドライバファイルを指定することを可能にする認証バイパスバグの結果でした。攻撃者が選択したファイルはDLLとしてロードされ、高度な特権を持つスプーラプロセスで実行され、攻撃者にSYSTEM特権を事実上付与しました。

この脆弱性の修正は、Point and Printと呼ばれる設計上の機能が存在するという事実によって複雑になりました。Point and Printでは、プリントサーバからクライアントへのドライバのインストールをスムーズに行うことができます。リモートサーバは、クライアント上の適切な構成(レジストリ設定)を前提として、クライアント上のadminプロンプトなしでドライバをインストールできます。修正が行われると、V3ドライバのユーザーは、多くの場合、大規模な環境で、プリンタを使用しようとしたときに突然Adminログインプロンプトが表示されるようになりました。V4ドライバのユーザーでは、この問題は発生しませんでした。V4モデルは、この脆弱性が発生した2021年の9年前の2012年に導入されましたが、ほとんどのプリンタは依然としてV3ドライバを使用していました。これは、ドライバベースのモデルのいくつかの課題を物語っています。

互換性

印刷ドライバの課題の1つは、その古さです。一部の印刷ドライバは数十年前のものであり、Control Flow Guard(CFG)、Control Flow Enforcement Technology(CET)、Arbitrary Code Guard(ACG)、およびMicrosoftが長年にわたって実装してきたその他の多くの保護など、最新のセキュリティ緩和策と互換性がありません。これらの保護は多くの場合、「オール・オア・ナッシング」です。つまり、保護を有効にするには、参加するすべてのバイナリが互換性を持つための手順を実行する必要があります。すべての印刷メーカーがこれらのドライバを更新するために必要な手順を実行しているわけではないため、印刷サービスは現在、これらの最新の不正利用緩和策の恩恵を受けていません。

過剰なアクセス許可

サードパーティからコードを読み込むには、セキュリティの観点からいくつかの課題があります。読み込むコードを確実に読み込む必要があるだけでなく、そのコードによってアプリケーションの動作が予期しない方法で変更される可能性があります。たとえば、ドライバは複雑な解析ロジックをサポートしているため、スプーラや関連する印刷プロセスを完全に制御できるバグが発生する可能性があります。多くのユーザーは、印刷ドライバが一般的な管理者アカウントよりも強力なSYSTEMとして実行されることを理解していません。そのため、ドライバのバグは攻撃者にとって非常に有用です。

ドライバに脆弱性が発見された場合、Microsoftサードパーティに依存してドライバを更新します。発行元が存在しなくなった場合、または古い製品がサポートされていないと考えられる場合、脆弱性に対処する明確な方法はありません。

IPPの基礎

インターネットプリンティングプロトコル(IPP)は、HTTPベースのプロトコルであり、HTTPに期待される多くの認証方法をサポートします。各IPP要求はHTTP POSTメッセージであり、プリンタはipps://printer.example.com/ipp/printなどのURIを使用して識別されます。IPPは、プリンタに期待されるすべての一般的な操作をサポートします。

ドライバレス印刷では、PWG RasterやPDFなどの公開標準に基づく限られた数のプリンタドキュメント言語(PDL)がサポートされています。これにより、オペレーティングシステムが変換のために処理する必要がある形式の固有の数が制限され、コードが大幅に簡素化されます。クライアント側のレンダリングは、プリンタに送信される最終的なドキュメントを生成するために使用されます。

LPR/LPDとは異なり、IPPは組み込みの暗号化をサポートしています。このサポートは、Web上でHTTPSを使用する場合に現在使用されている暗号化と同様です。アクセス制御と認証もプロトコルの一部です。セキュリティ上の利点を目的としたものではありませんが、IPPドライバレス仕様は少数のPDLをサポートしており、クライアントが必要とする複雑な解析の量を制限しています。現在、ドライバは40種類以上のPDLを実装しており、脆弱性が発生する可能性があります。

WindowsにおけるIPP印刷の今日の状況

Windows Print Teamは、以前からIPP印刷をより多くのユーザーに提供するために取り組んできました。現在、印刷ドキュメントを表示すると、通知が表示されます

この通知は、ユーザーが可能な場合はIPPに切り替えることを奨励し、業界パートナーがIPPベースの印刷に切り替えることを奨励することを目的としています。カスタム機能が必要な場合があり、ベンダーは印刷サポートアプリ(PSA)を作成することでサポートを拡張できます。現在のWindowsでのIPP印刷は、ドライバベースの印刷と並行して動作し、ユーザーはどちらの構成も選択できます。IPP印刷システムのいくつかのコンポーネントと、セキュリティの利点と欠点について説明します。

印刷サポートアプリ(PSA; Printer Support App)

PSAを使用すると、プリンタOEMおよびIHVは、既存のIPPサポートを拡張して特定のニーズに対応できます。すべてのプリンタが同じ機能と構成オプションをサポートしているわけではありません。PSAを使用すると、ユーザーが期待するエクスペリエンスを損なうことなく、カスタマイズされたユーザーエクスペリエンスを実現できます。

これらのアプリケーションは、Win32アプリケーションよりも制限されているUniversal Windows Application Platform(UWP)を利用します。ユーザーは、アプリケーションが使用できるアクセス許可をより詳細に制御でき、更新の管理はMicrosoftストアを通じて自動的に行われます。Windowsは、プリンタのハードウェアIDに基づいて、ユーザーに適切なPSAが存在する場合は、自動的にインストールします。

Point and Print

Point and Printは、ユーザーがドライバを提供せずにリモートプリンタに接続できるようにする機能であり、必要なすべてのドライバがクライアントにインストールされています。Point and PrintはIPPでも使用できますが、動作が異なります。ドライバをインストールする必要はなくなりましたが、プリンタを設定するには基本的な構成が必要です。このプロセスは、IPPでは次のように動作します。

  1. WindowsクライアントとサーバがRPCを介して接続する
  2. サーバとクライアントの両方が内蔵のMicrosoft IPPドライバを使用
  3. サーバーはIPPを使用してプリンタと通信する
  4. PSAがインストールされる(使用可能な場合)

セキュリティ

現在、WindowsでのIPPベースの印刷では、サードパーティのドライバが不要になり、印刷をサポートするためにインストールされたサードパーティのコードはAppContainer内で実行されるため、ユーザーのリスクが制限されます。暗号化はすべての通信でサポートされており、サポートされるPDLの数が限られているため、解析の複雑さは大幅に軽減されます。これは、ドライバの使用を必要とするモデルに比べて意味のある改善です。

ただし、現在でも、IPPベースの印刷はドライバベースの印刷と並行して実行されます。たとえば、Point and Printは、サーバーの要件に応じて、ドライバをインストールするか、現在の構成にIPPプリンタをインストールします。このアプローチは互換性のリスクを最小限に抑える一方で、セキュリティを向上させるために行うことができる変更を大幅に制限します。

現在、WindowsでのIPP印刷は、セキュリティの観点からすでに大きな前進となっており、ユーザーには可能な限り切り替えることをお勧めします。また、管理者には、このアクションを組織全体で優先することもお勧めします。

Windows保護印刷モード(Windows Protected Print Mode; WPP

WPPは、Mopria認定のプリンタのみがサポートされている既存のIPP印刷スタックに基づいて構築されており、サードパーティのドライバを読み込む機能を無効にします。これにより、Windowsの印刷セキュリティを大幅に向上させることができます。我々の目標は、最終的に最も安全な既定の構成を提供し、ユーザーがプリンタに互換性がないことを発見した場合にいつでも従来の(ドライバベースの)印刷に戻す柔軟性を提供することです。

ユーザーがWPPモードを有効にすると、通常のスプーラ操作は、WPPの改善を実装した新しいスプーラに委ねられます。これらの変更のいくつかを見てみましょう。

限定された/安全な印刷設定

WPPでは、多くの従来の構成が無効になりました。Windowsに対する一般的な攻撃では、プリンタポートがダイナミックリンクライブラリ(DLL)であるという事実が悪用され、攻撃者はこれを悪用して悪意のあるコードを読み込みます。また、攻撃者はシンボリックリンクを使用してスプーラを騙し、悪意のあるコードを読み込ませますが、これはもはや不可能です。IPPを使用する場合にのみ意味のある値に構成を制限するように更新された多くの従来のAPIがあります。これにより、攻撃者がスプーラを利用してシステム上のファイルを変更する機会が制限されます。

モジュールのブロック

モジュールの読み込みを可能にするアプリケーションプログラミングインターフェイスは、新しいモジュールが読み込まれないように変更されます。たとえば、AddPrintProviderWやその他の呼び出しを行うと、悪意のあるモジュールが読み込まれる可能性があります。また、IPPに必要なMicrosoft署名付きバイナリのみが読み込まれるように制限されます。

ユーザーごとのXPSレンダリング

XPSレンダリングは、WPPのSYSTEMの代わりにユーザーとして実行されます。現在、Windowsのほとんどの印刷ジョブにはXPS変換が含まれており、このタスク(PrintFilterPipelineSVC)を処理するプロセスが多くのメモリ破損の脆弱性の原因となっています。他の問題と同様に、このプロセスをユーザーとして実行することで、これらのバグの影響を最小限に抑えることができます。

共通スプーラタスクの低い権限

ドライバを削除すると、スプーラプロセスによって実行される一般的なタスクを実行し、それらをユーザーとして実行されているプロセスに移動することもできます。これらのプロセスにメモリ破損の脆弱性がある場合、その影響はユーザーだけが実行できるアクションに限定されます。

新しいスプーラワーカープロセスには、SeTcbPrivilege、SeAssignPrimaryTokenPrivilegeなどの多くの特権を削除する新しい制限付きトークンがあり、SYSTEM ILで実行されなくなりました。

今後削除する予定のSeImpersonatePrivilegeは保持されています。

バイナリ緩和

サードパーティのバイナリを削除することで、Microsoftが長年にわたって投資してきたバイナリ緩和策の多くを有効にできるようになりました。WPPのプロセスは、多くの新しいバイナリ緩和策で実行されます。以下にいくつかのハイライトを示します。

  • Control Flow Enforcement Technology(CFG、CET) -リターン指向プログラミング(ROP)ベースの攻撃を軽減するのに役立つハードウェアベースの軽減。
  • 子プロセスの作成を無効にする-子プロセスの作成はブロックされます。これにより、攻撃者がスプーラでコードを実行した場合に、新しいプロセスを生成できなくなります。
  • Redirection Guard-プリントスプーラを標的とすることが多い多くの一般的なパスリダイレクト攻撃を防止します。
  • Arbitrary Code Guard-プロセス内での動的なコード生成を防ぎます。

これらの保護により、脆弱性が発見された場合にそれを悪用することがより困難になります。

Point and Print

前述したように、Point and Printは通常、ドライバの読み込みとIPPプリンタの構成を許可します。一部のユーザーはIPPプリンタだけの環境を持っている場合がありますが、悪意のある攻撃者はプリンタのふりをしてユーザーをだましてドライバをインストールさせることができます。WPPは、Point and Printがサードパーティのドライバをインストールすることを防ぎ、このリスクを軽減します。

よりよいトランスポートのセキュリティ

プリンタはさまざまなトランスポートプロトコルを使用しており、トランスポート暗号化は常に使用されるわけではありません。多くの場合、トラフィックが暗号化されているかどうかはユーザーには不明であり、これを判断するのは困難です。IPPは、現在Webブラウザで使用されているような強力な暗号化をサポートしています。WPPは、トラフィックが暗号化されている場合にユーザーに明確にし、可能な場合は暗号化を有効にするようユーザーに促します。

Windows Secure by Designへの継続的な投資

ご覧のように、ドライバベースの印刷から離れることは、ユーザーに多くのメリットをもたらし、Microsoftは印刷システムに多くの意味のある改善を行うことができます。数十年前に確立された既存のドライバベースのシステムは、多くのサードパーティMicrosoftすべてがその役割を果たすことに依存しており、現代の脅威には遅すぎることが証明されています。

IP Pベースの印刷は十分にサポートされており、切り替えるユーザーは攻撃を受ける可能性を減らすことができます。Windows保護印刷モードに切り替えるユーザーは、攻撃者から安全であることをさらに保証します。WPPは現在Insiderビルドにあり、この機能を試してフィードバックを提供することで、テストにご協力いただければ幸いです。ユーザーは、ここに記載されている手順に従ってこの機能を有効にできます。

これは初期リリースです。多くの機能は不完全であり、フィードバックに基づいて変更される可能性があります。たとえば、今日ではUIがなく、多くのセキュリティ改善がまだ進行中です。時間の経過とともに、これらの改善は、WPPの改善に取り組むInsider Buildsに引き続き展開されます。

また、Windows Protected Print ModeはWindows Insider Preview Bounty Programの対象となり、セキュリティ研究者がバグを特定して報告することを奨励しています。

LOUCA23に参加してきました(全体印象・旅行記編)

超久しぶりのブログです。2年ぶり。えっ、そんなに?って感じですが、そんなにですね。 いろいろあってOSS活動からは半引退みたいになってるので、書くネタないんですよね。 久しぶりすぎて一瞬URLを忘れたぐらいです(ぉぃ

ええと、OSS活動は停滞気味ですがそれでもイベントには参加するわけで。 今回はインドネシアスラカルタというところで開催されたLOUCA23というイベントに参加してきました。 正式名称はLibreOffice Conference Asia x UbuCon Asia 2023ですね。

活動してないくせになんでイベントには行くんだよと言われそうですが、ぼくにだって友達に会う権利ぐらいはあってもいいんじゃないかなーと。 OSSなエリア、特にLibreOffice界隈にはいい友人がいっぱいいるし、彼らと会うと楽しいし、ひょっとして彼らが助けを求めていたりしたらそれは助けたい。 継続的な貢献は心情的に難しいけど*1、そういう気持ちはあるわけです。

今回もUbuCon Asia側で印刷ネタを話そうかと思ってたんですが、まんまとCfP Deadlineをぶっちぎり、一般参加者として参加することになりました。 ……ら、色々あって発表することにもなりました。

スライドはこちら。

お前OSS活動休止しててLibreOffice日本語チームからもTDFからも抜けたんじゃなかったのかよって思われそうです。自分もそう思います。オレがこのテーマ話すの?って。 まあ、色々あったんですよ。

質疑応答はまったく出なかったのでものすごく成功したとは言えないですが、発表中の聴衆の反応は悪くなかったですし、終わったあと何人かに声かけてもらったりしたので、そんなに悪くもなかったのかな……と、思っております。

イベント全体について

全体を通してみると、まあ、良いイベントだったとぼくは思います。

なんというのかな、誤解を恐れずにいうと、インドネシアの皆さんは勢いがあるけど荒っぽいんですよね。例えば、何かあることを予見して事前に色々するみたいなことはあんまり得意じゃないんじゃないかと思う。でも根本的には親切なので、なにか困ったら相談してくれ!とはみんな言ってくれます。現地でもたくさんもてなしてくれました。

だから特にグローバルなオーガナイザ側からしたら気が揉めてしょうがなかったと思うし、スポンサーとか集めきれてなかったんじゃないの? だからスピーカーの旅費も満額補助にならないんじゃないの?*2みたいなところはあったんだと思うんですが、それでも現地の勢いと熱気とおもてなしで、一参加者としては満足できたイベントでした。

グローバルオーガナイザー、ローカルチーム、そしてスポンサー、もちろん現地で絡んでくれた皆様、本当にありがとうございました!

旅行記的な

はてさて、それはともかくインドネシアです。 ……っていうかスラカルタってどこ?って感じです……。 空港はあるんですけど日本から直接発券しようとすると12万ぐらいするので早々に諦めました。 ジョグジャカルタという都市を経由すれば鉄道2時間ぐらいで着くらしい。じゃあそれで。ってなりました。 スクートでシンガポール経由で預け入れ荷物の権利買って8万弱ぐらい。

まあそんなわけでチケットは取ったんですが、

インドネシアはビザがいるんですが30日以内の観光の場合現地でお金払えば発給してくれる(VOA; Visa on Arrival)らしいんですね。 他の国だとVOA撥ねられることもあるというのは聞いたけど……どうなんだろ。でもネットでググるVOAで入国は普通らしいなあ。

とか、

インドネシアの鉄道の切符ってどうやって買うのかネット調べても出てこない。 というか、「インドネシア 鉄道」って検索すると開業を目前に控えたインドネシア高速鉄道の話ばかりがヒットして困る。 もちろん現地で買えるんだろうけど、旅慣れてもいないし英語も得手じゃない自分ちゃんと切符買えるのかしら?

とか、

行きはシンガポールで一夜過ごさなければいけないけどぼくのステータスではラウンジは入れない。 さすがに徹夜はこの年ではつらいのだけど、快適に過ごせる場所あるかしら……。

とか、

公共交通機関あんまり発達してないみたいだからタクシー移動が主になるだろうけどボラれたりしないかな?

とか、

まあ行くまでは色々不安でした。

贅沢を言えばここらへんの情報は現地メンバーからトラベルガイドみたいな形で出てほしいところではあるんですが、ま、そこんとこはしょうがないですかね。

最初は不安を和らげるために榎さんと一緒に行く予定だったのですが、榎さんがLibreOffice Confenrenceの最中に病気にかかってしまい、もう治ってはいるんだけど体力的には不安、とのことでお休みすることになりました。えっ、おれひとりで行くの?*3

そしたら現地メンバーの一人で旧知のAhmad Haris氏からメッセージが。「Shinjiが参加できないってことだけど、お前代わりに話してくんない?」と。えっ、オレが? このテーマで発表するんの? まあ発表準備さえできてるなら代わりに登壇するぐらいなら……と、念のために聞いてみたら、「資料はないです。メモ書きならあります」。メモ見せてもらったら、まあ活動内容を淡々としゃべるような内容っぽいので、それならまあできるかな? でも発表枠45分もあるよ、45分このネタで持たせられる気がしないなぁ……と思いつつ、一応資料は作りました。

さてさて10月5日木曜日、いよいよ出発。 ということで行きはトランジットを短くしたい(というか朝ゆっくりねたい)という理由で成田-台北-シンガポール-ジョグジャカルタという経路。

成田から台北

スクートさんお世話になります

台北は乗り継ぎじゃなくて一度全員降ろされてまた乗るってパターンなんですが、降りたついでに台湾らしいものを飲みました。

今度はシンガポール

台湾行くたびに飲んでるんだけど未だになんて飲み物なのか知らない

んでシンガポールについて、おビール飲みつつナチョスをつまんだりしましたよと。

ビール!

ナチョス

このペースで書いてたら終わらないな、ええと、結局、空港ではラウンジの近くにソファがゴロゴロあって、その中に電源取れる席があったので最初はそこでスライドなおしたりして、終わったからそこで寝ようと思ったら、ね、寝付けない……。 しょうがないので?とりあえずもういっぱいビールを飲んで、別のソファを探したらそっちは結構寝やすくて、まあまあ寝られました。3時間ぐらいは寝たかな?

で、飛行機としては最終目的地のジョグジャカルタへ。

ジョグジャカルタ行き

ジョグジャカルタ空港ではありとあらゆるところから声をかけてくるタクシー呼び込みさんたちをかいくぐりながら駅についたら「あーしばらく満席ですね、2時間後のこの列車なら空いてます」「ん、じゃあ、それで……」ちゃんと英語できる係員がいたので普通に切符買えました。よかったよかった。

時間たっぷりあるんでまずは昼ごはんを食べ(薄い鶏唐揚げにブラックペッパーソースをかけたやつ、結構美味しかった)、空港のベンチに座ってスライドを公式サイトにアップしようと思ったら……おっと、公式のスライドテンプレがあるじゃないですか……。なんだよー教えてくれよー(誰に言ってるんだ)。そんなわけでスライドテンプレに合わせ込む作業をやって、アップして、とやってたらほどよい時間になったので駅に移動して列車に乗り込みました。指定席なので楽ちん。

そして空港線から都市間鉄道に乗り換えなきゃなのでジョグジャカルタ駅で一度降りまして、またもや切符を購入。 ここもカウンターの人は英語が話せたので安心です。 どこの改札通ってどこのプラットフォーム行けばいいの?ってのが一瞬わかんなくて焦りましたが、駅員さんに切符見せたらちゃんと教えてくれてこれまたよかった。 やっぱりインドネシア、みんな親切です。

そしてスラカルタ、Solo Balapan駅につきまして。ホテルまで移動します。

Solo Balapan駅

徒歩25分ぐらいだっていうんでそれなら歩けるじゃん……と思って、タクシー呼び込みを振り切りつつ歩いたら……これが失敗。 歩道もないし、バイクはビュンビュン走ってるし、道には横断歩道がないしで、ここはなれてない外国人が荷物を持って歩くところではないですな……。 まあ後悔先に立たずですがちょっと怖い思いをしつつ、無事ホテルには着きました。

ホテル

お部屋こんな感じ。不潔でもないけどすごくきれいでもない。

ホテルの一室

で、部屋でダラダラしてたら友達が飯食い行こうぜー、俺達はホテルから歩いていくけどお前はタクシー乗ってきなよ、という連絡をくれたのでタクシーを呼ぶのですが。

えーと東南アジアで有名なタクシー配車サービスとしてGrabってのがあります。いわば東南アジア向けUberなんですが、このアプリ、私先日のベトナム出張時に入れてたんです。でも使うのは初めてだったんですよねえ。

で、あーでもないこーでもないとやってて全然呼べず、おっかしいなあーと悩んでたんですが、根本的な勘違いをしてただけでした。タクシーを呼ぶときに押すボタンが間違えていた。結局30分ぐらい格闘してたので友達を盛大に待たせてしまい悪いことをしました。でもご飯は美味しかったですし、満額おごってもらっちゃいました。ありがたや。

Grabつかえるようになると東南アジアではいろいろ便利なので、大人の階段登った気分です。インドネシア、タクシー安いしね(200円とかです)。

さて翌日からはいよいよカンファレンス。「同じホテルに泊まってる人でタクシー相乗りしない?」「いいねえ」ってことになったんですが、じゃあこの時間集合で!って言った時間に誰も来ない……のんきだね💦 まあ全員無事に集まって、会場にたどり着きました。

こんなゲートがあって

イベントとスポンサーのフラッグ

入口の写真撮り用ボード

写真ペタペタするの疲れてきたので止めますが、お昼ご飯はおべんとうが出て夜は土日2日とも招待! なんともありがたい。 インドネシア料理、初めてだったんですが結構好みでした*4

おやつタイムには現地のおやつがたくさん!

おやつ。盛り付けが美しいね

もちろんちゃんとセミナーも聞きましたよ!

これは基調講演でTDFとはなんぞやの説明をしてるところ

月曜日はバスツアーで、色んな所を回りました。楽しかったです(小学生みたいな感想)。

アーバス

ヘリテージパレスってところで写真撮ってもらった。青空がきれい

火曜日は朝早起きしてGrabで駅まで行って、ジョグジャカルタへ。 フライトが水曜朝なのでジョグジャカルタ宿泊にして一日観光しようという目論見です。

せっかくなのでトゥクトゥク初体験。宮殿に行って観光。その後別のトゥクトゥクのおっちゃんに押し切られて捕まり、影絵工房や画廊を見に行ったりコーヒーを飲みに行ったりしました。ホントはこういうところでお土産買わせることでキックバックもらってるんだろうなあと思いつつ何も買わず。そして博物館でおろしてもらって見学しました。日本語ガイドさんがついてくれたこともあって、なかなか充実の展示でした。

トゥクトゥクに乗る私

博物館の記念撮影マシーンでぱちり。疲れが見えます

でもなんか疲労感がすごくて、あとから考えると軽い熱中症になっていたのかもしれない、これはこの先の観光はちょっと無理だなと思って、Grab捕まえて駅に戻り、鉄道に乗ってジョグジャカルタ国際空港に移動。遅めの昼ごはんを食べて一息ついて、さてホテルに行こう……となったときにちょっと考えました。

日本から、空港から1km弱の宿代580円ぐらいのゲストハウスを抑えてたんですね。でも調べてみると、1km弱なのは直線距離で、実は道がつながってないみたいで歩くと45分ぐらいかかる。じゃあGrabだと空港特別プライスなので結構高い。しかもこのしんどさがゲストハウスで抜けるか……しかもゲストハウスだと夕食も朝食もないのでどこかで調達しなきゃいけない。それはめんどくさい。

うーん、ここは体力を金で買おう!ということで空港内のホテルを飛び込みで取りました。550,000ルピア(5000円ちょっと)で朝食付きならいいでしょ! ということでホテルでゆっくり休んで、美味しい晩御飯も食べて。

チキンレンダン。CNNが選ぶ世界で最も美味しい料理2017だそうな

体力すっかり回復して、ジョグジャカルタからシンガポールに着き、今はシンガポールの空港でこの記事を書いております。

まだ終わってないけど、いやー楽しかったね。おつかれさまでした。

*1:やな記憶がフラッシュバックしたりするので。

*2:ココらへんは私詳しくないので適当言ってます。LibO側とUbuntu側でも違うかも。

*3:日本からの参加者はもう一人案浦さんがいたんですが、彼は旅慣れているのとLOUCAのあと別のカンファレンスに出られるとのことで完全に別行動だったのです。

*4:どんな感じ?って聞かないでね、私表現力が乏しくて言えないです……。ピリ辛多めかな。あと鶏さんが骨付き。

父が亡くなりました

Facebookに書いたらクソ長文になっちゃって、私はFacebookというサービスというかメディア*1 をあんまり信用してないんで、ちょっとアレンジしてこっちにもおくことにしました。

TLDR

このギョーカイ(特にOSSな世界)独身で年老いた両親がいるって人も増えてるかもしれないので手短に我が家がラッキーだったことを書いとくと、事前にやって置けることとしては:

  • 生前に葬儀屋の会員サービスに申し込んでたこと
  • 同じく空っぽだけどお墓を持っていてお寺が決まってたこと

で、自力では何ともできないけどラッキーだったことは:

  • 言語障害を患って施設に長いこと入っていたので、プライベートの付き合いがほぼなく家族葬だと事前に決められていたこと
  • 一度事業に失敗して自己破産をし、不動産は私の所有になってたので、遺産は普通預金しかなく、また兄弟仲も悪くないので遺産相続がもめそうにないこと

ですね。やっておけばよかったなあってことは:

  • 生活インフラの名義人変更は、生前時間があるうちに
  • 亡くなったときに連絡を取るべき人たちを一覧にしておいて、常にカバンにいれておくなり、非常持ち出し袋的にイザというときに持ち出せるようにしておくこと
  • 親戚としてお通夜や告別式に参列する人でもお食事に出てくれるとは限らない、けち臭いことをいえばお食事に参加いただけるかちゃんと確認しといたほうがお財布にはやさしい

ってな感じでした。

disclaimer

  • この記事は人が死ぬということに伴うバタバタを描いて、あわよくば皆さんがそこから得るものがあればなという意図で書いてるものです。
  • ご愁傷さまとかそういうご挨拶だけのコメントはいらないです。自分の体験を踏まえて自分のときはこうで大変だったなあとか、こんなことは参考になったなあというコメントは大歓迎です。

では、クソ長本文の始まり始まり~~。Facebookからのコピペにちょっと加筆した程度なので、それFacebookで読んだよ、という人は記事ごと飛ばして大丈夫です。

……以下、Facebookからのコピペアレンジ……

11/8、月曜日に父が亡くなり、疾風怒濤で昨日通夜、本日告別式と初七日の法要と火葬を終えてお骨になった父を抱えて帰宅しました*2。 いやーーーーくたびれたーーーーー。

週末明けた月曜日、朝ごはんたべるかー、それと並行してコーヒーでも淹れよう……と、準備してるところに唐突に入電。 父の入院先からで、もうすぐ心臓が止まりそうなのですぐ来てくれと。とりあえず家族LINEにその旨だけ入れ、 会社に今日は休むことになるので打ち合わせ対応などお願いしますの連絡を入れて、猛ダッシュで病院に向かいましたが、 到着したときには心停止のアラートが鳴りっぱなしになっている父が。 その場でお医者様が死亡宣告出していただき、臨終ということになりました。死亡時刻は7時47分だったかな。 でも、まだ体が暖かいうちにお別れできただけでも幸運だったと思います。

もともと2回の脳梗塞を経て言語障害と左半身のマヒを抱えており、施設に入ってもらっていましたがそこの施設とは相性がよかったらしく、 本人も機嫌がよさそうでしたし、施設の職員さんからも(リップサービスかもしれないですが) 小笠原さんはやさしい、ほかの入居者さんのことをいつも気にしてくれている、と言ってもらっていて、穏やかに暮らしていました。

公務員を長くやったあと事業を始めて大やけどをして(わたしの父親ですからね、商売ができるわけがない)自己破産をして、 実家を父親から私が住宅ローンを組んで買い取ることにより抵当から抜くみたいな荒業をしたりしました。 そこからはしょぼくれた日々を送って、病気にもなり苦労もしたし老々介護で母親もメンタルが死にそうでしたが、 施設入りしたことでQoLが上がって、ああ、こういう穏やかな日々が来て本当によかった、と思っていた中。

コロナ禍で施設に面会にもいけない日が続くなか、今年の1/3に誤嚥性肺炎で入院したとの連絡が。 あわてて駆け付けたものの病院ももちろん面会不可なのでなにもすることはできず。 唯一できたことは、「万が一のことになっても延命措置はしないでください」というお願いをしたことぐらい。

そこからどうしても痰が切れなくて飲食ができない状態になって経鼻栄養になりましたが、 数か月経って家族で取った励まし動画を見せたらにっこり笑う程度に回復して、 このまま回復してまた口からモノ食べられたらいいなあって言ってたんですが(食べることがホントに好きな人だったので)。

夏場に一度悪化したときから酸素吸入も取れなくなって、 秋からビデオ面会が可能になったんですがそのときにはこっちの呼びかけにも反応しなくなっていて、 ああ、もうこのままこの病院で最期を迎えるんだな、という覚悟はしました。

ただ、11/10って父の誕生日で、今年で米寿なんですよね。なので次の面会は11/10にして、 家族でビデオメッセージ取って差し入れでもしようか、って話をしていた矢先のことでした。 あと二日頑張ってくれたら米寿だったのに……とは、言えないですね。 本人苦しそうなのずっと見てきたので、あれ以上頑張れとはとても言えない。 とりあえず頑張ったね、おつかれさまだね、といって、はてこれからどうしよう、と……。

幸いなことに生前に、 某葬儀屋グループの前払い会員的なものになっていたのですが、 なにしろ慌てて出てきたのでそこの会員向け書類なんかもぜんぶ置いてきたわけで。 私も母も、そもそもなんて葬儀屋さんと契約したのか覚えてない。

一方で病院からは霊安室を使える時間は限られてるのでなるはやで葬儀屋がいつ来るかを知らせろといわれ、 記憶を手繰って検索して出てきたところに電話をして「ウチってそちらの会員ですか?」から始める始末。 結果としては一発目からアタリで、すぐに人を寄こしていただくことになりました。 会員に入ってなければまず葬儀屋さんを決めないことには遺体の引き取りもできないので (いや、ウチの車なら普通に運べるしウチに置いておけるよ?って人は除く)、 事前に会員になってたことで、決めるべきことが一つ減ってよかったです。

で、遺体を引き取ってホールで安置いただいた上で、お葬式の段取りを相談することに。 わたしは一応長男なので(末っ子ですが)、母とどっちが喪主やる?って話になったのですが、 わたしは親戚やご近所とのお付き合いがほとんどないので、 母にはそちらの対応を任せるとなるとわたしがやるのがまあ合理的なので、喪主ってことになりました (我ながら頼りなさそうな喪主だ)。

でも喪主ってなにやんの? よくわからん。(幸いなことに)経験ないし身近で葬式を出した経験もない。 でも、事前に入っていた会員制度は、基本はパッケージになってて、オプションを足していくだけというわかりやすいサービス構成。 しかもスケーリングも考えて香典返しなどは多めに用意して使った分だけで後日清算、という便利さ。 お通夜の後のお食事会も近親者以外は会食で提供する食事の代わりになるお米をお渡しすることができる(これも使った分だけ)とか、 いやーサービスとしてよく考えられてるわ。 そして「一生に一度のことだから」といってついついオプションを足してしまうお気持ちをうまく利用したご商売が巧みですね(誉めてます)。

でまあさっき書いた通り11/10は父の米寿なので、単なるお別れの会じゃなくてできなかったお祝いの会にもしたい、可能なら11/10、11の日程だとうれしいと。 それは葬儀屋さん的には可能だけど、お坊さんの手配次第で、 ウチは(中身空っぽだけど)いちおうお寺さんにお墓持ってるのでそこの住職さんに聞いてほしい、とのことで、電話かけてもずーっと留守電。 どうしようか……と考え込んでたら葬儀屋さんが

「10、11で決めましょう! 米寿のお祝いを兼ねるってことは大事にしたいです。お坊さんは、もし都合がつかなかったら同じ宗派のお坊さんに相談してくれるとかもあるので何とかなりますよ!」

と言ってくれたのでハラを決めて、10日お通夜、11日告別式という日程にしました。

でもお坊さんが捕まらないの困るな……よし! お寺に直接うかがってみよう!30分もかからないところだし! ということでクルマに飛び乗り向かって、あと5分で作ってところで入電。 「すみません電話遅くなりまして……」 「あ、今そちらに向かってて、直接お話ししていいですか?」 「え、そうなんですか??ではお待ちしてます」ということでお寺に到着。

「えっ、日程決めてきちゃったの? まあ、それならなんとか都合はつけますよ……」と戸惑ってた住職さんですが、 父の出身が青森の奥入瀬渓流の近くだって話で「あそこは私も行きましたけどほんとにいいところですよね」みたいな話で盛り上がって、 「じゃあ奥入瀬から字を取って戒名作れないか考えてみます」ってことになって、結果的には襲撃してよかった。 最終的にはやっぱり会ってご相談したほうが、電話よりもずっといいと思います。 私初めて住職さんとお話ししたんですけど、さばけたよい人で、あーこの方なら任せても安心だなと。

翌11/9は友引なので何もない日なので勤務日にしたんですが、 我が家は電気ガス水道CATVなどの契約が全部父名義だったし父の口座からの引き落としなのでこれをなんとかせないかん。 もっと早くやっておけばって感じだったんですが、なんか父の死が近いってことを予期して動くのが気持ちよくなくてズルズルと引っ張ってきちゃったんですよね。 でもさすがにまずい。ということで仕事の隙間で、こういう関係とか保険とか年金とかそういうたぐいのところに電話をかけまくる必要があり仕事が進まない。 その予感はあったので朝5時起きして頑張ってたんだけどそれでも進捗出ない(そういう日に限ってチャットの問い合わせ対応が多かったりしてね……)。 私の仕事ってほぼ私一人でやってることが多いので、金曜までにやっておきたいことは火曜日までに終わらせなきゃいけないので、夜も12時まで仕事して3時間睡眠で、 お通夜当日の10時近くまで仕事してようやっと終わりました。やれやれ。

あともう一個あって、じつは日曜日に若くして亡くなった知人の告別式に行ってて、そのあと礼服クリーニングに出しちゃったんですよね。 で、これを取りに行かないといけない(クリーニングだしたのが日曜当日でよかった)。

あとさすがに喪主が二日続けて同じYシャツってのはどうかなと思いつつも白いワイシャツは1枚しかアパートから持って帰ってこなかったので買ってこないといけない。 そんなわけでこれも火曜日の夕方回収したり調達したりしました。綱渡りだな。

それ以外にも、例えば父の遺影と会場投影用の思い出写真を選んだりフィルム時代のやつはスキャナで取り込んだり、 家族LINEで相談したり、そういう写真データや、保留にしてた注文の類を葬儀屋さんに連絡したり、 まーいろいろと忙しすぎて、悲しいとか寂しいとか思う暇がなかった。うーん親が死んでもこんなもんか、自分案外つめたいやっちゃな、そんな風に思ってました。 で、お通夜までは時間があったので、屋根にカヤック積んだあんまり汚いクルマで喪主が乗り付けるのもなあと思って、 カヤックおろして久しぶりに洗車して、あと葬式ってカード払いとかダメで現金一括が多いので銀行行ったりして。 お通夜の15時ぐらいまではそんなことをギリギリまでやってました。 ほんとバタバタやな。

んでお通夜なんですが、長いことOSSのイベント手伝ったり主催したりしてたせいで、どこか手すきのところがあると気になってしょうがない。 受付頼んだ姉貴が、プチカメラ趣味なので張り切って写真撮ってるなか(思い出になるので写真撮ってもらうこと自体はありがたい)、 なぜかわたしが受付に立って受け取ったお香典を抱えてドキドキして、喪主なのにろくに会葬者に挨拶もしてないというですね。喪主ってなに……概念? まあでも祭壇のお花はすごいいいチョイスだったし、 「米寿なので赤いちゃんちゃんこをイメージしてポイントで赤を入れてほしい」「青森県人なのでリンゴが好き」みたいな要望にもばっちり、応えてもらって、 遺影の写真も素敵に仕上げてもらって、あーすごいよい式になりそうだなって。

f:id:naruoga:20211116062809j:plain
祭壇。まだ準備中なので仮位牌載ってないけど

で、お願いして、最後に喪主の挨拶をさせてもらうことにしました。 ぶっちゃけそれで緊張してて手汗がすごくて、ご焼香のときに手にお香がくっついちゃって閉口しましたw

で、台本もなしに「ぜひお別れの場だけではなく、父の米寿を祝う気持ちで見送ってほしい」みたいなことをしゃべってたら段々こみあげてきて、 あれ? さっきまで全然悲しくなかったのになんで? うそでしょ? もう涙が止まらくなってマスクの下は鼻水だらけだわ、お見苦しい挨拶でしたが、よいスピーチだと褒められてホッと一息。 その後、お食事してホールに泊まって、母と、普段は離れて暮らしてる姉と、父との別れを惜しんで話したりしました。

開けて翌11日、お葬式。今日は全然こみあげてこないし大丈夫、あー昨日はびっくりしたなあ、と思ってたんだけど、 最後にお棺にお花いれるときに、家族といろいろ話しながらやってたらまた涙がドバドバ出てきて……マスクしながら泣くと、 ぱっと鼻がかめないで困るということを学んだ二日間でした。

それから火葬場にいって最後にお見送りをして、火葬の間お食事をして、お骨拾って、ってときにはもうさっぱりしたもんで、 へー人間の骨って焼くとこんな感じになるんだー、こんな大きさの骨壺に入っちゃうんだなあ、そんなことを純粋に感じてました。

で、お骨になった父を連れて帰宅。青森から来てくれた叔父さんと姉貴も交えて話をいろいろしつつ、 最後に二人を駅まで送って、またまた礼服をクリーニングに出して、帰ってきて、経過をFacebookに投げたって感じです。

葬儀屋さんが届けてくれた花とかも飾ったら祭壇がすごい豪華になって、父も心なしかうれしそう。 施設に預けてから、正月に一時帰宅することはあってもず~~~~っと家にいなかったから、久しぶりに父がいる生活が四十九日までは続くことになりますね。

へーしゃの場合は1親等だと忌引三日なんですが(一般的かな?)、金曜日はもう行事的なことは終わったので比較的のんびりで、 午前中は水道料金の支払い請求の切り替えのために銀行に行き、ついでにインフルの予防接種も打って。 午後は役所にいって、葬儀屋さんが市からもらってきてくれたチェックリストをもとに各種手続きを済ませて、 その足で「手の皺と皺を合わせて」で有名な某仏具店に行き、仏壇や仏具の選定も済ませて。 いまの仏具っていろいろ便利? に進化してるんですねえ。 仏壇は母の寝室に置くことになってるので、母が気に入ったものを買えてよかった。

あとはおっかけで来るお香典も含めて収支弾いたり、まあ大イベントである四十九日の法要関係の手配と相続関係が残ってるけど、 とにかく喪主終えてほっとしました。よかったよかった。 もちろん父が死んでさみしいし悲しいけど、最後はホントに辛そうだったから、楽になってよかったという気持ちが大きいです。

今は朝晩、お線香は省略してお水換えてリンを慣らして、 「長いこと刻み食と経鼻栄養だったから、ご飯とかおやつとか食べられるようになってよかったねえ」 「お父さんは外面はいい人だったから、きっと常世の国に行ってもみんなに愛されるんじゃないかな」 「家族にはけっこうな人だったけどねw」 みたいな会話をしつつ日々すごしております。初七日は一緒にビールで乾杯しました。

ま、そんなわけで、人が亡くなるってのは大変だなあ、というつまらない述懐でしたよと。おしまい。長文読んでくれてありがとうございました。

f:id:naruoga:20211116063059j:plain
ウチに安置されてる父(の遺骨)。お花たくさんで本人も心なしかうれしそう。四十九日の法要まではこうやっておうちでお骨守ります

*1:最初「会社」って書いてたんだけど、今Facebookって会社はないじゃんねえ……。

*2:注;これをFacebookに書いた11/11木曜日時点のこと。

LibreOffice Conference 2021雑感

naruoga.hatenablog.com

前の ↑ 記事でも予告したように、LibreOffice Conference 2021(以下LibOCon、りぼこんと読んでね)参加してきました。

libocon.org

LibreOfficeのコミュニティ活動辞めたっていってたのに何で年次カンファレンス参加してるの? といわれるかもだけど、LibOコミュニティには知人が多いし応援したいプロジェクトでもあるし、ただメンタル弱ってるので「継続的に価値がある貢献を、周りと議論しながらやっていく」みたいなのは約束できないしそれを求められるのは正直苦痛だけど、イベント参加したりそれをTwitterにメモったりこういうブログ書くことは、誰ともかかわらずに一人でできますので。はい。

つーてもおおむね当日の内容はTogetterに書いてしまったのでそっちを見てください*1

togetter.com

また、発表のビデオについては順次YouTubeに上がっているので、上のTogetterをみて「へーこの話面白そう」って思った方は、そちらを直接見ていただくのもいいかもしれません。

www.youtube.com

なのでこの記事は、個別のセッションがどうとかではなく、全体的になんとなく感じたことを雑にまとめたいと思います。

ちなみにクソ長いです。分割しようかなとも思ったけどそれも大仰なので適当に流し読みして、気持ちがひっかかったところだけきっちり読んでくださいませ。

イベントのスケジュール

今回、イベントはハンブルグのLUGとの共同開催ということになってて、イベント自体はハンブルグタイムゾーンで企画されてたんですが、その時間は12:00-17:30と、割と短めに設定されていました。 その理由は明確には確認してないのですが、もしかしたらタイムゾーンが離れた我々極東の民のことも考慮してくれてたんでは……って、ちょっとだけ思いました。 日本時間だと19:00-00:30で、去年朝5時まで起きてなきゃいけなかったことを考えると天国のようにラクショーでしたし。 もしそうだとしたらうれしいなあ。 オンラインイベントは参加こそ容易ですが、時差だけはなんともならないですからね。

また、イベントのスケジュールページ:

https://events.documentfoundation.org/libocon2021/schedule/events.documentfoundation.org

にて、ブラウザのロケール設定を見て? タイムゾーンが選択できるようになってたのもありがたかったです。これまでだと、聞きたいプログラムをチェックして、それをGoogleカレンダーに現地タイムゾーンに登録する、っていちいちやってたので……。

公式アプリの存在

ほかのイベント(COSCUPとか)だとよくあったんですが、今回、LibOConにも公式アプリがリリースされてました。Androidだけですけど、Play Store だけじゃなくて F-Droid でも公開されてたのがそれらしい。

タイムゾーンを端末設定で選べること、興味があるセッションにマークすると時間にアラームで知らせてくれること、スケジュール変更があればリアルタイムで通知が来ることなど、なかなかよくできていました。これはいろんなイベントで取り込んでほしいなあ。

コミュニティ、エコシステムの関係と「LibreOffice Technology」「LibreOffice Enterprise」

今年の大きなテーマの一つは、この部分だったのかなあと思ってます。

ここでいう「エコシステム」っていうのは、すごい大雑把にいえばLibreOfficeのフルタイムの開発者を雇用する組織のことです。多くはLibreOfficeに関するなにか(例えば長期サポート版などの派生した有償のプロダクト、導入支援、サポート、教育など)を顧客に提供して対価を得る企業であることが多いですが、昔のミュンヘンのように自分たちが使うための問題を解決するために開発者を雇用していた組織もあります。

LibreOfficeコミュニティが、「エコシステムの金銭的利益(さらに言えば持続可能性)とコミュニティの関係や利益にどう折り合いをつけるか」って議論は結構重要です。やはり多くの開発行為はエコシステムからなるものが多く、特に特定のバグ対策ではない大きい機能改善は、フルタイム開発者でなければ実現できないことも多いですし、フルタイム開発者は霞を食べて生きていくわけにはいかないですから。もちろんエコシステムはコミュニティの重要な一部であり、彼らのコードやその他(イベントのスポンサーシップやGSoCのメンタリングなど)の貢献なしにはLibreOfficeプロジェクトは継続していくことは困難です。

一方で、LibreOfficeを取り巻く状況としては以下のようなものがあります。

  • そもそもデスクトップでアプリを使う、というユースケース自身が縮退しつつあるのでは
  • OSSを単にサポートするというビジネスの成功例はほとんどなく、新たな展開が必要
  • 派生版を提供するエコシステムにとって、「LibreOffice」というブランド力に頼りたい半面、それを前面に出してしまうと自組織のブランドイメージが向上しない
  • 各OSベンダーが提供するStoreシステムからLibOをインストールしたいという要望に対して、Storeの要求に合わせるコストをだれがどう負担するか、その負担分をどう回収するか

それから、今までは「Poorman’s MS Office」でやってこれたとしても、MS OfficeがOffice 365のライセンス費用を相当抑えてきており、Googleも個人利用では無償、商用でも競争力のある価格設定をしている現在、エコシステムへのサポート込みでLibreOfficeを使うことは決してコスト的に有利にならない、したがって「安いMS Officeの代替品」という立ち位置ではない、LibreOfficeならではの魅力を強力に発信していく必要があるわけです。

そこでLibreOfficeコミュニティとして旗印として立てているのが「コアの共通性」と「ODF」の二本柱です。

コアの共通性というのは、前から紹介している通り、LibreOffice OnlineはサーバーサイドでLibreOfficeを動かし、そこでレンダリングした結果をビットマップタイルとしてクライアントに送信するということで、クライアントの状態によらない統一した、デスクトップ版と変わらない(例えば、ほかのクラウド系オフィスソフトでは実現できていない縦書きなどもサポートした)レンダリング結果を実現しています。またCollaboraが開発しているCollabora Office for iOS/Androidは、基本的にはLOOLサーバを内蔵して、アプリはWebViewでLOOLクライアントとしてふるまうという実装をしています。つまりデスクトップ、クラウド、モバイルにて、統一したレンダリングエンジン、統一したコア実装を用いており、ユーザーはどのプラットフォームでも、同じレンダリング結果と、ほぼ共通の機能を得ることができるというわけです。

もちろんこの実装には利点も欠点もあるわけですが、それはおいておいてもこの「共通性」を強みとしてしっかりアピールしていきたい、と、LibreOfficeコミュニティは考えています。

そしてODFは、LibreOfficeの標準ファイルフォーマットであるだけでなく、オフィスドキュメントの相互運用性ということに真摯に向き合った国際標準でもあります。アプリケーションから利用するにも、ZIPファイルをほどいて中のXMLを人間が見ても、プログラムから操作するにも優れたフォーマットです(詳しくは過去記事を参照)。イギリス政府が「編集可能な文書ファイル形式」をプレーンテキストとODFに限定しているのは、このような優位性を認められてのことです。その優れた点の一つが、ワープロ表計算、プレゼン、図形描画と同じスキーマを持っていることです(OOXMLが、スキーマはおろかXMLファイルのディレクトリ配置すら異なるのとは対照的ですね)。これが二つ目の「共通性」というわけです。

この二つの「共通性」を基盤とし、ワープロ表計算、プレゼンといったアプリ、そしてPC(デスクトップ)、クラウド、モバイルが同じ基盤に乗っていること、これをLibreOfficeの優位性として積極的にアピールしていこう、というのを表すのが「LibreOffice Technology」という用語、だという理解です。

f:id:naruoga:20211010231024p:plain
LibreOffice Technologyの説明図

そして、エコシステムベンダーは、自社ブランドを冠したプロダクトに「LibreOffice Technology」を使っている、というアピールをすることができる、というわけです。

また、LibreOfficeに対して「大きく革新的な機能開発」を行うには、やはりボランティア開発者だけでは利用できる時間的に難しく*2、フルタイム開発者の力が必要です。このような場合、①そのような機能を求める顧客の要望に求めてエコシステムが対応する、か、②LibreOfficeを資金面で支える非営利法人The Document Foundation(以下TDF)が資金を供給して開発者を公募し、それを受けた開発者やベンダーが開発を担当する、の二つの方法があります。顧客にとってわかりやすい魅力的でない改善であっても重要なものというものがあり、それを解決するには②の手段を取る必要があります*3

その場合、資金の出どころはTDFということになるのですが、TDFにおける収入の大部分は実は寄付によっており、そして寄付は個人やSMB(中小企業)によるものがほとんどで、大規模な組織、つまりエンタープライズ(大企業、政府機関、自治体、学校法人など)からは行われていないというのが現状です。そして彼らがエコシステムにもお金を払っていないのであれば、いわばそれはエコシステムを含むコミュニティの成果にフリーライドしている、ということになります。

したがって、エンタープライズが寄付を行うつもりがなければ、積極的にエコシステムに対価を払うべきである、というのがLibreOfficeコミュニティからのメッセージで、それを表す言葉が、TDFからリリースされているバージョンに対する「LibreOffice Community」と、それに対してエコシステムが提供する「LibreOffice Enterprise」です。

このように、エコシステムの持続性をコミュニティの持続性と積極的に結び付け、エコシステムがより多くの利益を得ることでLibreOfficeがより良い方向に発展していく、というメッセージを強く発信したカンファレンスであった、と、感じています。

これは非常に重要なことで、当然意見は一様でなく、ここ数年の間、さまざまな議論を経て今回のメッセージを出すところまでようやっとたどり着いた、そういう風に考えています。 丁寧に議論を重ねてきたコミュニティメンバーたちには敬意を示すところです。

が……。

TDFメンバー・コミュニティメンバーに対する調査と取り組み

この手の議論はもちろん大事で、オープンな場で透明性を持った形で議論するのは望ましい……と、理屈ではそう思うのですが、この手の議論は紛糾するとひたすら長文の英語のメールが延々と流れることになり、そしてあまり英文読解が得意でなく、かつ議論のすべてを機械翻訳に通すほどの元気もない私は、「なんか対立関係が表面に出てきている」という印象だけを受け取ってしまいがち、ということがありました。

前にも書いたけど私がつらくなった一つの要因に「なんかグローバルなコミュニティでもギスギスした雰囲気を感じてた」ことがあるんですが、それは、こういう議論がとにかく紛糾しているけど詳細を追い切れるほどの気力も能力も欠けていた、ただ紛糾している雰囲気だけが見て取れてそれがつらかった、ということがあります。

その中の一つには、エコシステムの一つであるCollabora Productivity(以下単にCollabora)が一強になりすぎたってこともあると思います*4

エコシステムに開発の多くを依存しているLibreOfficeプロジェクトにおいては、エコシステムのビジネスが健全に発展し続け、十分な利益を得ることができ、それにより多くの貢献者が開発だけでなくその他の活動で生計をたてられる、あるいはサイドビジネスとして十分な利益を得られることは非常に望ましいです。

一方でSun Microsystemsという一組織に依存していたことからプロジェクトが継続できなくなったOpenOffice.orgの反省から、エコシステムとの距離感に対して警戒感を持つ人も少なくなく、ボランティア貢献者の中には「今のTDFは過剰にエコシステム方向を向きすぎている」とか「ボランティアによる貢献をエコシステムがタダ取りしている」などと考える人もいるようではあります。

先に書いたとおり私はそういう議論を逐一追えてはいないのですが、とにかく一種の緊張関係があるのは事実。私の目から見ると、今回のカンファレンスは、そういう緊張関係に対して、なんらかの解決を目指そう、という姿勢を感じました。それはTDFとして目指していくところをより丁寧に説明しようという点もそうですし、TDFのメンバーシップ委員会が企画した「コミュニティインタビュー」に対する振り返りとディスカッションというセッションの存在についてもそうです。

コミュニティは当然いろんな思惑がある人がいろんな動機で参加してくるところなので、「全員の思いや行動を揃えよう」とするのではなく「違いを尊重しつつ一緒にできることをやっていこう」というふうになればいいなと感じます。そしてそう思っている人はTDFのコアにも確実にいる、そういう思いを感じたカンファレンスでした。

LPIやUdemyと協業した新しい認定プログラム

このブログやTwitterなどで紹介したことがあるのでご存じの方はいるとは思いますが、TDFにはその公式の認定制度があります。

この認定制度は、例えばMicrosoftOracleCISCOといったベンダー認定と違い、「LibreOfficeに対して十分な知識と専門性を持っており、貢献の実績がある」ことを示すもの……という側面が強いものでした。なので、例えば移行専門家であれば「過去にこのような移行を推進した・支援した実績がある」といった証拠となるドキュメントを提出し、認定委員会による面接を経て認定される、というものでした。認定専門家には移行(マイグレーション)、トレーニング、開発が存在します。

もちろんこれらの認定制度は、どの企業にも属しないコミュニティベースのプロジェクトであるLibreOfficeでは重要な役割を果たしてきましたが、一方で以下のような課題がありました。

  1. 「利用者がLibreOfficeの使い方を正しく把握しているか」といった、例えばMOSOracle MasterCCNAのように「履歴書に書ける」資格が存在しない。たとえばLibreOfficeやODFを政府機関で採用している国や自治体においてはこのような資格は就職に有利に働く
  2. 認定専門家(特に移行とトレーニング)は当然、LibreOffice/TDFからのメッセージを正しく使える「代弁者」としての責務を担うことになるが、認定専門家が正しくその理念を伝えているとは限らないし、認定専門家の品質が悪いと逆にプロジェクトやコミュニティにネガティブな印象を与えうる
  3. 失効期間が曖昧で、アクティビティが低下している人でも資格持ち、という状態になりうる

このような問題意識のなかから、今回はいくつかアナウンスがありました。1. の解決手段として、LPIとの協業による新たな資格を用意するとのことです*5。すばらしいニュース! ただ、まだ検討を始めた段階であり実際のローンチには少し時間がかかりそうです。

また 2. と 3. については24か月ごとの活動状況の再チェックと、活動的でない認定専門家については再認定などを検討しているとのことです。そして「LibreOffice認定済(LibreOffice Certified)」的なポジションが用意され、これは基本的な面接を受けた後にUdemyから提供されるビデオ講座を受講してなることができるそうです。その資格を受けてから12か月以内に今の認定試験同様の基準を満たすことで(つまり移行やトレーニングの実務を行ったことを示すことで)、初めて今の「認定専門家」になれると。ただしTDFメンバーである場合は「LibreOffice認定済」を経ずに直接移行専門家の試験を受けられることにすることのこと。

まだ詳細決まってないことはあれど、いずれにせよ認定制度としては正常な進化だし、こういう方向でよりLibreOfficeの認定がカジュアルに取得でき、かつその利益が取得者にとって得られる社会に近づけばいいなと感じました。

LOOL(COOL) vs. WASM

ここの vs. は煽り気味です、はいw

開発についてのトークについてはこれというテーマがある感じではなく、これはもちろんデスクトップオフィスソフトとしてのLibreOfficeの成熟度を示しているってことはあるとは思うのですが、その中でしいていうならこのテーマですかね。

LibreOffice Online(LOOL)はブラウザベースでLibreOfficeを動かす仕組みで、なおかつCollabora Office for iOS/Androidはこれを応用して実現されているので、クラウド時代におけるLibreOfficeの新たな地平を開く、LibreOffice Technologyの鍵となる技術です。しかしLOOL自体はTDFのリポジトリに存在して一部外部の貢献者もいたものの、本体の開発および、LOOLの機能のためのLibreOfficeのコアの開発の多くはCollaboraのメンバーによりなされていました。そのためTDFリポジトリのLOOLは更新が凍結されて、Collabora Online(COOL)としてCollaboraのGitHubプロジェクト配下で管理されるようになりました*6

もちろん、COOLは相変わらずOSSでありCollaboraメンバー以外のPRやその他の貢献も受け付けていますし、GitHubベースになったことによって「モダンな」開発者にとっては参加の敷居が下がったと思われますし、さらに言えばCollaboraとビジネスパートナーになればCOOLをベースにした自社商品もリリースできる(想像です)と思うのですが、前述のようにLibreOffice Technologyの重要なキーが特定のエコシステムベンダーのものとなったことに嫌悪感や危機感を持ったコミュニティメンバーも少なくない、というのが私の感じているところです。

また技術的には、LOOLはいわゆるクライアント・サーバーモデルなので運用が結構大変ですし(個人やSMBで立てるのと、エンタープライズでごりごり使うにはノウハウが必要)、またCOOLとLibreOfficeコアのリポジトリが分かれているにもかかわらず密結合なところがあるので双方を見られる人じゃないと大きな機能追加は難しく、またメモリ使用量も比較的大きい重量級のシステムです。

と、いうことで、新たに注目されているのがWASMベースのLibreOfficeのポーティングです。2015年ごろにも構想されたもののWASM自体もツールチェーンのemscriptenも問題が多く挫折したのですが、W3Cの標準となり多くのブラウザで実装された現在、再びチャレンジすることになったということです。 これは、もちろん前述の技術的問題へのカウンターであることもそうですが、主に牽引しているのが、ドイツCIB社から分社したばかりの若いエコシステムベンダーであるallotropia社であることから、単純に技術的な挑戦だけではないのではと邪推しています。

とはいえWASMへのポートは相当いばらの道のようで、今年2月のFOSDEM 2021ではまだまだ戦いは始まったばかり、という感じでしたが、今回のカンファレンスのトーク聞きそびれたのでビデオ公開が待たれるところです。

WE WANT YOU!

長くなってきたので残りはなるべく手短に。

TDFの雇用メンバーに新たに加わったHossein Nourikhah氏は「Developer Community Architect」という役割で、これから新たな開発者を開拓していこうという取り組みをいろいろしていますが、氏による「Getting Started with LibreOffice Development」という90分のセミナーをはじめとして、LibreOffice SDKのサンプルを再構築しましょうとかLibOのソースはこう読めとかデバッグをこうやれとかそういうトークが多かったとします。日本からの参加者、案浦さんのGraphQLのエクステンション作ったよな発表もこの枠かな。

その中の一つ、Ilmari Lauhakangas氏によるセッション「A legendary bug reporter」がめちゃくちゃ面白かったので、ぜひYouTubeで公開されてるビデオ見てください。

日本でCJKバグを直すためのハンズオン的なものやりたかったらTDFは協力してくれるかな?と、マーケティング担当のMike Saunders氏を経由してHosseinさんに伝えてもらったらメールもらって「LibOConで講演するからまずはそれを見てね、手伝えることがあったら連絡ちょうだい」と言われてるんだけど、いまだに返事を返せていません……興味ある、参加したいって人は私のSNSなりなんなりで反応ください。個人的にはビルドやってなにやってって話もそうだけど、CJKバグに対する単体テストを書く、見たいなハンズオンをやってみたい。

って、継続した貢献はお約束できない、って言ってるぼくがいうのも変な話だな。まあ、単発のイベント回すぐらいならできるんで……。

終わりに

去年の似たようなエントリ

naruoga.hatenablog.com

で、来年は参加するかわかんない的なことを書いたけど、やっぱり参加したしやっぱり楽しかった。 あとはなあ、知り合いともっと話できるチャンスがあるといいんだけどなあ。ビール片手に。でもそれは時差がある分難しいですね。

来年の開催は「現在状況を見ながら慎重に議論を重ねていて、今話せることは何もない」だそうです。 オフライン開催になればいいけど、それでも日本から私が行けるかどうかはわからないしね(そもそもまだLibreOfficeコミュニティの一員として活動を復帰するとは言っていない)。

まあともかく、いろいろな中イベント開催に尽力してくれたみんなには感謝感謝です。ありがとでした!

*1:Togetterは公開期間にリミットがあるから、ずっと残したいコンテンツは別の手段を取った方がいいという説もありますが、まあ、イベントログ自体生モノなので、そこのところはあまり深く考えない方向で。

*2:可能な「すごい人」がいないとは限りませんが。

*3:もちろんエコシステムベンダーが「自発的に」そのような改善を行うこともありえますが。

*4:ここについてはあんまり大っぴらに書きにくい話も聞いたことがありますが、それは直接聞いてくれればお話ししますw

*5:今年のLibOConはLPIがスポンサーになってて、ありがたいことだけどちょっと意外、と感じてたんですが、このアナウンスを聞いてなるほどと。

*6:この説明はかなり雑なので、うのみにしないで詳細はCOOLのFAQなどを参照してくださいね。

【個人的メモ】LibreOffice Conference 2021 Onlineでどの発表を見るか

いよいよ近日開催、LibreOffice Conference 2021(以下長いのでLibOCon)。

libocon.org

今年のロゴ、なかなかかっこいいですね。

https://libocon.org/assets/libocon2021/libocon-2021-logo.png

カンファレンスグッズも各種取揃っており、イベントに向けて気持ちを盛り上げるには十分です*1

www.freewear.org

そんなわけで、今やLibreOfficeに関するいかなる組織にも属してないけど、市井のLibreOffice愛好家であり、一応日々LibreOfficeを使って仕事してる人間として、どんな発表に着目していてどれを見るかって個人的メモをここに書いておくという誰得エントリーを今回もやります。つーてももうコミュニティワークをしなくなって1年以上経つし、貢献もなにもしてない*2 人間のメモなので、「これを見た方がいいよ」とかそういうオススメではありませんので、そこらへんは踏まえてお読みいただけますと。

はてさて。グローバルなイベントがオンラインで気軽に参加できるようになったとはいえ、時差がつらい*3 という問題はあるわけですが、なんと幸いなことに、今年わたくしの勤務先はシルバーウィークで今週ぶち抜きお休みなんですよね*4 なのでヨーロッパ時間で行われるイベントに出ても昼寝すればオッケー。なんて楽勝なんだ……。

あともう一つうれしいのが、カンファレンスのスケジュールページでタイムゾーンが選択可能になってること!

f:id:naruoga:20210920160242p:plain
Asia/Tokyoが選べる! ブラウザの設定などによりほかの場所も選べるのかな?

これで、Googleカレンダーに聞きたいトークを全部入力して、実際には何時に始まるんだかを把握する、超めんどくさい作業から解放される……。

まあそんなわけで、昼寝をすればいいってのはチートですけど、現地でも開催時刻を少し遅らせて、終了も早めることで(現地時間12:00-17:30)、我々日本からの参加者でも、19:00-24:30というまあまあ人間的な時間帯に参加することができるようになりました。なので、全部通して聞けとは言わないけど、よかったら少し早めの面白そうなトークを狙って聞いてみると得るものも多いんじゃないかな。

では始めましょー。前回は超長くなってしまって3分割にしましたが今回は手短になるといいな。

Day 1(9/23(木))

現地午前中はオープニングアワーということで迷う必要がなくていいですね。

ここらへんはオープニングやスポンサートークで、LibOConにおいてはLibreOffice自体の大きな機能開発がやはりイベントのスポンサーである2企業(Collabora Productivityおよびallotopia)の主導で進んでいることは間違いないので聞いても損はないですね。最後のCertificationはあんまり興味はないんだけど、わざわざここにアナウンスを持ってきたってことは何か大きな変化があるかもしんないし。

21:30-22:00の休憩をはさんでからは3ルームに分かれるので悩ましいですがこんな感じで考えてます。

時刻 トーク 一言コメント
22:00 I feel the need... The need for speed..... :: LibreOffice Conference 2021 :: pretalx パフォーマンス向上の話は技術者として純粋に面白そう。裏番組は榎さんだけど、ごめんなさい :)
22:30 The Crashreporter Service used by LibreOffice :: LibreOffice Conference 2021 :: pretalx 実はCrashreportの仕組みちゃんと知らないので。会社でも死んだときにはこうやってレポート送ってね、ってことを推奨するようにもしたいし
23:00 LibreOffice Calc Survey: User Characteristics, Usability, and Future Enhancements :: LibreOffice Conference 2021 :: pretalx SVGエクスポートフィルタの話とも悩んだけどこちら。ソフト屋としてUXにも関心持たないと
23:30 Improved document searching with LibreOffice :: LibreOffice Conference 2021 :: pretalx 内容見てみたらヘッダやフッタ、図表のキャプションも含めて検索できるようにするよという話で面白そう
24:00 Multi-column support in LibreOffice 7.2 :: LibreOffice Conference 2021 :: pretalx 多段組サポートもうあるじゃん、って思ったけどなんか違うんでしょうね。CJKへの影響も含めて興味がある

Day 2(9/24(金))

時刻 トーク 一言コメント
19:00 openSUSE maintenance, when several projects cooperates for making LibreOffice a solid productivity suite :: LibreOffice Conference 2021 :: pretalx Marinaの話だという理由も大きいんだけどw、ディストロと上流プロジェクトの関係を考えるよさそうなセッションなので。ま、私はどっちの人でもないですけどね、どっちにも知り合いはいますし……。
19:30 COOL performance :: LibreOffice Conference 2021 :: pretalx こういっちゃなんだけど消去法でこっち。スペルチェック大事だけど我々日本人には、もっと手前でやることあるからね……
20:00 PPTX footer export & import interoperability :: LibreOffice Conference 2021 :: pretalx
Edit LibreOffice files directly from Nextcloud web interface :: LibreOffice Conference 2021 :: pretalx
Color Filter in Calc :: LibreOffice Conference 2021 :: pretalx
案浦さんのGlaphQLの話 とすごい悩んだんだけどLTっぽいこちらに。PPTXの相互運用の話とCalcのカラーフィルタの話が聞きたいので
20:30 ODF Status Update 2021 Edition :: LibreOffice Conference 2021 :: pretalx ODFの動向はちゃんと追っておきたいです。LibOはPoormans MS Officeとしてはもう負けが込んでるので、技術屋としてはODFの機械加工性の良さとかを推していきたい感があり。裏番組のDaeHyunさんにはごめんなさい。
21:00 Update about ODF Advocacy :: LibreOffice Conference 2021 :: pretalx 同上。Xrayの話もすごい興味があるけど、まあこれは後で録画で追いましょう
22:00 How to debug Writer, forwards and backwards (Epsiode 2) :: LibreOffice Conference 2021 :: pretalx 去年のセッションが面白すぎたので……。今年も聞かないわけにはいかんかなと。90分長いけど……
23:30 LibreOffice SDK Examples Overhaul :: LibreOffice Conference 2021 :: pretalx LibOのExtension周りは詳しくなさすぎるので土地勘持ちたいということも。って、一度実践してみたらいいのにね(セルフ突っ込み)
24:00 Converting LibreOffice Guides into Web Pages :: LibreOffice Conference 2021 :: pretalx こんな議論があるんだ、という新鮮な気持ちとともに。まあ確かにWebベースのほうが時代にあってるとはいえ

Day 3(9/25(土))

関係ないけどこの日から 2021.ubucon.asia が始まるため一部イベントの時間被っちゃうの*5で自分にはプチ残念。まあ、しょうがないね。

この日はマルチトラックなのはごく一部で表形式である必要はないんだけど、まあ、そのまま

時刻 トーク 一言コメント
19:00 LibreOffice in the browser, live and in color! :: LibreOffice Conference 2021 :: pretalx LibOのWASM実装の話、聞かないわけにいかないでしょ。おかげでUbuCon Asiaのソーシャルイベント出られないんだけど……発表の合間でちょっと顔出してみるかな
19:30 Building (and using) LibreOffice Online... again :: LibreOffice Conference 2021 :: pretalx タイトル見るとCollabora Productivityにコード移譲された 元の LOOLを動かそうって試みかな?
20:00 JSDialogs improvements over the past year :: LibreOffice Conference 2021 :: pretalx COOL(旧LOOL)で使われてるLibOの各種ダイアログをJSで実装するコンポーネントの説明と思われる、前にこれに関する発表聞いたけど面白かったので
20:30 LibreOffice Community Survey - retrospective feedback :: LibreOffice Conference 2021 :: pretalx 誤解を恐れずに言うとぼくがLibOの活動を一時休止してそのまま(組織的にはいくつかのところから)辞めるきっかけになったのは、グローバルのメーリングリストでもなんかギスギスした議論が目立つようになってきて、それをコロナ禍でよわったぼくの気持ちが受け止めきれなかったからなので、LibOコミュニティとして現状をどう受け止めているかというのはちょっと気になります
22:00 A legendary bug reporter :: LibreOffice Conference 2021 :: pretalx よいバグレポートをしよう!とかそういう啓蒙は大事だけど、個人にフォーカスしてるのは面白いすね
22:30 Introduction to TDF Membership :: LibreOffice Conference 2021 :: pretalx 今んとこまだTDFメンバーに戻れるにふさわしい活動をできる自信はないですけどねえ……
23:00 Introduction to TDF Membership :: LibreOffice Conference 2021 :: pretalx プロジェクトの継続性・健康性(一部の人間が病みながら頑張る、とかじゃなくて)ってどうやって担保すればいいんですかねえ、と、ドロップアウト組としては気になる
23:30 Q&A Session with BoD and MC :: LibreOffice Conference 2021 :: pretalx 今のBoDはMinutes見る限りだとコミュニティからの質問に答えようと機会を設けているけどうまく活用されているように(残念ながら)見られないので、オンラインイベントならそこらへん変わるのかなあと
24:00] Closing Session, with closing address by Lothar Becker :: LibreOffice Conference 2021 :: pretalx クロージングですしね、見ないわけにはいかないでしょう!

ま、そんなわけで。気が向いたらTwitterでSpace作ったりして、そこで話しながらセッション聞いたりしてもいいかも(私と話したい人がいれば、ね)。

*1:私発注したの2週間前ぐらいなので、イベントには間に合わないけどねw。

*2:https://github.com/naruoga/jOpenDocument が進捗したらODFエコシステムに対してのなにがしかの貢献になるだろうとは思ってるけど、まーーーーったく進んでないもんね。モノグサはよくないね。

*3:とか、ビール飲みながらじゃないとやっぱ英語での雑談がつらい(特にぼくみたいなコミュ障は、アルコールの力を借りないとなかなか人に話しかけられなかったり)とか。

*4:厳密には、弊社にはたぶん全日本人の9割ぐらいが既に忘れているプレミアムフライデーという制度がまだ生きており、ただ在宅勤務化で金曜日だけ早く終わってもあんまりうれしくないという理由で数か月分をくっつけてお休みを増やす方向にしているのです。なので9/21、9/22はその休暇、9/24は有給取得奨励日ってわけ。ぼくは弊社の創立メンバーではあるけど組織運営には一バイトもタッチしてない平社員だけど(その方が嬉しい)、こうやって従業員の働きやすさに向き合ってくれている経営層には本当に感謝しております。ですよ。はい。

*5:&昼寝ができなくなる……のは、まあ、いいか ;)

jOpenDocumentを2021年にリブートしてみる その4:GitHub ActionsでJDKを振って自動テスト

前回の記事はこちら。

naruoga.hatenablog.com

やはり2021年にもなって、手元でテスト回したりするのは犯罪でしょう。普通にpushしたりPull-Req作ったりしたらビルドのチェックとテストぐらいはしたい。

ということで、恥ずかしながら今まで使ったことがないGitHub Actionsを使ってみることにしました。

とりあえずActions登録

今更なのですがQuick Startを読みます。

docs.github.com

で、実は今やってる作業は締め切りがある話で、めちゃくちゃ締め切り迫ってるので、真面目に調べてる暇ない!って感じで、 こういう付け焼刃ホントよくないんですけど、このリポジトリにサンプルがいっぱいあるよってことで即見に行きました。

github.com

はいはい、顧客が本当に必要になったものありました。Mavenでビルドするための情報。

github.com

さくさくパクりまして、 .github/workflows/mvn-build-actions.yml というファイルをこんな風に書きました*1

name: Java CI with Maven

on:
  push:
    branches: [ $default-branch ]
  pull_request:
    branches: [ $default-branch ]

jobs:
  build:

    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v2
    - name: Set up JDK 11
      uses: actions/setup-java@v2
      with:
        java-version: '11'
        distribution: 'adopt'
    - name: Build with Maven
      run: mvn -B package --file pom.xml

で、こいつを master ブランチに入れて、push時のトリガを強制的にかけるために

touch foobar
git add foobar
git commit -m "GitHub Actions test"
git push

とかやったんですが動かない……なんぞ? なんかスキーマの書き間違い? でもサンプルのコピーだしなあ。

Actionsがトリガされない問題のチェック

Actionsの画面を見ると、手動実行のUIっぽい奴も特に存在しない……ううむ。

これは調べてみたら、

docs.github.com

ちゃんと答えが書いてあって、 workflow_dispatch ってトリガを追加すればいいらしいですね。で、こんな感じにした:

on:
  workflow_dispatch:
  push:
    branches: [ $default-branch ]
  pull_request:
    branches: [ $default-branch ]

ら、手動実行のボタンが出てきました。よしよし。ということはスキーマが全然違ってて認識できてないみたいなことはないらしい。

やれやれということで手動で実行してみたら、一回目は

Error:  Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:2.12.4:test (default-test) on project jOpenDocunentNg: Execution default-test of goal org.apache.maven.plugins:maven-surefire-plugin:2.12.4:test failed: Plugin org.apache.maven.plugins:maven-surefire-plugin:2.12.4 or one of its dependencies could not be resolved: Could not transfer artifact org.apache.maven.shared:maven-common-artifact-filters:jar:1.3 from/to central (https://repo.maven.apache.org/maven2): transfer failed for https://repo.maven.apache.org/maven2/org/apache/maven/shared/maven-common-artifact-filters/1.3/maven-common-artifact-filters-1.3.jar: Connection reset -> [Help 1]

とかなんとか言われて、えっ、手元ではビルドできてるんだけどな……なんでや……ってなったのですが、 ダメモトでもっかい再実行したらうまく行って、あとはずっと成功してます。 なんじゃそりゃ……と思いますが、まあ、いいでしょう。

それとは別にいくつかのサンプル見たら、そもそも push とか pull_requestbranch 指定してないのが普通っぽいので、それを取り除いて

on:
  workflow_dispatch:
  push:
  pull_request:

こうしたら、普通に push した場合でもActionsがキックされるようになりました。めでたしめでたし。

複数のJDKでビルドする

こういうときってジョブを割るのがいいのかActionを割るのがいいのか、たぶんちゃんとどこかにどうすればいいってプラクティスがあるんでしょうけど、 前述のように時間がない中付け焼刃でやってるので、雑にActionを割りました。 こういうときも共通部分をどこかに記述して差分(今回の場合はJDKのバージョン)だけを記述する方法が絶対あると思うのですが、 それはあとで考えるとして、いったんはJDK11側のファイルはこんな感じにしました。

name: Build with JDK11

on:
  workflow_dispatch:
  push:
  pull_request:

jobs:
  build-on-jdk11:

    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v2
      - name: Set up JDK 11
        uses: actions/setup-java@v2
        with:
          distribution: 'adopt'
          java-version: '11'
      - name: Build with Maven
        run: mvn -B package --file pom.xml

JDK8のファイルは11って書いてあるところが8ってなってるだけです……お恥ずかしい。

まあでも、いちおうこうやって二つ並んで、テストがそれぞれ走るようになりました。よかったよかった。

f:id:naruoga:20210716182138p:plain
JDK8とJDK11の両方でCIできるようになった

テストレポートがGitHubの画面から見たい

ここまででまあ一応「pushやPRのたびに自動テストをする」目的は達したんですが、Jenkins + JUnit プラグインを使ってた人間としてはやっぱり非常に寂しい。 ダッシュボードの上からテスト結果が見たいなあと思って、雑にググったらこういうプラグインがヒットしました。

github.com

で、各yamlファイルにこんな感じで書いてみました。

    steps:
      - uses: actions/checkout@v2
      - name: Set up JDK 11
        uses: actions/setup-java@v2
        with:
          distribution: 'adopt'
          java-version: '11'
      - name: Build with Maven
        run: mvn -B package --file pom.xml
      - name: Publish Test Report
        if: ${{ always() }}
        uses: scacap/action-surefire-report@v1
        with:
          check_name: JDK11 result

結果は……ちょっと期待と違って、

f:id:naruoga:20210716182649p:plain
片方のActionに両方の結果が出ちゃう

こんなふうに、片方のActionに両方の結果が出ちゃってます。中身もこんな感じで、ちょっと寂しい。

f:id:naruoga:20210716182822p:plain
履歴とかはなくてその時の結果の数しか見られない

Failしたときの結果も見てみたいけど、このプラグインの設定をもっと詰めるか、ほかのプラグインを探すかも含め、後日ですねー。

READMEにバッジをはる

つまらないことですがCIの結果をREADMEにバッジとして貼ると、なんか今風じゃないですか。ので貼ることにしました。

それぞれのActionの画面の右上の「…」ボタンを押して、「Create status badge」を押すと、

f:id:naruoga:20210716183133p:plain
メニューからバッジ作成

こんなダイアログが出てきて、README貼り付け用Markdownスニペットが得られます。

f:id:naruoga:20210716183252p:plain
バッジのMarkdown記法が得られる

これをREADMEにぺったんすると、

f:id:naruoga:20210716184021p:plain
バッジが並んで今風(そうか?

これでなんかモダンな開発をしているような雰囲気を醸し出すことができた……かな?

まあそんなわけで、まだまだやり残したことはありますが(というかまだ目的全然果たせてないですが)今回の短期集中連載はここまで。

今後の宿題としては:

  • XMLのValidatorをちゃんと動かす(最優先)
  • マトモなサンプルでちゃんと動くかを確認する(具体的には私の所属先のツール)
  • テストをきれいに直す
  • 会社名義でMaven Centralにpublishする
  • ODF 1.3対応をする
  • 下回り(ODF操作部分)を独自実装ではなくODF Toolkitに乗り換え

あたりかなー。協力者も募集ですよ。

*1:今回、JAR配布の予定はないので -B test でも十分なんですけど、まあ、もしかしたらするかもしれないし。

jOpenDocumentを2021年にリブートしてみる その3:落ちてるテストを成功させる

naruoga.hatenablog.com

のつづき。おつむの出来がしょぼいのでXMLスキーマValidationがコケてる理由がわからないため、ほかのテストのFailを潰していきます。

幸いなことにValidatorはテスト内部でしか使っていないので、これでもアプリ側から使う分には問題ない……はず*1

落ちてるテストを拾う

でも、実はValidation以外で落ちてるテストって二つだけなんですよねえ……。

f:id:naruoga:20210716112037p:plain
落ちてるテストは日付と時刻関係だけ

しかも落ち方が……あやしい。これはテストのGlobalization対応が不十分なんじゃないか?

f:id:naruoga:20210716112213p:plain
落ち方がいかにも怪しい

DataStyleTest.testFormat() を直す

まずは簡単そうなほうから。

junit.framework.ComparisonFailure: 
Expected :0,500
Actual   :0.500

これは絶対、Locale関係だろ……と思うので、見てみましょう。

落ちてるところまでコードを引用するとこんな感じ。

    public void testFormat() throws Exception {
        final ODPackage pkg = new ODPackage(this.getClass().getResourceAsStream("/cellFormat.ods"));
        final Sheet sheet = pkg.getSpreadSheet().getSheet(0);

        // * test that the framework format as OpenOffice
        final int lastRow = sheet.getCurrentRegion(0, 0).getEndPoint().y;
        for (int i = 0; i <= lastRow; i++) {
            final MutableCell<SpreadSheet> cell = sheet.getCellAt(0, i);
            final String byOO = cell.getTextValue();
            final ODValueType origType = cell.getValueType();
            final Object cellValue = cell.getValue();
            // like OO, we should allow any value without removing the data style
            cell.setValue("string");
            cell.setValue(12.3);
            cell.setValue(new Date());
            cell.setValue(true);
            cell.clearValue();
            if (origType != null)
                cell.setValue(cellValue, origType, false, false);
            assertEquals(byOO, cell.getTextValue()); // <---- ここで落ちてる
            assertEquals(origType, cell.getValueType());
        }

こら! テストコードで for 文書くなって教わらなかったのか! と怒りたいところですがそれはおいといて。

まずは読み込んでるファイルは cellFormat.ods というCalcファイルですね。 中身はこんな感じ。

f:id:naruoga:20210716130933p:plain
cellFormat.odsの内容

で、この1列目を各行ぐるぐる回ってセルの各要素のテキスト文字列を取り出した後、セルに書式指定を無視していろいろ値をセットして(表計算ソフトでは例えば数値書式のセルに文字列を突っ込んだりもできるので)、元の値と書式をセットしなおして結果が変わらないかを見る……って、いうのがテストの意図っぽいですね。

そして、expected が 0,500 で actual が 0.500 なので、元のドキュメントの標準言語はまあ、想像したとおりフランス語なので小数点は , で、だから取り出したセルの値は 0,500 で、cell.setValue() したときには私の動いてる環境の標準ロケールだから日本語で小数点が変わっちゃう……って、ことじゃないかな?

ん? じゃあ、これ、テストの問題じゃなくてプロダクトコードの問題じゃないですかね……。

ともかく、問題になってるのは2行目(セルの表記的には (0,1))なので、そこに条件付きブレークポイントを貼って調べますと、……あれ?

f:id:naruoga:20210716134246p:plain
contentがTextで0,500ってなってる!

テキストじゃん!

あーでも、attributes はこうなのか……。

f:id:naruoga:20210716134601p:plain
attributeでは確かにtype:floatになってる

ふむふむ、ODFの仕様をちゃんと読んでないことがバレバレなのですが、どうやらODFでは

  • セルに文字列で表示するための要素( cell.localElement.content[0]
  • セルに実際に入っている値( cell.attributes

を二重管理してて、前者は少なくともLibreOffice上では使われてない(セルの値と書式から動的に表示結果を作ってる)ってことなのでしょうか……。

で、

cell.setValue(cellValue, origType, false, false);

すると、「ドキュメント」のではなく「セル」の言語が使われて、0.500 になっちゃう、ってこと……みたいです。

……いや、違うかな。違いそう。何が違うかというと

「ドキュメント」のではなく「セル」の言語が使われて

です。というのはなぜかというと、cell.setValue() の実装をおいかけてくと、最終的に NumberStyle.format() ってメソッドに来るんだけど、

    @Override
    public String format(Object o, CellStyle defaultStyle, boolean lenient) {
        final Number n = (Number) o;
        final Namespace numberNS = this.getElement().getNamespace();
        final StringBuilder sb = new StringBuilder();
        @SuppressWarnings("unchecked")
        final List<Element> children = this.getElement().getChildren();
        for (final Element elem : children) {
            if (elem.getNamespace().equals(numberNS)) {
                if (elem.getName().equals("text")) {
                    sb.append(elem.getText());
                } else if (elem.getName().equals("number") || elem.getName().equals("scientific-number")) {
                    sb.append(formatNumberOrScientificNumber(elem, n, defaultStyle));
                } else if (elem.getName().equals("fraction")) {
                    // TODO fractions
                    reportError("Fractions not supported", lenient);
                    sb.append(MutableCell.formatNumber(n, defaultStyle));
                }
            }
        }
        return sb.toString();
    }
}

この中で呼ばれている formatNumberOrScientificNumber(elem, n, defaultStyle)defaultStyle に保持されてるセルのロケール情報見てないっぽい……ですね。 なのでこれはプラダクトコードの問題。

だけど、LibreOfficeというアプリケーションで使うことだけを考えると、テキストは付帯情報であって実際の値やフォーマット情報は適切に扱われているので、ここに不具合があってもすごくシリアスではないし、まあいいかなあという……FIXMEフラグだけつけときますか。

こういうこと考えると下周り(ODFを実際に操作する部分)をごっそりモダンなライブラリ……例えば:

github.com

に差し替えたくなりますね。

ということで乱暴ながら、

  • testFormat() の今落ちてる assert はコメントアウト
  • それ以外の assert は、期待値が即値なのが問題なのでいったん String.format() を利用するように書き換え(将来はセルのロケールに従った動きをしないとだめですが)

としました。

DataStyleTest.testDays() をどうするか

先ほども書いたけど、このテストでは期待値と実際の値が1時間ずれてるというもの。

Expected :27/10/2013 09:30:00
Actual   :27/10/2013 10:30:00

1時間ってことはタイムゾーンというか夏時間(DST)がおかしいんじゃない?と思うんですが、なんかコード見るとまさに夏時間向けの処理がごちゃごちゃと書いてある……。 これを直さなきゃいけないのかー。

と、思いましたが、 このテスト、ちらっと見た感じだと jOpenDocument 自体のテストをしてるように読めないんですよねー。

なので、えいっと無視することにしました。

mavenでdependsしてるのは JUnit4 なので、 @Ignore って書くだけじゃん、と思ってそう書いたら 「これはJUnit3形式のテストだから @Ignore じゃ無視されなくて、メソッド名を test で始まらないように _test ってすればいいよ」とIntellij IDEA君に教えてもらいました。 なんと、まあ。

JUni4 形式に移行することもIntellij IDEAの機能でできるらしいのですが(優秀)、 個人的には将来はJUnit5でもちょっとましなテストを書こうと思ってるんで*2 、 雑に _ をつけて無視する方法にしました。

動かないXMLのバリデーション

ここまで来たら毒皿なので、ここらへんも無視することにしちゃいましょう。

主にバリデーションがテストしたい部分で、これを通さないと落ちるテスト

  • OOXMLTest.testValidation()
  • SheetTest.testCreate()

についてはやはりIgnore(FIXMEつけて)。

それ以外のテストで、テストメソッド内にて SheetTest.assertValid() を呼んでいるテストについては、システムプロパティ jopendocument.test.validationtrue を指定しない限り無視するようにしました。 これも後々は直すつもりですが、まずは先に進みたいので。

ま、そんなわけで、テストは全部バスするようになりました*3

次はCI的なところをやっていきます。

*1:もちろん、スキーマをぶっ壊す可能性があるようなODF操作ライブラリとか怖くて使いたくないので、いずれは直しますよ、もちろん。ただ、優先度をいったん置くってことです。

*2:for文書くな、一つのテストメソッドで延々違うassertを繰り返すんじゃない、的な意味で。

*3:これは品質を満たしているという意味ではないので、まったくよろしくないけど。