# 通知設計書 12-MultiLinePasteDialog

## 概要

複数行テキストをクリップボードからペーストしようとした際に、意図しないコマンド実行を防止するための警告ダイアログ（ContentDialog）の設計書である。

### 本通知の処理概要

MultiLinePasteDialogは、ユーザーがクリップボードから複数行のテキストをターミナルにペーストしようとした際に表示される警告ダイアログである。

**業務上の目的・背景**：ターミナルシェルでは改行文字がコマンドの区切りとして解釈されるため、複数行テキストをペーストすると、ユーザーが意図しないコマンドが自動的に実行される危険性がある。特にブラケットペースト（bracketed paste）をサポートしていないシェルでは、攻撃者が悪意のあるコマンドを含むテキストをクリップボードに仕込み、ユーザーの気づかないうちに実行させる攻撃（GH#13014）が可能である。このダイアログは、そうした意図しないコマンド実行を防止するための安全機構として導入されている。

**通知の送信タイミング**：`_PasteFromClipboardHandler`メソッド内で、クリップボードテキストに改行文字（`\r`または`\n`）が含まれ、かつ`WarnAboutMultiLinePaste`設定がAlwaysまたはAutomatic（bracketed paste非対応時）の場合に表示される。

**通知の受信者**：アプリケーションを操作中のユーザー本人。モーダルダイアログとして表示され、ペースト操作を一時的にブロックする。

**通知内容の概要**：「Warning」というタイトルとともに、複数行テキストのペーストによるコマンド実行の危険性を警告するメッセージが表示される。加えて、クリップボードの内容がプレビュー表示される（1024文字を超える場合は省略される）。

**期待されるアクション**：ユーザーはクリップボードの内容を確認した上で、「Paste anyway」を選択してペーストを続行するか、「Cancel」を選択してペーストをキャンセルする。

## 通知種別

アプリ内通知（モーダルダイアログ / ContentDialog）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（モーダル、UIスレッドで表示） |
| 優先度 | 高 |
| リトライ | 無し |

### 送信先決定ロジック

アプリケーション操作中のユーザーに対して直接表示される。送信先の決定ロジックは存在しない。

## 通知テンプレート

### ダイアログ構成

| 項目 | 内容 |
|-----|------|
| タイトル | Warning |
| 警告テキスト | You are about to paste text that contains multiple lines. If you paste this text into your shell, it may result in the unexpected execution of commands. Do you wish to continue? |
| クリップボードヘッダー | Clipboard contents (preview): |
| クリップボード内容 | {ClipboardText}（動的） |
| プライマリボタン | Paste anyway |
| クローズボタン | Cancel |
| デフォルトボタン | Primary（Paste anyway） |

### 本文テンプレート

```
Title: Warning
Content:
  You are about to paste text that contains multiple lines.
  If you paste this text into your shell, it may result in
  the unexpected execution of commands. Do you wish to continue?

  Clipboard contents (preview):
  [クリップボードテキスト（ScrollViewer内、最大高さ100px）]

[Paste anyway]  [Cancel]
```

### 添付ファイル

該当なし。

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| ClipboardText | クリップボードの内容プレビュー（1024文字超の場合は512文字+省略記号） | clipboard::read()からの取得値 | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| 画面操作 | PasteFromClipboardイベント | クリップボードテキストに改行文字が含まれ、かつWarnAboutMultiLinePaste設定が有効 | ユーザーがCtrl+Vやコンテキストメニューからペースト実行時 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| WarnAboutMultiLinePaste設定がNever | グローバル設定で複数行ペースト警告が無効の場合 |
| Automatic設定かつbracketedPaste対応 | ブラケットペーストが有効なシェルの場合はAutomatic設定時にスキップ |
| テキストに改行が含まれない | 改行文字（`\r`/`\n`）が見つからない場合 |
| テキストが空 | クリップボードが空の場合 |
| 他のダイアログが表示中 | `_ShowDialogHelper`による排他制御 |
| LargePaste警告が優先される場合 | warnMultiLineとwarnLargeTextが両方trueの場合はwarnMultiLineが優先 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[PasteFromClipboardイベント発生] --> B[クリップボードテキスト取得]
    B --> C{TrimPaste設定?}
    C -->|Yes| D[テキストをトリム]
    C -->|No| E[そのまま]
    D --> F{テキストは空?}
    E --> F
    F -->|Yes| G[処理終了]
    F -->|No| H{WarnAboutMultiLinePaste設定}
    H -->|Always| I[warnMultiLine=true]
    H -->|Automatic| J{bracketedPaste対応?}
    H -->|Never| K[warnMultiLine=false]
    J -->|Yes| K
    J -->|No| I
    I --> L{テキストに改行あり?}
    L -->|No| K
    L -->|Yes| M[MultiLinePasteDialog表示]
    M --> N{ユーザーの選択}
    N -->|Paste anyway| O[テキストをペースト]
    N -->|Cancel| G
    K --> P{LargePaste条件?}
    P -->|Yes| Q[LargePasteDialog表示]
    P -->|No| O
```

## データベース参照・更新仕様

### 参照テーブル一覧

該当なし。本通知はメモリ上の状態とクリップボードのみを参照する。

### 更新テーブル一覧

該当なし。

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| クリップボード読み取り失敗 | OpenClipboardが失敗した場合 | リトライ付きのOpenClipboard（最大10回、指数バックオフ） |
| ダイアログ表示失敗 | 他のダイアログが既に表示中 | `_ShowDialogHelper`が処理をスキップ |
| UIスレッド切り替え失敗 | ウィンドウが既に破棄されている場合 | `weak_ref`の`get()`がnullptrを返し、処理が中止される |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 0（ダイアログ表示に対するリトライなし） |
| リトライ間隔 | - |
| リトライ対象エラー | - |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 制限 | 同時に1つのContentDialogのみ表示可能 |

### 配信時間帯

制限なし。ユーザー操作に応じて即時表示される。

## セキュリティ考慮事項

- クリップボードの内容がダイアログ内にプレビュー表示されるため、機密情報がクリップボードに含まれている場合は画面上に表示される。ただし、ダイアログが閉じられた後に`ClipboardText().Text({})`でテキストがクリアされる（TerminalPage.cpp 行3036）。
- クリップボードテキストの表示は1024文字に制限されており、サロゲートペアの途中で切断されないよう`til::utf16_iterate_prev`が使用されている。
- 本ダイアログは、悪意のあるペーストインジェクション攻撃（GH#13014）に対する防御機構として機能する。

## 備考

- `x:Load="False"`により遅延読み込みが適用されている。
- クリップボードプレビューはScrollViewer内に配置され、MaxHeight=100pxに制限されている。
- クリップボードテキストのフォントは`Cascadia Mono`が使用される。
- `minimumSizeForWarning`（5KiB）を超えるテキストについては、LargePasteDialogが優先的に表示される場合がある。ただし、warnMultiLineがtrueの場合はMultiLinePasteDialogが優先される。

---

## コードリーディングガイド

本通知を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

まず、ダイアログのUI定義、関連する設定値、文字列リソースを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | TerminalPage.xaml | `src/cascadia/TerminalApp/TerminalPage.xaml` | 行107-125: MultiLinePasteDialogのContentDialog定義。StackPanel内のTextBlock、ScrollViewer、ClipboardTextの構成 |
| 1-2 | Resources.resw | `src/cascadia/TerminalApp/Resources/en-US/Resources.resw` | 行541-552: ダイアログのタイトル、警告テキスト、ボタンテキスト、クリップボードヘッダーの文字列リソース |
| 1-3 | GlobalAppSettings.idl | `src/cascadia/TerminalSettingsModel/GlobalAppSettings.idl` | WarnAboutMultiLinePaste設定の定義 |

**読解のコツ**: `x:Uid="MultiLinePasteDialog"`によりダイアログのTitle/PrimaryButtonText/CloseButtonTextがリソースから自動バインドされ、`x:Uid="MultiLineWarningText"`と`x:Uid="ClipboardTextHeader"`により各TextBlockのTextプロパティがバインドされる。

#### Step 2: エントリーポイントを理解する

処理の起点となるペーストハンドラを特定する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | TerminalPage.cpp | `src/cascadia/TerminalApp/TerminalPage.cpp` | 行2960-3053: `_PasteFromClipboardHandler`メソッド。クリップボード読み取り、条件判定、ダイアログ表示の全フロー |

**主要処理フロー**:
1. **行2961**: `clipboard::read()`でクリップボードテキストを取得
2. **行2974-2988**: `WarnAboutMultiLinePaste`設定に基づくwarnMultiLine判定
3. **行2991-2994**: テキスト内の改行文字チェック
4. **行2997-2998**: 5KiB超のテキストに対するwarnLargeText判定
5. **行3007**: `FindName(L"MultiLinePasteDialog")`でXAMLオブジェクトをロード
6. **行3020**: `ClipboardText().Text()`でプレビューテキストを設定
7. **行3028**: `_ShowMultiLinePasteWarningDialog()`でダイアログ表示

#### Step 3: ダイアログ表示処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | TerminalPage.cpp | `src/cascadia/TerminalApp/TerminalPage.cpp` | 行925-928: `_ShowMultiLinePasteWarningDialog`メソッド |
| 3-2 | TerminalPage.h | `src/cascadia/TerminalApp/TerminalPage.h` | 行307: メソッド宣言 |

### プログラム呼び出し階層図

```
TermControl::PasteTextFromClipboard
    |
    +-- PasteFromClipboard.raise() イベント
            |
            +-- TerminalPage::_PasteFromClipboardHandler (TerminalPage.cpp:2940付近)
                    |
                    +-- clipboard::read() (TerminalPage.cpp:2961)
                    +-- WarnAboutMultiLinePaste判定 (行2974-2988)
                    +-- 改行文字チェック (行2991-2994)
                    +-- FindName(L"MultiLinePasteDialog") (行3007)
                    +-- ClipboardText().Text() 設定 (行3020)
                    +-- _ShowMultiLinePasteWarningDialog() (行3028)
                    |       |
                    |       +-- _ShowDialogHelper(L"MultiLinePasteDialog")
                    |
                    +-- eventArgs.HandleClipboardData() (行3051)
```

### データフロー図

```
[入力]                         [処理]                               [出力]

クリップボード           TerminalPage.cpp
テキスト        ------>  clipboard::read()
                             |
                        WarnAboutMultiLinePaste          MultiLinePasteDialog
                        設定値チェック         ------>   モーダル表示
                             |                            (プレビュー付き)
                        改行文字検出                         |
                             |                          ContentDialogResult
                        テキスト長さ            <------  (Primary / Close)
                        チェック                             |
                             |                          Primary -> HandleClipboardData()
                        プレビュー生成                   Close -> 中止
                        (1024文字制限)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| TerminalPage.xaml | `src/cascadia/TerminalApp/TerminalPage.xaml` | XAML定義 | MultiLinePasteDialogのUI定義（行107-125） |
| TerminalPage.cpp | `src/cascadia/TerminalApp/TerminalPage.cpp` | ソース | ペースト処理フロー・ダイアログ表示ロジック |
| TerminalPage.h | `src/cascadia/TerminalApp/TerminalPage.h` | ヘッダー | メソッド宣言 |
| Resources.resw | `src/cascadia/TerminalApp/Resources/en-US/Resources.resw` | リソース | 文字列リソース定義（行541-552, 702-703） |
| GlobalAppSettings.idl | `src/cascadia/TerminalSettingsModel/GlobalAppSettings.idl` | IDL定義 | WarnAboutMultiLinePaste設定の定義 |
| MTSMSettings.h | `src/cascadia/TerminalSettingsModel/MTSMSettings.h` | ヘッダー | 設定マクロ定義 |
