This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "FusionForge".
The branch, master has been updated
via 309bce4842a9845ed0bd189c2bb932e8107502b8 (commit)
via 54dcb9ce9d6f266f591613e1844670fa6e8a77c0 (commit)
via d53aeb132ba88cb42a0514ec3f8c83cfd27ab2b1 (commit)
via a9d53b2c9c5c7ebf89da0ed82e8a5107b041f5d9 (commit)
via d61575c6c0ba5f80d371a6a74f762fd4a32a96ff (commit)
via 13f0da02ae64d8b2f27156bb20901e781b038aef (commit)
via fbc3d4f9a3f4c41184d250c58b0a031a44075e62 (commit)
via c47cf1cf76cd9c120881ca552ec34890014d1cf6 (commit)
via 5f5b45d3915b5b3b1660db4f3f3e2a2564377fb1 (commit)
via fcfc96a351704dedbfa1c476b3791f431045fa72 (commit)
via 44e481fc6c362efdf59e7f46e3873292cbb1a278 (commit)
via 5fd6948620c22e6e2dce2988738b928a8a000748 (commit)
via 6ae5df09e1e72395bc9f2f9946ba8cbf2b88a393 (commit)
via 9dfa4394f1410c7eac4fa30a03a4e3e108cd5a2c (commit)
via 66433e4902ecdb1c988f6577bc86e930c474b022 (commit)
via b5974e32cf3b4b1f740c1bfd6229f225fb12671d (commit)
via 73fee0fc450df7c4ce29b90a252247f35f68b4f6 (commit)
via 466073989f6fc20b56e2c2d77b5676bbf7b3c36f (commit)
via 31377f63785917dced78bcf973997d756e321f66 (commit)
via e508c939f80dfbd0fd3473e94b5dd66a9c8f1fcd (commit)
via 4bb2c05c4232ea35dc59e60f5e7bf23ea206af50 (commit)
via 73f6d7db4eddf19317e52bea4ae35b90eb23d4e4 (commit)
via d82963884953e3ce8d759eea8f228fd8d141032d (commit)
via 4a3ca5f0768682f16550a92086fa1292b3c3e617 (commit)
via e457547e15c5a7815f6bf5ea86bdd26934376018 (commit)
via ea850cdc31a338298187e018d18389cdf5a1a807 (commit)
from 1db485dbb1e039dd9753b4a5171852d66d7f79ea (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
https://scm.fusionforge.org/anonscm/gitweb/?p=fusionforge/fusionforge.git;a=commitdiff;h=309bce4842a9845ed0bd189c2bb932e8107502b8
commit 309bce4842a9845ed0bd189c2bb932e8107502b8
Author: mirabilos <[email protected]>
Date: Thu Jun 11 03:53:42 2020 +0200
Update minijson and its testsuite from hello-php-world
Brings back PHP 5.0 compatibility, adds a test and makes the
testsuite more reliable, and 15–20% speed boost with PHP 7.4
diff --git a/src/common/include/minijson.php b/src/common/include/minijson.php
index bfb5310..ecb18c7 100644
--- a/src/common/include/minijson.php
+++ b/src/common/include/minijson.php
@@ -1,10 +1,12 @@
<?php
-if (count(get_included_files()) <= 1 && !defined('__main__'))
+if (!defined('__main__') && count(get_included_files()) <= 1 &&
count(debug_backtrace()) < 1)
define('__main__', __FILE__);
/**
* Minimal complete JSON generator and parser for FusionForge/Evolvis
* and SimKolab, including for debugging output serialisation
*
+ * Copyright © 2020
+ * mirabilos <[email protected]>
* Copyright © 2010, 2011, 2012, 2014, 2016, 2017
* mirabilos <[email protected]>
*
@@ -29,7 +31,7 @@ if (count(get_included_files()) <= 1 && !defined('__main__'))
*
* Call as CLI script to filter input as JSON pretty-printer. Options
* are -c (compact output, no indentation or spaces), -d depth (parse
- * depth defaulting to 32), -r (pretty-print resources as string) and
+ * depth defaulting to 32), -r (pretty-print resources as object) and
* -t truncsz (truncation size).
*/
@@ -42,7 +44,9 @@ if (count(get_included_files()) <= 1 && !defined('__main__'))
/**
* Encodes an array (indexed or associative) or any value as JSON.
* See minijson_encode_ob_string() for limitations on strings;
- * strings not encoded in UTF-8 and resources may not round-trip.
+ * strings not encoded in UTF-8 and resources do not round-trip.
+ *
+ * Optional arguments use the default value if NULL is passed for each.
*
* in: array x (Value to be encoded)
* in: string (optional) or bool false to skip beautification (default: '')
@@ -54,7 +58,8 @@ if (count(get_included_files()) <= 1 && !defined('__main__'))
*/
function minijson_encode($x, $ri='', $depth=32, $truncsz=0, $dumprsrc=false) {
ob_start();
- minijson_encode_ob($x, $ri, $depth, $truncsz, $dumprsrc);
+ minijson_encode_ob($x, !is_null($ri) ? $ri : '', $depth ? $depth : 32,
+ $truncsz ? $truncsz : 0, $dumprsrc ? $dumprsrc : false);
return ob_get_clean();
}
@@ -65,9 +70,10 @@ function minijson_encode($x, $ri='', $depth=32, $truncsz=0,
$dumprsrc=false) {
* in: string x (Value to be encoded)
* in: integer (optional) truncation size (default 0 to not truncate),
* makes output invalid JSON
+ * in: string (optional) always '"'
* out: stdout encoded
*/
-function minijson_encode_ob_string($x, $truncsz=0) {
+function minijson_encode_ob_string($x, $truncsz=0, $leader='"') {
if (!is_string($x))
$x = strval($x);
@@ -77,95 +83,92 @@ function minijson_encode_ob_string($x, $truncsz=0) {
echo 'TOO_LONG_STRING_TRUNCATED:';
$Sx = $truncsz;
}
- echo '"';
+ echo $leader;
/* assume UTF-8 first, for sanity */
ob_start(); /* in case a restart is needed */
$Sp = 0;
- minijson_encode_string_utf8:
- if ($Sp >= $Sx) {
- ob_end_flush();
- echo '"';
- return;
- }
+ while (true) {
+ if ($Sp >= $Sx) {
+ echo '"';
+ ob_end_flush();
+ return;
+ }
- /* read next octet */
- $c = ord(($ch = $x[$Sp++]));
+ /* read next octet */
+ $c = ord(($ch = $x[$Sp++]));
- if ($c === 0x5C) {
- /* just backslash */
- echo "\\\\";
- goto minijson_encode_string_utf8;
- }
+ if ($c > 0x22 && $c < 0x7F) {
+ /* printable ASCII except space, !, " */
+ if ($c === 0x5C)
+ echo $ch;
+ echo $ch;
+ continue;
+ }
- if ($c > 0x22 && $c < 0x7F) {
- /* printable ASCII except space, !, " and backslash */
- echo $ch;
- goto minijson_encode_string_utf8;
- }
+ if ($c < 0x80) {
+ /* C0 control character, space, !, " or DEL */
+ if (($c & 0x7E) === 0x20)
+ echo $ch;
+ elseif ($c === 0x22)
+ echo '\"';
+ elseif ($c === 0x08)
+ echo '\b';
+ elseif ($c === 0x09)
+ echo '\t';
+ elseif ($c === 0x0A)
+ echo '\n';
+ elseif ($c === 0x0C)
+ echo '\f';
+ elseif ($c === 0x0D)
+ echo '\r';
+ elseif (!$c)
+ $Sp = $Sx;
+ else
+ printf('\u%04X', $c);
+ continue;
+ }
- if ($c < 0x80) {
- /* C0 control character, space, !, " or DEL */
- if (($c & 0x7E) === 0x20)
- echo $ch;
- elseif ($c === 0x22)
- echo '\"';
- elseif ($c === 0x08)
- echo '\b';
- elseif ($c === 0x09)
- echo '\t';
- elseif ($c === 0x0A)
- echo '\n';
- elseif ($c === 0x0C)
- echo '\f';
- elseif ($c === 0x0D)
- echo '\r';
- elseif (!$c)
- $Sp = $Sx;
- else
- printf('\u%04X', $c);
- goto minijson_encode_string_utf8;
- }
+ /* UTF-8 lead byte */
+ if ($c < 0xE0) {
+ if ($c < 0xC2)
+ break;
+ $wc = ($c & 0x1F) << 6;
+ $wmin = 0x80;
+ $Ss = 1;
+ } elseif ($c < 0xF0) {
+ $wc = ($c & 0x0F) << 12;
+ $wmin = 0x800;
+ $Ss = 2;
+ } elseif ($c < 0xF8) {
+ $wc = ($c & 0x07) << 18;
+ $wmin = 0x10000;
+ $Ss = 3;
+ } else {
+ break;
+ }
+ $u = $ch;
+ /* UTF-8 trail bytes */
+ if ($Sp + $Ss > $Sx)
+ break;
+ while ($Ss--)
+ if (($c = ord(($ch = $x[$Sp++])) ^ 0x80) <= 0x3F) {
+ $wc |= $c << (6 * $Ss);
+ $u .= $ch;
+ } else
+ break 2;
+ /* complete wide character */
+ if ($wc < $wmin)
+ break;
- /* UTF-8 lead byte */
- if ($c < 0xC2 || $c >= 0xF8) {
- goto minijson_encode_string_latin1;
- } elseif ($c < 0xE0) {
- $wc = ($c & 0x1F) << 6;
- $wmin = 0x80;
- $Ss = 1;
- } elseif ($c < 0xF0) {
- $wc = ($c & 0x0F) << 12;
- $wmin = 0x800;
- $Ss = 2;
- } else {
- $wc = ($c & 0x07) << 18;
- $wmin = 0x10000;
- $Ss = 3;
- }
- /* UTF-8 trail bytes */
- if ($Sp + $Ss > $Sx)
- goto minijson_encode_string_latin1;
- while ($Ss--)
- if (($c = ord($x[$Sp++]) ^ 0x80) <= 0x3F)
- $wc |= $c << (6 * $Ss);
- else
- goto minijson_encode_string_latin1;
- /* complete wide character */
- if ($wc < $wmin)
- goto minijson_encode_string_latin1;
-
- if ($wc < 0x00A0)
- printf('\u%04X', $wc);
- elseif ($wc < 0x0800)
- echo chr(0xC0 | ($wc >> 6)) .
- chr(0x80 | ($wc & 0x3F));
- elseif ($wc > 0xFFFD || ($wc >= 0xD800 && $wc <= 0xDFFF) ||
- ($wc >= 0x2028 && $wc <= 0x2029)) {
- if ($wc > 0xFFFF) {
+ if (($wc >= 0x00A0 && $wc < 0x2028) ||
+ ($wc > 0x2029 && $wc < 0xD800) ||
+ ($wc > 0xDFFF && $wc <= 0xFFFD))
+ echo $u;
+ elseif ($wc > 0xFFFF) {
if ($wc > 0x10FFFF)
- goto minijson_encode_string_latin1;
+ break;
/* UTF-16 */
$wc -= 0x10000;
printf('\u%04X\u%04X',
@@ -173,15 +176,10 @@ function minijson_encode_ob_string($x, $truncsz=0) {
0xDC00 | ($wc & 0x03FF));
} else
printf('\u%04X', $wc);
- } else
- echo chr(0xE0 | ($wc >> 12)) .
- chr(0x80 | (($wc >> 6) & 0x3F)) .
- chr(0x80 | ($wc & 0x3F));
- /* process next char */
- goto minijson_encode_string_utf8;
+ /* process next char */
+ }
- minijson_encode_string_latin1:
/* failed, interpret as sorta latin1 but display only ASCII */
ob_end_clean();
@@ -190,9 +188,8 @@ function minijson_encode_ob_string($x, $truncsz=0) {
/* similar logic as above, just not as golfed for speed */
if ($c >= 0x20 && $c < 0x7F) {
if ($c === 0x22 || $c === 0x5C)
- echo "\\" . $ch;
- else
- echo $ch;
+ echo "\\";
+ echo $ch;
} else switch ($c) {
case 0x08:
echo '\b';
@@ -229,8 +226,7 @@ function minijson_encode_ob_string($x, $truncsz=0) {
* out: stdout encoded
*/
function minijson_encode_ob($x, $ri, $depth, $truncsz, $dumprsrc) {
- if (!$depth-- || !isset($x) || is_null($x) || (is_float($x) &&
- (is_nan($x) || is_infinite($x)))) {
+ if (!$depth-- || !isset($x) || is_null($x)) {
echo 'null';
return;
}
@@ -244,37 +240,36 @@ function minijson_encode_ob($x, $ri, $depth, $truncsz,
$dumprsrc) {
return;
}
- if (is_int($x)) {
- $y = (int)$x;
- $z = strval($y);
- if (strval($x) === $z) {
- echo $z;
+ if (is_int($x) || is_float($x)) {
+ if (is_int($x)) {
+ $y = (int)$x;
+ $z = strval($y);
+ if (strval($x) === $z) {
+ echo $z;
+ return;
+ }
+ } else if (is_nan($x) || is_infinite($x)) {
+ echo 'null';
return;
}
- goto minijson_encode_number;
- }
-
- if (is_float($x)) {
- minijson_encode_number:
$rs = sprintf('%.14e', $x);
$v = explode('e', $rs);
$rs = rtrim($v[0], '0');
- if (substr($rs, -1) === '.')
- $rs .= '0';
- if ($v[1] !== '-0' && $v[1] !== '+0')
- $rs .= 'E' . $v[1];
echo $rs;
+ if ($rs[strlen($rs) - 1] === '.')
+ echo '0';
+ if ($v[1] !== '-0' && $v[1] !== '+0')
+ echo 'E' . $v[1];
return;
}
- /* strings or unknown scalars */
- if (is_string($x) ||
- (!is_array($x) && !is_object($x) && is_scalar($x))) {
+ /* strings */
+ if (is_string($x)) {
minijson_encode_ob_string($x, $truncsz);
return;
}
- /* arrays, objects, resources, unknown non-scalars */
+ /* arrays, objects, resources, unknown scalars and nōn-scalars */
if ($ri === false) {
$si = false;
@@ -296,27 +291,47 @@ function minijson_encode_ob($x, $ri, $depth, $truncsz,
$dumprsrc) {
return;
}
ob_start();
- echo '[';
+ echo '['/*]*/;
+ $isarr = true;
for ($v = 0; $v < $n; ++$v) {
if (!array_key_exists($v, $x)) {
/* failed — sparse or associative */
- ob_end_clean();
- goto minijson_encode_object;
+ $isarr = false;
+ break;
}
echo $xi;
minijson_encode_ob($x[$v],
$si, $depth, $truncsz, $dumprsrc);
$xi = $Si;
}
- ob_end_flush();
- echo $xr . ']';
- return;
- }
-
- /* http://de2.php.net/manual/en/function.is-resource.php#103942 */
- if (!is_object($x) && !is_null($rsrctype = @get_resource_type($x))) {
+ if ($isarr) {
+ ob_end_flush();
+ echo $xr . /*[*/']';
+ return;
+ }
+ ob_end_clean();
+ /* sparse or associative array */
+ } elseif (is_object($x)) {
+ /* PHP objects are mostly like associative arrays */
+ if (!($x = (array)$x)) {
+ echo '{}';
+ return;
+ }
+ /* converted into nōn-empty associative array */
+ /* https://www.php.net/manual/en/function.is-resource.php#103942 */
+ } elseif (!is_null($rsrctype = @get_resource_type($x))) {
if (!$dumprsrc) {
- minijson_encode_ob_string($x, $truncsz);
+ $rs = (int)$x;
+ $x = strval($x);
+ $rsrctype = 'resource('/*)*/ . $rs . ($rsrctype ?
+ (/*(*/')<' . $rsrctype . '>') : /*(*/'?)');
+ if ($x === ('Resource id #' . $rs))
+ $x = $rsrctype . ';';
+ elseif (strncmp($x, 'Resource ', 9) === 0)
+ $x = $rsrctype . substr($x, 8);
+ else
+ $x = $rsrctype . '{' . $x . '}';
+ minijson_encode_ob_string($x, $truncsz, '"\u0000');
return;
}
$rs = array(
@@ -349,20 +364,24 @@ function minijson_encode_ob($x, $ri, $depth, $truncsz,
$dumprsrc) {
$rs['status'] = pg_result_status($x,
PGSQL_STATUS_STRING);
break;
}
- echo '{' . $xi . '"\u0000resource"' . $Sd;
+ echo '{'/*}*/ . $xi . '"\u0000resource:"' . $Sd;
minijson_encode_ob($rs, $si, $depth + 1, $truncsz, $dumprsrc);
- echo $xr . '}';
+ echo $xr . /*{*/'}';
+ return;
+ } elseif (is_scalar($x)) {
+ /* unknown scalar (treat as String) */
+ minijson_encode_ob_string($x, $truncsz);
return;
+ } else {
+ /* unknown nōn-scalar (treat as Object and cast, see above) */
+ if (!($x = (array)$x)) {
+ echo '{}';
+ return;
+ }
}
- /* treat everything else as Object */
+ /* array, object or unknown nōn-scalar, cast as associative array */
- /* PHP objects are mostly like associative arrays */
- if (!($x = (array)$x)) {
- echo '{}';
- return;
- }
- minijson_encode_object:
$s = array();
foreach (array_keys($x) as $k) {
$v = $k;
@@ -374,7 +393,7 @@ function minijson_encode_ob($x, $ri, $depth, $truncsz,
$dumprsrc) {
$s[$k] = $v;
}
asort($s, SORT_STRING);
- echo '{';
+ echo '{'/*}*/;
foreach ($s as $k => $v) {
echo $xi;
minijson_encode_ob_string($v, $truncsz);
@@ -382,7 +401,7 @@ function minijson_encode_ob($x, $ri, $depth, $truncsz,
$dumprsrc) {
minijson_encode_ob($x[$k], $si, $depth, $truncsz, $dumprsrc);
$xi = $Si;
}
- echo $xr . '}';
+ echo $xr . /*{*/'}';
}
/**
@@ -406,7 +425,7 @@ function minijson_decode($s, &$ov, $depth=32) {
$rv = false;
/* skip Byte Order Mark if present */
- if (substr($s, 0, 3) === "\xEF\xBB\xBF")
+ if (strncmp($s, "\xEF\xBB\xBF", 3) === 0)
$Sp = 3;
/* skip leading whitespace */
@@ -423,7 +442,7 @@ function minijson_decode($s, &$ov, $depth=32) {
minijson_skip_wsp($s, $Sp, $Sx);
/* end of string? */
if ($Sp < $Sx) {
- $ov = 'expected EOS';
+ $ov = 'unexpected trailing garbage';
$rv = false;
}
}
@@ -438,382 +457,380 @@ function minijson_decode($s, &$ov, $depth=32) {
/* skip all characters that are JSON whitespace */
function minijson_skip_wsp($s, &$Sp, $Sx) {
while ($Sp < $Sx)
- switch (ord($s[$Sp])) {
- default:
- return;
- case 0x09:
- case 0x0A:
- case 0x0D:
- case 0x20:
+ if (($c = ord($s[$Sp])) === 0x20 ||
+ $c === 0x0A || $c === 0x09 || $c === 0x0D)
++$Sp;
- }
+ else
+ return $c;
+ return -1;
}
function minijson_decode_array($s, &$Sp, $Sx, &$ov, $depth) {
$ov = array();
/* skip optional whitespace between tokens */
- minijson_skip_wsp($s, $Sp, $Sx);
+ $c = minijson_skip_wsp($s, $Sp, $Sx);
/* check for end of array or first member */
- if ($Sp >= $Sx) {
- minijson_decode_array_eos:
- $ov = 'unexpected EOS in Array';
- return false;
- }
- switch ($s[$Sp]) {
- case ',':
- $ov = 'unexpected leading comma in Array';
- return false;
- case ']':
+ if ($c === 0x5D) {
++$Sp;
return true;
+ } elseif ($c === -1) {
+ $ov = 'unexpected EOS after ['/*]*/;
+ return false;
}
- goto minijson_decode_array_member;
-
- minijson_decode_array_loop:
- /* skip optional whitespace between tokens */
- minijson_skip_wsp($s, $Sp, $Sx);
+ while (true) {
+ /* parse the member value */
+ $v = NULL;
+ if (!minijson_decode_value($s, $Sp, $Sx, $v, $depth)) {
+ /* pass through error code */
+ $ov = $v;
+ return false;
+ }
+ /* consume, rinse, repeat */
+ $ov[] = $v;
- /* check for end of array or next member */
- if ($Sp >= $Sx)
- goto minijson_decode_array_eos;
- switch ($s[$Sp++]) {
- case ']':
- return true;
- case ',':
- break;
- default:
- --$Sp;
- $ov = 'missing comma in Array';
- return false;
- }
+ /* skip optional whitespace between tokens */
+ $c = minijson_skip_wsp($s, $Sp, $Sx);
- minijson_decode_array_member:
- /* parse the member value */
- $v = NULL;
- if (!minijson_decode_value($s, $Sp, $Sx, $v, $depth)) {
- /* pass through error code */
- $ov = $v;
- return false;
+ /* check for end of array or next member */
+ if ($c === 0x2C) {
+ ++$Sp;
+ } elseif ($c === 0x5D) {
+ ++$Sp;
+ return true;
+ } else {
+ $ov = /*[*/'comma (,) or ] expected';
+ return false;
+ }
}
- /* consume, rinse, repeat */
- $ov[] = $v;
- goto minijson_decode_array_loop;
}
function minijson_decode_object($s, &$Sp, $Sx, &$ov, $depth) {
$ov = array();
/* skip optional whitespace between tokens */
- minijson_skip_wsp($s, $Sp, $Sx);
+ $c = minijson_skip_wsp($s, $Sp, $Sx);
/* check for end of object or first member */
- if ($Sp >= $Sx) {
- minijson_decode_object_eos:
- $ov = 'unexpected EOS in Object';
- return false;
- }
- switch ($s[$Sp]) {
- case ',':
- $ov = 'unexpected leading comma in Object';
- return false;
- case '}':
+ if ($c === 0x7D) {
++$Sp;
return true;
+ } elseif ($c === -1) {
+ $ov = 'unexpected EOS after {'/*}*/;
+ return false;
}
- goto minijson_decode_object_member;
+ while (true) {
+ /* skip optional whitespace between tokens */
+ $c = minijson_skip_wsp($s, $Sp, $Sx);
- minijson_decode_object_loop:
- /* skip optional whitespace between tokens */
- minijson_skip_wsp($s, $Sp, $Sx);
-
- /* check for end of object or next member */
- if ($Sp >= $Sx)
- goto minijson_decode_object_eos;
- switch ($s[$Sp++]) {
- case '}':
- return true;
- case ',':
- break;
- default:
- --$Sp;
- $ov = 'missing comma in Object';
- return false;
- }
+ /* look for the member key */
+ if ($c !== 0x22) {
+ $ov = 'key string for Object member expected';
+ return false;
+ }
+ ++$Sp;
+ if (($k = minijson_decode_string($s, $Sp, $Sx)) !== true) {
+ ob_end_clean();
+ /* pass through error code */
+ $ov = $k;
+ return false;
+ }
+ $k = ob_get_clean();
- minijson_decode_object_member:
- /* skip optional whitespace between tokens */
- minijson_skip_wsp($s, $Sp, $Sx);
+ /* skip optional whitespace between tokens */
+ $c = minijson_skip_wsp($s, $Sp, $Sx);
- /* look for the member key */
- if ($Sp >= $Sx)
- goto minijson_decode_object_eos;
- if ($s[$Sp++] !== '"') {
- --$Sp;
- $ov = 'expected key string for Object member';
- return false;
- }
- if (($k = minijson_decode_string($s, $Sp, $Sx)) !== true) {
- ob_end_clean();
- /* pass through error code */
- $ov = $k;
- return false;
- }
- $k = ob_get_clean();
+ /* check for separator between key and value */
+ if ($c !== 0x3A) {
+ $ov = 'colon (:) expected';
+ return false;
+ }
+ ++$Sp;
- /* skip optional whitespace between tokens */
- minijson_skip_wsp($s, $Sp, $Sx);
+ /* parse the member value */
+ $v = NULL;
+ if (!minijson_decode_value($s, $Sp, $Sx, $v, $depth)) {
+ /* pass through error code */
+ $ov = $v;
+ return false;
+ }
+ /* consume, rinse, repeat */
+ $ov[$k] = $v;
- /* check for separator between key and value */
- if ($Sp >= $Sx)
- goto minijson_decode_object_eos;
- if ($s[$Sp++] !== ':') {
- --$Sp;
- $ov = 'expected colon in Object member';
- return false;
- }
+ /* skip optional whitespace between tokens */
+ $c = minijson_skip_wsp($s, $Sp, $Sx);
- /* parse the member value */
- $v = NULL;
- if (!minijson_decode_value($s, $Sp, $Sx, $v, $depth)) {
- /* pass through error code */
- $ov = $v;
- return false;
+ /* check for end of object or next member */
+ if ($c === 0x2C) {
+ ++$Sp;
+ } elseif ($c === 0x7D) {
+ ++$Sp;
+ return true;
+ } else {
+ $ov = /*{*/'comma (,) or } expected';
+ return false;
+ }
}
- /* consume, rinse, repeat */
- $ov[$k] = $v;
- goto minijson_decode_object_loop;
}
function minijson_decode_value($s, &$Sp, $Sx, &$ov, $depth) {
/* skip optional whitespace between tokens */
- minijson_skip_wsp($s, $Sp, $Sx);
-
- /* parse begin of Value token */
- if ($Sp >= $Sx) {
- $ov = 'unexpected EOS, Value expected';
- return false;
- }
- $c = $s[$Sp++];
+ $c = minijson_skip_wsp($s, $Sp, $Sx);
- /* style: falling through exits with false */
- if ($c === 'n') {
+ /* parse start of Value token; falling through exits with false */
+ if ($c === 0x22) {
+ ++$Sp;
+ if (($ov = minijson_decode_string($s, $Sp, $Sx)) !== true) {
+ ob_end_clean();
+ return false;
+ }
+ $ov = ob_get_clean();
+ return true;
+ } elseif ($c === 0x7B) {
+ if (--$depth > 0) {
+ ++$Sp;
+ return minijson_decode_object($s, $Sp, $Sx, $ov,
$depth);
+ }
+ $ov = 'recursion limit exceeded by Object';
+ } elseif ($c === 0x5B) {
+ if (--$depth > 0) {
+ ++$Sp;
+ return minijson_decode_array($s, $Sp, $Sx, $ov, $depth);
+ }
+ $ov = 'recursion limit exceeded by Array';
+ } elseif ($c <= 0x39 && ($c >= 0x30 || $c === 0x2D)) {
+ return minijson_decode_number($s, $Sp, $Sx, $ov);
+ } elseif ($c === 0x6E) {
/* literal null? */
- if (substr($s, $Sp, 3) === 'ull') {
- $Sp += 3;
+ if (substr_compare($s, 'null', $Sp, 4) === 0) {
+ $Sp += 4;
$ov = NULL;
return true;
}
- --$Sp;
- $ov = 'expected “ull” after “n”';
- } elseif ($c === 't') {
+ $ov = 'after “n”, “ull” expected';
+ } elseif ($c === 0x74) {
/* literal true? */
- if (substr($s, $Sp, 3) === 'rue') {
- $Sp += 3;
+ if (substr_compare($s, 'true', $Sp, 4) === 0) {
+ $Sp += 4;
$ov = true;
return true;
}
- --$Sp;
- $ov = 'expected “rue” after “t”';
- } elseif ($c === 'f') {
+ $ov = 'after “t”, “rue” expected';
+ } elseif ($c === 0x66) {
/* literal false? */
- if (substr($s, $Sp, 4) === 'alse') {
- $Sp += 4;
+ if (substr_compare($s, 'false', $Sp, 5) === 0) {
+ $Sp += 5;
$ov = false;
return true;
}
- --$Sp;
- $ov = 'expected “alse” after “f”';
- } elseif ($c === '[') {
- if (--$depth > 0)
- return minijson_decode_array($s, $Sp, $Sx, $ov, $depth);
- --$Sp;
- $ov = 'recursion limit exceeded by Array';
- } elseif ($c === '{') {
- if (--$depth > 0)
- return minijson_decode_object($s, $Sp, $Sx, $ov,
$depth);
- --$Sp;
- $ov = 'recursion limit exceeded by Object';
- } elseif ($c === '"') {
- if (($ov = minijson_decode_string($s, $Sp, $Sx)) !== true) {
- ob_end_clean();
- return false;
- }
- $ov = ob_get_clean();
- return true;
- } elseif ($c === '-' || (ord($c) >= 0x30 && ord($c) <= 0x39)) {
- --$Sp;
- return minijson_decode_number($s, $Sp, $Sx, $ov);
- } elseif (ord($c) >= 0x20 && ord($c) <= 0x7E) {
- --$Sp;
- $ov = "unexpected “{$c}”, Value expected";
+ $ov = 'after “f”, “alse” expected';
+ } elseif ($c <= 0x7E && $c >= 0x20) {
+ $ov = 'unexpected “' . chr($c) . '”, Value expected';
+ } elseif ($c !== -1) {
+ $ov = sprintf('unexpected 0x%02X, Value expected', $c);
} else {
- --$Sp;
- $ov = sprintf('unexpected 0x%02X, Value expected', ord($c));
+ $ov = 'unexpected EOS, Value expected';
}
return false;
}
function minijson_decode_string($s, &$Sp, $Sx) {
ob_start();
- minijson_decode_string_loop:
- if ($Sp >= $Sx)
- return 'unexpected EOS in String';
- /* get next octet; switch on what to do with it */
- if (($ch = $s[$Sp++]) === '"') {
- /* regular exit point for the loop */
- return true;
- }
- /* backslash escape? */
- if ($ch === "\\") {
- if ($Sp >= $Sx)
- return 'unexpected EOS after backslash in String';
- $ch = $s[$Sp++];
- if ($ch === '"' || $ch === '/' || $ch === "\\")
- echo $ch;
- elseif ($ch === 't')
- echo "\x09";
- elseif ($ch === 'n')
- echo "\x0A";
- elseif ($ch === 'r')
- echo "\x0D";
- elseif ($ch === 'b')
- echo "\x08";
- elseif ($ch === 'f')
- echo "\x0C";
- elseif ($ch !== 'u') {
- $Sp -= 2;
- return "invalid escape '\\$ch' in String";
- } else {
- $surrogate = 0;
- minijson_decode_string_unicode_escape:
- $wc = 0;
- if ($Sp + 4 > $Sx) {
+ while ($Sp < $Sx) {
+ /* get next octet; switch on what to do with it */
+ if (($c = ord(($ch = $s[$Sp++]))) === 0x22) {
+ /* regular exit point for the loop */
+ return true;
+ }
+ /* backslash escape? */
+ if ($c === 0x5C) {
+ if ($Sp >= $Sx)
+ return 'incomplete escape sequence';
+ $c = ord(($ch = $s[$Sp++]));
+ if ($c === 0x22 || $c === 0x5C || $c === 0x2F)
+ echo $ch;
+ elseif ($c === 0x74)
+ echo "\x09";
+ elseif ($c === 0x6E)
+ echo "\x0A";
+ elseif ($c === 0x75) {
+ $c = minijson_decode_uescape($s, $Sp, $Sx, $ch);
+ if ($c >= 0xD800 && $c <= 0xDFFF)
+ $c = minijson_decode_surrogate($s, $Sp,
+ $Sx, $c, $ch);
+ if ($c === 0)
+ return $ch;
+ if ($c < 0x80)
+ echo chr($c);
+ elseif ($c < 0x0800)
+ echo chr(0xC0 | ($c >> 6)) .
+ chr(0x80 | ($c & 0x3F));
+ elseif ($c <= 0xFFFF)
+ echo chr(0xE0 | ($c >> 12)) .
+ chr(0x80 | (($c >> 6) & 0x3F)) .
+ chr(0x80 | ($c & 0x3F));
+ else
+ echo chr(0xF0 | ($c >> 18)) .
+ chr(0x80 | (($c >> 12) & 0x3F)) .
+ chr(0x80 | (($c >> 6) & 0x3F)) .
+ chr(0x80 | ($c & 0x3F));
+ } elseif ($c === 0x72)
+ echo "\x0D";
+ elseif ($c === 0x62)
+ echo "\x08";
+ elseif ($c === 0x66)
+ echo "\x0C";
+ else {
$Sp -= 2;
- return 'unexpected EOS in Unicode escape
sequence';
+ return "invalid escape sequence “\\{$ch}”";
}
- for ($tmp = 1; $tmp <= 4; $tmp++) {
- $wc <<= 4;
- switch (ord($s[$Sp++])) {
- case 0x30: break;
- case 0x31: $wc += 1; break;
- case 0x32: $wc += 2; break;
- case 0x33: $wc += 3; break;
- case 0x34: $wc += 4; break;
- case 0x35: $wc += 5; break;
- case 0x36: $wc += 6; break;
- case 0x37: $wc += 7; break;
- case 0x38: $wc += 8; break;
- case 0x39: $wc += 9; break;
- case 0x41: case 0x61: $wc += 10; break;
- case 0x42: case 0x62: $wc += 11; break;
- case 0x43: case 0x63: $wc += 12; break;
- case 0x44: case 0x64: $wc += 13; break;
- case 0x45: case 0x65: $wc += 14; break;
- case 0x46: case 0x66: $wc += 15; break;
- default:
- --$Sp;
- return "invalid hex digit #$tmp/4 in
Unicode escape sequence";
- }
+ continue;
+ }
+ echo $ch;
+ if ($c < 0x80) {
+ if ($c >= 0x20)
+ continue;
+ --$Sp;
+ return sprintf('unexpected C0 control 0x%02X', $c);
+ }
+ /* UTF-8 BMP sequence (unrolled) */
+ if ($c < 0xE0) {
+ if ($c < 0xC2) {
+ --$Sp;
+ return sprintf('invalid UTF-8 lead octet
0x%02X',
+ $c);
}
- if ($surrogate) {
- if ($wc < 0xDC00 || $wc > 0xDFFF) {
- $Sp -= 6;
- return sprintf('expected low surrogate,
not %04X, after high surrogate %04X', $wc, $surrogate);
- }
- $wc = 0x10000 + (($surrogate & 0x03FF) << 10) +
($wc & 0x03FF);
- } elseif ($wc >= 0xD800 && $wc <= 0xDBFF) {
- $surrogate = $wc;
- /* UTF-16 expects the low surrogate */
- if (substr($s, $Sp, 2) !== '\u')
- return 'expected Unicode escape after
high surrogate';
- $Sp += 2;
- goto minijson_decode_string_unicode_escape;
- } elseif ($wc >= 0xDC00 && $wc <= 0xDFFF) {
- $Sp -= 6;
- return sprintf('loose low surrogate %04X', $wc);
- } elseif ($wc < 1 || $wc > 0xFFFD) {
- $Sp -= 6;
- return sprintf('non-Unicode escape %04X', $wc);
+ if ($Sp + 1 > $Sx) {
+ --$Sp;
+ return 'incomplete UTF-8 sequence';
}
- if ($wc < 0x80) {
- echo chr($wc);
- goto minijson_decode_string_loop;
+ if (($c = ord(($ch = $s[$Sp++])) ^ 0x80) > 0x3F) {
+ --$Sp;
+ return sprintf('invalid UTF-8 trail octet
0x%02X',
+ $c ^ 0x80);
}
- minijson_decode_string_unicode_char:
- if ($wc < 0x0800)
- echo chr(0xC0 | ($wc >> 6)) .
- chr(0x80 | ($wc & 0x3F));
- elseif ($wc <= 0xFFFF)
- echo chr(0xE0 | ($wc >> 12)) .
- chr(0x80 | (($wc >> 6) & 0x3F)) .
- chr(0x80 | ($wc & 0x3F));
- else
- echo chr(0xF0 | ($wc >> 18)) .
- chr(0x80 | (($wc >> 12) & 0x3F)) .
- chr(0x80 | (($wc >> 6) & 0x3F)) .
- chr(0x80 | ($wc & 0x3F));
+ echo $ch;
+ continue;
+ } elseif ($c >= 0xF0) {
+ --$Sp;
+ return sprintf('invalid UTF-8 lead octet 0x%02X', $c);
+ }
+ if ($Sp + 2 > $Sx) {
+ --$Sp;
+ return 'incomplete UTF-8 sequence';
}
- goto minijson_decode_string_loop;
- }
- if (($c = ord($ch)) < 0x20) {
- --$Sp;
- return sprintf('unescaped control character 0x%02X in String',
$c);
- }
- if ($c < 0x80) {
- echo $ch;
- goto minijson_decode_string_loop;
- }
- /* decode UTF-8 */
- if ($c < 0xC2 || $c >= 0xF0) {
- --$Sp;
- return sprintf('invalid UTF-8 lead octet 0x%02X in String', $c);
- }
- if ($c < 0xE0) {
- $wc = ($c & 0x1F) << 6;
- $wmin = 0x80; /* redundant */
- $Ss = 1;
- } else {
$wc = ($c & 0x0F) << 12;
- $wmin = 0x800;
- $Ss = 2;
- }
- if ($Sp + $Ss > $Sx) {
- --$Sp;
- return 'unexpected EOS after UTF-8 lead byte in String';
- }
- while ($Ss--)
- if (($c = ord($s[$Sp++]) ^ 0x80) <= 0x3F)
- $wc |= $c << (6 * $Ss);
- else {
+ if (($c = ord(($ch = $s[$Sp++])) ^ 0x80) <= 0x3F) {
+ $wc |= $c << 6;
+ echo $ch;
+ } else {
+ --$Sp;
+ return sprintf('invalid UTF-8 trail octet 0x%02X',
+ $c ^ 0x80);
+ }
+ if (($c = ord(($ch = $s[$Sp++])) ^ 0x80) <= 0x3F) {
+ $wc |= $c;
+ echo $ch;
+ } else {
--$Sp;
- return sprintf('invalid UTF-8 trail octet 0x%02X in
String', $c ^ 0x80);
+ return sprintf('invalid UTF-8 trail octet 0x%02X',
+ $c ^ 0x80);
+ }
+ if ($wc < 0x0800) {
+ $Sp -= 3;
+ return sprintf('non-minimal encoding for %04X', $wc);
+ }
+ if ($wc >= 0xD800 && $wc <= 0xDFFF) {
+ $Sp -= 3;
+ return sprintf('unescaped surrogate %04X', $wc);
+ }
+ if ($wc > 0xFFFD) {
+ $Sp -= 3;
+ return sprintf('unescaped non-character %04X', $wc);
}
- if ($wc < $wmin) {
- $Sp -= 3; /* only for E0‥EF-led sequence */
- return sprintf('non-minimalistic encoding for Unicode char %04X
in String', $wc);
}
+ return 'unexpected EOS in String';
+}
- if ($wc >= 0xD800 && $wc <= 0xDFFF) {
- $Sp -= 3;
- return sprintf('unescaped surrogate %04X in String', $wc);
+/* decodes the four nybbles after “\u” */
+function minijson_decode_uescape($s, &$Sp, $Sx, &$e) {
+ if ($Sp + 4 > $Sx) {
+ $Sp -= 2;
+ $e = 'incomplete escape sequence';
+ return 0;
+ }
+ $wc = 0;
+ for ($tmp = 1; $tmp <= 4; $tmp++) {
+ $wc <<= 4;
+ switch (ord($s[$Sp++])) {
+ case 0x30: break;
+ case 0x31: $wc += 1; break;
+ case 0x32: $wc += 2; break;
+ case 0x33: $wc += 3; break;
+ case 0x34: $wc += 4; break;
+ case 0x35: $wc += 5; break;
+ case 0x36: $wc += 6; break;
+ case 0x37: $wc += 7; break;
+ case 0x38: $wc += 8; break;
+ case 0x39: $wc += 9; break;
+ case 0x41: case 0x61: $wc += 10; break;
+ case 0x42: case 0x62: $wc += 11; break;
+ case 0x43: case 0x63: $wc += 12; break;
+ case 0x44: case 0x64: $wc += 13; break;
+ case 0x45: case 0x65: $wc += 14; break;
+ case 0x46: case 0x66: $wc += 15; break;
+ default:
+ --$Sp;
+ $e = 'hexadecimal digit expected';
+ return 0;
+ }
}
- if ($wc <= 0xFFFD)
- goto minijson_decode_string_unicode_char;
- $Sp -= 3;
- return sprintf('non-Unicode char %04X in String', $wc);
+ if ($wc < 1 || $wc > 0xFFFD) {
+ $Sp -= 6;
+ $e = sprintf('invalid escape \\u%04X', $wc);
+ return 0;
+ }
+ return $wc;
+}
+
+/* called if decoding the above resulted in a surrogate */
+function minijson_decode_surrogate($s, &$Sp, $Sx, $wc, &$e) {
+ /* loose low surrogate? */
+ if ($wc >= 0xDC00) {
+ $Sp -= 6;
+ $e = sprintf('unexpected low surrogate \\u%04X', $wc);
+ return 0;
+ }
+ /* wc is a high surrogate */
+ if ($Sp + 6 > $Sx || $s[$Sp] !== '\\' || $s[$Sp + 1] !== 'u') {
+ $e = 'escaped low surrogate expected';
+ return 0;
+ }
+ $Sp += 2;
+ if (($lc = minijson_decode_uescape($s, $Sp, $Sx, $e)) === 0)
+ return 0;
+ if ($lc < 0xDC00 || $lc > 0xDFFF) {
+ $Sp -= 6;
+ $e = sprintf('unexpected \\u%04X, low surrogate expected', $lc);
+ return 0;
+ }
+ return 0x10000 + (($wc & 0x03FF) << 10) + ($lc & 0x03FF);
}
function minijson_decode_number($s, &$Sp, $Sx, &$ov) {
$matches = array('');
if
(!preg_match('/-?(?:0|[1-9][0-9]*)(?:\.[0-9]+)?(?:[Ee][+-]?[0-9]+)?/A',
- $s, $matches, 0, $Sp) || strlen($matches[0]) < 1) {
- $ov = 'expected Number';
+ $s, $matches, 0, $Sp) || ($Ss = strlen($matches[0])) < 1) {
+ $ov = 'Number expected';
+ return false;
+ }
+ if ($Sp + $Ss > $Sx) {
+ $ov = 'unexpected EOS in Number';
return false;
}
- $Sp += strlen($matches[0]);
+ $Sp += $Ss;
if (strpos($matches[0], '.') === false) {
/* possible integer */
$ov = (int)$matches[0];
diff --git a/tests/unit/common/minijsonTest.php
b/tests/unit/common/minijsonTest.php
index 3857e1f..24f733e 100644
--- a/tests/unit/common/minijsonTest.php
+++ b/tests/unit/common/minijsonTest.php
@@ -25,14 +25,17 @@
*/
require_once('PHPUnit/Framework/TestCase.php');
-require_once(dirname(__FILE__) . '/../../../src/common/include/minijson.php');
class Minijson_Tests extends PHPUnit\Framework\TestCase {
+ public function testMiniJson() {
+ $s = error_reporting(-1);
+ require_once(dirname(__FILE__) .
'/../../../src/common/include/minijson.php');
+
/****************************************************************/
/* $s_orig [parse] print_r->$s_printr [encode] $s_ecompact or
$s_epadded */
/* $s_e* [decode] print_r ->$s_printrs (due to Object key sorting) */
- var $s_orig = '[
+ $s_orig = '[
"JSON Test Pattern pass1",
{"object with 1 member":["array with 1 element"]},
{},
@@ -91,7 +94,7 @@ class Minijson_Tests extends PHPUnit\Framework\TestCase {
1e00,2e+00,2e-00
,"rosebud"]';
- var $s_printr = 'Array
+ $s_printr = 'Array
(
[0] => JSON Test Pattern pass1
[1] => Array
@@ -127,8 +130,7 @@ class Minijson_Tests extends PHPUnit\Framework\TestCase {
[space] => ' . '
[quote] => "
[backslash] => \\
- [controls] => ' . '
-
' . '
+ [controls] => ' . "\x08\x0C\x0A\x0D\x09" . '
[slash] => / & /
[alpha] => abcdefghijklmnopqrstuvwyz
[ALPHA] => ABCDEFGHIJKLMNOPQRSTUVWYZ
@@ -175,8 +177,7 @@ class Minijson_Tests extends PHPUnit\Framework\TestCase {
[jsontext] => {"object with 1 member":["array with 1 element"]}
[quotes] => " " %22 0x22 034 "
- [/\\"쫾몾ꮘﳞ볚' . '
-
`1~!@#$%^&*()_+-=[]{}|;:\',./<>?] => A key can be any string
+ [/\\"쫾몾ꮘﳞ볚' . "\x0A\x0D\x09" .
'`1~!@#$%^&*()_+-=[]{}|;:\',./<>?] => A key can be any string
)
[9] => 0.5
@@ -193,7 +194,7 @@ class Minijson_Tests extends PHPUnit\Framework\TestCase {
)
';
- var $s_printrs = 'Array
+ $s_printrs = 'Array
(
[0] => JSON Test Pattern pass1
[1] => Array
@@ -232,8 +233,7 @@ class Minijson_Tests extends PHPUnit\Framework\TestCase {
)
[# -- --> */] => ' . '
- [/\\"쫾몾ꮘﳞ볚' . '
-
`1~!@#$%^&*()_+-=[]{}|;:\',./<>?] => A key can be any string
+ [/\\"쫾몾ꮘﳞ볚' . "\x08\x0C\x0A\x0D\x09" .
'`1~!@#$%^&*()_+-=[]{}|;:\',./<>?] => A key can be any string
[0123456789] => digit
[ALPHA] => ABCDEFGHIJKLMNOPQRSTUVWYZ
[E] => 1.23456789E+34
@@ -256,8 +256,7 @@ class Minijson_Tests extends PHPUnit\Framework\TestCase {
[6] => 7
)
- [controls] => ' . '
-
' . '
+ [controls] => ' . "\x08\x0C\x0A\x0D\x09" . '
[digit] => 0123456789
[e] => 1.23456789E-13
[false] => ' . '
@@ -295,8 +294,8 @@ class Minijson_Tests extends PHPUnit\Framework\TestCase {
)
';
- var $s_ecompact = '["JSON Test Pattern pass1",{"object with 1
member":["array with 1
element"]},[],[],-42,true,false,null,{"":2.3456789012E+76," s p a c e d
":[1,2,3,4,5,6,7],"# -- --> */":"
","/\\\\\\"쫾몾ꮘﳞ볚\\b\\f\\n\\r\\t`1~!@#$%^&*()_+-=[]{}|;:\',./<>?":"A key can be
any
string","0123456789":"digit","ALPHA":"ABCDEFGHIJKLMNOPQRSTUVWYZ","E":1.23456789E+34,"address":"50
St. James
Street","alpha":"abcdefghijklmnopqrstuvwyz","array":[],"backslash":"\\\\","comment":"//
/* <!--
--","compact":[1,2,3,4,5,6,7],"controls":"\\b\\f\\n\\r\\t","digit":"0123456789","e":1.23456789E-13,"false":false,"hex":"ģ䕧覫췯ꯍ","integer":1234567890,"jsontext":"{\\"object
with 1 member\\":[\\"array with 1
element\\"]}","null":null,"object":[],"one":1,"quote":"\\"","quotes":"" \\"
%22 0x22 034 "","real":-9.87654321E+3,"slash":"/ & /","space":"
","special":"`1~!@#$%^&*()_+-={\':[,]}|;.</>?","true":true,"url":"http://www.JSON.org/","zero":0},5.0E-1,9.86E+1,9.944E+1,1066,1.0E+1,1.0,1.0E-1,1.0,2.0,2.0,"rosebud"]';
- var $s_epadded = '[
+ $s_ecompact = '["JSON Test Pattern pass1",{"object with 1
member":["array with 1
element"]},[],[],-42,true,false,null,{"":2.3456789012E+76," s p a c e d
":[1,2,3,4,5,6,7],"# -- --> */":"
","/\\\\\\"쫾몾ꮘﳞ볚\\b\\f\\n\\r\\t`1~!@#$%^&*()_+-=[]{}|;:\',./<>?":"A key can be
any
string","0123456789":"digit","ALPHA":"ABCDEFGHIJKLMNOPQRSTUVWYZ","E":1.23456789E+34,"address":"50
St. James
Street","alpha":"abcdefghijklmnopqrstuvwyz","array":[],"backslash":"\\\\","comment":"//
/* <!--
--","compact":[1,2,3,4,5,6,7],"controls":"\\b\\f\\n\\r\\t","digit":"0123456789","e":1.23456789E-13,"false":false,"hex":"ģ䕧覫췯ꯍ","integer":1234567890,"jsontext":"{\\"object
with 1 member\\":[\\"array with 1
element\\"]}","null":null,"object":[],"one":1,"quote":"\\"","quotes":"" \\"
%22 0x22 034 "","real":-9.87654321E+3,"slash":"/ & /","space":"
","special":"`1~!@#$%^&*()_+-={\':[,]}|;.</>?","true":true,"url":"http://www.JSON.org/","zero":0},5.0E-1,9.86E+1,9.944E+1,1066,1.0E+1,1.0,1.0E-1,1.0,2.0,2.0,"rosebud"]';
+ $s_epadded = '[
"JSON Test Pattern pass1",
{
"object with 1 member": [
@@ -374,33 +373,40 @@ class Minijson_Tests extends PHPUnit\Framework\TestCase {
/****************************************************************/
- public function testMiniJson() {
$parsed = 'bla';
- $presult = minijson_decode($this->s_orig, $parsed);
+ $presult = minijson_decode($s_orig, $parsed);
$this->assertTrue($presult);
$this->assertEquals('array', gettype($parsed), 'FAIL
parse-basic');
$printrd = print_r($parsed, true);
- $this->assertEquals($this->s_printr, $printrd, 'parsed');
+ $this->assertEquals($s_printr, $printrd, 'parsed');
$encoded = minijson_encode($parsed, false);
- $this->assertEquals($this->s_ecompact, $encoded,
'encode-compact');
+ $this->assertEquals($s_ecompact, $encoded, 'encode-compact');
$reparsed = 'bla';
$presult = minijson_decode($encoded, $reparsed);
$this->assertTrue($presult, 'can-reparse-compact');
$this->assertEquals('array', gettype($reparsed), 'FAIL
reparse-compact-basic');
$printrd = print_r($reparsed, true);
- $this->assertEquals($this->s_printrs, $printrd,
'reparsed-compact');
+ $this->assertEquals($s_printrs, $printrd, 'reparsed-compact');
$encoded = minijson_encode($parsed);
- $this->assertEquals($this->s_epadded, $encoded,
'encode-padded');
+ $this->assertEquals($s_epadded, $encoded, 'encode-padded');
$reparsed = 'bla';
$presult = minijson_decode($encoded, $reparsed);
$this->assertTrue($presult, 'can-reparse-padded');
$this->assertEquals('array', gettype($reparsed), 'FAIL
reparse-padded-basic');
$printrd = print_r($reparsed, true);
- $this->assertEquals($this->s_printrs, $printrd,
'reparsed-padded');
+ $this->assertEquals($s_printrs, $printrd, 'reparsed-padded');
+
+ $encoded = '0';
+ $reparsed = 'bla';
+ $presult = minijson_decode($encoded, $reparsed);
+ $this->assertTrue($presult, 'can-parse-0');
+ $this->assertEquals(0, $reparsed);
+
+ error_reporting($s);
}
}
https://scm.fusionforge.org/anonscm/gitweb/?p=fusionforge/fusionforge.git;a=commitdiff;h=54dcb9ce9d6f266f591613e1844670fa6e8a77c0
commit 54dcb9ce9d6f266f591613e1844670fa6e8a77c0
Merge: 1db485d d53aeb1
Author: mirabilos <[email protected]>
Date: Thu Jun 11 03:45:24 2020 +0200
Update post-receive-email to latest version
• fix typos
• enable UTF-8 filenames in output; from an IRC question by madduck
• rework Subject header encoding to be more reliable
(this merges the FusionForge-local change to prefer PHP over Perl)
• detect whether git rev-list actually outputted anything;
issue a "no new revisions added by this update" message if not
• sort out logs in eMails when multiple branches are pushed at once
• diff showing in branch creation mail (with empty-tree even on new
histories)
• update header
• move to C.UTF-8 from en_US.UTF-8 (more widespread by now)
• update list of requirements to include cURL; indicate PHP preference
(cURL is only needed if curlhooks are used, of course)
• indicate multiple recipients convention
elaborate more on one vs. multiple addresses
• skip diff if no new revisions
• attempt to clean up the first eMail paragraph a little
Merge branch 'standalone' of
git+ssh://evolvis.org/scmrepos/git/evolvis-platfrm/recvhook
https://scm.fusionforge.org/anonscm/gitweb/?p=fusionforge/fusionforge.git;a=commitdiff;h=d53aeb132ba88cb42a0514ec3f8c83cfd27ab2b1
commit d53aeb132ba88cb42a0514ec3f8c83cfd27ab2b1
Author: mirabilos <[email protected]>
Date: Sat May 9 18:06:31 2020 +0200
attempt to clean up the first eMail paragraph a little
diff --git a/post-receive-email b/post-receive-email
index 38f6cac..abde17e 100755
--- a/post-receive-email
+++ b/post-receive-email
@@ -1,11 +1,13 @@
#!/bin/mksh
#
+# Copyright © 2016, 2020
+# mirabilos <[email protected]>
# Copyright © 2013
# Thorsten “mirabilos” Glaser <[email protected]>
# Copyright © 2011, 2012, 2013, 2014, 2015, 2018, 2019
# Thorsten “mirabilos” Glaser <[email protected]>
# Copyright © 2016
-# martin f krafft (madduck), Thorsten Glaser (mirabilos)
+# martin f krafft (madduck)
#
# Copyright (c) 2007 Andy Parkins
#
@@ -288,6 +290,7 @@ generate_email()
generate_email_header()
{
local routing_headers subj senc failc=0
+ local repolabel
# --- Email (all stdout will be the email)
# Generate header
@@ -330,6 +333,12 @@ generate_email_header()
senc="Subject: post-receive-email: no Subject, RFC2047 MIME
encoding failed"
fi
+ if [[ $shortdesc = "$projectdesc" ]]; then
+ repolabel=$PWD
+ else
+ repolabel=$shortdesc
+ fi
+
cat <<-EOF
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
@@ -342,9 +351,10 @@ generate_email_header()
$senc
Auto-Submitted: auto-generated
- This is an automated email from the git hooks/post-receive script. It
was
- generated because a ref change was pushed to the repository containing
- the project "$projectdesc".
+ This is an automated email from the git hooks/post-receive script.
+ It was generated because a ref change was pushed to the repository
+ "$repolabel" containing the project
+ "$projectdesc".
The $refname_type, $short_refname has been ${change_type}d
EOF
https://scm.fusionforge.org/anonscm/gitweb/?p=fusionforge/fusionforge.git;a=commitdiff;h=a9d53b2c9c5c7ebf89da0ed82e8a5107b041f5d9
commit a9d53b2c9c5c7ebf89da0ed82e8a5107b041f5d9
Author: mirabilos <[email protected]>
Date: Mon Nov 11 00:14:41 2019 +0100
skip diff if no new revisions
diff --git a/post-receive-email b/post-receive-email
index c5ccc28..38f6cac 100755
--- a/post-receive-email
+++ b/post-receive-email
@@ -551,19 +551,20 @@ generate_update_branch_email()
[[ -n $rewind_only ]] || newrevs=$(show_new_revisions)
echo ""
- if [[ -n $newrevs ]]; then
- echo "Those revisions listed above that are new to this
repository have"
- echo "not appeared on any other notification email; so we list
those"
- echo "revisions in full, below."
-
- echo ""
- echo $LOGBEGIN
- print -r -- "$newrevs"
- echo $LOGEND
- else
+ if [[ -z $newrevs ]]; then
echo "No new revisions were added by this update."
+ return 0
fi
+ echo "Those revisions listed above that are new to this repository have"
+ echo "not appeared on any other notification email; so we list those"
+ echo "revisions in full, below."
+
+ echo ""
+ echo $LOGBEGIN
+ print -r -- "$newrevs"
+ echo $LOGEND
+
# The diffstat is shown from the old revision to the new revision.
# This is to show the truth of what happened in this change.
# There's no point showing the stat from the base to the new
https://scm.fusionforge.org/anonscm/gitweb/?p=fusionforge/fusionforge.git;a=commitdiff;h=d61575c6c0ba5f80d371a6a74f762fd4a32a96ff
commit d61575c6c0ba5f80d371a6a74f762fd4a32a96ff
Author: mirabilos <[email protected]>
Date: Fri Jan 25 18:08:06 2019 +0100
elaborate more on one vs. multiple addresses
diff --git a/post-receive-email b/post-receive-email
index a8c2b46..c5ccc28 100755
--- a/post-receive-email
+++ b/post-receive-email
@@ -70,10 +70,10 @@
# it blank to default to the mailinglist field. The announce emails list
# the short log summary of the changes since the last annotated tag.
# hooks.replyto
-# If set, replies are requested to be directed to this eMail address.
+# If set, replies are requested to be directed to this eMail address(es).
# hooks.envelopesender
# If set then the -f option is passed to sendmail to allow the envelope
-# sender address to be set. This is also used as From header.
+# sender to be set (one address only). This is also used as From header.
# hooks.emailprefix
# If set, e.g. to '[SCM] ', all eMails have their subjects prefixed
# with this string to aid filtering.
https://scm.fusionforge.org/anonscm/gitweb/?p=fusionforge/fusionforge.git;a=commitdiff;h=13f0da02ae64d8b2f27156bb20901e781b038aef
commit 13f0da02ae64d8b2f27156bb20901e781b038aef
Author: mirabilos <[email protected]>
Date: Fri Jan 25 18:07:16 2019 +0100
typos
diff --git a/post-receive-email b/post-receive-email
index b88a27b..a8c2b46 100755
--- a/post-receive-email
+++ b/post-receive-email
@@ -67,13 +67,13 @@
# multiple recipients (but please only use addresses, not full names).
# hooks.announcelist
# This is the list(s) that all pushes of annotated tags will go to. Leave
-# it blank to default to the mailinglist field. The announce emails lists
+# it blank to default to the mailinglist field. The announce emails list
# the short log summary of the changes since the last annotated tag.
# hooks.replyto
# If set, replies are requested to be directed to this eMail address.
# hooks.envelopesender
# If set then the -f option is passed to sendmail to allow the envelope
-# sender address to be set. This is also used as Header From.
+# sender address to be set. This is also used as From header.
# hooks.emailprefix
# If set, e.g. to '[SCM] ', all eMails have their subjects prefixed
# with this string to aid filtering.
https://scm.fusionforge.org/anonscm/gitweb/?p=fusionforge/fusionforge.git;a=commitdiff;h=fbc3d4f9a3f4c41184d250c58b0a031a44075e62
commit fbc3d4f9a3f4c41184d250c58b0a031a44075e62
Author: mirabilos <[email protected]>
Date: Fri Jan 25 18:06:00 2019 +0100
indicate multiple recipients convention
diff --git a/post-receive-email b/post-receive-email
index 6d8cc76..b88a27b 100755
--- a/post-receive-email
+++ b/post-receive-email
@@ -63,10 +63,11 @@
# ------
# hooks.mailinglist
# This is the list that all pushes will go to; leave it blank to not send
-# emails for every ref update.
+# emails for every ref update. This fills the To header, so use comma for
+# multiple recipients (but please only use addresses, not full names).
# hooks.announcelist
-# This is the list that all pushes of annotated tags will go to. Leave it
-# blank to default to the mailinglist field. The announce emails lists
+# This is the list(s) that all pushes of annotated tags will go to. Leave
+# it blank to default to the mailinglist field. The announce emails lists
# the short log summary of the changes since the last annotated tag.
# hooks.replyto
# If set, replies are requested to be directed to this eMail address.
https://scm.fusionforge.org/anonscm/gitweb/?p=fusionforge/fusionforge.git;a=commitdiff;h=c47cf1cf76cd9c120881ca552ec34890014d1cf6
commit c47cf1cf76cd9c120881ca552ec34890014d1cf6
Author: mirabilos <[email protected]>
Date: Fri Jan 25 18:02:25 2019 +0100
update list of requirements to include cURL; indicate PHP preference
diff --git a/post-receive-email b/post-receive-email
index 49598ad..6d8cc76 100755
--- a/post-receive-email
+++ b/post-receive-email
@@ -42,8 +42,9 @@
# # but that can only be used for a Forge-controlled repository
#
# This hook script needs the “C.UTF-8” locale set up (or change below).
-# The MirBSD Korn Shell (mksh) must be installed as /bin/mksh and usable.
-# Perl or PHP with the Multibyte extension are required as well.
+# Other requirementa are: The MirBSD Korn Shell (mksh) as /bin/mksh;
+# PHP with the mbstring extension (preferred) or Perl 5; curl, if you
+# wish to use the curltrigger functionality.
#
# This hook script assumes it is enabled on the central repository of a
# project, with all users pushing only to it and not between each other. It
https://scm.fusionforge.org/anonscm/gitweb/?p=fusionforge/fusionforge.git;a=commitdiff;h=5f5b45d3915b5b3b1660db4f3f3e2a2564377fb1
commit 5f5b45d3915b5b3b1660db4f3f3e2a2564377fb1
Author: mirabilos <[email protected]>
Date: Fri Jan 25 17:58:51 2019 +0100
move to C.UTF-8 from en_US.UTF-8 (more widespread by now)
diff --git a/post-receive-email b/post-receive-email
index e347b9a..49598ad 100755
--- a/post-receive-email
+++ b/post-receive-email
@@ -2,7 +2,7 @@
#
# Copyright © 2013
# Thorsten “mirabilos” Glaser <[email protected]>
-# Copyright © 2011, 2012, 2013, 2014, 2015, 2018
+# Copyright © 2011, 2012, 2013, 2014, 2015, 2018, 2019
# Thorsten “mirabilos” Glaser <[email protected]>
# Copyright © 2016
# martin f krafft (madduck), Thorsten Glaser (mirabilos)
@@ -41,7 +41,7 @@
# ln -sf /etc/gforge/plugins/scmgit/post-receive-email.sh hooks/post-receive
# # but that can only be used for a Forge-controlled repository
#
-# This hook script needs the “en_US.UTF-8” locale set up on the server.
+# This hook script needs the “C.UTF-8” locale set up (or change below).
# The MirBSD Korn Shell (mksh) must be installed as /bin/mksh and usable.
# Perl or PHP with the Multibyte extension are required as well.
#
@@ -120,7 +120,7 @@
nl='
'
unset LANGUAGE LC_ALL
-export LANG=C LC_ADDRESS=C LC_COLLATE=C LC_CTYPE=en_US.UTF-8 \
+export LANG=C LC_ADDRESS=C LC_COLLATE=C LC_CTYPE=C.UTF-8 \
LC_IDENTIFICATION=C LC_MEASUREMENT=C LC_MESSAGES=C \
LC_MONETARY=C LC_NAME=C LC_NUMERIC=C LC_PAPER=C \
LC_TELEPHONE=C LC_TIME=C
https://scm.fusionforge.org/anonscm/gitweb/?p=fusionforge/fusionforge.git;a=commitdiff;h=fcfc96a351704dedbfa1c476b3791f431045fa72
commit fcfc96a351704dedbfa1c476b3791f431045fa72
Author: mirabilos <[email protected]>
Date: Wed Sep 5 19:34:31 2018 +0200
update header
diff --git a/post-receive-email b/post-receive-email
index 171881f..e347b9a 100755
--- a/post-receive-email
+++ b/post-receive-email
@@ -15,12 +15,12 @@
#
# An example hook script to mail out commit update information.
#
-# NOTE: This script is no longer under active development. There
-# is another script, git-multimail, which is more capable and
-# configurable and is largely backwards-compatible with this script;
-# please see "contrib/hooks/multimail/". For instructions on how to
-# migrate from post-receive-email to git-multimail, please see
-# "README.migrate-from-post-receive-email" in that directory.
+# This script is not under active development by the git team, with
+# git-multimail being suggested as replacement. It has downsides,
+# of course; this script is maintained as a fork, by mirabilos, for
+# 100% compatibility with the old version, plus bugfixes (encoding)
+# and new features (more and better diffs shown; cURL triggers and
+# “KGB” bot support, etc.) and optional FusionForge integration.
#
# This hook sends emails listing new revisions to the repository
# introduced by the change being reported. The rule is that (for
@@ -43,6 +43,7 @@
#
# This hook script needs the “en_US.UTF-8” locale set up on the server.
# The MirBSD Korn Shell (mksh) must be installed as /bin/mksh and usable.
+# Perl or PHP with the Multibyte extension are required as well.
#
# This hook script assumes it is enabled on the central repository of a
# project, with all users pushing only to it and not between each other. It
https://scm.fusionforge.org/anonscm/gitweb/?p=fusionforge/fusionforge.git;a=commitdiff;h=44e481fc6c362efdf59e7f46e3873292cbb1a278
commit 44e481fc6c362efdf59e7f46e3873292cbb1a278
Author: mirabilos <[email protected]>
Date: Wed Sep 5 19:22:05 2018 +0200
fix branch creation diff (with empty-tree even on new histories);
it’s only still wonky when a non-new created branch starts with
a merge commit (the left/first parent is used, but things can
get weird, depending on what is already known history)
diff --git a/post-receive-email b/post-receive-email
index a0f387a..171881f 100755
--- a/post-receive-email
+++ b/post-receive-email
@@ -379,8 +379,7 @@ generate_create_branch_email()
echo "Below, we list all revisions that are new to this repository and"
echo "have not appeared on any other notification email. The diff below"
- echo "represents the summarised changes, except those from an initial"
- echo "commit (i.e. diffing starts with the first commit’s tree)."
+ echo "represents the summarised changes from the first known parent:"
echo ""
echo $LOGBEGIN
@@ -389,10 +388,12 @@ generate_create_branch_email()
# experimental summarised changes diff
echo ""
echo "Summary of changes:"
- echo $(git rev-parse --not "${other_branches[@]}" | \
- git rev-list --stdin $newrev) | \
- git -c core.quotePath=false diff-tree --stdin $diffopts | \
- sed 1d
+ git rev-parse --not "${other_branches[@]}" | \
+ git rev-list --parents --topo-order --reverse --stdin $newrev | \
+ head -n 1 |&
+ read -p commit parent otherparents
+ git -c core.quotePath=false diff-tree $diffopts \
+ "${parent:-$(:|git hash-object -t tree --stdin)}" "$newrev"
}
#
https://scm.fusionforge.org/anonscm/gitweb/?p=fusionforge/fusionforge.git;a=commitdiff;h=5fd6948620c22e6e2dce2988738b928a8a000748
commit 5fd6948620c22e6e2dce2988738b928a8a000748
Author: mirabilos <[email protected]>
Date: Wed Sep 5 19:13:16 2018 +0200
this did not work (see also git diff-tree -c | --cc)
diff --git a/post-receive-email b/post-receive-email
index 02d9d66..a0f387a 100755
--- a/post-receive-email
+++ b/post-receive-email
@@ -389,9 +389,8 @@ generate_create_branch_email()
# experimental summarised changes diff
echo ""
echo "Summary of changes:"
-set -x # --parents --topo-order also doesn’t work
echo $(git rev-parse --not "${other_branches[@]}" | \
- git rev-list --parents --topo-order --stdin $newrev) | \
+ git rev-list --stdin $newrev) | \
git -c core.quotePath=false diff-tree --stdin $diffopts | \
sed 1d
}
https://scm.fusionforge.org/anonscm/gitweb/?p=fusionforge/fusionforge.git;a=commitdiff;h=6ae5df09e1e72395bc9f2f9946ba8cbf2b88a393
commit 6ae5df09e1e72395bc9f2f9946ba8cbf2b88a393
Author: mirabilos <[email protected]>
Date: Wed Sep 5 19:10:31 2018 +0200
experimental diff showing in branch creation mail, needs work…
diff --git a/post-receive-email b/post-receive-email
index f2a89da..02d9d66 100755
--- a/post-receive-email
+++ b/post-receive-email
@@ -377,9 +377,23 @@ generate_create_branch_email()
return 0
fi
+ echo "Below, we list all revisions that are new to this repository and"
+ echo "have not appeared on any other notification email. The diff below"
+ echo "represents the summarised changes, except those from an initial"
+ echo "commit (i.e. diffing starts with the first commit’s tree)."
+
+ echo ""
echo $LOGBEGIN
print -r -- "$newrevs"
echo $LOGEND
+ # experimental summarised changes diff
+ echo ""
+ echo "Summary of changes:"
+set -x # --parents --topo-order also doesn’t work
+ echo $(git rev-parse --not "${other_branches[@]}" | \
+ git rev-list --parents --topo-order --stdin $newrev) | \
+ git -c core.quotePath=false diff-tree --stdin $diffopts | \
+ sed 1d
}
#
https://scm.fusionforge.org/anonscm/gitweb/?p=fusionforge/fusionforge.git;a=commitdiff;h=9dfa4394f1410c7eac4fa30a03a4e3e108cd5a2c
commit 9dfa4394f1410c7eac4fa30a03a4e3e108cd5a2c
Author: mirabilos <[email protected]>
Date: Wed Sep 5 18:02:06 2018 +0200
sort out logs in eMails when multiple branches are pushed at once
diff --git a/post-receive-email b/post-receive-email
index aee0363..f2a89da 100755
--- a/post-receive-email
+++ b/post-receive-email
@@ -750,7 +750,7 @@ show_new_revisions()
# (see generate_update_branch_email for the explanation of this
# command)
- local revspec other_branches onerev
+ local revspec onerev
# Revision range passed to rev-list differs for new vs. updated
# branches.
@@ -763,9 +763,7 @@ show_new_revisions()
revspec=$oldrev..$newrev
fi
- other_branches=$(git for-each-ref --format='%(refname)' refs/heads/ |
- grep -F -v $refname)
- git rev-parse --not $other_branches |
+ git rev-parse --not "${other_branches[@]}" |
if [ -z "$custom_showrev" ]
then
git rev-list --pretty --stdin $revspec
@@ -856,15 +854,40 @@ if [ -n "$1" -a -n "$2" -a -n "$3" ]; then
# themselves
prep_for_email $2 $3 $1 && PAGER= generate_email
else
- ilines=
- while read oldrev newrev refname
- do
- ilines="$ilines$oldrev $newrev $refname$nl"
+ # get a list of all branches
+ set -A other_branches -- $(git for-each-ref \
+ --format='%(refname)' refs/heads/)
+ set -A ilines
+ while IFS= read -r line; do
+ # store for later
+ ilines+=("$line")
+ # check if refname is a branch name
+ refname=${line##* }
+ [[ $refname = refs/heads/* ]] || continue
+ # filter out from other_branches if matching
+ i=-1 j=${#other_branches[@]}
+ while (( ++i < j )); do
+ [[ ${other_branches[i]} = "$refname" ]] || continue
+ unset other_branches[i]
+ break
+ done
+ set -A other_branches -- "${other_branches[@]}"
+ done
+ # process one by one for eMails
+ for line in "${ilines[@]}"; do
+ oldrev=${line%% *}
+ newrev=${line#* }
+ newrev=${newrev%% *}
+ refname=${line##* }
prep_for_email $oldrev $newrev $refname || continue
generate_email $maxlines | send_mail
+ # append to list of branches for which eMails have been sent
+ [[ $refname = refs/heads/* ]] && other_branches+=("$refname")
done
if [[ -n $kgbconffile && -s $kgbconffile ]]; then
- print -nr -- "$ilines" | kgb-client \
+ for line in "${ilines[@]}"; do
+ print -r -- "$line"
+ done | kgb-client \
--conf "$kgbconffile" --repository git --git-reflog -
fi
set -o noglob
https://scm.fusionforge.org/anonscm/gitweb/?p=fusionforge/fusionforge.git;a=commitdiff;h=66433e4902ecdb1c988f6577bc86e930c474b022
commit 66433e4902ecdb1c988f6577bc86e930c474b022
Author: mirabilos <[email protected]>
Date: Wed Sep 5 17:48:57 2018 +0200
detect whether git rev-list actually outputted anything;
issue a "no new revisions added by this update" message if not
diff --git a/post-receive-email b/post-receive-email
index dd864c9..aee0363 100755
--- a/post-receive-email
+++ b/post-receive-email
@@ -370,8 +370,15 @@ generate_create_branch_email()
echo " at $newrev ($newrev_type)"
echo ""
+ local newrevs=$(show_new_revisions)
+
+ if [[ -z $newrevs ]]; then
+ echo "No new revisions were added by this update."
+ return 0
+ fi
+
echo $LOGBEGIN
- show_new_revisions
+ print -r -- "$newrevs"
echo $LOGEND
}
@@ -523,20 +530,18 @@ generate_update_branch_email()
fi
fi
+ local newrevs=
+ [[ -n $rewind_only ]] || newrevs=$(show_new_revisions)
+
echo ""
- if [ -z "$rewind_only" ]; then
+ if [[ -n $newrevs ]]; then
echo "Those revisions listed above that are new to this
repository have"
echo "not appeared on any other notification email; so we list
those"
echo "revisions in full, below."
echo ""
echo $LOGBEGIN
- show_new_revisions
-
- # XXX: Need a way of detecting whether git rev-list actually
- # outputted anything, so that we can issue a "no new
- # revisions added by this update" message
-
+ print -r -- "$newrevs"
echo $LOGEND
else
echo "No new revisions were added by this update."
@@ -745,6 +750,8 @@ show_new_revisions()
# (see generate_update_branch_email for the explanation of this
# command)
+ local revspec other_branches onerev
+
# Revision range passed to rev-list differs for new vs. updated
# branches.
if [ "$change_type" = create ]
https://scm.fusionforge.org/anonscm/gitweb/?p=fusionforge/fusionforge.git;a=commitdiff;h=b5974e32cf3b4b1f740c1bfd6229f225fb12671d
commit b5974e32cf3b4b1f740c1bfd6229f225fb12671d
Author: mirabilos <[email protected]>
Date: Wed Sep 5 17:26:34 2018 +0200
rework Subject header encoding to be more reliable:
• strongly prefer PHP over Perl, now that sid’s is totally unusable
(although I expect that will be fixed in time)
• output debugging for what failed
• if encoding failed still send the eMail (with fixed-string Subject)
diff --git a/post-receive-email b/post-receive-email
index 3e8a7b3..dd864c9 100755
--- a/post-receive-email
+++ b/post-receive-email
@@ -2,7 +2,7 @@
#
# Copyright © 2013
# Thorsten “mirabilos” Glaser <[email protected]>
-# Copyright © 2011, 2012, 2013, 2014, 2015
+# Copyright © 2011, 2012, 2013, 2014, 2015, 2018
# Thorsten “mirabilos” Glaser <[email protected]>
# Copyright © 2016
# martin f krafft (madduck), Thorsten Glaser (mirabilos)
@@ -284,7 +284,7 @@ generate_email()
generate_email_header()
{
- local routing_headers subj
+ local routing_headers subj senc failc=0
# --- Email (all stdout will be the email)
# Generate header
@@ -295,14 +295,36 @@ generate_email_header()
subj="Subject: ${emailprefix}$shortdesc $refname_type $short_refname
${change_type}d. $describe"
- # Note: the Perl call is known to occasionally insert extra whitespace
- # cf. https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=787513
- subj=$(print -nr -- "$subj" | \
- perl -C7 -0777 -Mutf8 -MEncode -e "print encode('MIME-Q', <>);")
-
- if [[ -z $subj ]]; then
+ # Try to encode. Strongly prefer PHP over Perl and Python, sadly;
+ # evidence provided in Debian bugs #787511, #787512, #787513,
+ # #819155, #879204, #879205, #881955, #907891 though.
+ senc=$(print -nr -- "$subj" | php -r '
+ mb_internal_encoding("UTF-8");
+ echo mb_encode_mimeheader(file_get_contents("php://stdin"),
+ "UTF-8", "Q", "\012");
+ ' 2>/dev/null) || { (( failc |= 1 )); senc=; }
+ [[ $senc = Subject:?("$nl")' '* ]] || { (( failc |= 2 )); senc=; }
+ [[ -n $senc ]] || senc=$(print -nr -- "$subj" | perl \
+ -C7 -0777 -Mutf8 -MEncode -e "
+ print encode('MIME-Q', <>);
+ " 2>/dev/null) || { (( failc |= 4 )); senc=; }
+ [[ $senc = Subject:?("$nl")' '* ]] || { (( failc |= 8 )); senc=; }
+
+ if [[ -z $senc ]]; then
print -u2 "E: Subject empty, RFC2047 MIME encoding failed"
- exit 1
+ if ! whence -p php >/dev/null 2>&1; then
+ : show only the Perl-related error messages below
+ elif (( failc & 1 )); then
+ print -u2 "N: PHP encoding failed, perhaps install
php-mbstring."
+ elif (( failc & 2 )); then
+ print -u2 "N: PHP encoding produced bad output, WTF‽"
+ fi
+ if (( failc & 4 )); then
+ print -u2 "N: Perl encoding failed, WTF‽ Also, install
PHP."
+ elif (( failc & 8 )); then
+ print -u2 "N: Perl encoding produced bad output,
install PHP!"
+ fi
+ senc="Subject: post-receive-email: no Subject, RFC2047 MIME
encoding failed"
fi
cat <<-EOF
@@ -314,7 +336,7 @@ generate_email_header()
X-Git-Reftype: $refname_type
X-Git-Oldrev: $oldrev
X-Git-Newrev: $newrev
- $subj
+ $senc
Auto-Submitted: auto-generated
This is an automated email from the git hooks/post-receive script. It
was
https://scm.fusionforge.org/anonscm/gitweb/?p=fusionforge/fusionforge.git;a=commitdiff;h=73fee0fc450df7c4ce29b90a252247f35f68b4f6
commit 73fee0fc450df7c4ce29b90a252247f35f68b4f6
Author: mirabilos <[email protected]>
Date: Thu Jul 14 17:53:28 2016 +0200
enable UTF-8 filenames in output; from an IRC question by madduck
diff --git a/post-receive-email b/post-receive-email
index 17245c2..3e8a7b3 100755
--- a/post-receive-email
+++ b/post-receive-email
@@ -4,6 +4,8 @@
# Thorsten “mirabilos” Glaser <[email protected]>
# Copyright © 2011, 2012, 2013, 2014, 2015
# Thorsten “mirabilos” Glaser <[email protected]>
+# Copyright © 2016
+# martin f krafft (madduck), Thorsten Glaser (mirabilos)
#
# Copyright (c) 2007 Andy Parkins
#
@@ -527,7 +529,7 @@ generate_update_branch_email()
# non-fast-forward updates.
echo ""
echo "Summary of changes:"
- git diff-tree $diffopts $oldrev..$newrev
+ git -c core.quotePath=false diff-tree $diffopts $oldrev..$newrev
}
#
https://scm.fusionforge.org/anonscm/gitweb/?p=fusionforge/fusionforge.git;a=commitdiff;h=466073989f6fc20b56e2c2d77b5676bbf7b3c36f
commit 466073989f6fc20b56e2c2d77b5676bbf7b3c36f
Author: mirabilos <[email protected]>
Date: Thu Oct 29 13:06:43 2015 +0100
fix typo
diff --git a/post-receive-email b/post-receive-email
index 0a44c21..17245c2 100755
--- a/post-receive-email
+++ b/post-receive-email
@@ -96,7 +96,7 @@
# hooks.diffopts
# Alternate options for the git diff-tree invocation that shows changes.
# Default is "-p --stat --summary --find-copies-harder". Remove -p from
-# those options to skil including a unified diff of changes in addition
+# those options to skip including a unified diff of changes in addition
# to the summary output. See hooks.showrev for more discussion on this.
# hooks.kgbconffile
# Full path to a configuration file for kgb-client, or unset/empty.
https://scm.fusionforge.org/anonscm/gitweb/?p=fusionforge/fusionforge.git;a=commitdiff;h=31377f63785917dced78bcf973997d756e321f66
commit 31377f63785917dced78bcf973997d756e321f66
Author: Thorsten Glaser <[email protected]>
Date: Tue Jun 2 14:30:19 2015 +0200
SECURITY: avoid globbing dot arguments
diff --git a/post-receive-email b/post-receive-email
index 95d0080..0a44c21 100755
--- a/post-receive-email
+++ b/post-receive-email
@@ -810,11 +810,11 @@ emailprefix=$(git config hooks.emailprefix)
custom_showrev=$(git config hooks.showrev)
maxlines=$(git config hooks.emailmaxlines)
diffopts=$(git config hooks.diffopts)
-: ${diffopts:="-p --stat --summary --find-copies-harder"}
+: "${diffopts:="-p --stat --summary --find-copies-harder"}"
kgbconffile=$(git config hooks.kgbconffile)
replyto=$(git config hooks.replyto)
shortdesc=$(git config hooks.shortdesc)
-: ${shortdesc:=$projectdesc}
+: "${shortdesc:=$projectdesc}"
# --- Main loop
# Allow dual mode: run from the command line just like the update hook, or
https://scm.fusionforge.org/anonscm/gitweb/?p=fusionforge/fusionforge.git;a=commitdiff;h=e508c939f80dfbd0fd3473e94b5dd66a9c8f1fcd
commit e508c939f80dfbd0fd3473e94b5dd66a9c8f1fcd
Author: Thorsten Glaser <[email protected]>
Date: Tue Jun 2 14:17:54 2015 +0200
add note about debbugs #787513; verify all changes from upstream are merged
diff --git a/post-receive-email b/post-receive-email
index 356b0e7..95d0080 100755
--- a/post-receive-email
+++ b/post-receive-email
@@ -292,6 +292,9 @@ generate_email_header()
[[ -n $replyto ]] && routing_headers="$routing_headers${nl}Reply-To:
$replyto"
subj="Subject: ${emailprefix}$shortdesc $refname_type $short_refname
${change_type}d. $describe"
+
+ # Note: the Perl call is known to occasionally insert extra whitespace
+ # cf. https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=787513
subj=$(print -nr -- "$subj" | \
perl -C7 -0777 -Mutf8 -MEncode -e "print encode('MIME-Q', <>);")
https://scm.fusionforge.org/anonscm/gitweb/?p=fusionforge/fusionforge.git;a=commitdiff;h=4bb2c05c4232ea35dc59e60f5e7bf23ea206af50
commit 4bb2c05c4232ea35dc59e60f5e7bf23ea206af50
Author: Thorsten Glaser <[email protected]>
Date: Tue Jun 2 14:17:33 2015 +0200
pull Subject encoding out of the here document and add a sanity check
diff --git a/post-receive-email b/post-receive-email
index 133bc66..356b0e7 100755
--- a/post-receive-email
+++ b/post-receive-email
@@ -292,6 +292,13 @@ generate_email_header()
[[ -n $replyto ]] && routing_headers="$routing_headers${nl}Reply-To:
$replyto"
subj="Subject: ${emailprefix}$shortdesc $refname_type $short_refname
${change_type}d. $describe"
+ subj=$(print -nr -- "$subj" | \
+ perl -C7 -0777 -Mutf8 -MEncode -e "print encode('MIME-Q', <>);")
+
+ if [[ -z $subj ]]; then
+ print -u2 "E: Subject empty, RFC2047 MIME encoding failed"
+ exit 1
+ fi
cat <<-EOF
MIME-Version: 1.0
@@ -302,8 +309,7 @@ generate_email_header()
X-Git-Reftype: $refname_type
X-Git-Oldrev: $oldrev
X-Git-Newrev: $newrev
- $(print -nr -- "$subj" | \
- perl -C7 -0777 -Mutf8 -MEncode -e "print encode('MIME-Q', <>);")
+ $subj
Auto-Submitted: auto-generated
This is an automated email from the git hooks/post-receive script. It
was
https://scm.fusionforge.org/anonscm/gitweb/?p=fusionforge/fusionforge.git;a=commitdiff;h=73f6d7db4eddf19317e52bea4ae35b90eb23d4e4
commit 73f6d7db4eddf19317e52bea4ae35b90eb23d4e4
Author: Thorsten Glaser <[email protected]>
Date: Tue Jun 2 13:39:10 2015 +0200
pass Subject to RFC2047 Perl encoder by stdin; fixes bug with single quotes
Bug reported in FusionForge by Sylvain Beucler (beuc-inria)
Corrected bugfix by me ipso; also sets Perl stdio to UTF-8
diff --git a/post-receive-email b/post-receive-email
index 0a3cc7d..133bc66 100755
--- a/post-receive-email
+++ b/post-receive-email
@@ -302,7 +302,8 @@ generate_email_header()
X-Git-Reftype: $refname_type
X-Git-Oldrev: $oldrev
X-Git-Newrev: $newrev
- $(perl -Mutf8 -MEncode -e "print encode('MIME-Q', '$subj');")
+ $(print -nr -- "$subj" | \
+ perl -C7 -0777 -Mutf8 -MEncode -e "print encode('MIME-Q', <>);")
Auto-Submitted: auto-generated
This is an automated email from the git hooks/post-receive script. It
was
https://scm.fusionforge.org/anonscm/gitweb/?p=fusionforge/fusionforge.git;a=commitdiff;h=d82963884953e3ce8d759eea8f228fd8d141032d
commit d82963884953e3ce8d759eea8f228fd8d141032d
Author: Thorsten Glaser <[email protected]>
Date: Tue Jun 2 13:38:10 2015 +0200
pull mail subject generation out of here document
diff --git a/post-receive-email b/post-receive-email
index 8385a47..0a3cc7d 100755
--- a/post-receive-email
+++ b/post-receive-email
@@ -282,7 +282,7 @@ generate_email()
generate_email_header()
{
- local routing_headers
+ local routing_headers subj
# --- Email (all stdout will be the email)
# Generate header
@@ -291,6 +291,8 @@ generate_email_header()
[[ -n $envelopesender ]] && routing_headers="From:
$envelopesender${nl}$routing_headers"
[[ -n $replyto ]] && routing_headers="$routing_headers${nl}Reply-To:
$replyto"
+ subj="Subject: ${emailprefix}$shortdesc $refname_type $short_refname
${change_type}d. $describe"
+
cat <<-EOF
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
@@ -300,7 +302,7 @@ generate_email_header()
X-Git-Reftype: $refname_type
X-Git-Oldrev: $oldrev
X-Git-Newrev: $newrev
- $(perl -Mutf8 -MEncode -e "print encode('MIME-Q', 'Subject:
${emailprefix}$shortdesc $refname_type $short_refname ${change_type}d.
$describe');")
+ $(perl -Mutf8 -MEncode -e "print encode('MIME-Q', '$subj');")
Auto-Submitted: auto-generated
This is an automated email from the git hooks/post-receive script. It
was
https://scm.fusionforge.org/anonscm/gitweb/?p=fusionforge/fusionforge.git;a=commitdiff;h=4a3ca5f0768682f16550a92086fa1292b3c3e617
commit 4a3ca5f0768682f16550a92086fa1292b3c3e617
Author: Thorsten Glaser <[email protected]>
Date: Tue Jun 2 13:36:38 2015 +0200
use “local” for newly introduced function-local variables
diff --git a/post-receive-email b/post-receive-email
index 9494217..8385a47 100755
--- a/post-receive-email
+++ b/post-receive-email
@@ -282,6 +282,8 @@ generate_email()
generate_email_header()
{
+ local routing_headers
+
# --- Email (all stdout will be the email)
# Generate header
https://scm.fusionforge.org/anonscm/gitweb/?p=fusionforge/fusionforge.git;a=commitdiff;h=e457547e15c5a7815f6bf5ea86bdd26934376018
commit e457547e15c5a7815f6bf5ea86bdd26934376018
Author: Thorsten Glaser <[email protected]>
Date: Wed Apr 1 17:58:50 2015 +0200
also announce the URI used
diff --git a/post-receive-email b/post-receive-email
index 79a5ebc..9494217 100755
--- a/post-receive-email
+++ b/post-receive-email
@@ -824,6 +824,7 @@ else
fi
set -o noglob
for uri in $(git config hooks.curltrigger); do
+ print -r -- "‣‣‣ $uri"
curl "$uri"
done
fi
https://scm.fusionforge.org/anonscm/gitweb/?p=fusionforge/fusionforge.git;a=commitdiff;h=ea850cdc31a338298187e018d18389cdf5a1a807
commit ea850cdc31a338298187e018d18389cdf5a1a807
Author: Thorsten Glaser <[email protected]>
Date: Wed Apr 1 17:51:11 2015 +0200
cURL trigger
diff --git a/post-receive-email b/post-receive-email
index e083bbb..79a5ebc 100755
--- a/post-receive-email
+++ b/post-receive-email
@@ -2,7 +2,7 @@
#
# Copyright © 2013
# Thorsten “mirabilos” Glaser <[email protected]>
-# Copyright © 2011, 2012, 2013, 2014
+# Copyright © 2011, 2012, 2013, 2014, 2015
# Thorsten “mirabilos” Glaser <[email protected]>
#
# Copyright (c) 2007 Andy Parkins
@@ -101,6 +101,9 @@
# hooks.kgbconffile
# Full path to a configuration file for kgb-client, or unset/empty.
# If set, kgb-client will be invoked.
+# hooks.curltrigger
+# List (expanded by shell “for”, so be careful) of URIs to trigger on
+# each push to be accessed with cURL.
#
# Notes
# -----
@@ -819,4 +822,8 @@ else
print -nr -- "$ilines" | kgb-client \
--conf "$kgbconffile" --repository git --git-reflog -
fi
+ set -o noglob
+ for uri in $(git config hooks.curltrigger); do
+ curl "$uri"
+ done
fi
-----------------------------------------------------------------------
Summary of changes:
src/common/include/minijson.php | 889 +++++++++++----------
.../hooks/postreceiveemail/post-receive-email | 187 +++--
tests/unit/common/minijsonTest.php | 48 +-
3 files changed, 615 insertions(+), 509 deletions(-)
hooks/post-receive
--
FusionForge
_______________________________________________
Fusionforge-commits mailing list
[email protected]
http://lists.fusionforge.org/cgi-bin/mailman/listinfo/fusionforge-commits