Skip to content
This repository was archived by the owner on Dec 7, 2018. It is now read-only.

Commit 3ef6b74

Browse files
committed
fixes double-encoding, removed GA, interface enhancements
1 parent 3174017 commit 3ef6b74

File tree

3 files changed

+133
-64
lines changed

3 files changed

+133
-64
lines changed

finediff.php

+3-3
Original file line numberDiff line numberDiff line change
@@ -671,17 +671,17 @@ private static function renderToTextFromOpcode($opcode, $from, $from_offset, $fr
671671

672672
private static function renderDiffToHTMLFromOpcode($opcode, $from, $from_offset, $from_len) {
673673
if ( $opcode === 'c' ) {
674-
echo htmlentities(htmlentities(substr($from, $from_offset, $from_len)));
674+
echo htmlentities(substr($from, $from_offset, $from_len));
675675
}
676676
else if ( $opcode === 'd' ) {
677677
$deletion = substr($from, $from_offset, $from_len);
678678
if ( strcspn($deletion, " \n\r") === 0 ) {
679679
$deletion = str_replace(array("\n","\r"), array('\n','\r'), $deletion);
680680
}
681-
echo '<del>', htmlentities(htmlentities($deletion)), '</del>';
681+
echo '<del>', htmlentities($deletion), '</del>';
682682
}
683683
else /* if ( $opcode === 'i' ) */ {
684-
echo '<ins>', htmlentities(htmlentities(substr($from, $from_offset, $from_len))), '</ins>';
684+
echo '<ins>', htmlentities(substr($from, $from_offset, $from_len)), '</ins>';
685685
}
686686
}
687687
}

viewdiff-ex.php

+2-15
Original file line numberDiff line numberDiff line change
@@ -82,22 +82,9 @@
8282
#htmldiff.onlyInsertions del {display:none}
8383
</style>
8484
<title>PHP Fine Diff</title>
85-
<script type="text/javascript">
86-
var _gaq = _gaq || [];
87-
_gaq.push(['_setAccount', 'UA-5586753-2']);
88-
_gaq.push(['_trackPageview']);
89-
(function() {
90-
var ga = document.createElement('script');
91-
ga.type = 'text/javascript';
92-
ga.async = true;
93-
ga.src = 'http://www.google-analytics.com/ga.js';
94-
var s = document.getElementsByTagName('script')[0];
95-
s.parentNode.insertBefore(ga, s);
96-
})();
97-
</script>
9885
</head>
9986
<body>
100-
<a href="https://github.com/gorhill/PHP-FineDiff"><img style="position:absolute;top:0;right:0;border:0;" src="https://d3nwyuy0nl342s.cloudfront.net/img/7afbc8b248c68eb468279e8c17986ad46549fb71/687474703a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f72696768745f6461726b626c75655f3132313632312e706e67" alt="Fork me on GitHub"></a>
87+
<a href="https://github.com/gorhill/PHP-FineDiff"><img style="position: absolute; top: 0; right: 0; border: 0;" src="https://camo.githubusercontent.com/38ef81f8aca64bb9a64448d0d70f1308ef5341ab/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f72696768745f6461726b626c75655f3132313632312e706e67" alt="Fork me on GitHub" data-canonical-src="https://s3.amazonaws.com/github/ribbons/forkme_right_darkblue_121621.png"></a>
10188
<h1>PHP Fine Diff</h1>
10289
<div>
10390
<p style="margin-right:5em">This page demonstrate the <a href="finediff-code.php"><code>FineDiff</code></a> class (as in &ldquo;<b>fine</b> granularity <b>diff</b>&rdquo;) I wrote &ndash; starting from scratch &ndash; to generate a <u>lossless</u> (won't eat your line breaks), <u>compact</u> opcodes string listing the sequence of atomic actions (copy/delete/insert) necessary to transform one string into another (thereafter referred as the &ldquo;From&rdquo; and &ldquo;To&rdquo; string). The &ldquo;To&rdquo; string can be rebuilt by running the opcodes string on the &ldquo;From&rdquo; string. The <code>FineDiff</code> class allows to specify the granularity, and up to character-level granularity is possible, in order to generate the smallest diff possible (at the <i>potential</i> cost of increased CPU cycles.)</p>
@@ -281,7 +268,7 @@ function extractFragments($text, $delimiter) {
281268
</div></div></div>
282269
<div class="panecontainer"><p>Rendered Diff:&emsp;<span style="font-size:smaller">Show <input type="radio" name="htmldiffshow" onclick="setHTMLDiffVisibility('deletions');">Deletions only&ensp;<input type="radio" name="htmldiffshow" checked="checked" onclick="setHTMLDiffVisibility();">All&ensp;<input type="radio" name="htmldiffshow" onclick="setHTMLDiffVisibility('insertions');">Insertions only</span></p>
283270
<div id="htmldiff">
284-
<div class="pane" style="white-space:pre-line"><?php echo $rendered_diff; ?></div>
271+
<div class="pane" style="white-space:pre-wrap"><?php echo $rendered_diff; ?></div>
285272
</div>
286273
</div>
287274
<script type="text/javascript">

viewdiff.php

+128-46
Original file line numberDiff line numberDiff line change
@@ -11,26 +11,16 @@
1111
#params {margin:1em 0;font: 14px sans-serif}
1212
.panecontainer > p {margin:0;border:1px solid #bcd;border-bottom:none;padding:1px 3px;background:#def;font:14px sans-serif}
1313
.panecontainer > p + div {margin:0;padding:2px 0 2px 2px;border:1px solid #bcd;border-top:none}
14-
.pane {margin:0;padding:0;border:0;width:100%;min-height:30em;overflow:auto;font:12px monospace}
15-
.diff {color:gray}
14+
.pane {margin:0;padding:0;border:0;width:100%;min-height:20em;overflow:auto;font:12px monospace}
15+
#htmldiff {color:gray}
16+
#htmldiff.onlyDeletions ins {display:none}
17+
#htmldiff.onlyInsertions del {display:none}
1618
</style>
1719
<title>PHP Fine Diff: Online Diff Viewer</title>
18-
<script type="text/javascript">
19-
var _gaq = _gaq || [];
20-
_gaq.push(['_setAccount', 'UA-5586753-2']);
21-
_gaq.push(['_trackPageview']);
22-
(function() {
23-
var ga = document.createElement('script');
24-
ga.type = 'text/javascript';
25-
ga.async = true;
26-
ga.src = 'http://www.google-analytics.com/ga.js';
27-
var s = document.getElementsByTagName('script')[0];
28-
s.parentNode.insertBefore(ga, s);
29-
})();
30-
</script>
20+
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
3121
</head>
3222
<body>
33-
<a href="https://github.com/gorhill/PHP-FineDiff"><img style="position:absolute;top:0;right:0;border:0;" src="https://d3nwyuy0nl342s.cloudfront.net/img/7afbc8b248c68eb468279e8c17986ad46549fb71/687474703a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f72696768745f6461726b626c75655f3132313632312e706e67" alt="Fork me on GitHub"></a>
23+
<a href="https://github.com/gorhill/PHP-FineDiff"><img style="position: absolute; top: 0; right: 0; border: 0;" src="https://camo.githubusercontent.com/38ef81f8aca64bb9a64448d0d70f1308ef5341ab/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f72696768745f6461726b626c75655f3132313632312e706e67" alt="Fork me on GitHub" data-canonical-src="https://s3.amazonaws.com/github/ribbons/forkme_right_darkblue_121621.png"></a>
3424
<h1>PHP Fine Diff: Online Diff Viewer</h1>
3525
<div>
3626
<?php
@@ -42,54 +32,146 @@ function stripslashes_deep(&$value) {
4232
if ( (function_exists("get_magic_quotes_gpc") && get_magic_quotes_gpc()) || (ini_get('magic_quotes_sybase') && strtolower(ini_get('magic_quotes_sybase'))!="off") ) {
4333
stripslashes_deep($_GET);
4434
stripslashes_deep($_POST);
45-
stripslashes_deep($_REQUEST);
4635
}
4736

4837
include 'finediff.php';
4938

50-
$granularity = 2;
51-
if ( isset($_REQUEST['granularity']) && ctype_digit($_REQUEST['granularity']) ) {
52-
$granularity = max(min(intval($_REQUEST['granularity']),3),0);
53-
}
39+
$cache_lo_water_mark = 900;
40+
$cache_hi_water_mark = 1100;
41+
$compressed_serialized_filename_extension = '.store.gz';
5442

43+
$granularity = 2;
5544
$from_text = '';
5645
$to_text = '';
57-
if ( !empty($_REQUEST['from']) || !empty($_REQUEST['to'])) {
58-
if ( !empty($_REQUEST['from']) ) {
59-
$from_text = $_REQUEST['from'];
60-
}
61-
if ( !empty($_REQUEST['to']) ) {
62-
$to_text = $_REQUEST['to'];
46+
$diff_opcodes = '';
47+
$diff_opcodes_len = 0;
48+
$data_key = '';
49+
50+
$start_time = gettimeofday(true);
51+
52+
// restore from cache
53+
if ( isset($_GET['data']) ) {
54+
if ( ctype_alnum($_GET['data']) ) {
55+
$filename = "{$_GET['data']}{$compressed_serialized_filename_extension}";
56+
$compressed_serialized_data = @file_get_contents("./cache/{$filename}");
57+
if ( $compressed_serialized_data !== false ) {
58+
@touch("./cache/{$filename}");
59+
$data_from_serialization = unserialize(gzuncompress($compressed_serialized_data));
60+
$granularity = $data_from_serialization['granularity'];
61+
$from_text = $data_from_serialization['from_text'];
62+
$diff_opcodes = $data_from_serialization['diff_opcodes'];
63+
$diff_opcodes_len = strlen($diff_opcodes);
64+
$to_text = FineDiff::renderToTextFromOpcodes($from_text, $diff_opcodes);
65+
$data_key = $data_from_serialization['data_key'];
66+
}
67+
else {
68+
echo '<p style="font-size:smaller">The page you are looking for has expired.</p>', "\n";
69+
}
6370
}
71+
$exec_time = gettimeofday(true) - $start_time;
6472
}
73+
// new diff
74+
else {
75+
if ( isset($_POST['granularity']) && ctype_digit($_POST['granularity']) ) {
76+
$granularity = max(min(intval($_POST['granularity']),3),0);
77+
}
78+
if ( !empty($_POST['from']) || !empty($_POST['to'])) {
79+
if ( !empty($_POST['from']) ) {
80+
$from_text = $_POST['from'];
81+
}
82+
if ( !empty($_POST['to']) ) {
83+
$to_text = $_POST['to'];
84+
}
85+
}
86+
// limit input
87+
$from_text = substr($from_text, 0, 1024*100);
88+
$to_text = substr($to_text, 0, 1024*100);
6589

66-
$diff = '';
90+
// ensure input is suitable for diff
91+
$from_text = mb_convert_encoding($from_text, 'HTML-ENTITIES', 'UTF-8');
92+
$to_text = mb_convert_encoding($to_text, 'HTML-ENTITIES', 'UTF-8');
6793

68-
$granularityStacks = array(
69-
FineDiff::$paragraphGranularity,
70-
FineDiff::$sentenceGranularity,
71-
FineDiff::$wordGranularity,
72-
FineDiff::$characterGranularity
73-
);
94+
$granularityStacks = array(
95+
FineDiff::$paragraphGranularity,
96+
FineDiff::$sentenceGranularity,
97+
FineDiff::$wordGranularity,
98+
FineDiff::$characterGranularity
99+
);
100+
$diff_opcodes = FineDiff::getDiffOpcodes($from_text, $to_text, $granularityStacks[$granularity]);
101+
$diff_opcodes_len = strlen($diff_opcodes);
102+
$exec_time = gettimeofday(true) - $start_time;
103+
if ( $diff_opcodes_len ) {
104+
$data_key = sha1(serialize(array('granularity' => $granularity, 'from_text' => $from_text, 'diff_opcodes' => $diff_opcodes)));
105+
$filename = "{$data_key}{$compressed_serialized_filename_extension}";
106+
if ( !file_exists("./cache/{$filename}") ) {
107+
// purge cache if too many files
108+
if ( !(time() % 100) ) {
109+
$files = glob("./cache/*{$compressed_serialized_filename_extension}");
110+
$num_files = $files ? count($files) : 0;
111+
if ( $num_files > $cache_hi_water_mark ) {
112+
$sorted_files = array();
113+
foreach ( $files as $file ) {
114+
$sorted_files[strval(@filemtime("./cache/{$file}")).$file] = $file;
115+
}
116+
ksort($sorted_files);
117+
foreach ( $sorted_files as $file ) {
118+
@unlink("./cache/{$file}");
119+
$num_files -= 1;
120+
if ( $num_files < $cache_lo_water_mark ) {
121+
break;
122+
}
123+
}
124+
}
125+
}
126+
// save diff in cache
127+
$data_to_serialize = array(
128+
'granularity' => $granularity,
129+
'from_text' => $from_text,
130+
'diff_opcodes' => $diff_opcodes,
131+
'data_key' => $data_key,
132+
);
133+
$serialized_data = serialize($data_to_serialize);
134+
@file_put_contents("./cache/{$filename}", gzcompress($serialized_data));
135+
@chmod("./cache/{$filename}", 0666);
136+
}
137+
}
138+
}
74139

140+
$rendered_diff = FineDiff::renderDiffToHTMLFromOpcodes($from_text, $diff_opcodes);
75141
$from_len = strlen($from_text);
76142
$to_len = strlen($to_text);
77-
$start_time = gettimeofday(true);
78-
$diff = new FineDiff($from_text, $to_text, $granularityStacks[$granularity]);
79-
$edits = $diff->getOps();
80-
$exec_time = gettimeofday(true) - $start_time;
81-
$rendered_diff = $diff->renderDiffToHTML();
82-
$rendering_time = gettimeofday(true) - $start_time;
83-
$diff_len = strlen($diff->getOpcodes());
143+
144+
if ( !empty($data_key) ) {
145+
echo '<p style="margin-right:8em;font-size:smaller">Tempolink: <a href="viewdiff.php?data=', $data_key, '">http://', $_SERVER['HTTP_HOST'], '/viewdiff.php?data=', $data_key, '</a> <span style="color:#aaa">(This link is not viewable by others, unless it has been explicitly shared by the creator. This link will exist for a limited period of time, which depends on how often it is visited.)</span></p>', "\n";
146+
}
84147
?>
148+
<div class="panecontainer" style="width:99%"><p>Diff <span style="color:gray">(diff: <?php printf('%.3f', $exec_time); ?> seconds, diff len: <?php echo $diff_opcodes_len; ?> chars)</span>&emsp;/&emsp;Show <input type="radio" name="htmldiffshow" onclick="setHTMLDiffVisibility('deletions');">Deletions only&ensp;<input type="radio" name="htmldiffshow" checked="checked" onclick="setHTMLDiffVisibility();">All&ensp;<input type="radio" name="htmldiffshow" onclick="setHTMLDiffVisibility('insertions');">Insertions only</p><div><div id="htmldiff" class="pane" style="white-space:pre-wrap"><?php
149+
echo $rendered_diff; ?></div></div>
150+
</div>
85151
<form action="viewdiff.php" method="post">
86-
<div class="panecontainer" style="display:inline-block;width:49.5%"><p>From</p><div><textarea name="from" class="pane"><?php echo htmlentities($from_text); ?></textarea></div></div>
87-
<div class="panecontainer" style="display:inline-block;width:49.5%"><p>To</p><div><textarea name="to" class="pane"><?php echo htmlentities($to_text); ?></textarea></div></div>
152+
<p style="margin:1em 0 0.5em 0">Enter text to diff below:</p>
153+
<div class="panecontainer" style="display:inline-block;width:49.5%"><p>From</p><div><textarea name="from" class="pane"><?php echo htmlentities($from_text, ENT_QUOTES, 'UTF-8'); ?></textarea></div></div>
154+
<div class="panecontainer" style="display:inline-block;width:49.5%"><p>To</p><div><textarea name="to" class="pane"><?php echo htmlentities($to_text, ENT_QUOTES, 'UTF-8'); ?></textarea></div></div>
88155
<p id="params">Granularity:<input name="granularity" type="radio" value="0"<?php if ( $granularity === 0 ) { echo ' checked="checked"'; } ?>>&thinsp;Paragraph/lines&ensp;<input name="granularity" type="radio" value="1"<?php if ( $granularity === 1 ) { echo ' checked="checked"'; } ?>>&thinsp;Sentence&ensp;<input name="granularity" type="radio" value="2"<?php if ( $granularity === 2 ) { echo ' checked="checked"'; } ?>>&thinsp;Word&ensp;<input name="granularity" type="radio" value="3"<?php if ( $granularity === 3 ) { echo ' checked="checked"'; } ?>>&thinsp;Character&emsp;<input type="submit" value="View diff">&emsp;<a href="viewdiff.php"><button>Clear all</button></a></p>
89156
</form>
90-
<div class="panecontainer" style="width:99%"><p>Diff <span style="color:gray">(diff: <?php printf('%.3f', $exec_time); ?> sec, rendering: <?php printf('%.3f', $rendering_time); ?> sec, diff len: <?php echo $diff_len; ?> chars)</span></p><div><div class="pane diff" style="white-space:pre-line"><?php
91-
echo $rendered_diff; ?></div></div>
92-
</div>
93157
<p style="margin-top:1em"><a href="viewdiff-ex.php">Go to main page</a></p>
158+
<script type="text/javascript">
159+
<!--
160+
function setHTMLDiffVisibility(what) {
161+
var htmldiffEl = document.getElementById('htmldiff'),
162+
className = htmldiffEl.className;
163+
className = className.replace(/\bonly(Insertions|Deletions)\b/g, '').replace(/\s{2,}/g, ' ').replace(/\s+$/, '').replace(/^\s+/, '');
164+
if ( what === 'deletions' ) {
165+
htmldiffEl.className = className + ' onlyDeletions';
166+
}
167+
else if ( what === 'insertions' ) {
168+
htmldiffEl.className = className + ' onlyInsertions';
169+
}
170+
else {
171+
htmldiffEl.className = className;
172+
}
173+
}
174+
// -->
175+
</script>
94176
</body>
95177
</html>

0 commit comments

Comments
 (0)