对php中file_get_contents方法进行源码改造
需求,在php.ini中设置 allow_domain 参数 格式如下
allow_domain = avc.com,xyz.cn
当php使用file_get_contents($url)时,需要判断url中主机名称是否被allow_domain所包含
在php安装包内找到file_get_contents的源文件,进行修改
PHP_FUNCTION(file_get_contents)
{
char *filename;
size_t filename_len;
zend_bool use_include_path = 0;
php_stream *stream;
zend_long offset = 0;
zend_long maxlen = (ssize_t) PHP_STREAM_COPY_ALL;
zval *zcontext = NULL;
php_stream_context *context = NULL;
zend_string *contents;
/* Parse arguments */
ZEND_PARSE_PARAMETERS_START(1, 5)
Z_PARAM_PATH(filename, filename_len)
Z_PARAM_OPTIONAL
Z_PARAM_BOOL(use_include_path)
Z_PARAM_RESOURCE_EX(zcontext, 1, 0)
Z_PARAM_LONG(offset)
Z_PARAM_LONG(maxlen)
ZEND_PARSE_PARAMETERS_END();
/*Check remote request is illegal . by netstat in 20200526 */
char *allow_domain ;
if (FAILURE != cfg_get_string("allow_domain", &allow_domain) && strlen(allow_domain) > 0 ) {
char *url = (char *)malloc(strlen(filename) + 1);
strcpy(url,filename);
char http[5];
char ftp[4];
char *domains = "";
int allowRequest = 0 ;
char pattern[strlen(allow_domain)];
memset(http,0,sizeof(http));
memset(ftp,0,sizeof(ftp));
strcpy(pattern,allow_domain);
strncpy(http,url,sizeof(http) - 1);
strncpy(ftp,url,sizeof(ftp) - 1);
if(strcmp(http,"http") == 0 || strcmp(ftp,"ftp") == 0){
//获取url中的域名
char *delim = "/";
char *pToken = NULL;
char *pSave = NULL;
strtok_r(url, delim, &pSave);
domains = strtok_r(NULL, delim,&pSave);
// printf("%s\n",domains);
//获取php.ini中allow_domain得设置
delim = ",";
pToken = NULL;
pSave = NULL;
pToken = strtok_r(pattern, delim, &pSave);
int length , pos = 0;
char dString[33];
while(pToken){
length = strlen(pToken);
pos = strlen(domains) - length;
strncpy(dString,domains+pos,length);
// printf("pattern:%s,strlen(pattren):%d,url:%s\n",pToken,length,dString);
if(strcmp(pToken,dString) == 0){
allowRequest = 1;
break;
}
pToken = strtok_r(NULL, delim, &pSave);
}
free(url);
if(allowRequest == 0 ){
char *errmsg = "Illegal Url Request:";
char *result = malloc(strlen(errmsg) +strlen(filename)+ 1);
strcpy(result,errmsg);
strcat(result,filename);
// free(result);
php_error_docref(NULL, E_ERROR, result);
RETURN_FALSE;
}
}
}
if (ZEND_NUM_ARGS() == 5 && maxlen < 0) {
php_error_docref(NULL, E_WARNING, "length must be greater than or equal to zero");
RETURN_FALSE;
}
context = php_stream_context_from_zval(zcontext, 0);
stream = php_stream_open_wrapper_ex(filename, "rb",
(use_include_path ? USE_PATH : 0) | REPORT_ERRORS,
NULL, context);
if (!stream) {
RETURN_FALSE;
}
if (offset != 0 && php_stream_seek(stream, offset, ((offset > 0) ? SEEK_SET : SEEK_END)) < 0) {
php_error_docref(NULL, E_WARNING, "Failed to seek to position " ZEND_LONG_FMT " in the stream", offset);
php_stream_close(stream);
RETURN_FALSE;
}
if (maxlen > INT_MAX) {
php_error_docref(NULL, E_WARNING, "maxlen truncated from " ZEND_LONG_FMT " to %d bytes", maxlen, INT_MAX);
maxlen = INT_MAX;
}
if ((contents = php_stream_copy_to_mem(stream, maxlen, 0)) != NULL) {
RETVAL_STR(contents);
} else {
RETVAL_EMPTY_STRING();
}
php_stream_close(stream);
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库