fgetcsv() 不尊重 $enclosure
Posted
技术标签:
【中文标题】fgetcsv() 不尊重 $enclosure【英文标题】:fgetcsv() not respecting $enclosure 【发布时间】:2013-01-25 21:56:51 【问题描述】:我正在编写一个通过 Sockets 与 SMTP 服务器通信的脚本,并且我正在尝试实现 DIGEST-MD5 身份验证,但我无法解析在 AUTH 命令后返回的字符串。
在base64_decode()
之后,它看起来像:
realm="smtp.domain.net",nonce="AJRUc5Jx0UQbv5SJ9FoyUnaZpqZIHDhLTU+Awn/K0Uw=",qop="auth,auth-int",charset=utf-8,algorithm=md5-sess
本来想用str_getcsv()
,但是服务器还在php 5.2上,所以得到了下面的代码from the comments on PHP.net,看起来还不错:
<?php
if (!function_exists('str_getcsv'))
function str_getcsv($input, $delimiter=',', $enclosure='"', $escape=null, $eol=null)
$temp=fopen("php://memory", "rw");
fwrite($temp, $input);
fseek($temp, 0);
$r = array();
while (($data = fgetcsv($temp, 4096, $delimiter, $enclosure)) !== false)
$r[] = $data;
fclose($temp);
return $r;
但它返回以下内容:
array (
0 =>
array (
0 => 'realm="smtp.domain.net"',
1 => 'nonce="2PuESkmrNzGu/5b8N6eIYQoW7mSlScnYAB/PSYebkYo="',
2 => 'qop="auth',
3 => 'auth-int"',
4 => 'charset=utf-8',
5 => 'algorithm=md5-sess',
),
)
请注意,索引 2 和 3 应该是单个 qop="auth,auth-int"
。
在写这篇文章时,我意识到可能fgetcsv()
期望$enclosure
字符包含整个字段,而不仅仅是其中的一部分,但在这种情况下,我必须知道如何正确解析这个字符串。
【问题讨论】:
如果您的机箱不是"
,请使用'
。如果您的附件是"
,则realm="smtp.domain.net"
是无效字符串。至少应该是realm=\"smtp.domain.net\"
。
@Ninsuo 我无法控制传入的数据格式,不管我喜不喜欢都是realm="smtp.domain.net"
。
但是您可以尝试使用另一个附件调用您的str_getcsv
方法吗? (反正功能不错,我自己拿来^^)
讨厌fgetcsv
得不到尊重。
这不是 CSV 格式,因此 str_getcsv() 或 fgetcsv() 不起作用:您可以尝试使用 parse_str() - php.net/manual/en/function.parse-str.php - 代替
【参考方案1】:
在我对“PHP DIGEST-MD5”的谷歌搜索中,我遇到了a patch for another project,它处理与以下行相同的格式字符串:
preg_match_all('/(\w+)=(?:"([^"]*)|([^,]*))/', $challenge, $matches);
这给了我:
array (
0 =>
array (
0 => 'realm="smtp.domain.net',
1 => 'nonce="AJRUc5Jx0UQbv5SJ9FoyUnaZpqZIHDhLTU+Awn/K0Uw=',
2 => 'qop="auth,auth-int',
3 => 'charset=utf-8',
4 => 'algorithm=md5-sess',
),
1 =>
array (
0 => 'realm',
1 => 'nonce',
2 => 'qop',
3 => 'charset',
4 => 'algorithm',
),
2 =>
array (
0 => 'smtp.domain.net',
1 => 'AJRUc5Jx0UQbv5SJ9FoyUnaZpqZIHDhLTU+Awn/K0Uw=',
2 => 'auth,auth-int',
3 => '',
4 => '',
),
3 =>
array (
0 => '',
1 => '',
2 => '',
3 => 'utf-8',
4 => 'md5-sess',
),
)
然后我可以用这个循环填充一个有用的数组:
$authvars = array();
foreach( $auth_matches[1] as $key => $val )
if( !empty($auth_matches[2][$key]) )
$authvars[$val] = $auth_matches[2][$key];
else
$authvars[$val] = $auth_matches[3][$key];
这给了我:
array (
'realm' => 'ns103.zabco.net',
'nonce' => 'xITX1qgqlCDmYX6IrctN0WZRx7+Q4W7jjaXCCeUZnU8=',
'qop' => 'auth,auth-int',
'charset' => 'utf-8',
'algorithm' => 'md5-sess',
)
它并不完全漂亮,但它完成了工作。
【讨论】:
【参考方案2】:$decodedString = 'realm="smtp.domain.net",nonce="AJRUc5Jx0UQbv5SJ9FoyUnaZpqZIHDhLTU+Awn/K0Uw=",qop="auth,auth-int",charset=utf-8,algorithm=md5-sess';
parse_str(preg_replace('/(?:(")(.*?)("))?,(?:(")(.*?)("))?/','$1$2$3&$4$5$6',$decodedString), $values);
var_dump($values);
如果您还想去掉结果数组值周围的引号,请使用
$values = array_map(
function ($value)
return trim($value,'"');
,
$values
);
var_dump($values);
【讨论】:
以上是关于fgetcsv() 不尊重 $enclosure的主要内容,如果未能解决你的问题,请参考以下文章
PHP 高效导入导出Excel(csv)方法之fgetcsv()和fputcsv()函数
如何使用 PHP 和 fgetcsv 函数从 CSV 文件创建数组
使用 curl 作为 fgetcsv 的 fopen 文件资源的替代方法
php读取csv文件时 用phpexcel很慢 用fgetcsv()函数中文乱码 请问还有啥excel库或函数方法来读csv文件吗