$ary=array('neko','yagi','kani','same'); $ids_str = "'" . implode("','", $ary) . "'"; //出力→ $ids_str = 'neko','yagi','kani','same'
説明
a要素のhrefへ、自由にURLを指定できるようなシステムの場合、XSSの危険性がある。XSSを引き起こすコードの例
サンプル
ソースコード<?php $xssList=array( "http://example.com/\"onmouseover=\"alert(1)\"", "http://example.com/?<script>alert(document.domain);</script>", "https://example.com/?neko=1&yagi=2\"onmouseover=\"alert(1)\"", "javascript:alert('XSS')", "jav ascript:alert('XSS');", "color:expression(alert('XSS'));", "behavior:url(test.sct)", ); foreach($xssList as $xss){ $s=htmlspecialchars_url($xss); echo htmlspecialchars($xss); echo " → "; echo htmlspecialchars($s); echo "<br>"; } /** * URL用のサニタイズ * 記号「<>"'」をエンコードし、記号「:;」を除去する。 * ただし「http:」「https:」に付いている「:」は除去しない。 * @param $xss サニタイズ対象文字 * @return サニタイズ後の文字 */ function htmlspecialchars_url($xss){ $s=htmlspecialchars($xss, ENT_QUOTES, 'UTF-8'); $s=str_replace('http:','http<',$s); $s=str_replace('https:','https<',$s); $s=str_replace(':','',$s); $s=str_replace(';','',$s); $s=str_replace('http<','http:',$s); $s=str_replace('https<','https:',$s); return $s; } ?>
if(!empty($_FILES)){ $lenth=count($_FILES["files"]["name"]); for($i=0;$i<$lenth;$i++){ //日本語ファイル名の文字化け対策 $file_name = mb_convert_encoding($_FILES['files']['name'][$i], "SJIS", "auto"); //一時ファイルをtestフォルダにコピー move_uploaded_file($_FILES["files"]["tmp_name"][$i], "test/" . $file_name); } }
/** * 日本語ディレクトリの存在チェック * @param $dn ディレクトリ名 * @return boolean true:存在 false:未存在 */ function is_dir_ex($dn){ $dn=mb_convert_encoding($dn,'SJIS','UTF-8'); if (is_dir($dn)){ return true; }else{ return false; } }
$destinationPath = 'app/public/uploads/rich_menu'; // ディレクトリが存在しない場合に作成 if (!file_exists($destinationPath)) { // ディレクトリを作成する。(中間のディレクトリも作成) if (!mkdir($destinationPath, 0777, true)) { die('ディレクトリの作成に失敗しました。'); } }
/**
* 拡張コピー 存在しないディテクトリも自動生成
* 日本語ファイルに対応
* @param コピー元ファイル名 $sourceFn
* @param コピー先ファイル名 $copyFn
*/
function copyEx($sourceFn,$copyFn){
//フルファイル名からパスを取得する。
$di=dirname($copyFn);
//コピー先ファイル名とコピー元ファイル名が同名であれば、Nullを返して処理を終了
if($sourceFn==$copyFn){
return null;
}
//ディレクトリが存在するかチェック。
if (is_dir_ex($di)){
//存在するならそのままコピー処理
$sourceFn=mb_convert_encoding($sourceFn,'SJIS','UTF-8');
$copyFn=mb_convert_encoding($copyFn,'SJIS','UTF-8');
copy($sourceFn,$copyFn);
}else{
//存在しない場合。
//パスを各ディレクトリに分解し、ディレクトリ配列をして取得する。
$ary=explode('/', $di);
//ディレクトリ配列の件数分以下の処理を繰り返す。
$iniFlg=true;
foreach ($ary as $key => $val){
//作成したディレクトリが存在しない場合、ディレクトリを作成
if ($iniFlg==true){
$iniFlg=false;
$dd=$val;
}else{
$dd.='/'.$val;
}
if (!(is_dir_ex($dd))){
mkdir($dd);//ディレクトリを作成
}
}
$sourceFn=mb_convert_encoding($sourceFn,'SJIS','UTF-8');
$copyFn=mb_convert_encoding($copyFn,'SJIS','UTF-8');
copy($sourceFn,$copyFn);//ファイルをコピーする。
}
}
/**
* 日本語ディレクトリの存在チェック
* @param $dn ディレクトリ名
* @return boolean true:存在 false:未存在
*/
function is_dir_ex($dn){
$dn=mb_convert_encoding($dn,'SJIS','UTF-8');
if (is_dir($dn)){
return true;
}else{
return false;
}
}
$fn="日本語.pdf";
$ffn="tmp2/".$fn;
$ffn2 ='dummy2/'. $fn;//コピー先。dummy2は未作成でも良い。
//拡張コピー。存在しないディレクトリも自動生成し、日本語ファイル名にも対応。
copyEx($ffn,$ffn2);
旧式
/** * scandir関数の拡張関数。 * * @note * 「.」「..」となっているファイル名は除外する。 * 日本語ファイル名に対応するためUTF-8に変換している。 * そのため、当関数で取得したファイル名でWindows上のファイルを扱う場合、Shift-JISに戻す必要がある。 * WindowsのファイルはShift-JISで扱わねばならないためである。 * * @param $dir_name ディレクトリ名 * @return ファイル名の配列 */ function scandir2($dir_name){ $files = scandir($dir_name); // 「.」,「..」名のファイルを除去、および日本語ファイルに対応。 $files2 = array(); foreach($files as $file){ if($file=='.' || $file=='..'){ continue; } $file = mb_convert_encoding($file, 'UTF-8', 'SJIS'); $files2[] = $file; } return $files2; }
$dir_name="tmp2";
$files = scandir2($dir_name);
echo var_dump($files);
$fileNames = getAllFileNamesInDir('tmp');
var_dump($fileNames);
/**
* ディレクトリ階層化の全ファイル名を取得する
* @param string $dir ディレクトリ
* @param array $list ファイル名リスト(内部処理用なのでセット不要)
* @return ファイル名リスト
*/
function getAllFileNamesInDir($dir,$list=array()) {
if ($handle = opendir("$dir")) {
while (false !== ($item = readdir($handle))) {
if ($item != "." && $item != "..") {
if (is_dir("$dir/$item")) {
$list = getAllFileNamesInDir("$dir/$item",$list);
} else {
//unlink("$dir/$item");
$list[] = "$dir/$item";
}
}
}
closedir($handle);
}
return $list;
}
array (size=11) 0 => string 'tmp/xxx/icon_kabuto.jpg' (length=23) 1 => string 'tmp/xxx/icon_tilapia.jpg' (length=24) 2 => string 'tmp/xxx/imori.jpg' (length=17) 3 => string 'tmp/xxx/imori_md.jpg' (length=20) 4 => string 'tmp/xxx/imori_md.png' (length=20) 5 => string 'tmp/xxx/inago.jpg' (length=17) 6 => string 'tmp/xxx/sasigame.jpg' (length=20) 7 => string 'tmp/xxx/smp1.png' (length=16) 8 => string 'tmp/xxx/test1.jpg' (length=17) 9 => string 'tmp/xxx/test3.jpg' (length=17)
/**
* パスを削除します。
* @note
* ディレクトリごとファイルを削除できます。
* 階層化のファイルまで削除可能。
* もちろん通常のファイルも削除可能。
* パスの指定先にファイルやディレクトリが無くてもエラーになりません。
*
* @param string $path 削除対象ディレクトリ(絶対パスで指定する。セパレータはスラッシュ、バックスラッシュが混在しても良い)
* @return [] 削除に失敗したパス名のリスト
*/
public function removePath($path){
$falseData = [];
$this->removePath0($path, $falseData);
return $falseData;
}
/**
* パスを削除します。 このメソッドは再帰呼び出し処理がなされています。
* @note
* ディレクトリごとファイルを削除できます。
* 階層化のファイルまで削除可能。
* もちろん通常のファイルも削除可能。
* パスの指定先にファイルやディレクトリが無くてもエラーになりません。
*
* @param string $path 削除対象ディレクトリ(絶対パスで指定する。セパレータはスラッシュ、バックスラッシュが混在しても良い)
* @param [] $falseData 失敗ファイルリスト 削除に失敗したパスの情報
* @return [] 削除に失敗したパス名のリスト
*/
private function removePath0($path, &$falseData) {
// ディレクトリでないなら即削除
if (!is_dir($path)) {
if(@unlink($path) == false) $falseData[] = $path; // 「@」を付けることにより、ディレクトリやファイルが存在しなくてもWarningがでないようにする。
return $falseData;
}
if ($handle = opendir($path)) {
while (false !== ($item = readdir($handle))) {
if ($item != "." && $item != "..") {
$dp = $path . '/' . $item;
if (is_dir($dp)) {
$this->removePath0($dp, $falseData);
} else {
if(@unlink($dp) == false) $falseData[] = $path; // ファイルを削除。失敗した場合は失敗リストにパス名を追加する。
}
}
}
closedir($handle);
if(rmdir($path) == false) $falseData[] = $path; // ディレクトリを削除。失敗した場合は失敗リストにパス名を追加する。
}
return $falseData;
}
/**
* ディレクトリ内のファイルをまとめて削除する。
* @param $dir_name ファイル削除対象のディレクト名
* @return
*/
function dirClear($dir_name){
//フォルダ内のファイルを列挙
$files = scandir($dir_name);
$files = array_filter($files, function ($file) {
return !in_array($file, array('.', '..'));
});
foreach($files as $fn){
$ffn=$dir_name.'/'.$fn;
try {
unlink($ffn);//削除
} catch (Exception $e) {
throw e;
}
}
return true;
}
$dir_name="tmp3";
dirClear($dir_name);
echo 'フォルダ内のファイルを削除しました。';
/**
* ディレクトリごとファイルを削除する。(階層化のファイルまで削除可能)
* @param string $dir 削除対象ディレクトリ(絶対パスで指定する。セパレータはスラッシュ、バックスラッシュが混在しても良い)
*/
public function removeDirectory($dir) {
// ディレクトリでないなら即削除
if (!is_dir($dir)) {
@unlink($dir); // 「@」を付けることにより、ディレクトリやファイルが存在しなくてもWarningがでないようにする。
return;
}
if ($handle = opendir($dir)) {
while (false !== ($item = readdir($handle))) {
if ($item != "." && $item != "..") {
$dp = $dir . '/' . $item;
if (is_dir($dp)) {
$this->removeDirectory($dp);
} else {
@unlink($dp);
}
}
}
closedir($handle);
rmdir($dir);
}
}
参考サイト
/**
* ディレクトリ内のファイルとフォルダをまとめて削除する。
* @param string $dir_name ファイル削除対象のディレクト名
*/
private function dirClearEx($dir_name){
//フォルダ内のファイルを列挙
$files = scandir($dir_name);
$files = array_filter($files, function ($file) {
return !in_array($file, array('.', '..'));
});
foreach($files as $fn){
$ffn=$dir_name.'/'.$fn;
try {
//unlink($ffn);//削除
$this->removeDirectory($ffn);
} catch (Exception $e) {
throw e;
}
}
return true;
}
/**
* ディレクトリごとファイルを削除する。(階層化のファイルまで削除可能)
* @param string $dir 削除対象ディレクトリ
*/
private function removeDirectory($dir) {
if ($handle = opendir($dir)) {
while (false !== ($item = readdir($handle))) {
if ($item != "." && $item != "..") {
$dp = $dir . '/' . $item;
if (is_dir($dp)) {
removeDirectory($dp);
} else {
unlink($dp);
}
}
}
closedir($handle);
rmdir($dir);
}
}
<?php
$sample = new Sample();
$sample->removeFileByOldDay('sample', 2);
class Sample{
/**
* 危険処理
* 指定日数より古い更新日のファイルをすべて削除する
*
* @note
*指定日数に2を指定した場合、二日以上前のファイルをすべて削除。
*0を指定すると、すべてのファイルを削除
*
* @param string $dp ディレクトリパス
* @param number $day_num 指定日数
* @param string $ext 削除ファイルの拡張子(小文字) null:すべてのファイルが対象
*/
public function removeFileByOldDay($dp, $day_num = 1, $ext = null){
$fps = $this->scandir3($dp); // ディレクトリ内にあるすべてのファイルのファイルパスを取得する
$today = date("Y-m-d");
foreach($fps as $fp){
$dt = date("Y-m-d", filemtime($fp));
$diff_day = $this->diffDay($today, $dt); // 2つの日付の日数差を算出する
// 日付差が指定日数以上なら、ファイル削除とする。
if($day_num <= $diff_day){
// ファイルパスから拡張子(小文字)を取得
$pi = pathinfo($fp);
$ext2 = mb_strtolower($pi['extension']);
// 拡張子が一致するなら、このファイルを削除する
if($ext == $ext2){
unlink($fp);
}
}
}
}
/**
* 2つの日付の日数差を算出する
*
* diff = d2 - d1
*
* @param date or string $d2
* @param date or string $d1
* @return int 日数差
*/
private function diffDay($d2,$d1){
$u1=strtotime($d1);
$u2=strtotime($d2);
//日数を算出
$diff=$u2-$u1;
$d_cnt=$diff/86400;
return $d_cnt;
}
/**
* scandir関数の拡張関数。
*
* @note
* 「.」「..」となっているファイル名は除外する。
*
* @param string $dp ディレクトリ名
* @param string $sep セパレータ(省略可)
* @return array ファイルパスリスト
*/
private function scandir3($dp, $sep = '/'){
$files = scandir($dp);
// ディレクトリパスの末尾にセパレータを付け足す
$dp2 = $dp;
if(mb_substr($dp2, -1) != $sep){
$dp2 .= $sep;
}
// 「.」,「..」名のファイルを除去、および日本語ファイルに対応。
$fps = [];
foreach($files as $file){
if($file=='.' || $file=='..'){
continue;
}
$fps[] = $dp2 . $file;
}
return $fps;
}
}
function debug($var){
echo '<pre>';
var_dump($var);
echo '</pre>';
}
?>
$pi = pathinfo('/okinawa/kunigami/oku/habu.jpg'); echo $pi['dirname'], //→ '/okinawa/kunigami/oku', echo $pi['basename']; //→ 'habu.jpg', echo $pi['extension']; //→ 'jpg' echo $pi['filename']; //→ 'habu'
$dirName = "C:\xampp\htdocs\xample\test";
makeDirEx($dirName);
mkdirの拡張メソッド
パスに新しく作成せねばならないディレクトリ情報が複数含まれている場合でも、順次ディレクトリを作成する。
/**
* ディレクトリを作成する
*
* @note
* ディレクトリが既に存在しているならディレクトリを作成しない。
* パスに新しく作成せねばならないディレクトリ情報が複数含まれている場合でも、順次ディレクトリを作成する。
* 日本語ディレクトリ名にも対応。
* パスセパレータは「/」と「¥」に対応。
* ディレクトリのパーミッションの変更をを行う。(既にディレクトリが存在する場合も)
* セパレータから始まるディレクトリはホームルートパスからの始まりとみなす。
*
* @version 1.3
* @date 2014-4-13 | 2018-8-18
*
* @param string $dir_path ディレクトリパス
*/
private function makeDirEx($dir_path,$permission = 0705){
if(empty($dir_path)){return;}
$home_flg = false; // ホームディレクトリパス 1:ホーム(htdocsより以降)からのパス
$s1 = mb_substr($dir_path,0,1);
if($s1 == '/' || $s1 == DIRECTORY_SEPARATOR){
$home_flg = 1;
}
// 日本語名を含むパスに対応する
$dir_path=mb_convert_encoding($dir_path,'SJIS','UTF-8');
// ディレクトリが既に存在する場合、書込み可能にする。
if (is_dir($dir_path)){
chmod($dir_path,$permission);// 書込み可能なディレクトリとする
return;
}
// パスセパレータを取得する
$sep = DIRECTORY_SEPARATOR;
if(strpos($dir_path,"/")!==false){
$sep = "/";
}
//パスを各ディレクトリに分解し、ディレクトリ配列をして取得する。
$ary=explode($sep, $dir_path);
//ディレクトリ配列の件数分以下の処理を繰り返す。
$dd = '';
foreach ($ary as $i => $val){
if($i==0){
$dd=$val;
if($home_flg == 1){
$dd = $_SERVER['DOCUMENT_ROOT'] . $sep . $dd;
}
}else{
$dd .= $sep.$val;
}
//作成したディレクトリが存在しない場合、ディレクトリを作成
if (!is_dir($dd)){
mkdir($dd,$permission);//ディレクトリを作成
chmod($dd,$permission);// 書込み可能なディレクトリとする
}
}
}
$ffn='/sample/xxx/日本語.pdf'; $ffn=mb_convert_encoding($ffn,'SJIS','UTF-8');//日本語ファイル名に対応 if(file_exists($ffn)){//ファイルが存在するか? unlink($ffn);//ファイルを削除 }
/** * ディレクトリを深く探り、ファイル群のファイルパス配列を取得する * @param string $path ディレクトリパス * @param array $data 内部処理用・ファイルパスリスト * @return array ファイルパスリスト */ function getFilePathFromDeep($path, &$data=array()){ if(is_file($path)){ $data[] = $path; }else{ foreach(glob($path . '/*') as $path2){ $data = getFilePathFromDeep($path2, $data); } } return $data; }
$ipAddr=$_SERVER["REMOTE_ADDR"];//IPアドレス取得 $ipVal = ip2long($ipAddr);// IPアドレスを数値変換 $ipAddr=$this->request->clientIp(false);//CakePHPでのIPアドレス取得サンプル