Merge branch 'develop' into develop
This commit is contained in:
commit
af4f834149
|
|
@ -24,6 +24,7 @@ v0.15.0 (?? ??? 2018)
|
|||
- Added parsing of internal links in HTML reader @lalop #1336
|
||||
- Several improvements to charts @JAEK-S #1332
|
||||
- Add parsing of html image in base64 format @jgpATs2w #1382
|
||||
- Added Support for Indentation & Tabs on RTF Writer. @smaug1985 #1405
|
||||
|
||||
### Fixed
|
||||
- Fix reading of docx default style - @troosan #1238
|
||||
|
|
@ -36,6 +37,9 @@ v0.15.0 (?? ??? 2018)
|
|||
- Fix colspan and rowspan for tables in HTML Writer @mattbolt #1292
|
||||
- Fix parsing of Heading and Title formating @troosan @gthomas2 #465
|
||||
- Fix Dateformat typo, fix hours casing, add Month-Day-Year formats @ComputerTinker #591
|
||||
- Support reading of w:drawing for documents produced by word 2011+ @gthomas2 #464 #1324
|
||||
- Fix missing column width in ODText writer @potofcoffee #413
|
||||
- Disable entity loader before parsing XML to avoid XXE injection @Tom4t0 #1427
|
||||
|
||||
### Changed
|
||||
- Remove zend-stdlib dependency @Trainmaster #1284
|
||||
|
|
|
|||
|
|
@ -61,10 +61,12 @@
|
|||
"php": "^5.3.3 || ^7.0",
|
||||
"ext-xml": "*",
|
||||
"zendframework/zend-escaper": "^2.2",
|
||||
"phpoffice/common": "^0.2"
|
||||
"phpoffice/common": "^0.2.9"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^4.8.36 || ^5.0",
|
||||
"ext-zip": "*",
|
||||
"ext-gd": "*",
|
||||
"phpunit/phpunit": "^4.8.36 || ^7.0",
|
||||
"squizlabs/php_codesniffer": "^2.9",
|
||||
"friendsofphp/php-cs-fixer": "^2.2",
|
||||
"phpmd/phpmd": "2.*",
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
includes:
|
||||
- vendor/phpstan/phpstan/conf/config.level1.neon
|
||||
parameters:
|
||||
memory-limit: 200000
|
||||
memory-limit: 20000000
|
||||
autoload_directories:
|
||||
- tests
|
||||
autoload_files:
|
||||
|
|
|
|||
|
|
@ -6,8 +6,7 @@
|
|||
convertNoticesToExceptions="true"
|
||||
convertWarningsToExceptions="true"
|
||||
processIsolation="false"
|
||||
stopOnFailure="false"
|
||||
syntaxCheck="false">
|
||||
stopOnFailure="false">
|
||||
<testsuites>
|
||||
<testsuite name="PhpWord Test Suite">
|
||||
<directory>./tests/PhpWord</directory>
|
||||
|
|
@ -22,7 +21,7 @@
|
|||
</whitelist>
|
||||
</filter>
|
||||
<logging>
|
||||
<log type="coverage-html" target="./build/coverage" charset="UTF-8" highlight="true" />
|
||||
<log type="coverage-html" target="./build/coverage" />
|
||||
<log type="coverage-clover" target="./build/logs/clover.xml" />
|
||||
</logging>
|
||||
</phpunit>
|
||||
|
|
@ -1,6 +1,5 @@
|
|||
<?php
|
||||
use PhpOffice\PhpWord\Style\Font;
|
||||
use PhpOffice\PhpWord\Style\Paragraph;
|
||||
|
||||
include_once 'Sample_Header.php';
|
||||
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ namespace PhpOffice\PhpWord\Element;
|
|||
* @method TOC addTOC(mixed $fontStyle = null, mixed $tocStyle = null, int $minDepth = 1, int $maxDepth = 9)
|
||||
* @method PageBreak addPageBreak()
|
||||
* @method Table addTable(mixed $style = null)
|
||||
* @method Image addImage(string $source, mixed $style = null, bool $isWatermark = false)
|
||||
* @method Image addImage(string $source, mixed $style = null, bool $isWatermark = false, $name = null)
|
||||
* @method OLEObject addOLEObject(string $source, mixed $style = null)
|
||||
* @method TextBox addTextBox(mixed $style = null)
|
||||
* @method Field addField(string $type = null, array $properties = array(), array $options = array(), mixed $text = null)
|
||||
|
|
|
|||
|
|
@ -65,6 +65,13 @@ class Image extends AbstractElement
|
|||
*/
|
||||
private $watermark;
|
||||
|
||||
/**
|
||||
* Name of image
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $name;
|
||||
|
||||
/**
|
||||
* Image type
|
||||
*
|
||||
|
|
@ -127,15 +134,17 @@ class Image extends AbstractElement
|
|||
* @param string $source
|
||||
* @param mixed $style
|
||||
* @param bool $watermark
|
||||
* @param string $name
|
||||
*
|
||||
* @throws \PhpOffice\PhpWord\Exception\InvalidImageException
|
||||
* @throws \PhpOffice\PhpWord\Exception\UnsupportedImageTypeException
|
||||
*/
|
||||
public function __construct($source, $style = null, $watermark = false)
|
||||
public function __construct($source, $style = null, $watermark = false, $name = null)
|
||||
{
|
||||
$this->source = $source;
|
||||
$this->setIsWatermark($watermark);
|
||||
$this->style = $this->setNewStyle(new ImageStyle(), $style, true);
|
||||
$this->setIsWatermark($watermark);
|
||||
$this->setName($name);
|
||||
|
||||
$this->checkImage();
|
||||
}
|
||||
|
|
@ -170,6 +179,26 @@ class Image extends AbstractElement
|
|||
return $this->sourceType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the image name
|
||||
*
|
||||
* @param string $value
|
||||
*/
|
||||
public function setName($value)
|
||||
{
|
||||
$this->name = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get image name
|
||||
*
|
||||
* @return null|string
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get image media ID
|
||||
*
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ class OLEObject extends AbstractElement
|
|||
$this->style = $this->setNewStyle(new ImageStyle(), $style, true);
|
||||
$this->icon = realpath(__DIR__ . "/../resources/{$ext}.png");
|
||||
|
||||
return $this;
|
||||
return;
|
||||
}
|
||||
|
||||
throw new InvalidObjectException();
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ class PreserveText extends AbstractElement
|
|||
/**
|
||||
* Text content
|
||||
*
|
||||
* @var string
|
||||
* @var string|array
|
||||
*/
|
||||
private $text;
|
||||
|
||||
|
|
@ -64,8 +64,6 @@ class PreserveText extends AbstractElement
|
|||
if (isset($matches[0])) {
|
||||
$this->text = $matches;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -91,7 +89,7 @@ class PreserveText extends AbstractElement
|
|||
/**
|
||||
* Get Text content
|
||||
*
|
||||
* @return string
|
||||
* @return string|array
|
||||
*/
|
||||
public function getText()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -135,18 +135,40 @@ class Table extends AbstractElement
|
|||
public function countColumns()
|
||||
{
|
||||
$columnCount = 0;
|
||||
if (is_array($this->rows)) {
|
||||
$rowCount = count($this->rows);
|
||||
for ($i = 0; $i < $rowCount; $i++) {
|
||||
/** @var \PhpOffice\PhpWord\Element\Row $row Type hint */
|
||||
$row = $this->rows[$i];
|
||||
$cellCount = count($row->getCells());
|
||||
if ($columnCount < $cellCount) {
|
||||
$columnCount = $cellCount;
|
||||
}
|
||||
|
||||
$rowCount = count($this->rows);
|
||||
for ($i = 0; $i < $rowCount; $i++) {
|
||||
/** @var \PhpOffice\PhpWord\Element\Row $row Type hint */
|
||||
$row = $this->rows[$i];
|
||||
$cellCount = count($row->getCells());
|
||||
if ($columnCount < $cellCount) {
|
||||
$columnCount = $cellCount;
|
||||
}
|
||||
}
|
||||
|
||||
return $columnCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* The first declared cell width for each column
|
||||
*
|
||||
* @return int[]
|
||||
*/
|
||||
public function findFirstDefinedCellWidths()
|
||||
{
|
||||
$cellWidths = array();
|
||||
|
||||
foreach ($this->rows as $row) {
|
||||
$cells = $row->getCells();
|
||||
if (count($cells) <= count($cellWidths)) {
|
||||
continue;
|
||||
}
|
||||
$cellWidths = array();
|
||||
foreach ($cells as $cell) {
|
||||
$cellWidths[] = $cell->getWidth();
|
||||
}
|
||||
}
|
||||
|
||||
return $cellWidths;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,14 +61,12 @@ class Title extends AbstractElement
|
|||
*/
|
||||
public function __construct($text, $depth = 1)
|
||||
{
|
||||
if (isset($text)) {
|
||||
if (is_string($text)) {
|
||||
$this->text = CommonText::toUTF8($text);
|
||||
} elseif ($text instanceof TextRun) {
|
||||
$this->text = $text;
|
||||
} else {
|
||||
throw new \InvalidArgumentException('Invalid text, should be a string or a TextRun');
|
||||
}
|
||||
if (is_string($text)) {
|
||||
$this->text = CommonText::toUTF8($text);
|
||||
} elseif ($text instanceof TextRun) {
|
||||
$this->text = $text;
|
||||
} else {
|
||||
throw new \InvalidArgumentException('Invalid text, should be a string or a TextRun');
|
||||
}
|
||||
|
||||
$this->depth = $depth;
|
||||
|
|
@ -76,8 +74,6 @@ class Title extends AbstractElement
|
|||
if (array_key_exists($styleName, Style::getStyles())) {
|
||||
$this->style = str_replace('_', '', $styleName);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
namespace PhpOffice\PhpWord\Metadata;
|
||||
|
||||
use PhpOffice\PhpWord\Shared\Microsoft\PasswordEncoder;
|
||||
use PhpOffice\Common\Microsoft\PasswordEncoder;
|
||||
use PhpOffice\PhpWord\SimpleType\DocProtect;
|
||||
|
||||
/**
|
||||
|
|
@ -113,7 +113,7 @@ class Protection
|
|||
/**
|
||||
* Set password
|
||||
*
|
||||
* @param $password
|
||||
* @param string $password
|
||||
* @return self
|
||||
*/
|
||||
public function setPassword($password)
|
||||
|
|
@ -136,7 +136,7 @@ class Protection
|
|||
/**
|
||||
* Set count for hash iterations
|
||||
*
|
||||
* @param $spinCount
|
||||
* @param int $spinCount
|
||||
* @return self
|
||||
*/
|
||||
public function setSpinCount($spinCount)
|
||||
|
|
@ -159,7 +159,7 @@ class Protection
|
|||
/**
|
||||
* Set algorithm
|
||||
*
|
||||
* @param $algorithm
|
||||
* @param string $algorithm
|
||||
* @return self
|
||||
*/
|
||||
public function setAlgorithm($algorithm)
|
||||
|
|
|
|||
|
|
@ -261,6 +261,20 @@ abstract class AbstractPart
|
|||
}
|
||||
$parent->addImage($imageSource);
|
||||
}
|
||||
} elseif ($node->nodeName == 'w:drawing') {
|
||||
// Office 2011 Image
|
||||
$xmlReader->registerNamespace('wp', 'http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing');
|
||||
$xmlReader->registerNamespace('r', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships');
|
||||
$xmlReader->registerNamespace('pic', 'http://schemas.openxmlformats.org/drawingml/2006/picture');
|
||||
$xmlReader->registerNamespace('a', 'http://schemas.openxmlformats.org/drawingml/2006/main');
|
||||
|
||||
$name = $xmlReader->getAttribute('name', $node, 'wp:inline/a:graphic/a:graphicData/pic:pic/pic:nvPicPr/pic:cNvPr');
|
||||
$embedId = $xmlReader->getAttribute('r:embed', $node, 'wp:inline/a:graphic/a:graphicData/pic:pic/pic:blipFill/a:blip');
|
||||
$target = $this->getMediaTarget($docPart, $embedId);
|
||||
if (!is_null($target)) {
|
||||
$imageSource = "zip://{$this->docFile}#{$target}";
|
||||
$parent->addImage($imageSource, null, false, $name);
|
||||
}
|
||||
} elseif ($node->nodeName == 'w:object') {
|
||||
// Object
|
||||
$rId = $xmlReader->getAttribute('r:id', $node, 'o:OLEObject');
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ class Settings extends AbstractPart
|
|||
*
|
||||
* @param XMLReader $xmlReader
|
||||
* @param PhpWord $phpWord
|
||||
* @param \DOMNode $node
|
||||
* @param \DOMElement $node
|
||||
*/
|
||||
protected function setThemeFontLang(XMLReader $xmlReader, PhpWord $phpWord, \DOMElement $node)
|
||||
{
|
||||
|
|
@ -102,7 +102,7 @@ class Settings extends AbstractPart
|
|||
*
|
||||
* @param XMLReader $xmlReader
|
||||
* @param PhpWord $phpWord
|
||||
* @param \DOMNode $node
|
||||
* @param \DOMElement $node
|
||||
*/
|
||||
protected function setDocumentProtection(XMLReader $xmlReader, PhpWord $phpWord, \DOMElement $node)
|
||||
{
|
||||
|
|
@ -119,7 +119,7 @@ class Settings extends AbstractPart
|
|||
*
|
||||
* @param XMLReader $xmlReader
|
||||
* @param PhpWord $phpWord
|
||||
* @param \DOMNode $node
|
||||
* @param \DOMElement $node
|
||||
*/
|
||||
protected function setProofState(XMLReader $xmlReader, PhpWord $phpWord, \DOMElement $node)
|
||||
{
|
||||
|
|
@ -141,7 +141,7 @@ class Settings extends AbstractPart
|
|||
*
|
||||
* @param XMLReader $xmlReader
|
||||
* @param PhpWord $phpWord
|
||||
* @param \DOMNode $node
|
||||
* @param \DOMElement $node
|
||||
*/
|
||||
protected function setZoom(XMLReader $xmlReader, PhpWord $phpWord, \DOMElement $node)
|
||||
{
|
||||
|
|
@ -158,7 +158,7 @@ class Settings extends AbstractPart
|
|||
*
|
||||
* @param XMLReader $xmlReader
|
||||
* @param PhpWord $phpWord
|
||||
* @param \DOMNode $node
|
||||
* @param \DOMElement $node
|
||||
*/
|
||||
protected function setRevisionView(XMLReader $xmlReader, PhpWord $phpWord, \DOMElement $node)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -71,10 +71,11 @@ class Html
|
|||
}
|
||||
|
||||
// Load DOM
|
||||
libxml_disable_entity_loader(true);
|
||||
$dom = new \DOMDocument();
|
||||
$dom->preserveWhiteSpace = $preserveWhiteSpace;
|
||||
$dom->loadXML($html);
|
||||
self::$xpath = new \DOMXpath($dom);
|
||||
self::$xpath = new \DOMXPath($dom);
|
||||
$node = $dom->getElementsByTagName('body');
|
||||
|
||||
self::parseNode($node->item(0), $element);
|
||||
|
|
|
|||
|
|
@ -1,235 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is part of PHPWord - A pure PHP library for reading and writing
|
||||
* word processing documents.
|
||||
*
|
||||
* PHPWord is free software distributed under the terms of the GNU Lesser
|
||||
* General Public License version 3 as published by the Free Software Foundation.
|
||||
*
|
||||
* For the full copyright and license information, please read the LICENSE
|
||||
* file that was distributed with this source code. For the full list of
|
||||
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
|
||||
*
|
||||
* @see https://github.com/PHPOffice/PHPWord
|
||||
* @copyright 2010-2018 PHPWord contributors
|
||||
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3
|
||||
*/
|
||||
|
||||
namespace PhpOffice\PhpWord\Shared\Microsoft;
|
||||
|
||||
/**
|
||||
* Password encoder for microsoft office applications
|
||||
*/
|
||||
class PasswordEncoder
|
||||
{
|
||||
const ALGORITHM_MD2 = 'MD2';
|
||||
const ALGORITHM_MD4 = 'MD4';
|
||||
const ALGORITHM_MD5 = 'MD5';
|
||||
const ALGORITHM_SHA_1 = 'SHA-1';
|
||||
const ALGORITHM_SHA_256 = 'SHA-256';
|
||||
const ALGORITHM_SHA_384 = 'SHA-384';
|
||||
const ALGORITHM_SHA_512 = 'SHA-512';
|
||||
const ALGORITHM_RIPEMD = 'RIPEMD';
|
||||
const ALGORITHM_RIPEMD_160 = 'RIPEMD-160';
|
||||
const ALGORITHM_MAC = 'MAC';
|
||||
const ALGORITHM_HMAC = 'HMAC';
|
||||
|
||||
/**
|
||||
* Mapping between algorithm name and algorithm ID
|
||||
*
|
||||
* @var array
|
||||
* @see https://msdn.microsoft.com/en-us/library/documentformat.openxml.wordprocessing.writeprotection.cryptographicalgorithmsid(v=office.14).aspx
|
||||
*/
|
||||
private static $algorithmMapping = array(
|
||||
self::ALGORITHM_MD2 => array(1, 'md2'),
|
||||
self::ALGORITHM_MD4 => array(2, 'md4'),
|
||||
self::ALGORITHM_MD5 => array(3, 'md5'),
|
||||
self::ALGORITHM_SHA_1 => array(4, 'sha1'),
|
||||
self::ALGORITHM_MAC => array(5, ''), // 'mac' -> not possible with hash()
|
||||
self::ALGORITHM_RIPEMD => array(6, 'ripemd'),
|
||||
self::ALGORITHM_RIPEMD_160 => array(7, 'ripemd160'),
|
||||
self::ALGORITHM_HMAC => array(9, ''), //'hmac' -> not possible with hash()
|
||||
self::ALGORITHM_SHA_256 => array(12, 'sha256'),
|
||||
self::ALGORITHM_SHA_384 => array(13, 'sha384'),
|
||||
self::ALGORITHM_SHA_512 => array(14, 'sha512'),
|
||||
);
|
||||
|
||||
private static $initialCodeArray = array(
|
||||
0xE1F0,
|
||||
0x1D0F,
|
||||
0xCC9C,
|
||||
0x84C0,
|
||||
0x110C,
|
||||
0x0E10,
|
||||
0xF1CE,
|
||||
0x313E,
|
||||
0x1872,
|
||||
0xE139,
|
||||
0xD40F,
|
||||
0x84F9,
|
||||
0x280C,
|
||||
0xA96A,
|
||||
0x4EC3,
|
||||
);
|
||||
|
||||
private static $encryptionMatrix = array(
|
||||
array(0xAEFC, 0x4DD9, 0x9BB2, 0x2745, 0x4E8A, 0x9D14, 0x2A09),
|
||||
array(0x7B61, 0xF6C2, 0xFDA5, 0xEB6B, 0xC6F7, 0x9DCF, 0x2BBF),
|
||||
array(0x4563, 0x8AC6, 0x05AD, 0x0B5A, 0x16B4, 0x2D68, 0x5AD0),
|
||||
array(0x0375, 0x06EA, 0x0DD4, 0x1BA8, 0x3750, 0x6EA0, 0xDD40),
|
||||
array(0xD849, 0xA0B3, 0x5147, 0xA28E, 0x553D, 0xAA7A, 0x44D5),
|
||||
array(0x6F45, 0xDE8A, 0xAD35, 0x4A4B, 0x9496, 0x390D, 0x721A),
|
||||
array(0xEB23, 0xC667, 0x9CEF, 0x29FF, 0x53FE, 0xA7FC, 0x5FD9),
|
||||
array(0x47D3, 0x8FA6, 0x0F6D, 0x1EDA, 0x3DB4, 0x7B68, 0xF6D0),
|
||||
array(0xB861, 0x60E3, 0xC1C6, 0x93AD, 0x377B, 0x6EF6, 0xDDEC),
|
||||
array(0x45A0, 0x8B40, 0x06A1, 0x0D42, 0x1A84, 0x3508, 0x6A10),
|
||||
array(0xAA51, 0x4483, 0x8906, 0x022D, 0x045A, 0x08B4, 0x1168),
|
||||
array(0x76B4, 0xED68, 0xCAF1, 0x85C3, 0x1BA7, 0x374E, 0x6E9C),
|
||||
array(0x3730, 0x6E60, 0xDCC0, 0xA9A1, 0x4363, 0x86C6, 0x1DAD),
|
||||
array(0x3331, 0x6662, 0xCCC4, 0x89A9, 0x0373, 0x06E6, 0x0DCC),
|
||||
array(0x1021, 0x2042, 0x4084, 0x8108, 0x1231, 0x2462, 0x48C4),
|
||||
);
|
||||
|
||||
private static $passwordMaxLength = 15;
|
||||
|
||||
/**
|
||||
* Create a hashed password that MS Word will be able to work with
|
||||
* @see https://blogs.msdn.microsoft.com/vsod/2010/04/05/how-to-set-the-editing-restrictions-in-word-using-open-xml-sdk-2-0/
|
||||
*
|
||||
* @param string $password
|
||||
* @param string $algorithmName
|
||||
* @param string $salt
|
||||
* @param int $spinCount
|
||||
* @return string
|
||||
*/
|
||||
public static function hashPassword($password, $algorithmName = self::ALGORITHM_SHA_1, $salt = null, $spinCount = 10000)
|
||||
{
|
||||
$origEncoding = mb_internal_encoding();
|
||||
mb_internal_encoding('UTF-8');
|
||||
|
||||
$password = mb_substr($password, 0, min(self::$passwordMaxLength, mb_strlen($password)));
|
||||
|
||||
// Get the single-byte values by iterating through the Unicode characters of the truncated password.
|
||||
// For each character, if the low byte is not equal to 0, take it. Otherwise, take the high byte.
|
||||
$passUtf8 = mb_convert_encoding($password, 'UCS-2LE', 'UTF-8');
|
||||
$byteChars = array();
|
||||
|
||||
for ($i = 0; $i < mb_strlen($password); $i++) {
|
||||
$byteChars[$i] = ord(substr($passUtf8, $i * 2, 1));
|
||||
|
||||
if ($byteChars[$i] == 0) {
|
||||
$byteChars[$i] = ord(substr($passUtf8, $i * 2 + 1, 1));
|
||||
}
|
||||
}
|
||||
|
||||
// build low-order word and hig-order word and combine them
|
||||
$combinedKey = self::buildCombinedKey($byteChars);
|
||||
// build reversed hexadecimal string
|
||||
$hex = str_pad(strtoupper(dechex($combinedKey & 0xFFFFFFFF)), 8, '0', \STR_PAD_LEFT);
|
||||
$reversedHex = $hex[6] . $hex[7] . $hex[4] . $hex[5] . $hex[2] . $hex[3] . $hex[0] . $hex[1];
|
||||
|
||||
$generatedKey = mb_convert_encoding($reversedHex, 'UCS-2LE', 'UTF-8');
|
||||
|
||||
// Implementation Notes List:
|
||||
// Word requires that the initial hash of the password with the salt not be considered in the count.
|
||||
// The initial hash of salt + key is not included in the iteration count.
|
||||
$algorithm = self::getAlgorithm($algorithmName);
|
||||
$generatedKey = hash($algorithm, $salt . $generatedKey, true);
|
||||
|
||||
for ($i = 0; $i < $spinCount; $i++) {
|
||||
$generatedKey = hash($algorithm, $generatedKey . pack('CCCC', $i, $i >> 8, $i >> 16, $i >> 24), true);
|
||||
}
|
||||
$generatedKey = base64_encode($generatedKey);
|
||||
|
||||
mb_internal_encoding($origEncoding);
|
||||
|
||||
return $generatedKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get algorithm from self::$algorithmMapping
|
||||
*
|
||||
* @param string $algorithmName
|
||||
* @return string
|
||||
*/
|
||||
private static function getAlgorithm($algorithmName)
|
||||
{
|
||||
$algorithm = self::$algorithmMapping[$algorithmName][1];
|
||||
if ($algorithm == '') {
|
||||
$algorithm = 'sha1';
|
||||
}
|
||||
|
||||
return $algorithm;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the algorithm ID
|
||||
*
|
||||
* @param string $algorithmName
|
||||
* @return int
|
||||
*/
|
||||
public static function getAlgorithmId($algorithmName)
|
||||
{
|
||||
return self::$algorithmMapping[$algorithmName][0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Build combined key from low-order word and high-order word
|
||||
*
|
||||
* @param array $byteChars byte array representation of password
|
||||
* @return int
|
||||
*/
|
||||
private static function buildCombinedKey($byteChars)
|
||||
{
|
||||
$byteCharsLength = count($byteChars);
|
||||
// Compute the high-order word
|
||||
// Initialize from the initial code array (see above), depending on the passwords length.
|
||||
$highOrderWord = self::$initialCodeArray[$byteCharsLength - 1];
|
||||
|
||||
// For each character in the password:
|
||||
// For every bit in the character, starting with the least significant and progressing to (but excluding)
|
||||
// the most significant, if the bit is set, XOR the key’s high-order word with the corresponding word from
|
||||
// the Encryption Matrix
|
||||
for ($i = 0; $i < $byteCharsLength; $i++) {
|
||||
$tmp = self::$passwordMaxLength - $byteCharsLength + $i;
|
||||
$matrixRow = self::$encryptionMatrix[$tmp];
|
||||
for ($intBit = 0; $intBit < 7; $intBit++) {
|
||||
if (($byteChars[$i] & (0x0001 << $intBit)) != 0) {
|
||||
$highOrderWord = ($highOrderWord ^ $matrixRow[$intBit]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Compute low-order word
|
||||
// Initialize with 0
|
||||
$lowOrderWord = 0;
|
||||
// For each character in the password, going backwards
|
||||
for ($i = $byteCharsLength - 1; $i >= 0; $i--) {
|
||||
// low-order word = (((low-order word SHR 14) AND 0x0001) OR (low-order word SHL 1) AND 0x7FFF)) XOR character
|
||||
$lowOrderWord = (((($lowOrderWord >> 14) & 0x0001) | (($lowOrderWord << 1) & 0x7FFF)) ^ $byteChars[$i]);
|
||||
}
|
||||
// Lastly, low-order word = (((low-order word SHR 14) AND 0x0001) OR (low-order word SHL 1) AND 0x7FFF)) XOR strPassword length XOR 0xCE4B.
|
||||
$lowOrderWord = (((($lowOrderWord >> 14) & 0x0001) | (($lowOrderWord << 1) & 0x7FFF)) ^ $byteCharsLength ^ 0xCE4B);
|
||||
|
||||
// Combine the Low and High Order Word
|
||||
return self::int32(($highOrderWord << 16) + $lowOrderWord);
|
||||
}
|
||||
|
||||
/**
|
||||
* Simulate behaviour of (signed) int32
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
* @param int $value
|
||||
* @return int
|
||||
*/
|
||||
private static function int32($value)
|
||||
{
|
||||
$value = ($value & 0xFFFFFFFF);
|
||||
|
||||
if ($value & 0x80000000) {
|
||||
$value = -((~$value & 0xFFFFFFFF) + 1);
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
|
|
@ -47,6 +47,9 @@ final class Language extends AbstractStyle
|
|||
const HE_IL = 'he-IL';
|
||||
const HE_IL_ID = 1037;
|
||||
|
||||
const IT_IT = 'it-IT';
|
||||
const IT_IT_ID = 1040;
|
||||
|
||||
const JA_JP = 'ja-JP';
|
||||
const JA_JP_ID = 1041;
|
||||
|
||||
|
|
|
|||
|
|
@ -163,6 +163,13 @@ class Table extends Border
|
|||
/** @var TblWidthComplexType|null */
|
||||
private $indent;
|
||||
|
||||
/**
|
||||
* The width of each column, computed based on the max cell width of each column
|
||||
*
|
||||
* @var int[]
|
||||
*/
|
||||
private $columnWidths;
|
||||
|
||||
/**
|
||||
* Create new table style
|
||||
*
|
||||
|
|
@ -748,4 +755,24 @@ class Table extends Border
|
|||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the columnWidths
|
||||
*
|
||||
* @return number[]
|
||||
*/
|
||||
public function getColumnWidths()
|
||||
{
|
||||
return $this->columnWidths;
|
||||
}
|
||||
|
||||
/**
|
||||
* The column widths
|
||||
*
|
||||
* @param int[] $value
|
||||
*/
|
||||
public function setColumnWidths(array $value = null)
|
||||
{
|
||||
$this->columnWidths = $value;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -113,6 +113,7 @@ class TemplateProcessor
|
|||
*/
|
||||
protected function transformSingleXml($xml, $xsltProcessor)
|
||||
{
|
||||
libxml_disable_entity_loader(true);
|
||||
$domDocument = new \DOMDocument();
|
||||
if (false === $domDocument->loadXML($xml)) {
|
||||
throw new Exception('Could not load the given XML document.');
|
||||
|
|
|
|||
|
|
@ -17,6 +17,10 @@
|
|||
|
||||
namespace PhpOffice\PhpWord\Writer\ODText\Element;
|
||||
|
||||
use PhpOffice\Common\XMLWriter;
|
||||
use PhpOffice\PhpWord\Element\Row as RowElement;
|
||||
use PhpOffice\PhpWord\Element\Table as TableElement;
|
||||
|
||||
/**
|
||||
* Table element writer
|
||||
*
|
||||
|
|
@ -36,32 +40,59 @@ class Table extends AbstractElement
|
|||
}
|
||||
$rows = $element->getRows();
|
||||
$rowCount = count($rows);
|
||||
$colCount = $element->countColumns();
|
||||
|
||||
if ($rowCount > 0) {
|
||||
$xmlWriter->startElement('table:table');
|
||||
$xmlWriter->writeAttribute('table:name', $element->getElementId());
|
||||
$xmlWriter->writeAttribute('table:style', $element->getElementId());
|
||||
|
||||
$xmlWriter->startElement('table:table-column');
|
||||
$xmlWriter->writeAttribute('table:number-columns-repeated', $colCount);
|
||||
$xmlWriter->endElement(); // table:table-column
|
||||
// Write columns
|
||||
$this->writeColumns($xmlWriter, $element);
|
||||
|
||||
// Write rows
|
||||
foreach ($rows as $row) {
|
||||
$xmlWriter->startElement('table:table-row');
|
||||
/** @var $row \PhpOffice\PhpWord\Element\Row Type hint */
|
||||
foreach ($row->getCells() as $cell) {
|
||||
$xmlWriter->startElement('table:table-cell');
|
||||
$xmlWriter->writeAttribute('office:value-type', 'string');
|
||||
|
||||
$containerWriter = new Container($xmlWriter, $cell);
|
||||
$containerWriter->write();
|
||||
|
||||
$xmlWriter->endElement(); // table:table-cell
|
||||
}
|
||||
$xmlWriter->endElement(); // table:table-row
|
||||
$this->writeRow($xmlWriter, $row);
|
||||
}
|
||||
$xmlWriter->endElement(); // table:table
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write column.
|
||||
*
|
||||
* @param \PhpOffice\Common\XMLWriter $xmlWriter
|
||||
* @param \PhpOffice\PhpWord\Element\Table $element
|
||||
*/
|
||||
private function writeColumns(XMLWriter $xmlWriter, TableElement $element)
|
||||
{
|
||||
$colCount = $element->countColumns();
|
||||
|
||||
for ($i = 0; $i < $colCount; $i++) {
|
||||
$xmlWriter->startElement('table:table-column');
|
||||
$xmlWriter->writeAttribute('table:style-name', $element->getElementId() . '.' . $i);
|
||||
$xmlWriter->endElement();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write row.
|
||||
*
|
||||
* @param \PhpOffice\Common\XMLWriter $xmlWriter
|
||||
* @param \PhpOffice\PhpWord\Element\Row $row
|
||||
*/
|
||||
private function writeRow(XMLWriter $xmlWriter, RowElement $row)
|
||||
{
|
||||
$xmlWriter->startElement('table:table-row');
|
||||
/** @var $row \PhpOffice\PhpWord\Element\Row Type hint */
|
||||
foreach ($row->getCells() as $cell) {
|
||||
$xmlWriter->startElement('table:table-cell');
|
||||
$xmlWriter->writeAttribute('office:value-type', 'string');
|
||||
|
||||
$containerWriter = new Container($xmlWriter, $cell);
|
||||
$containerWriter->write();
|
||||
|
||||
$xmlWriter->endElement(); // table:table-cell
|
||||
}
|
||||
$xmlWriter->endElement(); // table:table-row
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -239,6 +239,7 @@ class Content extends AbstractPart
|
|||
$style->setStyleName('fr' . $element->getMediaIndex());
|
||||
$this->autoStyles['Image'][] = $style;
|
||||
} elseif ($element instanceof Table) {
|
||||
/** @var \PhpOffice\PhpWord\Style\Table $style */
|
||||
$style = $element->getStyle();
|
||||
if ($style === null) {
|
||||
$style = new TableStyle();
|
||||
|
|
@ -246,6 +247,7 @@ class Content extends AbstractPart
|
|||
$style = Style::getStyle($style);
|
||||
}
|
||||
$style->setStyleName($element->getElementId());
|
||||
$style->setColumnWidths($element->findFirstDefinedCellWidths());
|
||||
$this->autoStyles['Table'][] = $style;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,5 +45,19 @@ class Table extends AbstractStyle
|
|||
$xmlWriter->writeAttribute('table:align', 'center');
|
||||
$xmlWriter->endElement(); // style:table-properties
|
||||
$xmlWriter->endElement(); // style:style
|
||||
|
||||
$cellWidths = $style->getColumnWidths();
|
||||
$countCellWidths = count($cellWidths);
|
||||
|
||||
for ($i = 0; $i < $countCellWidths; $i++) {
|
||||
$width = $cellWidths[$i];
|
||||
$xmlWriter->startElement('style:style');
|
||||
$xmlWriter->writeAttribute('style:name', $style->getStyleName() . '.' . $i);
|
||||
$xmlWriter->writeAttribute('style:family', 'table-column');
|
||||
$xmlWriter->startElement('style:table-column-properties');
|
||||
$xmlWriter->writeAttribute('style:column-width', number_format($width * 0.0017638889, 2, '.', '') . 'cm');
|
||||
$xmlWriter->endElement(); // style:table-column-properties
|
||||
$xmlWriter->endElement(); // style:style
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,45 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is part of PHPWord - A pure PHP library for reading and writing
|
||||
* word processing documents.
|
||||
*
|
||||
* PHPWord is free software distributed under the terms of the GNU Lesser
|
||||
* General Public License version 3 as published by the Free Software Foundation.
|
||||
*
|
||||
* For the full copyright and license information, please read the LICENSE
|
||||
* file that was distributed with this source code. For the full list of
|
||||
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
|
||||
*
|
||||
* @see https://github.com/PHPOffice/PHPWord
|
||||
* @copyright 2010-2018 PHPWord contributors
|
||||
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3
|
||||
*/
|
||||
|
||||
namespace PhpOffice\PhpWord\Writer\RTF\Style;
|
||||
|
||||
/**
|
||||
* RTF indentation style writer
|
||||
*
|
||||
* @since 0.11.0
|
||||
*/
|
||||
class Indentation extends AbstractStyle
|
||||
{
|
||||
/**
|
||||
* Write style
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function write()
|
||||
{
|
||||
$style = $this->getStyle();
|
||||
if (!$style instanceof \PhpOffice\PhpWord\Style\Indentation) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$content = '\fi' . $style->getFirstLine();
|
||||
$content .= '\li' . $style->getLeft();
|
||||
$content .= '\ri' . $style->getRight();
|
||||
|
||||
return $content . ' ';
|
||||
}
|
||||
}
|
||||
|
|
@ -64,9 +64,49 @@ class Paragraph extends AbstractStyle
|
|||
if (isset($alignments[$style->getAlignment()])) {
|
||||
$content .= $alignments[$style->getAlignment()];
|
||||
}
|
||||
$content .= $this->writeIndentation($style->getIndentation());
|
||||
$content .= $this->getValueIf($spaceBefore !== null, '\sb' . $spaceBefore);
|
||||
$content .= $this->getValueIf($spaceAfter !== null, '\sa' . $spaceAfter);
|
||||
|
||||
$styles = $style->getStyleValues();
|
||||
$content .= $this->writeTabs($styles['tabs']);
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes an \PhpOffice\PhpWord\Style\Indentation
|
||||
*
|
||||
* @param null|\PhpOffice\PhpWord\Style\Indentation $indent
|
||||
* @return string
|
||||
*/
|
||||
private function writeIndentation($indent = null)
|
||||
{
|
||||
if (isset($indent) && $indent instanceof \PhpOffice\PhpWord\Style\Indentation) {
|
||||
$writer = new Indentation($indent);
|
||||
|
||||
return $writer->write();
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes tabs
|
||||
*
|
||||
* @param \PhpOffice\PhpWord\Style\Tab[] $tabs
|
||||
* @return string
|
||||
*/
|
||||
private function writeTabs($tabs = null)
|
||||
{
|
||||
$content = '';
|
||||
if (!empty($tabs)) {
|
||||
foreach ($tabs as $tab) {
|
||||
$styleWriter = new Tab($tab);
|
||||
$content .= $styleWriter->write();
|
||||
}
|
||||
}
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,49 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is part of PHPWord - A pure PHP library for reading and writing
|
||||
* word processing documents.
|
||||
*
|
||||
* PHPWord is free software distributed under the terms of the GNU Lesser
|
||||
* General Public License version 3 as published by the Free Software Foundation.
|
||||
*
|
||||
* For the full copyright and license information, please read the LICENSE
|
||||
* file that was distributed with this source code. For the full list of
|
||||
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
|
||||
*
|
||||
* @see https://github.com/PHPOffice/PHPWord
|
||||
* @copyright 2010-2018 PHPWord contributors
|
||||
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3
|
||||
*/
|
||||
|
||||
namespace PhpOffice\PhpWord\Writer\RTF\Style;
|
||||
|
||||
/**
|
||||
* Line numbering style writer
|
||||
*
|
||||
* @since 0.10.0
|
||||
*/
|
||||
class Tab extends AbstractStyle
|
||||
{
|
||||
/**
|
||||
* Write style.
|
||||
*/
|
||||
public function write()
|
||||
{
|
||||
$style = $this->getStyle();
|
||||
if (!$style instanceof \PhpOffice\PhpWord\Style\Tab) {
|
||||
return;
|
||||
}
|
||||
$tabs = array(
|
||||
\PhpOffice\PhpWord\Style\Tab::TAB_STOP_RIGHT => '\tqr',
|
||||
\PhpOffice\PhpWord\Style\Tab::TAB_STOP_CENTER => '\tqc',
|
||||
\PhpOffice\PhpWord\Style\Tab::TAB_STOP_DECIMAL => '\tqdec',
|
||||
);
|
||||
$content = '';
|
||||
if (isset($tabs[$style->getType()])) {
|
||||
$content .= $tabs[$style->getType()];
|
||||
}
|
||||
$content .= '\tx' . $style->getPosition();
|
||||
|
||||
return $content;
|
||||
}
|
||||
}
|
||||
|
|
@ -76,21 +76,7 @@ class Table extends AbstractElement
|
|||
*/
|
||||
private function writeColumns(XMLWriter $xmlWriter, TableElement $element)
|
||||
{
|
||||
$rows = $element->getRows();
|
||||
$rowCount = count($rows);
|
||||
|
||||
$cellWidths = array();
|
||||
for ($i = 0; $i < $rowCount; $i++) {
|
||||
$row = $rows[$i];
|
||||
$cells = $row->getCells();
|
||||
if (count($cells) <= count($cellWidths)) {
|
||||
continue;
|
||||
}
|
||||
$cellWidths = array();
|
||||
foreach ($cells as $cell) {
|
||||
$cellWidths[] = $cell->getWidth();
|
||||
}
|
||||
}
|
||||
$cellWidths = $element->findFirstDefinedCellWidths();
|
||||
|
||||
$xmlWriter->startElement('w:tblGrid');
|
||||
foreach ($cellWidths as $width) {
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ class Title extends AbstractElement
|
|||
$xmlWriter->endElement();
|
||||
}
|
||||
|
||||
$bookmarkRId = null;
|
||||
if ($element->getDepth() !== 0) {
|
||||
$rId = $element->getRelationId();
|
||||
$bookmarkRId = $element->getPhpWord()->addBookmark();
|
||||
|
|
|
|||
|
|
@ -330,11 +330,11 @@ class Chart extends AbstractPart
|
|||
$valueAxisTitle = $style->getValueAxisTitle();
|
||||
|
||||
if ($axisType == 'c:catAx') {
|
||||
if (isset($categoryAxisTitle)) {
|
||||
if (!is_null($categoryAxisTitle)) {
|
||||
$this->writeAxisTitle($xmlWriter, $categoryAxisTitle);
|
||||
}
|
||||
} elseif ($axisType == 'c:valAx') {
|
||||
if (isset($valueAxisTitle)) {
|
||||
if (!is_null($valueAxisTitle)) {
|
||||
$this->writeAxisTitle($xmlWriter, $valueAxisTitle);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,9 +17,9 @@
|
|||
|
||||
namespace PhpOffice\PhpWord\Writer\Word2007\Part;
|
||||
|
||||
use PhpOffice\Common\Microsoft\PasswordEncoder;
|
||||
use PhpOffice\PhpWord\ComplexType\ProofState;
|
||||
use PhpOffice\PhpWord\ComplexType\TrackChangesView;
|
||||
use PhpOffice\PhpWord\Shared\Microsoft\PasswordEncoder;
|
||||
use PhpOffice\PhpWord\Style\Language;
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -236,4 +236,40 @@ class ElementTest extends AbstractTestReader
|
|||
$this->assertEquals('Title', $formattedTitle->getStyle());
|
||||
$this->assertInstanceOf('PhpOffice\PhpWord\Element\TextRun', $formattedTitle->getText());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test reading Drawing
|
||||
*/
|
||||
public function testReadDrawing()
|
||||
{
|
||||
$documentXml = '<w:p>
|
||||
<w:r>
|
||||
<w:drawing xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing">
|
||||
<wp:inline distT="0" distB="0" distL="0" distR="0">
|
||||
<wp:extent cx="5727700" cy="6621145"/>
|
||||
<wp:docPr id="1" name="Picture 1"/>
|
||||
<a:graphic xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main">
|
||||
<a:graphicData uri="http://schemas.openxmlformats.org/drawingml/2006/picture">
|
||||
<pic:pic xmlns:pic="http://schemas.openxmlformats.org/drawingml/2006/picture">
|
||||
<pic:nvPicPr>
|
||||
<pic:cNvPr id="1" name="file_name.jpg"/>
|
||||
<pic:cNvPicPr/>
|
||||
</pic:nvPicPr>
|
||||
<pic:blipFill>
|
||||
<a:blip r:embed="rId4" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">
|
||||
</a:blip>
|
||||
</pic:blipFill>
|
||||
</pic:pic>
|
||||
</a:graphicData>
|
||||
</a:graphic>
|
||||
</wp:inline>
|
||||
</w:drawing>
|
||||
</w:r>
|
||||
</w:p>';
|
||||
|
||||
$phpWord = $this->getDocumentFromString(array('document' => $documentXml));
|
||||
|
||||
$elements = $phpWord->getSection(0)->getElements();
|
||||
$this->assertInstanceOf('PhpOffice\PhpWord\Element\TextRun', $elements[0]);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,4 +64,18 @@ class Word2007Test extends \PHPUnit\Framework\TestCase
|
|||
$doc = TestHelperDOCX::getDocument($phpWord);
|
||||
$this->assertFalse($doc->elementExists('/w:document/w:body/w:p/w:r[w:t/node()="italics"]/w:rPr/w:b'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a Word 2011 file
|
||||
*/
|
||||
public function testLoadWord2011()
|
||||
{
|
||||
$filename = __DIR__ . '/../_files/documents/reader-2011.docx';
|
||||
$phpWord = IOFactory::load($filename);
|
||||
|
||||
$this->assertInstanceOf('PhpOffice\\PhpWord\\PhpWord', $phpWord);
|
||||
|
||||
$doc = TestHelperDOCX::getDocument($phpWord);
|
||||
$this->assertTrue($doc->elementExists('/w:document/w:body/w:p[3]/w:r/w:pict/v:shape/v:imagedata'));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,91 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is part of PHPWord - A pure PHP library for reading and writing
|
||||
* word processing documents.
|
||||
*
|
||||
* PHPWord is free software distributed under the terms of the GNU Lesser
|
||||
* General Public License version 3 as published by the Free Software Foundation.
|
||||
*
|
||||
* For the full copyright and license information, please read the LICENSE
|
||||
* file that was distributed with this source code. For the full list of
|
||||
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
|
||||
*
|
||||
* @see https://github.com/PHPOffice/PHPWord
|
||||
* @copyright 2010-2018 PHPWord contributors
|
||||
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3
|
||||
*/
|
||||
|
||||
namespace PhpOffice\PhpWord\Shared;
|
||||
|
||||
use PhpOffice\PhpWord\Shared\Microsoft\PasswordEncoder;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* Test class for PhpOffice\PhpWord\Shared\Html
|
||||
* @coversDefaultClass \PhpOffice\PhpWord\Shared\Html
|
||||
*/
|
||||
class PasswordEncoderTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
/**
|
||||
* Test that a password can be hashed without specifying any additional parameters
|
||||
*/
|
||||
public function testEncodePassword()
|
||||
{
|
||||
//given
|
||||
$password = 'test';
|
||||
|
||||
//when
|
||||
$hashPassword = PasswordEncoder::hashPassword($password);
|
||||
|
||||
//then
|
||||
TestCase::assertEquals('M795/MAlmGU8RIsY9Q9uDLHC7bk=', $hashPassword);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that a password can be hashed with a custom salt
|
||||
*/
|
||||
public function testEncodePasswordWithSalt()
|
||||
{
|
||||
//given
|
||||
$password = 'test';
|
||||
$salt = base64_decode('uq81pJRRGFIY5U+E9gt8tA==');
|
||||
|
||||
//when
|
||||
$hashPassword = PasswordEncoder::hashPassword($password, PasswordEncoder::ALGORITHM_SHA_1, $salt);
|
||||
|
||||
//then
|
||||
TestCase::assertEquals('QiDOcpia1YzSVJPiKPwWebl9p/0=', $hashPassword);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that the encoder falls back on SHA-1 if a non supported algorithm is given
|
||||
*/
|
||||
public function testDafaultsToSha1IfUnsupportedAlgorithm()
|
||||
{
|
||||
//given
|
||||
$password = 'test';
|
||||
$salt = base64_decode('uq81pJRRGFIY5U+E9gt8tA==');
|
||||
|
||||
//when
|
||||
$hashPassword = PasswordEncoder::hashPassword($password, PasswordEncoder::ALGORITHM_MAC, $salt);
|
||||
|
||||
//then
|
||||
TestCase::assertEquals('QiDOcpia1YzSVJPiKPwWebl9p/0=', $hashPassword);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that the encoder falls back on SHA-1 if a non supported algorithm is given
|
||||
*/
|
||||
public function testEncodePasswordWithNullAsciiCodeInPassword()
|
||||
{
|
||||
//given
|
||||
$password = 'test' . chr(0);
|
||||
$salt = base64_decode('uq81pJRRGFIY5U+E9gt8tA==');
|
||||
|
||||
//when
|
||||
$hashPassword = PasswordEncoder::hashPassword($password, PasswordEncoder::ALGORITHM_MAC, $salt, 1);
|
||||
|
||||
//then
|
||||
TestCase::assertEquals('rDV9sgdDsztoCQlvRCb1lF2wxNg=', $hashPassword);
|
||||
}
|
||||
}
|
||||
|
|
@ -17,7 +17,6 @@
|
|||
|
||||
namespace PhpOffice\PhpWord\Style;
|
||||
|
||||
use PhpOffice\PhpWord\PhpWord;
|
||||
use PhpOffice\PhpWord\TestHelperDOCX;
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ class ElementTest extends \PHPUnit\Framework\TestCase
|
|||
$text2->setTrackChange(new TrackChange(TrackChange::DELETED, 'another author', new \DateTime()));
|
||||
|
||||
$dom = $this->getAsHTML($phpWord);
|
||||
$xpath = new \DOMXpath($dom);
|
||||
$xpath = new \DOMXPath($dom);
|
||||
|
||||
$this->assertTrue($xpath->query('/html/body/p[1]/ins')->length == 1);
|
||||
$this->assertTrue($xpath->query('/html/body/p[2]/del')->length == 1);
|
||||
|
|
@ -94,7 +94,7 @@ class ElementTest extends \PHPUnit\Framework\TestCase
|
|||
$cell22->addText('second cell');
|
||||
|
||||
$dom = $this->getAsHTML($phpWord);
|
||||
$xpath = new \DOMXpath($dom);
|
||||
$xpath = new \DOMXPath($dom);
|
||||
|
||||
$this->assertTrue($xpath->query('/html/body/table/tr[1]/td')->length == 1);
|
||||
$this->assertEquals('2', $xpath->query('/html/body/table/tr/td[1]')->item(0)->attributes->getNamedItem('colspan')->textContent);
|
||||
|
|
@ -123,7 +123,7 @@ class ElementTest extends \PHPUnit\Framework\TestCase
|
|||
$row3->addCell(500)->addText('third cell being spanned');
|
||||
|
||||
$dom = $this->getAsHTML($phpWord);
|
||||
$xpath = new \DOMXpath($dom);
|
||||
$xpath = new \DOMXPath($dom);
|
||||
|
||||
$this->assertTrue($xpath->query('/html/body/table/tr[1]/td')->length == 2);
|
||||
$this->assertEquals('3', $xpath->query('/html/body/table/tr[1]/td[1]')->item(0)->attributes->getNamedItem('rowspan')->textContent);
|
||||
|
|
|
|||
|
|
@ -17,7 +17,9 @@
|
|||
|
||||
namespace PhpOffice\PhpWord\Writer\RTF;
|
||||
|
||||
use PhpOffice\PhpWord\Writer\RTF;
|
||||
use PhpOffice\PhpWord\Writer\RTF\Style\Border;
|
||||
use PHPUnit\Framework\Assert;
|
||||
|
||||
/**
|
||||
* Test class for PhpOffice\PhpWord\Writer\RTF\Style subnamespace
|
||||
|
|
@ -29,7 +31,7 @@ class StyleTest extends \PHPUnit\Framework\TestCase
|
|||
*/
|
||||
public function testEmptyStyles()
|
||||
{
|
||||
$styles = array('Font', 'Paragraph', 'Section');
|
||||
$styles = array('Font', 'Paragraph', 'Section', 'Tab', 'Indentation');
|
||||
foreach ($styles as $style) {
|
||||
$objectClass = 'PhpOffice\\PhpWord\\Writer\\RTF\\Style\\' . $style;
|
||||
$object = new $objectClass();
|
||||
|
|
@ -55,4 +57,55 @@ class StyleTest extends \PHPUnit\Framework\TestCase
|
|||
|
||||
$this->assertEquals($expected, $content);
|
||||
}
|
||||
|
||||
public function testIndentation()
|
||||
{
|
||||
$indentation = new \PhpOffice\PhpWord\Style\Indentation();
|
||||
$indentation->setLeft(1);
|
||||
$indentation->setRight(2);
|
||||
$indentation->setFirstLine(3);
|
||||
|
||||
$indentWriter = new \PhpOffice\PhpWord\Writer\RTF\Style\Indentation($indentation);
|
||||
$indentWriter->setParentWriter(new RTF());
|
||||
$result = $indentWriter->write();
|
||||
|
||||
Assert::assertEquals('\fi3\li1\ri2 ', $result);
|
||||
}
|
||||
|
||||
public function testRightTab()
|
||||
{
|
||||
$tabRight = new \PhpOffice\PhpWord\Style\Tab();
|
||||
$tabRight->setType(\PhpOffice\PhpWord\Style\Tab::TAB_STOP_RIGHT);
|
||||
$tabRight->setPosition(5);
|
||||
|
||||
$tabWriter = new \PhpOffice\PhpWord\Writer\RTF\Style\Tab($tabRight);
|
||||
$tabWriter->setParentWriter(new RTF());
|
||||
$result = $tabWriter->write();
|
||||
|
||||
Assert::assertEquals('\tqr\tx5', $result);
|
||||
}
|
||||
|
||||
public function testCenterTab()
|
||||
{
|
||||
$tabRight = new \PhpOffice\PhpWord\Style\Tab();
|
||||
$tabRight->setType(\PhpOffice\PhpWord\Style\Tab::TAB_STOP_CENTER);
|
||||
|
||||
$tabWriter = new \PhpOffice\PhpWord\Writer\RTF\Style\Tab($tabRight);
|
||||
$tabWriter->setParentWriter(new RTF());
|
||||
$result = $tabWriter->write();
|
||||
|
||||
Assert::assertEquals('\tqc\tx0', $result);
|
||||
}
|
||||
|
||||
public function testDecimalTab()
|
||||
{
|
||||
$tabRight = new \PhpOffice\PhpWord\Style\Tab();
|
||||
$tabRight->setType(\PhpOffice\PhpWord\Style\Tab::TAB_STOP_DECIMAL);
|
||||
|
||||
$tabWriter = new \PhpOffice\PhpWord\Writer\RTF\Style\Tab($tabRight);
|
||||
$tabWriter->setParentWriter(new RTF());
|
||||
$result = $tabWriter->write();
|
||||
|
||||
Assert::assertEquals('\tqdec\tx0', $result);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,11 +17,10 @@
|
|||
|
||||
namespace PhpOffice\PhpWord\Writer\Word2007\Part;
|
||||
|
||||
use PhpOffice\Common\Microsoft\PasswordEncoder;
|
||||
use PhpOffice\PhpWord\ComplexType\ProofState;
|
||||
use PhpOffice\PhpWord\ComplexType\TrackChangesView;
|
||||
use PhpOffice\PhpWord\PhpWord;
|
||||
use PhpOffice\PhpWord\Settings;
|
||||
use PhpOffice\PhpWord\Shared\Microsoft\PasswordEncoder;
|
||||
use PhpOffice\PhpWord\SimpleType\Zoom;
|
||||
use PhpOffice\PhpWord\Style\Language;
|
||||
use PhpOffice\PhpWord\TestHelperDOCX;
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -37,9 +37,9 @@ class XmlDocument
|
|||
private $dom;
|
||||
|
||||
/**
|
||||
* DOMXpath object
|
||||
* DOMXPath object
|
||||
*
|
||||
* @var \DOMXpath
|
||||
* @var \DOMXPath
|
||||
*/
|
||||
private $xpath;
|
||||
|
||||
|
|
@ -76,8 +76,10 @@ class XmlDocument
|
|||
$this->file = $file;
|
||||
|
||||
$file = $this->path . '/' . $file;
|
||||
libxml_disable_entity_loader(false);
|
||||
$this->dom = new \DOMDocument();
|
||||
$this->dom->load($file);
|
||||
libxml_disable_entity_loader(true);
|
||||
|
||||
return $this->dom;
|
||||
}
|
||||
|
|
@ -96,7 +98,7 @@ class XmlDocument
|
|||
}
|
||||
|
||||
if (null === $this->xpath) {
|
||||
$this->xpath = new \DOMXpath($this->dom);
|
||||
$this->xpath = new \DOMXPath($this->dom);
|
||||
$this->xpath->registerNamespace('w14', 'http://schemas.microsoft.com/office/word/2010/wordml');
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue