外部連携・パッケージ

Ourin — NAR Double‑Click Installer 仕様書(NAR-INSTALL/1.0M, macOS, ToC付き)

開発版の資料です。仕様・設計の記述には実装予定や過去の記述を含みます。現在の対応範囲は対応状況・既知の問題と合わせて確認してください。配布中のアプリへの収録状況はリリースノートをご確認ください。 対応状況 · 既知の問題

Status: Draft
Updated: 2025-07-28 20:07 UTC+09:00
Target: macOS 10.15+(Catalina 以降), Universal 2(arm64 / x86_64)

目的:拡張子 .nar(実体は ZIP アーカイブ)をダブルクリックまたは「このAppで開く」で Ourin が受け取り、install.txt の語彙に従って ghost / balloon / shell / plugin / package を所定ディレクトリに安全に展開・登録するための規格。SSP の慣行(D&D/ダブルクリック)を踏襲しつつ、UTF‑8 を既定・CP932 受理・Zip Slip防止を必須とする。


0. 用語・前提

  • .nar:Ukagaka 配布パッケージ。実体は ZIP。
  • install.txt:アーカイブ最上位に置かれるインストール定義(type/directory/*.directory ほか)。
  • Ourin 標準設置先:~/Library/Application Support/Ourin/ 配下。
  • 文字コード:UTF‑8 既定、CP932 受理(内部は UTF‑8 正規化)。

1. 適用範囲と非目標

  • 対象:Finder のダブルクリック/「このAppで開く」/Ourin ウィンドウへのD&Dでのインストール。
  • 非目標:Windows のバイナリ互換再現や、Install UI の完全模倣。プロトコル(install.txt の語彙)互換を重視。

2. 依存仕様と参考

  • Apple UTI/Document Types:.nar を custom UTI としてエクスポートし、public.zip-archive に準拠。CFBundleDocumentTypes で関連付け、App は open handler を実装する。
  • NSApplicationDelegate:application(_:openFiles:) / application(_:open:) で URL/パス受理。
  • Ukadoc:install.txt / 配布 / ネットワーク更新などの運用慣行に準拠(updates2.dau/delete.txt/ドラッグ&ドロップ/ダブルクリック)。

3. 受付と関連付け(UTI/Document Types)

  • UTExportedTypeDeclarations に jp.ourin.nar を宣言し、UTTypeConformsTo = public.zip-archive、拡張子 nar を紐付ける。
  • CFBundleDocumentTypes に LSItemContentTypes = jp.ourin.nar を設定(Role は Viewer/Editor いずれでも可)。
  • 競合した場合の優先度は LSHandlerRank で調整。

4. 受け口(open handler)

  • App 起動時/起動中の両方で呼ばれるよう、NSApplicationDelegate.application(_:openFiles:)(複数)と application(_:open:)(URL)双方を実装。SwiftUI 構成でも AppKit デリゲートをブリッジ。

5. アーカイブ検証と文字コード判定

  • MIME/UTType で zip 互換を確認し、先頭レコードもチェック。
  • install.txt は UTF‑8 を優先して読む。失敗時は CP932 で再試行し、内部は UTF‑8 正規化。BOM・CRLF も受理。

6. install.txt の語彙(受理する要点)

  • 必須:type,<種別>/directory,<設置名>(supplement・package は directory 省略可)
  • 任意:accept,<識別名>、*.directory,<同梱名>(例:balloon.directory,MyBalloon)、*.source.directory など。
  • 推奨:charset,UTF-8 を先頭に明記。

6.1 type の受理値と設置先

type 値 受理される表記バリアント 設置先(<base> = ~/Documents/Ourin)
ghost — <base>/ghost/<directory>
balloon — <base>/balloon/<directory>
shell — <base>/ghost/<accept>/shell/<directory>
plugin — <base>/plugin/<directory>
headline — <base>/headline/<directory>
package — <base>/package/<directory>
supplement — <base>/ghost/<accept>/ (directory は任意)
calendar/skin calendar skin、calendarskin <base>/calendar/skin/<directory>
calendar/plugin calendar plugin、calendarplugin <base>/calendar/plugin/<directory>
calendar — (skin/plugin 区別が無い旧形式) <base>/calendar/<directory>
language — <base>/language/<directory>

calendar/skin・calendar/plugin はいずれも大文字小文字・スペース・スラッシュの有無を問わず受理される(InstallTxtParser.swift → OurinPaths.installTarget())。旧形式 calendar(区別なし)は後方互換のため維持。language は UKADOC install.txt の language 種別に対応。

shell および supplement は accept フィールドで対象ゴーストのディレクトリ名を指定する必要がある。未指定時は installTxtMissingKey("accept") エラー。

6.2 refreshundeletemask フィールド

refreshundeletemask,ファイル名パターン1:ファイル名パターン2:...
  • UKADOC 準拠の区切り文字は コロン(:)。
  • 既存データとの互換性のため カンマ(,) も許容する(InstallTxtParser.swift:106)。
  • 値は正規表現パターンの集合として refreshUndeleteMask: [String] に格納される。
  • refresh,1 と組み合わせて使用する。refresh,1 が指定されたとき、マスクに一致するパスはインストール前削除から除外される。

例:

refresh,1
refreshundeletemask,savedata:*.sav:userconfig.txt

上記ではコロン区切り 3 要素(savedata、*.sav、userconfig.txt)として解析される。

7. 展開ポリシー(安全な unzip と配置)

  • 一時ディレクトリに安全に解凍→ install.txt を解釈 → 設置先にコピー。
  • 除外:__MACOSX/、.DS_Store、Thumbs.db は自動除外。
  • ケース整合:ファイル名の大小を厳密に扱い、重複衝突は警告。

8. 競合と更新(accept/delete/homeurl)

  • 既存 {directory} がある場合:accept 一致なら上書き更新、相違なら別名提案。
  • delete.txt があれば不要資産を削除。更新配布は homeurl + updates2.dau に追従。

9. ログ・失敗時の UX

  • 主要フェーズ(検証/解析/展開/事後処理)を OSLog に記録。
  • 代表エラー:InstallTxtMissing、UnsupportedType、ZipSlipDetected、NameConflict、DecodeFailed(sjis)。

10. セキュリティ(Zip Slip / 隔離属性)

  • Zip Slip:展開前にパス正規化し、../絶対パス/シンボリックリンクによるターゲット外書込みを拒否。
  • ダウンロード由来の隔離属性はユーザ操作起点(ダブルクリック/ドロップ)で正規フローと見做す。

11. 互換性メモ(Windows/大小・改行差分)

  • Windows 既存配布は Shift_JIS/\\ 区切りのまま入ってくることがある。Ourin は 入力受理し、内部を UTF‑8/UNIX パスに正規化する。
  • 改行は CRLF/LF どちらも受理。

付録A. Info.plist 宣言例

<!-- Info.plist 抜粋:UTI と Document Types -->
<key>UTExportedTypeDeclarations</key>
<array>
  <dict>
    <key>UTTypeIdentifier</key><string>jp.ourin.nar</string>
    <key>UTTypeDescription</key><string>Ukagaka NAR</string>
    <key>UTTypeConformsTo</key>
    <array><string>public.zip-archive</string></array>
    <key>UTTypeTagSpecification</key>
    <dict>
      <key>public.filename-extension</key><array><string>nar</string></array>
      <key>public.mime-type</key><string>application/x-ukagaka-nar</string>
    </dict>
  </dict>
</array>

<key>CFBundleDocumentTypes</key>
<array>
  <dict>
    <key>CFBundleTypeName</key><string>Ukagaka NAR</string>
    <key>LSItemContentTypes</key>
    <array><string>jp.ourin.nar</string></array>
    <key>CFBundleTypeRole</key><string>Viewer</string>
  </dict>
</array>

付録B. 成功/失敗フロー

Finder(.nar) → Launch Services → Ourin(app open)
 → open handler
   → validate(zip) OK? → read install.txt → parse {type,directory,...}
   → resolve install path
   → safeExtract → copy/merge → post steps(readme/terms, switch)
   → success toast

NG:
  - no install.txt → error: InstallTxtMissing
  - unsupported type → error: UnsupportedType
  - zip slip → error: ZipSlipDetected
  - directory conflict → user prompt(rename/overwrite)

付録C. サンプル構成

OURIN_NAR_INSTALL_1_0M/
  NAR_INSTALL_1.0M_SPEC.md
  NAR_INSTALL_1.0M_PLAN.md
  sample/
    Sources/OurinNarInstallerSample/
      AppDelegate.swift
      SampleNarInstaller.swift
      InstallTxtParser.swift
      ZipUtil.swift
      Paths.swift
    Info.plist (example)

実装状況(Implementation Status)

更新日: 2025-10-20

Ourin における実装

  • [x] NAR ファイルの関連付け: Info.plist にて .nar の UTI 宣言と関連付けを実装済み
  • [x] ダブルクリック/D&D 受付: AppDelegate での openFiles ハンドラ実装済み
  • [x] ZIP 展開: ZipUtil.swift にて実装済み
  • [x] install.txt 解析: InstallTxtParser.swift にて実装済み
  • [x] 文字コード自動検出: UTF-8 および CP932 の自動検出を実装済み
  • [x] Zip Slip 防止: ZipUtil.secureCopyTree() にて実装済み
  • [x] 型別インストール: OurinPaths.installTarget() にて ghost/balloon/shell/supplement/plugin/headline/package/calendar/calendar/skin/calendar/plugin/language の配置先解決を実装済み
  • [x] 基本的なエラー処理: インストールエラーの検出と報告を実装済み
  • [ ] 競合時の UI: accept/delete/homeurl の完全な UI 実装は未完了
  • [x] 更新機能: updates2.dau / updates.txt / update.txt の取得、Version 2/3形式の解析、MD5検証、増分ファイル/NAR適用を実装済み。ベースウェア更新はステージング .app へ適用する。
  • [x] 削除機能: ネットワーク更新時の delete.txt 取得・安全な相対パス削除を実装済み(パッケージ内の削除指示にも対応)。

実装済みの機能

  1. パッケージ受付 - Finder からのダブルクリック - Ourin ウィンドウへのドラッグ&ドロップ - 「このアプリケーションで開く」からの起動

  2. 展開と検証 - ZIP ヘッダの検証(PK マジックナンバー) - 一時ディレクトリへの安全な展開 - install.txt の存在確認

  3. install.txt 解析 - type フィールドの解析(ghost, balloon, shell, supplement, plugin, headline, package, calendar/skin, calendar/plugin, calendar, language) - directory および *.directory の解析 - UTF-8/CP932 の自動判定とデコード

  4. 安全な配置 - Zip Slip 攻撃の防止(親ディレクトリへの脱出防止) - ~/Library/Application Support/Ourin/ 配下への配置 - 型別のディレクトリ振り分け(ghost, balloon, shell, supplement, plugin, headline, package, calendar/skin, calendar/plugin, calendar, language)

  5. エラーハンドリング - NAR 形式エラー(NotZip) - install.txt 欠落(InstallTxtNotFound) - デコードエラー(InstallTxtDecodeFailed) - 未対応型(UnsupportedType) - Zip Slip 検出(ZipSlipDetected) - ディレクトリ衝突(DirectoryConflict)

未実装の機能

  1. 競合解決 UI - accept フィールドによる上書き確認ダイアログ - ユーザーへのリネーム/上書き選択肢の提示

  2. 削除処理 - アンインストール時のファイル削除 UI

  3. 高度な機能 - README/利用規約の表示 - インストール後の自動切り替え - homeurl の処理

ソースコード位置

  • Ourin/NarInstall/LocalNarInstaller.swift: インストーラ本体
  • Ourin/NarInstall/InstallTxtParser.swift: install.txt 解析
  • Ourin/NarInstall/ZipUtil.swift: ZIP 展開ユーティリティ
  • Ourin/NarInstall/Paths.swift: パス解決(OurinPaths)
  • Ourin/NarInstall/NarInstallViewModel.swift: UI ViewModel
  • Ourin/NarInstall/NarInstallView.swift: SwiftUI インストール画面

変更履歴

  • 2026-08-14: updates2.dau / updates.txt のMD5検証付き増分更新と delete.txt の安全な取得・削除を実装。更新/削除パスのトラバーサル検査と回帰テストを追加。
  • 2026-06-28: §6.1 type 受理値テーブルを追加(calendar/skin、calendar/plugin、calendar、language を追記)。§6.2 refreshundeletemask フィールドの区切り文字仕様(コロン主・カンマ互換)を追記。実装状況の type 一覧を更新。
  • 2025-10-20: 実装状況セクションを追加
  • 2025-07-28 20:07 UTC+09:00: 初版(NAR-INSTALL/1.0M)。

出典と編集について

Ourin / Furin Lab・contributors。文書はCC BY-SA 4.0(第三者の個別表記を除く)。Web版は見出し・リンクの整備とローカルパスの一般化を行っています。更新基準日: 2026-10-30。

元資料: docs/NAR_INSTALL_1.0M_SPEC_ja-jp.md
ソース SHA-256: 0ddef35f601345850e5710100aa4a38c323894833eeec0af41f96c459717bfc2

ライセンス · 出典一覧 · 資料一覧に戻る