PHPで相対パスから絶対パスを生成

PHPでプログラミングしてるとき、Location ヘッダで302転送かけようと思ったのですが、
RFCの仕様上は転送先を絶対パスで指定しなくちゃいけなくて、
おまけにPHPの標準関数では相対パスを絶対パスに変換する関数がないし、
(※ realpath関数 はローカルで実在するパスにしか使えません)
ググッてみたら色んな人が自前で作って公開してたけど、
Windowsローカル環境&ウェブ環境の両方で使うおいらにはマッチしなかったので自前で作ってみた。

作ってから たいていのブラウザではLocationヘッダを相対パスで指定してもちゃんと動く ということを知りましたケドね☆彡

んで、特徴はたいていのパスの書き方には対応してることです。
・Windows / Unix 形式両対応
・Windowsのネットワークパス対応 ( \\dcserver\NETLOGON とか )
・ほとんどのプロトコルに対応 (http, https, ftp, gopher, mmtp ... )
・相対パス同士の連結には使えません

以下ソース。



/*
 * 相対パスを絶対パスに変換する処理。
 *  $absolute_path : カレントディレクトリの絶対パス
 *  $relative_path : 相対パス
 */
function toAbsolutePath$absolute_path$relative_path )
{
    
$pattern_root '/^([a-z]{2,10}://[^/]+/|[a-z]:|\[^]+|/)(.*)$/i';
    
    
// 絶対パスのroot部の特定
    
if( !preg_match$pattern_root$absolute_path$rec ) ) {
        return 
false;    // 非対応のパス形式です
    
}
    
$root $rec[1];
    
$apath $rec[2];
    
    
// セパレータ(/,) の特定
    
if( preg_match('///'$absolute_path) ) {
        
$separator '/';
    } elseif( 
preg_match('//'$absolute_path) ) {
        
$separator "";
    } else {
        return 
false;    // セパレータが特定できません
    
}
    
    
// 処理
    
$a preg_split('/(/|)/'$apath);
    if( 
$a[count($a) -1] == '' ) {
        unset(
$a[count($a) -1]);
    }
    
$r preg_split('/(/|)/'$relative_path);
    
$ia count($a);
    
$ir 0;
    if( 
$r[$ir] == '' ) {        // foo や /foo/bar のような先頭セパレータ指定の場合
        
$a = array();
        
$ia 0;
        
$ir++;
    }
    
$ir_limit count($r);
    while( 
$ir $ir_limit ){
        switch( 
$c $r[$ir] ) {
            case 
'..':
                if( --
$ia ) {
                    return 
false;
                }
                unset(
$a[$ia]);
                break;
            case 
'.':
                break;
            default:
                
$a[$ia++] = $c;
        }
        
$ir++;
    }
    
    return 
$root implode($separator$a);
}


※ハイライト処理には PHPソースをハイライト表示をお借りしました。ありがとうございます!

Tips
・ローカルパスで変換処理するときは、基準となる絶対パスは realpath('./') で求めるといいです。
・URLでやるときは、 $_SERVER['SCRIPT_URI'] で、現在実行中のPHPファイルの http(s):// で始まる絶対パスが取得できるので、これに dirname関数 をかけてファイル名を削ってから使ってくださいね。

あ、もちろん著作権がどうとか言いませんので、使っちゃってくださいませ。


以下、テストコードの結果を掲載しておきます。
▼URLに対応。
[*] http://www.example.net/~hoge/foo/bar/ = http://www.example.net/~hoge/ + foo/bar/
▼Windows形式のパス対応。
[*] C:\Windows\SYSTEM32\WindowsUpdate.log = C:\Windows\SYSTEM32 + WindowsUpdate.log
▼Unix形式のパス対応。
[*] /var/www/htdocs/image/banner.png = /var/www/htdocs + image/banner.png
▼絶対パス側は末尾の / や \ の有無は問いません。
[*] /var/www/htdocs/image/banner.png = /var/www/htdocs/ + image/banner.png
▼注意:絶対パス側の要素はすべてフォルダとみなします!予めdirname関数で処理しといてね!
[*] https://www.example.net/~hoge/index.php/image/top.gif = https://www.example.net/~hoge/index.php + image/top.gif
▼相対パスの先頭 /,\ にも もちろん対応。
[*] http://www.example.net/~user/index.html = http://www.example.net/~hoge/ + /~user/index.html
▼. や .. にも もちろん対応。
[*] http://www.example.net/~user/image/ = http://www.example.net/~hoge/ + ../~user/./image/
▼マイナーなプロトコルにも対応。
[*] gopher://www.example.net/foo2/bar2 = gopher://www.example.net/~hoge/foo/bar/ + /foo2/bar2
▼\ と / がごっちゃになっててもどうにかします(絶対パス基準で)
[*] ftp://www.example.net/~hoge/foo/bar3/hoge.zip = ftp://www.example.net/~hoge/foo/bar/ + ..\bar3\hoge.zip
▼Windowsのネットワークパス形式にも対応。
[*] \\dcserver\SYSVOL = \\dcserver\NETLOGON\batch + \SYSVOL
▼.. を使いすぎた不正なパスはエラー(falseを返す)
[x] Failed.. = mmtp://www.example.net/x1/ + ../../foo.asf



余談ですが、こーゆーのってスゴイ人はほんの10行くらいでスマートに書いちゃったりしそうで、とっても羨ましいでございます。
by golorih | 2011-11-21 20:12 | ソフトウェア開発 | Trackback | Comments(0)
トラックバックURL : https://golorih.exblog.jp/tb/16906913
トラックバックする(会員専用) [ヘルプ]
※このブログはトラックバック承認制を適用しています。 ブログの持ち主が承認するまでトラックバックは表示されません。


システム関連の個人的な備忘録。基本的にWindows関連です。

プロフィール

関連


Memoる

一生懸命だと知恵が出る
中途半端だと愚痴が出る
いい加減だと言い訳が出る

「やりたい」なんて言葉は使う必要が無い。「今やってる」「もうやった」「やらないことにした」なら使って良い。
まずは相手を好きになる、その次に相手のいい部分を探す、そして評価できる部分を見つける。それからです、誉めるのは。

カテゴリ

全体
ソフトウェア関連
ソフトウェア開発
Linuxサーバ
その他
Webサービス
MySQL
システム管理
test
バッチファイル
つぶやき
パソコンメーカー
jQuery
レビュー
実験と検証
セキュリティ対策
YahooPipes
vbs
ハードウェア関連
WordPress
JavaScript
HTML&CSS
Welcart
未分類

以前の記事

2019年 03月
2019年 02月
2018年 10月
2018年 09月
2018年 01月
2017年 12月
2017年 10月
2017年 09月
2017年 07月
2016年 12月
2016年 10月
2016年 08月
2016年 07月
2016年 04月
2016年 03月
2016年 01月
2015年 12月
2015年 11月
2015年 10月
2015年 09月
2015年 08月
2015年 07月
2015年 06月
2015年 05月
2015年 03月
2015年 01月
2014年 11月
2014年 10月
2014年 09月
2014年 08月
2014年 06月
2014年 05月
2014年 04月
2014年 03月
2014年 02月
2014年 01月
2013年 12月
2013年 11月
2013年 10月
2013年 09月
2013年 08月
2013年 07月
2013年 06月
2013年 05月
2013年 04月
2013年 03月
2013年 02月
2013年 01月
2012年 12月
2012年 11月
2012年 10月
2012年 09月
2012年 08月
2012年 07月
2012年 05月
2012年 04月
2012年 03月
2012年 02月
2011年 11月
2011年 10月
2011年 09月
2011年 06月
2011年 05月
2011年 04月
2011年 03月
2011年 02月
2010年 12月
2010年 11月
2010年 10月
2010年 09月
2010年 08月
2010年 07月
2010年 06月
2010年 02月
2009年 12月
2009年 10月
2008年 12月
2008年 06月
2008年 05月
2008年 04月
2008年 03月
2008年 01月
2007年 12月
2007年 11月
2007年 08月
2007年 07月
2005年 09月
2005年 08月

フォロー中のブログ

最新のコメント

msiファイルが見つから..
by 7of9 at 13:25
当方win10、むらびと..
by luna at 14:18
検索でこちらにたどり着き..
by ペカティエ at 16:04
2と3の間に「アレでNI..
by むらびとA at 23:03
たった今試してみたんです..
by むらびとA at 23:01
ワークグループ環境にws..
by ヒジキ at 16:27
こんにちは。 別件の検..
by luka3 at 17:00
win10ではアレが使え..
by A at 17:56
現在(2018/04/2..
by むらびとA at 10:27
こんにちは RDP W..
by U at 16:29

その他のジャンル

ファン

記事ランキング

ブログジャンル

ネット・IT技術

画像一覧