PageRenderTime 25ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/htdocs/wp-content/plugins/contact-form-7-to-database-extension/Spout-2.7.1/Common/Escaper/XLSX.php

https://gitlab.com/VTTE/sitios-vtte
PHP | 178 lines | 73 code | 23 blank | 82 comment | 3 complexity | 51ef926c93d89a39464cdc97941aae46 MD5 | raw file
  1. <?php
  2. namespace Box\Spout\Common\Escaper;
  3. use Box\Spout\Common\Singleton;
  4. /**
  5. * Class XLSX
  6. * Provides functions to escape and unescape data for XLSX files
  7. *
  8. * @package Box\Spout\Common\Escaper
  9. */
  10. class XLSX implements EscaperInterface
  11. {
  12. use Singleton;
  13. /** @var string Regex pattern to detect control characters that need to be escaped */
  14. protected $escapableControlCharactersPattern;
  15. /** @var string[] Map containing control characters to be escaped (key) and their escaped value (value) */
  16. protected $controlCharactersEscapingMap;
  17. /** @var string[] Map containing control characters to be escaped (value) and their escaped value (key) */
  18. protected $controlCharactersEscapingReverseMap;
  19. /**
  20. * Initializes the singleton instance
  21. */
  22. protected function init()
  23. {
  24. $this->escapableControlCharactersPattern = $this->getEscapableControlCharactersPattern();
  25. $this->controlCharactersEscapingMap = $this->getControlCharactersEscapingMap();
  26. $this->controlCharactersEscapingReverseMap = array_flip($this->controlCharactersEscapingMap);
  27. }
  28. /**
  29. * Escapes the given string to make it compatible with XLSX
  30. *
  31. * @param string $string The string to escape
  32. * @return string The escaped string
  33. */
  34. public function escape($string)
  35. {
  36. $escapedString = $this->escapeControlCharacters($string);
  37. $escapedString = htmlspecialchars($escapedString, ENT_QUOTES);
  38. return $escapedString;
  39. }
  40. /**
  41. * Unescapes the given string to make it compatible with XLSX
  42. *
  43. * @param string $string The string to unescape
  44. * @return string The unescaped string
  45. */
  46. public function unescape($string)
  47. {
  48. $unescapedString = htmlspecialchars_decode($string, ENT_QUOTES);
  49. $unescapedString = $this->unescapeControlCharacters($unescapedString);
  50. return $unescapedString;
  51. }
  52. /**
  53. * @return string Regex pattern containing all escapable control characters
  54. */
  55. protected function getEscapableControlCharactersPattern()
  56. {
  57. // control characters values are from 0 to 1F (hex values) in the ASCII table
  58. // some characters should not be escaped though: "\t", "\r" and "\n".
  59. return '[\x00-\x08' .
  60. // skipping "\t" (0x9) and "\n" (0xA)
  61. '\x0B-\x0C' .
  62. // skipping "\r" (0xD)
  63. '\x0E-\x1F]';
  64. }
  65. /**
  66. * Builds the map containing control characters to be escaped
  67. * mapped to their escaped values.
  68. * "\t", "\r" and "\n" don't need to be escaped.
  69. *
  70. * NOTE: the logic has been adapted from the XlsxWriter library (BSD License)
  71. * @link https://github.com/jmcnamara/XlsxWriter/blob/f1e610f29/xlsxwriter/sharedstrings.py#L89
  72. *
  73. * @return string[]
  74. */
  75. protected function getControlCharactersEscapingMap()
  76. {
  77. $controlCharactersEscapingMap = [];
  78. // control characters values are from 0 to 1F (hex values) in the ASCII table
  79. for ($charValue = 0x00; $charValue <= 0x1F; $charValue++) {
  80. $character = chr($charValue);
  81. if (preg_match("/{$this->escapableControlCharactersPattern}/", $character)) {
  82. $charHexValue = dechex($charValue);
  83. $escapedChar = '_x' . sprintf('%04s' , strtoupper($charHexValue)) . '_';
  84. $controlCharactersEscapingMap[$escapedChar] = $character;
  85. }
  86. }
  87. return $controlCharactersEscapingMap;
  88. }
  89. /**
  90. * Converts PHP control characters from the given string to OpenXML escaped control characters
  91. *
  92. * Excel escapes control characters with _xHHHH_ and also escapes any
  93. * literal strings of that type by encoding the leading underscore.
  94. * So "\0" -> _x0000_ and "_x0000_" -> _x005F_x0000_.
  95. *
  96. * NOTE: the logic has been adapted from the XlsxWriter library (BSD License)
  97. * @link https://github.com/jmcnamara/XlsxWriter/blob/f1e610f29/xlsxwriter/sharedstrings.py#L89
  98. *
  99. * @param string $string String to escape
  100. * @return string
  101. */
  102. protected function escapeControlCharacters($string)
  103. {
  104. $escapedString = $this->escapeEscapeCharacter($string);
  105. // if no control characters
  106. if (!preg_match("/{$this->escapableControlCharactersPattern}/", $escapedString)) {
  107. return $escapedString;
  108. }
  109. return preg_replace_callback("/({$this->escapableControlCharactersPattern})/", function($matches) {
  110. return $this->controlCharactersEscapingReverseMap[$matches[0]];
  111. }, $escapedString);
  112. }
  113. /**
  114. * Escapes the escape character: "_x0000_" -> "_x005F_x0000_"
  115. *
  116. * @param string $string String to escape
  117. * @return string The escaped string
  118. */
  119. protected function escapeEscapeCharacter($string)
  120. {
  121. return preg_replace('/_(x[\dA-F]{4})_/', '_x005F_$1_', $string);
  122. }
  123. /**
  124. * Converts OpenXML escaped control characters from the given string to PHP control characters
  125. *
  126. * Excel escapes control characters with _xHHHH_ and also escapes any
  127. * literal strings of that type by encoding the leading underscore.
  128. * So "_x0000_" -> "\0" and "_x005F_x0000_" -> "_x0000_"
  129. *
  130. * NOTE: the logic has been adapted from the XlsxWriter library (BSD License)
  131. * @link https://github.com/jmcnamara/XlsxWriter/blob/f1e610f29/xlsxwriter/sharedstrings.py#L89
  132. *
  133. * @param string $string String to unescape
  134. * @return string
  135. */
  136. protected function unescapeControlCharacters($string)
  137. {
  138. $unescapedString = $string;
  139. foreach ($this->controlCharactersEscapingMap as $escapedCharValue => $charValue) {
  140. // only unescape characters that don't contain the escaped escape character for now
  141. $unescapedString = preg_replace("/(?<!_x005F)($escapedCharValue)/", $charValue, $unescapedString);
  142. }
  143. return $this->unescapeEscapeCharacter($unescapedString);
  144. }
  145. /**
  146. * Unecapes the escape character: "_x005F_x0000_" => "_x0000_"
  147. *
  148. * @param string $string String to unescape
  149. * @return string The unescaped string
  150. */
  151. protected function unescapeEscapeCharacter($string)
  152. {
  153. return preg_replace('/_x005F(_x[\dA-F]{4}_)/', '$1', $string);
  154. }
  155. }