正则表达式获取MTOM二进制内容

时间:2018-06-13 15:25:19

标签: php regex soap mtom

我试图使用扩展的SoapClient类获取MTOM二进制内容,响应是这样的:

    --uuid:8c73f23e-47d9-49fb-a61c-c1df7b19a306+id=2
    Content-ID: 
    <http://tempuri.org/0>
    Content-Transfer-Encoding: 8bit
    Content-Type: application/xop+xml;charset=utf-8;type="text/xml"    

    <big-xml-here>

           <xop:Include href="cid:http://tempuri.org/1/636644204289948690" xmlns:xop="http://www.w3.org/2004/08/xop/include"/>

        </big-xml-here>

--uuid:8c73f23e-47d9-49fb-a61c-c1df7b19a306+id=2--

在XML之后,MTOM响应继续使用与&#34; cid&#34;相关的二进制文件。网址:

Content-ID: <http://tempuri.org/1/636644204289948690>
Content-Transfer-Encoding: binary
Content-Type: application/octet-stream

%PDF-1.4
%���� (lots of binary content here)

--uuid:7329cfb8-46a4-40a8-b15b-39b7b0988b57+id=4--

要提取我尝试过此代码的所有内容:

$xop_elements = null;
        preg_match_all('/<xop[\s\S]*?\/>/', $response, $xop_elements);

        $xop_elements = reset($xop_elements);

        if (is_array($xop_elements) && count($xop_elements)) {

            foreach ($xop_elements as $xop_element) {

                $cid = null;
                preg_match('/cid:(.*?)"/', $xop_element, $cid);

                if(isset($cid[1])){
                    $cid = $cid[1];
                    $binary = null;
                    preg_match("/Content-ID:.*?$cid.*?(.*?)uuid/", $response, $binary);
                    var_dump($binary);
                    exit();
                }
            }
        }

虽然preg_match_all和第一个preg_match正在运作,但最后一个:

/Content-ID:.*?$cid.*?(.*?)uuid/ 

无效

在原始来源:https://github.com/debuss/MTOMSoapClient/blob/master/MTOMSoapClient.php

正则表达式

/Content-ID:[\s\S].+?'.$cid.'[\s\S].+?>([\s\S]*?)--uuid/

但我在PHP 7上遇到错误:

  

preg_match():未知的修饰符&#39; /&#39;

是否需要获取每个CID的MTOM二进制文件?

提前致谢!

2 个答案:

答案 0 :(得分:0)

您需要首先取消引用$cid,因为这会导致您的第一个错误

$cid = preg_quote($cid[1], '/');

接下来,您需要使用s修饰符标记,以便.匹配新行

preg_match("/Content-ID:.*?$cid.*?(.*?)uuid/s", $response, $binary);
  

s(PCRE_DOTALL)   如果设置了此修饰符,则模式中的点元字符将匹配所有字符,包括换行符。没有它,排除了换行符。此修饰符等效于Perl的/ s修饰符。诸如[^ a]之类的否定类始终匹配换行符,与此修饰符的设置无关。

答案 1 :(得分:0)

据我了解,您正在尝试将原始代码调整为修改后的文件SOAP版本。

您希望在http://tempuri.org/1/636644204289948690变量中捕获整个$cid(而不是数字)(您可能希望重命名var)。为此,您可以使用以下正则表达式,该正则表达式与捕获组1中除双引号之外的所有内容均匹配:cid:([^"]+)

preg_match('/cid:([^"]+)/', $xop_element, $cid);

到目前为止,太好了。从描述中猜测,您应该使用以下模式捕获二进制部分:

'%Content-ID: <'.$cid.'>([\s\S]*?)--uuid%'

我们使用修饰的点[\ s \ S]跨多行进行匹配(如原始实现中所示)。否则,添加s |单行标志或(?s) inline modifier。另外,我使用替代的正则表达式定界符%来避免转义问题。 Tarun建议仍然使用preg_quote($cid[1], '%')

Demo

现在,您可以从捕获组1中检索有问题的块:

trim($binary[1]);