a-blog cms PHP API Reference

MediaSourceImporter
in package

ローカルファイルパスからメディアを取り込み、media_id を返す

CSV インポート(CMS-7715)向け。実際の検証(パストラバーサル対策/mime 検証/ サイズ上限)はここに閉じ、呼び出し側は import() の戻り値(media_id)だけを扱えばよい。 失敗時は例外を投げるだけに留め、「行をどう扱うか」の判断は呼び出し側に委ねる。

Why not: URL(https 経由)からの取得は当初の設計に含めていたが、社内 MTG の判断で 一旦スコープ外となったため削除した(SSRF 対策・PSR-18 クライアント実装を含む一式)。 復活する場合は git 履歴(MediaSourceImporter の URL 経路実装コミット)を参照すること。

Table of Contents

Properties

$cache  : array<string, int>
$localPathBase  : string
$localStorage  : Filesystem
$maxFileSize  : int
$mediaHelper  : Helper

Methods

__construct()  : mixed
import()  : int
ローカルファイルパスからメディアを取得し登録する
importDryRun()  : MediaImportPreview
import() のドライラン版(CSV インポートのドライラン機能向け)
createTempFilePath()  : string
extractFilename()  : string
source からファイル名部分だけを取り出す(拡張子判定・表示名として使う)
extractUrlPath()  : string
http(s):// URL からパス部分を取り出す
fetchFromLocalPath()  : string
ローカルファイルパスを取り込みベースディレクトリ配下の実在ファイルとして検証し、 サイズ上限内であることを確認したうえで一時ファイルへコピーしてそのパスを返す
resolveExistingLocalPath()  : string
ローカルファイルパスを取り込みベースディレクトリ配下の実在ファイルとして検証し、 サイズ上限内であることを確認したうえで、実ファイルの解決済み絶対パスを返す (ファイルのコピーは行わない)。import()/importDryRun() 共通の検証ロジック。
resolveLocalCandidate()  : string
CSV の値を、取り込みベースディレクトリ配下の候補パスに変換する

Properties

$cache

private array<string, int> $cache = []

参照先文字列 → media_id(同一インスタンス内の重複排除キャッシュ)

Methods

__construct()

public __construct(Filesystem $localStorage, Helper $mediaHelper, string $localPathBase, int $maxFileSize) : mixed
Parameters
$localStorage : Filesystem
$mediaHelper : Helper
$localPathBase : string
$maxFileSize : int

import()

ローカルファイルパスからメディアを取得し登録する

public import(string $source) : int

同一インスタンス内で同一の $source が再度渡された場合は、登録済みの media_id を返す (取得・登録処理は再実行しない)。

Parameters
$source : string
Tags
throws
MediaSourceImportException

取得・検証・登録のいずれかに失敗した場合

Return values
int

importDryRun()

import() のドライラン版(CSV インポートのドライラン機能向け)

public importDryRun(string $source) : MediaImportPreview

ファイルの実在・パストラバーサル・サイズ上限の検証と、内容ハッシュによる重複検知までは import() と同じ経路を通るが、実ファイルのコピー・保存・media テーブルへの登録は 一切行わない。呼び出し側は戻り値の MediaImportPreview から「既存メディアが 再利用される見込みか」「新規登録される見込みか」を判定できる。

Parameters
$source : string
Tags
throws
MediaSourceImportException

検証(存在・パストラバーサル・サイズ・mime)に失敗した場合

Return values
MediaImportPreview

createTempFilePath()

private createTempFilePath(string $source) : string
Parameters
$source : string
Return values
string

extractFilename()

source からファイル名部分だけを取り出す(拡張子判定・表示名として使う)

private extractFilename(string $source) : string

http(s):// URL はクエリ文字列を含むため、パス部分だけを取り出してから ファイル名を得る(resolveLocalCandidate() と同じ「URL のパス表記」の扱いに揃える)。

Parameters
$source : string
Return values
string

extractUrlPath()

http(s):// URL からパス部分を取り出す

private extractUrlPath(string $source) : string

Why not Rfc3986Uri::getPath() をそのまま使わないか:

  • getPath() は .. セグメントを正規化してしまうため、validateDirectoryTraversalPath() に渡す前にトラバーサルの手がかりが失われる。getRawPath() で正規化前の生パスを渡し、 ベース外への脱出判定は後続の validateDirectoryTraversalPath() に委ねる。
  • Rfc3986Uri::parse() は生の Unicode 文字(パーセントエンコードされていない日本語 ファイル名等)を含む URL を無効な URI として null を返す。移行元 DB にはそのような URL がそのまま残っていることが多いため、失敗時は WHATWG 準拠のパーサーへ フォールバックする(WhatWgUrl::getPath() は正規化済みだが、Unicode を含むケースは 稀に .. を併用するとは考えにくいため許容する)。

getRawPath() はパーセントエンコードもそのまま残すため、正しくエンコードされた日本語 ファイル名(%E7%94%BB...)を含むURLは rawurldecode() しないと実ファイル名と一致しない。 デコードで ..(%2e%2e 等)が現れても、resolveLocalCandidate() で localPathBase と 連結した後に validateDirectoryTraversalPath() 側で Path::makeAbsolute() により 正規化・境界判定されるため、デコード自体がトラバーサル検証を迂回させることはない (素の .. セグメントを含む URL と同じ経路・同じメッセージで拒否される)。

Parameters
$source : string
Return values
string

fetchFromLocalPath()

ローカルファイルパスを取り込みベースディレクトリ配下の実在ファイルとして検証し、 サイズ上限内であることを確認したうえで一時ファイルへコピーしてそのパスを返す

private fetchFromLocalPath(string $source) : string
Parameters
$source : string
Tags
throws
MediaSourceImportException
Return values
string

resolveExistingLocalPath()

ローカルファイルパスを取り込みベースディレクトリ配下の実在ファイルとして検証し、 サイズ上限内であることを確認したうえで、実ファイルの解決済み絶対パスを返す (ファイルのコピーは行わない)。import()/importDryRun() 共通の検証ロジック。

private resolveExistingLocalPath(string $source) : string
Parameters
$source : string
Tags
throws
MediaSourceImportException
Return values
string

resolveLocalCandidate()

CSV の値を、取り込みベースディレクトリ配下の候補パスに変換する

private resolveLocalCandidate(string $source) : string

file:// プレフィックスは剥がす。相対パスはベースディレクトリからの相対として解決し、 絶対パスはそのまま validateDirectoryTraversalPath() の判定に委ねる。

http(s):// URL はホストを無視し、パス部分だけを取り込みベースディレクトリからの 相対パスとして解決する(実際に URL へ HTTP アクセスすることはない)。移行元 DB に 残る絶対 URL をそのまま CSV に書き写せるよう、移行元のディレクトリ構造を FTP で ベースディレクトリ配下に再現しておく運用を想定する(URL 取得自体のスコープ外方針 は変えない。あくまで「URL に見えるパス表記」からの解決先の話)。

Parameters
$source : string
Return values
string

        
On this page

Search results