添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
不要命的菠萝  ·  book save ...·  1 年前    · 
痛苦的帽子  ·  PyTest 使用 Email 发送 ...·  2 年前    · 
热心肠的香蕉  ·  SQL 通配符 | 菜鸟教程·  2 年前    · 
喝醉的爆米花  ·  【SpringBoot MQ ...·  2 年前    · 

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement . We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Describe the Bug

It seems the regex used to search the block doesn't work with a template we use, the problem seems to be in relation with the lazy quantifiers, large strings and PHP v7.3 and superior, it works well with PHP v7.2.

Steps to Reproduce

I can't send the template because it's confidential, but :

  • When I test lazy quantifiers on simple tests nothing is wrong (PHP v7.3 + v7.4).
  • When I test with exact same data minus unuseful tags it works too (PHP v7.3 + v7.4).
  • When I test with the full file content there is no match with PHP v7.3+ but a match with v7.2.
  • Expected Behavior

    The blocks have to be cloned...

    Current Behavior

    ...but tags remain visibles.

    Context

  • PHP Version: 7.3+
  • PHPWord Version: 0.17.0
  • I met other problematic cases when the matches returned by preg_match() is too big (I suppose but it's very probable), I'm a big newbie with the Word file format but I've rewritten this function with what I've seen in my cases, the function to replace is in file /src/PhpWord/TemplateProcessor.php and here is my alternative which uses mb_*str*() functions and works at least in all of my cases :

    public function cloneBlock($blockname, $clones = 1, $replace = true, $indexVariables = false, $variableReplacements = null)
        $idx_tag = mb_strpos($this->tempDocumentMainPart, '${'.$blockname.'}');
        if ( $idx_tag === false )
          return null;
        $idx_start = mb_strrpos(mb_substr($this->tempDocumentMainPart, 0, $idx_tag), '<w:p '                       );
        $idx_end   =  mb_strpos(          $this->tempDocumentMainPart,               '${/'.$blockname.'}', $idx_tag);
        if ( $idx_start === false || $idx_end === false )
          return null;
        $idx_end = mb_strpos($this->tempDocumentMainPart, '</w:p>', $idx_end);
        if ( $idx_end === false )
          return null;
        $idx_end += 6;
        $what = mb_substr($this->tempDocumentMainPart, $idx_start, $idx_end - $idx_start);
        // --- //
        $idx_content_start =   mb_strpos($what, 'p>');
        $idx_content_end   =  mb_strrpos($what, '<w:p ');
        if ( $idx_content_start === false || $idx_content_end === false )
          return null;
        $idx_content_start += 2;
        $xmlBlock = mb_substr($what, $idx_content_start, $idx_content_end - $idx_content_start);
        // --- //
        if ( $replace )
            $by = array();
            if ( $indexVariables )
                $by = $this->indexClonedVariables($clones, $xmlBlock);
            elseif ( $variableReplacements !== null && is_array($variableReplacements) )
                $by = $this->replaceClonedVariables($variableReplacements, $xmlBlock);
                for ( $i = 1 ; $i <= $clones ; $i++ )
                    $by[] = $xmlBlock;
            $by = implode('', $by);
            $this->tempDocumentMainPart = str_replace($what, $by, $this->tempDocumentMainPart);
        return $xmlBlock;
              

    cloneBlock and other functions using preg_match ignore the return result from preg_match and therefore any errors. Checking preg_last_error after a failed cloneBlock shows the PREG_BACKTRACK_LIMIT_ERROR error.

    Increasing pcre.backtrack_limit fixes this.

    Adding ini_set("pcre.backtrack_limit", "2000000"); (double the default) to your script prior to calling TemplateProcessor::cloneBlock() works for me, for some large documents you may need to increase it further or set the limit to unlimited (-1)

    PR [#1354] does look to be the cleanest replacement using xml parsing rather than regular expressions, but in the meantime increasing the backtrack limit does save you from needing to keep a patched TemplateProcessor

    cloneBlock and other functions using preg_match ignore the return result from preg_match and therefore any errors. Checking preg_last_error after a failed cloneBlock shows the PREG_BACKTRACK_LIMIT_ERROR error.

    Increasing pcre.backtrack_limit fixes this.

    Adding ini_set("pcre.backtrack_limit", "2000000"); (double the default) to your script prior to calling TemplateProcessor::cloneBlock() works for me, for some large documents you may need to increase it further or set the limit to unlimited (-1)

    PR [#1354] does look to be the cleanest replacement using xml parsing rather than regular expressions, but in the meantime increasing the backtrack limit does save you from needing to keep a patched TemplateProcessor

    This worked, although had to keep increasing the limit... Might need to also check for a newer version of PHPOffice. But Thanks for the quick fix in my case!

    cloneBlock and other functions using preg_match ignore the return result from preg_match and therefore any errors. Checking preg_last_error after a failed cloneBlock shows the PREG_BACKTRACK_LIMIT_ERROR error.

    Increasing pcre.backtrack_limit fixes this.

    Adding ini_set("pcre.backtrack_limit", "2000000"); (double the default) to your script prior to calling TemplateProcessor::cloneBlock() works for me, for some large documents you may need to increase it further or set the limit to unlimited (-1)

    PR [#1354] does look to be the cleanest replacement using xml parsing rather than regular expressions, but in the meantime increasing the backtrack limit does save you from needing to keep a patched TemplateProcessor

    This works fine for me on PHP 5.6+, i added ini_set("pcre.backtrack_limit", "2000000"); at the beggining of cloneBlock function and voilà.
    p.s. (still had to max out the limit for larger docx)