对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);

}

posted @   从雍和宫走到电影学院  阅读(10)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
点击右上角即可分享
微信分享提示