PHP文件包含以及部分封装协议

概述

最近总是遇到有关文件包含的问题,所以觉得有必要学习整理下有关这方面的内容。
php支持的协议可以查阅官方手册

1
2
3
4
5
6
7
8
9
10
11
12
file:// — 访问本地文件系统
http:// — 访问 HTTP(s) 网址
ftp:// — 访问 FTP(s) URLs
php:// — 访问各个输入/输出流(I/O streams)
zlib:// — 压缩流
data:// — 数据(RFC 2397)
glob:// — 查找匹配的文件路径模式
phar:// — PHP 归档
ssh2:// — Secure Shell 2
rar:// — RAR
ogg:// — 音频流
expect:// — 处理交互式的流

这里顺便记一下有关php文件包含的函数:

1
2
3
4
5
6
7
8
fopen()
file_get_contents()
curl_exec()
readfile()
require()
require_once()
include()
include_once()

PHP部分封装协议

file 协议

文件系统 是 PHP 使用的默认封装协议,展现了本地文件系统。 当指定了一个相对路径(不以/、\、\或 Windows 盘符开头的路径)提供的路径将基于当前的工作目录。 在很多情况下是脚本所在的目录,除非被修改了。 使用 CLI 的时候,目录默认是脚本被调用时所在的目录。

在某些函数里,例如 fopen() 和 file_get_contents(), include_path 会可选地搜索,也作为相对的路径。

1
2
3
4
5
6
7
8
9
<?php
$gfile = $_GET['gfile'];
if (isset($gfile)){
print_r(file_get_contents($gfile));
}else {
print_r("Please input gfile !<br />");
}
// ?gfile=file://C:\mySoft\xampp\htdocs\phpinfo.php
// ?gfile=file://C:/mySoft/xampp/htdocs/phpinfo.php

http、https 协议

允许通过 HTTP 1.0 的 GET方法,以只读访问文件或资源(需要allow_url_fopen=On并且 allow_url_include=On)。 HTTP请求会附带一个Host:头,用于兼容基于域名的虚拟主机。如果在你的 php.ini 文件中或字节流上下文(context)配置了user_agent字符串,它也会被包含在请求之中。
数据流允许读取资源的 body,而 headers 则储存在了 $http_response_header 变量里。
如果需要知道文档资源来自哪个 URL(经过所有重定向的处理后), 需要处理数据流返回的系列响应报头(response headers)。

example:

1
2
3
4
5
6
7
8
<?php
$gfile = $_GET['gfile'];
if (isset($gfile)){
readfile($gfile);
}else {
print_r("Please input gfile !<br />");
}
// ?gfile=http://www.example.com

php 协议

filter

php://filter 是一种元封装器,设计用于数据流打开时的筛选过滤应用(需要allow_url_include=On)。 这对于一体式(all-in-one)的文件函数非常有用,类似 readfile()、file() 和 file_get_contents(), 在数据流内容读取之前没有机会应用其他过滤器。
php://filter 目标使用以下的参数作为它路径的一部分。 复合过滤链能够在一个路径上指定。

php://filter 参数

  1. resource=<要过滤的数据流> 这个参数是必须的。它指定了你要筛选过滤的数据流。
  2. read=<读链的筛选列表> 该参数可选。可以设定一个或多个过滤器名称,以管道符(|)分隔。
  3. write=<写链的筛选列表> 该参数可选。可以设定一个或多个过滤器名称,以管道符(|)分隔。

example:

1
2
3
4
5
6
7
8
9
10
11
<?php
$gfile = $_GET['gfile'];
if (isset($gfile)){
readfile($gfile);
}else {
print_r("Please input gfile !<br />");
}
// ?gfile=php://filter/read=string.toupper/resource=http://www.example.com
// ?gfile=php://filter/read=string.toupper|string.rot13/resource=http://www.example.com
// ?gfile=php://filter/read=convert.base64-encode/resource/resource=http://www.example.com

input

php://input 是个可以访问请求的原始数据的只读流(需要allow_url_include=On)。POST 请求的情况下,最好使用 php://input 来代替 $HTTP_RAW_POST_DATA,因为它不依赖于特定的 php.ini 指令。而且,这样的情况下 $HTTP_RAW_POST_DATA 默认没有填充,比激活 always_populate_raw_post_data 潜在需要更少的内存。 enctype=”multipart/form-data”的时候 php://input 是无效的。

example:

1
2
3
<?php
$content = file_get_contents("php://input");
echo $content; //输出name=tom&age=22

zlib

zlib: PHP 4.0.4 - PHP 4.2.3(仅支持带 fopencookie 的系统)
compress.zlib:// 和 compress.bzip2:// PHP 4.3.0 及以上

用法:

  1. compress.zlib://file.gz
  2. compress.bzip2://file.bz2
  3. zip://archive.zip#dir/file.txt

data

自 PHP 5.2.0 起 data:(» RFC 2397)数据流封装器开始有效(需要allow_url_include=On)。

example :

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
$gfile = $_GET['gfile'];
if (isset($gfile)){
echo include($gfile);
}else {
print_r("Please input gfile !<br />");
}
// ?gfile=data://text/plain;base64,SSBsb3ZlIFBIUAo=
// ?gfile=data://text/plain;charset=unicode,(●'◡'●)
// ?gfile=data://text/plain;base64,PD9waHAgcGhwaW5mbygpOyA/Pg==
// ?gfile=data://text/plain,<?php phpinfo(); ?>

glob

glob:// — 查找匹配的文件路径模式。glob: 数据流包装器自 PHP 5.3.0 起开始有效,可绕过绕过open_basedir读写文件。

example :

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
$gfile = $_GET['gfile'];
if (isset($gfile)){
$it = new DirectoryIterator($gfile);
foreach($it as $f) {
printf("%s: %.1FK<br />", $f->getFilename(), $f->getSize()/1024);
}
}else {
print_r("Please input gfile !<br />");
}
// ?gfile=glob://C:\mySoft\xampp\htdocs\*.php
// ?gfile=glob://C:/mySoft/xampp/htdocs/*.php

phar

phar:// 数据流包装器自 PHP 5.3.0 起开始有效。PHP 归档。

1
2
3
4
5
6
7
8
9
<?php
$gfile = $_GET['gfile'];
if (isset($gfile)){
include($gfile);
}else {
print_r("Please input gfile !<br />");
}
// 把php代码写入phpinfo文件,然后压缩成zip,再改后缀为.jpg
// ?gfile=phar://phpinfo.jpg/phpinfo

大概就先这样把,下次有问题再添加。