# 機能設計書 57-omz_urlencode

## 概要

本ドキュメントは、Oh My Zshの`omz_urlencode`関数の機能設計を記載する。この関数は、文字列をRFC 2396準拠でURLエンコードするユーティリティ関数である。

### 本機能の処理概要

`omz_urlencode`関数は、文字列をURLで安全に使用できる形式にエンコードする。RFC 2396に準拠したエスケープ処理を行い、オプションによって予約文字やマーク文字のエスケープも制御できる。

**業務上の目的・背景**：WebアプリケーションやCLIツールにおいて、URLに含める文字列を適切にエンコードする必要がある場面は頻繁にある。例えば、検索クエリ、ファイル名、認証情報などをURLに埋め込む際に、特殊文字が正しくエスケープされていないとURLが壊れたりセキュリティ問題を引き起こす可能性がある。この関数は、zshシェル環境で手軽にRFC準拠のURLエンコードを行う手段を提供する。

**機能の利用シーン**：
- シェルスクリプトでURLを組み立てる際に特殊文字をエスケープする場合
- curlやwgetで使用するURLのクエリパラメータをエンコードする場合
- ファイル名やパスをURLに埋め込む際にエスケープが必要な場合
- ターミナルから直接URLエンコードされた文字列を取得したい場合

**主要な処理内容**：
1. オプション解析（-r: 予約文字エスケープ、-m: マーク文字エスケープ、-P: スペースを%20に）
2. 入力文字列のエンコーディング変換（必要に応じてUTF-8に変換）
3. 文字ごとにエスケープ処理を実行
4. エンコードされた文字列を標準出力に出力

**関連システム・外部連携**：zsh/langinfoモジュール、iconvコマンドに依存。

**権限による制御**：特にロールによる制御はない。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | CLIユーティリティ関数のため関連画面なし |

## 機能種別

文字列変換 / エンコード処理 / ユーティリティ

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| -r | flag | No | 予約文字（;/?:@&=+$,）もエスケープする | なし |
| -m | flag | No | マーク文字（_.!~*'()-）もエスケープする | なし |
| -P | flag | No | スペースを+ではなく%20にエンコードする | なし |
| $@ (string) | string | Yes | エンコードする文字列 | なし |

### 入力データソース

コマンドライン引数として直接入力

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 標準出力 | string | URLエンコードされた文字列 |
| 戻り値 | integer | 0: 成功、非0: エラー（エンコーディング変換失敗等） |

### 出力先

- 標準出力（エンコードされた文字列）
- 標準エラー出力（エラーメッセージ）

## 処理フロー

### 処理シーケンス

```
1. オプション解析
   └─ zparseopts で -r, -m, -P オプションを解析
2. スペース処理方法決定
   └─ -P なし: スペースを + に変換
   └─ -P あり: スペースを %20 に変換
3. エンコーディング確認・変換
   └─ UTF-8以外の場合、iconvでUTF-8に変換
4. エスケープ対象文字の決定
   └─ -r オプションに応じて予約文字を含めるか決定
   └─ -m オプションに応じてマーク文字を含めるか決定
5. 文字ごとのエンコード処理
   └─ エスケープ不要文字はそのまま出力
   └─ スペースは + または %20 に変換
   └─ その他の文字は %XX 形式にエンコード
6. 結果出力
   └─ echo -E でエンコード結果を出力
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[オプション解析]
    B --> C{エンコーディングがUTF-8?}
    C -->|No| D[iconvでUTF-8に変換]
    C -->|Yes| E[エスケープ対象決定]
    D --> E
    E --> F[文字ループ開始]
    F --> G{エスケープ不要?}
    G -->|Yes| H[文字をそのまま追加]
    G -->|No| I{スペース?}
    I -->|Yes| J{-Pオプション?}
    J -->|Yes| K[%20を追加]
    J -->|No| L[+を追加]
    I -->|No| M[%XX形式でエンコード]
    H --> N{次の文字あり?}
    K --> N
    L --> N
    M --> N
    N -->|Yes| F
    N -->|No| O[結果を出力]
    O --> P[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-57-1 | RFC 2396準拠 | URLエンコードはRFC 2396に準拠する | 常時 |
| BR-57-2 | デフォルト動作 | 予約文字とマーク文字はデフォルトでエスケープしない | -r, -mオプションなし |
| BR-57-3 | スペース変換 | デフォルトでスペースは+に変換、-Pで%20に変換 | 常時 |
| BR-57-4 | UTF-8必須 | URLはUTF-8でエンコードされる必要がある | 常時 |
| BR-57-5 | 安全文字 | A-Z, a-z, 0-9 はエスケープしない | 常時 |

### 計算ロジック

エスケープ処理の主要ロジック：
```zsh
# エスケープ対象の決定
local dont_escape="[A-Za-z0-9"
if [[ -z $opts[(r)-r] ]]; then
    dont_escape+=$reserved  # ;/?:@&=+$,
fi
if [[ -z $opts[(r)-m] ]]; then
    dont_escape+=$mark      # _.!~*'()-
fi
dont_escape+="]"

# 文字ごとのエンコード
for (( i = 1; i <= ${#str}; ++i )); do
    byte="$str[i]"
    if [[ "$byte" =~ "$dont_escape" ]]; then
        url_str+="$byte"
    elif [[ "$byte" == " " && -n $spaces_as_plus ]]; then
        url_str+="+"
    else
        ord=$(( [##16] #byte ))
        url_str+="%$ord"
    fi
done
```

## データベース操作仕様

### 操作別データベース影響一覧

本機能はデータベース操作を行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 1 | エンコーディング変換エラー | iconvによるUTF-8変換に失敗 | 入力のエンコーディングを確認 |

### リトライ仕様

該当なし。

## トランザクション仕様

該当なし。

## パフォーマンス要件

文字列長に比例した線形時間（O(n)）。パフォーマンス向上のため、単一のprintfコールを使用し、ループ内でのサブシェル呼び出しを回避している。

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

- URLエンコードはセキュリティ対策の一部として使用されることがある
- 適切にエスケープされていない文字はインジェクション攻撃の原因となる可能性
- この関数はRFC 2396に準拠しているが、用途に応じて適切なオプションを選択する必要がある

## 備考

- omz_urldecode関数とペアで使用される
- Termux環境ではUTF-8以外のロケールが利用できないため、特別な処理がある
- Windows環境でのパフォーマンス最適化が含まれている

---

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

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

### 推奨読解順序

#### Step 1: 関数全体の構造を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | functions.zsh | `lib/functions.zsh` | omz_urlencode関数の定義（176-238行目） |

**読解のコツ**: この関数は比較的長いため、以下の順序で読むことを推奨：
1. コメント部分（152-175行目）で機能概要を把握
2. オプション解析部分（180-186行目）
3. エンコーディング変換部分（189-199行目）
4. エスケープ対象決定部分（204-216行目）
5. 文字ごとのエンコード処理（218-236行目）

#### Step 2: ドキュメントコメントを読む

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | functions.zsh | `lib/functions.zsh` | 関数上部のコメント（152-175行目） |

**ドキュメントコメントの内容**:
- RFC 2396準拠のURLエンコード
- 各オプション（-r, -m, -P）の説明
- 使用例

#### Step 3: オプション解析を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | functions.zsh | `lib/functions.zsh` | zparseoptsによるオプション解析（180-181行目） |

**主要処理フロー**:
- **180行目**: `local -a opts` - オプション配列の宣言
- **181行目**: `zparseopts -D -E -a opts r m P` - オプション解析

#### Step 4: エンコード処理の核心を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | functions.zsh | `lib/functions.zsh` | 文字ごとのエンコード処理（221-236行目） |

**主要処理フロー**:
- **221行目**: `for (( i = 1; i <= ${#str}; ++i ))` - 文字ループ
- **222行目**: `byte="$str[i]"` - 1文字取得
- **223行目**: エスケープ不要文字のチェック
- **226行目**: スペースの特別処理
- **232行目**: `ord=$(( [##16] #byte ))` - 文字コードを16進数に変換
- **233行目**: `url_str+="%$ord"` - %XX形式で追加

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

```
omz_urlencode()
    │
    ├─ zparseopts (zshビルトイン)
    │       └─ オプション解析
    │
    ├─ $langinfo[CODESET] (zsh/langinfo)
    │       └─ 現在のエンコーディング取得
    │
    ├─ iconv (外部コマンド - 条件付き)
    │       └─ UTF-8変換
    │
    └─ echo -E (zshビルトイン)
            └─ 結果出力
```

### データフロー図

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

文字列 ─────────────▶ オプション解析
                           │
                           ▼
                    エンコーディング確認
                           │
                    ┌──────┴──────┐
                    │             │
               [UTF-8]      [非UTF-8]
                    │             │
                    │        iconv変換
                    │             │
                    └──────┬──────┘
                           │
                           ▼
                    エスケープ対象決定
                           │
                           ▼
                    文字ごとエンコード
                           │
                           ▼
                    echo -E ─────────▶ URLエンコード文字列
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| functions.zsh | `lib/functions.zsh` | ソース | omz_urlencode関数およびomz_urldecode関数の定義 |
| oh-my-zsh.sh | `oh-my-zsh.sh` | ソース | lib/functions.zshを読み込むエントリポイント |
