/Upload/inc/3rdparty/diff/Diff/Engine/Shell.php

https://gitlab.com/Conors99/ppm-1.8 · PHP · 165 lines · 94 code · 18 blank · 53 comment · 14 complexity · b749e68eae96b226344418e0c27f2575 MD5 · raw file

  1. <?php
  2. /**
  3. * Class used internally by Diff to actually compute the diffs.
  4. *
  5. * This class uses the Unix `diff` program via shell_exec to compute the
  6. * differences between the two input arrays.
  7. *
  8. * Copyright 2007-2011 Horde LLC (http://www.horde.org/)
  9. *
  10. * See the enclosed file COPYING for license information (LGPL). If you did
  11. * not receive this file, see http://www.horde.org/licenses/lgpl21.
  12. *
  13. * @author Milian Wolff <mail@milianw.de>
  14. * @package Text_Diff
  15. */
  16. // Disallow direct access to this file for security reasons
  17. if(!defined("IN_MYBB"))
  18. {
  19. die("Direct initialization of this file is not allowed.<br /><br />Please make sure IN_MYBB is defined.");
  20. }
  21. class Horde_Text_Diff_Engine_Shell
  22. {
  23. /**
  24. * Path to the diff executable
  25. *
  26. * @var string
  27. */
  28. protected $_diffCommand = 'diff';
  29. /**
  30. * Returns the array of differences.
  31. *
  32. * @param array $from_lines lines of text from old file
  33. * @param array $to_lines lines of text from new file
  34. *
  35. * @return array all changes made (array with Horde_Text_Diff_Op_* objects)
  36. */
  37. public function diff($from_lines, $to_lines)
  38. {
  39. array_walk($from_lines, array('Horde_Text_Diff', 'trimNewlines'));
  40. array_walk($to_lines, array('Horde_Text_Diff', 'trimNewlines'));
  41. // Execute gnu diff or similar to get a standard diff file.
  42. $from_file = Horde_Util::getTempFile('Horde_Text_Diff');
  43. $to_file = Horde_Util::getTempFile('Horde_Text_Diff');
  44. $fp = fopen($from_file, 'w');
  45. fwrite($fp, implode("\n", $from_lines));
  46. fclose($fp);
  47. $fp = fopen($to_file, 'w');
  48. fwrite($fp, implode("\n", $to_lines));
  49. fclose($fp);
  50. $diff = shell_exec($this->_diffCommand . ' ' . $from_file . ' ' . $to_file);
  51. unlink($from_file);
  52. unlink($to_file);
  53. if (is_null($diff)) {
  54. // No changes were made
  55. return array(new Horde_Text_Diff_Op_Copy($from_lines));
  56. }
  57. $from_line_no = 1;
  58. $to_line_no = 1;
  59. $edits = array();
  60. // Get changed lines by parsing something like:
  61. // 0a1,2
  62. // 1,2c4,6
  63. // 1,5d6
  64. preg_match_all('#^(\d+)(?:,(\d+))?([adc])(\d+)(?:,(\d+))?$#m', $diff,
  65. $matches, PREG_SET_ORDER);
  66. foreach ($matches as $match) {
  67. if (!isset($match[5])) {
  68. // This paren is not set every time (see regex).
  69. $match[5] = false;
  70. }
  71. if ($match[3] == 'a') {
  72. $from_line_no--;
  73. }
  74. if ($match[3] == 'd') {
  75. $to_line_no--;
  76. }
  77. if ($from_line_no < $match[1] || $to_line_no < $match[4]) {
  78. // copied lines
  79. assert('$match[1] - $from_line_no == $match[4] - $to_line_no');
  80. array_push($edits,
  81. new Horde_Text_Diff_Op_Copy(
  82. $this->_getLines($from_lines, $from_line_no, $match[1] - 1),
  83. $this->_getLines($to_lines, $to_line_no, $match[4] - 1)));
  84. }
  85. switch ($match[3]) {
  86. case 'd':
  87. // deleted lines
  88. array_push($edits,
  89. new Horde_Text_Diff_Op_Delete(
  90. $this->_getLines($from_lines, $from_line_no, $match[2])));
  91. $to_line_no++;
  92. break;
  93. case 'c':
  94. // changed lines
  95. array_push($edits,
  96. new Horde_Text_Diff_Op_Change(
  97. $this->_getLines($from_lines, $from_line_no, $match[2]),
  98. $this->_getLines($to_lines, $to_line_no, $match[5])));
  99. break;
  100. case 'a':
  101. // added lines
  102. array_push($edits,
  103. new Horde_Text_Diff_Op_Add(
  104. $this->_getLines($to_lines, $to_line_no, $match[5])));
  105. $from_line_no++;
  106. break;
  107. }
  108. }
  109. if (!empty($from_lines)) {
  110. // Some lines might still be pending. Add them as copied
  111. array_push($edits,
  112. new Horde_Text_Diff_Op_Copy(
  113. $this->_getLines($from_lines, $from_line_no,
  114. $from_line_no + count($from_lines) - 1),
  115. $this->_getLines($to_lines, $to_line_no,
  116. $to_line_no + count($to_lines) - 1)));
  117. }
  118. return $edits;
  119. }
  120. /**
  121. * Get lines from either the old or new text
  122. *
  123. * @access private
  124. *
  125. * @param array &$text_lines Either $from_lines or $to_lines
  126. * @param int &$line_no Current line number
  127. * @param int $end Optional end line, when we want to chop more
  128. * than one line.
  129. *
  130. * @return array The chopped lines
  131. */
  132. protected function _getLines(&$text_lines, &$line_no, $end = false)
  133. {
  134. if (!empty($end)) {
  135. $lines = array();
  136. // We can shift even more
  137. while ($line_no <= $end) {
  138. array_push($lines, array_shift($text_lines));
  139. $line_no++;
  140. }
  141. } else {
  142. $lines = array(array_shift($text_lines));
  143. $line_no++;
  144. }
  145. return $lines;
  146. }
  147. }