From d5774f76b1bc78689f23d357b729aff091f77a35 Mon Sep 17 00:00:00 2001 From: stefan Date: Fri, 5 Jun 2020 19:46:25 +0200 Subject: [PATCH] Release nkorg/extstats 4.4.3 --- dev/Spyc.php | 1161 ++++++++++++++++++++++++++++++++++++++++++++++++ dev/dev.7z | Bin 16144 -> 0 bytes dev/moddb.sh | 80 ++++ dev/modules.db | Bin 0 -> 36864 bytes 4 files changed, 1241 insertions(+) create mode 100644 dev/Spyc.php delete mode 100644 dev/dev.7z create mode 100644 dev/moddb.sh create mode 100644 dev/modules.db diff --git a/dev/Spyc.php b/dev/Spyc.php new file mode 100644 index 0000000..49e0cbb --- /dev/null +++ b/dev/Spyc.php @@ -0,0 +1,1161 @@ + + * @author Chris Wanstrath + * @link https://github.com/mustangostang/spyc/ + * @copyright Copyright 2005-2006 Chris Wanstrath, 2006-2011 Vlad Andersen + * @license http://www.opensource.org/licenses/mit-license.php MIT License + * @package Spyc + */ + +if (!function_exists('spyc_load')) { + /** + * Parses YAML to array. + * @param string $string YAML string. + * @return array + */ + function spyc_load ($string) { + return Spyc::YAMLLoadString($string); + } +} + +if (!function_exists('spyc_load_file')) { + /** + * Parses YAML to array. + * @param string $file Path to YAML file. + * @return array + */ + function spyc_load_file ($file) { + return Spyc::YAMLLoad($file); + } +} + +if (!function_exists('spyc_dump')) { + /** + * Dumps array to YAML. + * @param array $data Array. + * @return string + */ + function spyc_dump ($data) { + return Spyc::YAMLDump($data, false, false, true); + } +} + +if (!class_exists('Spyc')) { + +/** + * The Simple PHP YAML Class. + * + * This class can be used to read a YAML file and convert its contents + * into a PHP array. It currently supports a very limited subsection of + * the YAML spec. + * + * Usage: + * + * $Spyc = new Spyc; + * $array = $Spyc->load($file); + * + * or: + * + * $array = Spyc::YAMLLoad($file); + * + * or: + * + * $array = spyc_load_file($file); + * + * @package Spyc + */ +class Spyc { + + // SETTINGS + + const REMPTY = "\0\0\0\0\0"; + + /** + * Setting this to true will force YAMLDump to enclose any string value in + * quotes. False by default. + * + * @var bool + */ + public $setting_dump_force_quotes = false; + + /** + * Setting this to true will forse YAMLLoad to use syck_load function when + * possible. False by default. + * @var bool + */ + public $setting_use_syck_is_possible = false; + + + + /**#@+ + * @access private + * @var mixed + */ + private $_dumpIndent; + private $_dumpWordWrap; + private $_containsGroupAnchor = false; + private $_containsGroupAlias = false; + private $path; + private $result; + private $LiteralPlaceHolder = '___YAML_Literal_Block___'; + private $SavedGroups = array(); + private $indent; + /** + * Path modifier that should be applied after adding current element. + * @var array + */ + private $delayedPath = array(); + + /**#@+ + * @access public + * @var mixed + */ + public $_nodeId; + +/** + * Load a valid YAML string to Spyc. + * @param string $input + * @return array + */ + public function load ($input) { + return $this->_loadString($input); + } + + /** + * Load a valid YAML file to Spyc. + * @param string $file + * @return array + */ + public function loadFile ($file) { + return $this->_load($file); + } + + /** + * Load YAML into a PHP array statically + * + * The load method, when supplied with a YAML stream (string or file), + * will do its best to convert YAML in a file into a PHP array. Pretty + * simple. + * Usage: + * + * $array = Spyc::YAMLLoad('lucky.yaml'); + * print_r($array); + * + * @access public + * @return array + * @param string $input Path of YAML file or string containing YAML + */ + public static function YAMLLoad($input) { + $Spyc = new Spyc; + return $Spyc->_load($input); + } + + /** + * Load a string of YAML into a PHP array statically + * + * The load method, when supplied with a YAML string, will do its best + * to convert YAML in a string into a PHP array. Pretty simple. + * + * Note: use this function if you don't want files from the file system + * loaded and processed as YAML. This is of interest to people concerned + * about security whose input is from a string. + * + * Usage: + * + * $array = Spyc::YAMLLoadString("---\n0: hello world\n"); + * print_r($array); + * + * @access public + * @return array + * @param string $input String containing YAML + */ + public static function YAMLLoadString($input) { + $Spyc = new Spyc; + return $Spyc->_loadString($input); + } + + /** + * Dump YAML from PHP array statically + * + * The dump method, when supplied with an array, will do its best + * to convert the array into friendly YAML. Pretty simple. Feel free to + * save the returned string as nothing.yaml and pass it around. + * + * Oh, and you can decide how big the indent is and what the wordwrap + * for folding is. Pretty cool -- just pass in 'false' for either if + * you want to use the default. + * + * Indent's default is 2 spaces, wordwrap's default is 40 characters. And + * you can turn off wordwrap by passing in 0. + * + * @access public + * @return string + * @param array|\stdClass $array PHP array + * @param int $indent Pass in false to use the default, which is 2 + * @param int $wordwrap Pass in 0 for no wordwrap, false for default (40) + * @param bool $no_opening_dashes Do not start YAML file with "---\n" + */ + public static function YAMLDump($array, $indent = false, $wordwrap = false, $no_opening_dashes = false) { + $spyc = new Spyc; + return $spyc->dump($array, $indent, $wordwrap, $no_opening_dashes); + } + + + /** + * Dump PHP array to YAML + * + * The dump method, when supplied with an array, will do its best + * to convert the array into friendly YAML. Pretty simple. Feel free to + * save the returned string as tasteful.yaml and pass it around. + * + * Oh, and you can decide how big the indent is and what the wordwrap + * for folding is. Pretty cool -- just pass in 'false' for either if + * you want to use the default. + * + * Indent's default is 2 spaces, wordwrap's default is 40 characters. And + * you can turn off wordwrap by passing in 0. + * + * @access public + * @return string + * @param array $array PHP array + * @param int $indent Pass in false to use the default, which is 2 + * @param int $wordwrap Pass in 0 for no wordwrap, false for default (40) + */ + public function dump($array,$indent = false,$wordwrap = false, $no_opening_dashes = false) { + // Dumps to some very clean YAML. We'll have to add some more features + // and options soon. And better support for folding. + + // New features and options. + if ($indent === false or !is_numeric($indent)) { + $this->_dumpIndent = 2; + } else { + $this->_dumpIndent = $indent; + } + + if ($wordwrap === false or !is_numeric($wordwrap)) { + $this->_dumpWordWrap = 40; + } else { + $this->_dumpWordWrap = $wordwrap; + } + + // New YAML document + $string = ""; + if (!$no_opening_dashes) $string = "---\n"; + + // Start at the base of the array and move through it. + if ($array) { + $array = (array)$array; + $previous_key = -1; + foreach ($array as $key => $value) { + if (!isset($first_key)) $first_key = $key; + $string .= $this->_yamlize($key,$value,0,$previous_key, $first_key, $array); + $previous_key = $key; + } + } + return $string; + } + + /** + * Attempts to convert a key / value array item to YAML + * @access private + * @return string + * @param $key The name of the key + * @param $value The value of the item + * @param $indent The indent of the current node + */ + private function _yamlize($key,$value,$indent, $previous_key = -1, $first_key = 0, $source_array = null) { + if(is_object($value)) $value = (array)$value; + if (is_array($value)) { + if (empty ($value)) + return $this->_dumpNode($key, array(), $indent, $previous_key, $first_key, $source_array); + // It has children. What to do? + // Make it the right kind of item + $string = $this->_dumpNode($key, self::REMPTY, $indent, $previous_key, $first_key, $source_array); + // Add the indent + $indent += $this->_dumpIndent; + // Yamlize the array + $string .= $this->_yamlizeArray($value,$indent); + } elseif (!is_array($value)) { + // It doesn't have children. Yip. + $string = $this->_dumpNode($key, $value, $indent, $previous_key, $first_key, $source_array); + } + return $string; + } + + /** + * Attempts to convert an array to YAML + * @access private + * @return string + * @param $array The array you want to convert + * @param $indent The indent of the current level + */ + private function _yamlizeArray($array,$indent) { + if (is_array($array)) { + $string = ''; + $previous_key = -1; + foreach ($array as $key => $value) { + if (!isset($first_key)) $first_key = $key; + $string .= $this->_yamlize($key, $value, $indent, $previous_key, $first_key, $array); + $previous_key = $key; + } + return $string; + } else { + return false; + } + } + + /** + * Returns YAML from a key and a value + * @access private + * @return string + * @param $key The name of the key + * @param $value The value of the item + * @param $indent The indent of the current node + */ + private function _dumpNode($key, $value, $indent, $previous_key = -1, $first_key = 0, $source_array = null) { + // do some folding here, for blocks + if (is_string ($value) && ((strpos($value,"\n") !== false || strpos($value,": ") !== false || strpos($value,"- ") !== false || + strpos($value,"*") !== false || strpos($value,"#") !== false || strpos($value,"<") !== false || strpos($value,">") !== false || strpos ($value, '%') !== false || strpos ($value, ' ') !== false || + strpos($value,"[") !== false || strpos($value,"]") !== false || strpos($value,"{") !== false || strpos($value,"}") !== false) || strpos($value,"&") !== false || strpos($value, "'") !== false || strpos($value, "!") === 0 || + substr ($value, -1, 1) == ':') + ) { + $value = $this->_doLiteralBlock($value,$indent); + } else { + $value = $this->_doFolding($value,$indent); + } + + if ($value === array()) $value = '[ ]'; + if ($value === "") $value = '""'; + if (self::isTranslationWord($value)) { + $value = $this->_doLiteralBlock($value, $indent); + } + if (trim ($value) != $value) + $value = $this->_doLiteralBlock($value,$indent); + + if (is_bool($value)) { + $value = $value ? "true" : "false"; + } + + if ($value === null) $value = 'null'; + if ($value === "'" . self::REMPTY . "'") $value = null; + + $spaces = str_repeat(' ',$indent); + + //if (is_int($key) && $key - 1 == $previous_key && $first_key===0) { + if (is_array ($source_array) && array_keys($source_array) === range(0, count($source_array) - 1)) { + // It's a sequence + $string = $spaces.'- '.$value."\n"; + } else { + // if ($first_key===0) throw new Exception('Keys are all screwy. The first one was zero, now it\'s "'. $key .'"'); + // It's mapped + if (strpos($key, ":") !== false || strpos($key, "#") !== false) { $key = '"' . $key . '"'; } + $string = rtrim ($spaces.$key.': '.$value)."\n"; + } + return $string; + } + + /** + * Creates a literal block for dumping + * @access private + * @return string + * @param $value + * @param $indent int The value of the indent + */ + private function _doLiteralBlock($value,$indent) { + if ($value === "\n") return '\n'; + if (strpos($value, "\n") === false && strpos($value, "'") === false) { + return sprintf ("'%s'", $value); + } + if (strpos($value, "\n") === false && strpos($value, '"') === false) { + return sprintf ('"%s"', $value); + } + $exploded = explode("\n",$value); + $newValue = '|'; + if (isset($exploded[0]) && ($exploded[0] == "|" || $exploded[0] == "|-" || $exploded[0] == ">")) { + $newValue = $exploded[0]; + unset($exploded[0]); + } + $indent += $this->_dumpIndent; + $spaces = str_repeat(' ',$indent); + foreach ($exploded as $line) { + $line = trim($line); + if (strpos($line, '"') === 0 && strrpos($line, '"') == (strlen($line)-1) || strpos($line, "'") === 0 && strrpos($line, "'") == (strlen($line)-1)) { + $line = substr($line, 1, -1); + } + $newValue .= "\n" . $spaces . ($line); + } + return $newValue; + } + + /** + * Folds a string of text, if necessary + * @access private + * @return string + * @param $value The string you wish to fold + */ + private function _doFolding($value,$indent) { + // Don't do anything if wordwrap is set to 0 + + if ($this->_dumpWordWrap !== 0 && is_string ($value) && strlen($value) > $this->_dumpWordWrap) { + $indent += $this->_dumpIndent; + $indent = str_repeat(' ',$indent); + $wrapped = wordwrap($value,$this->_dumpWordWrap,"\n$indent"); + $value = ">\n".$indent.$wrapped; + } else { + if ($this->setting_dump_force_quotes && is_string ($value) && $value !== self::REMPTY) + $value = '"' . $value . '"'; + if (is_numeric($value) && is_string($value)) + $value = '"' . $value . '"'; + } + + + return $value; + } + + private function isTrueWord($value) { + $words = self::getTranslations(array('true', 'on', 'yes', 'y')); + return in_array($value, $words, true); + } + + private function isFalseWord($value) { + $words = self::getTranslations(array('false', 'off', 'no', 'n')); + return in_array($value, $words, true); + } + + private function isNullWord($value) { + $words = self::getTranslations(array('null', '~')); + return in_array($value, $words, true); + } + + private function isTranslationWord($value) { + return ( + self::isTrueWord($value) || + self::isFalseWord($value) || + self::isNullWord($value) + ); + } + + /** + * Coerce a string into a native type + * Reference: http://yaml.org/type/bool.html + * TODO: Use only words from the YAML spec. + * @access private + * @param $value The value to coerce + */ + private function coerceValue(&$value) { + if (self::isTrueWord($value)) { + $value = true; + } else if (self::isFalseWord($value)) { + $value = false; + } else if (self::isNullWord($value)) { + $value = null; + } + } + + /** + * Given a set of words, perform the appropriate translations on them to + * match the YAML 1.1 specification for type coercing. + * @param $words The words to translate + * @access private + */ + private static function getTranslations(array $words) { + $result = array(); + foreach ($words as $i) { + $result = array_merge($result, array(ucfirst($i), strtoupper($i), strtolower($i))); + } + return $result; + } + +// LOADING FUNCTIONS + + private function _load($input) { + $Source = $this->loadFromSource($input); + return $this->loadWithSource($Source); + } + + private function _loadString($input) { + $Source = $this->loadFromString($input); + return $this->loadWithSource($Source); + } + + private function loadWithSource($Source) { + if (empty ($Source)) return array(); + if ($this->setting_use_syck_is_possible && function_exists ('syck_load')) { + $array = syck_load (implode ("\n", $Source)); + return is_array($array) ? $array : array(); + } + + $this->path = array(); + $this->result = array(); + + $cnt = count($Source); + for ($i = 0; $i < $cnt; $i++) { + $line = $Source[$i]; + + $this->indent = strlen($line) - strlen(ltrim($line)); + $tempPath = $this->getParentPathByIndent($this->indent); + $line = self::stripIndent($line, $this->indent); + if (self::isComment($line)) continue; + if (self::isEmpty($line)) continue; + $this->path = $tempPath; + + $literalBlockStyle = self::startsLiteralBlock($line); + if ($literalBlockStyle) { + $line = rtrim ($line, $literalBlockStyle . " \n"); + $literalBlock = ''; + $line .= ' '.$this->LiteralPlaceHolder; + $literal_block_indent = strlen($Source[$i+1]) - strlen(ltrim($Source[$i+1])); + while (++$i < $cnt && $this->literalBlockContinues($Source[$i], $this->indent)) { + $literalBlock = $this->addLiteralLine($literalBlock, $Source[$i], $literalBlockStyle, $literal_block_indent); + } + $i--; + } + + // Strip out comments + if (strpos ($line, '#')) { + $line = preg_replace('/\s*#([^"\']+)$/','',$line); + } + + while (++$i < $cnt && self::greedilyNeedNextLine($line)) { + $line = rtrim ($line, " \n\t\r") . ' ' . ltrim ($Source[$i], " \t"); + } + $i--; + + $lineArray = $this->_parseLine($line); + + if ($literalBlockStyle) + $lineArray = $this->revertLiteralPlaceHolder ($lineArray, $literalBlock); + + $this->addArray($lineArray, $this->indent); + + foreach ($this->delayedPath as $indent => $delayedPath) + $this->path[$indent] = $delayedPath; + + $this->delayedPath = array(); + + } + return $this->result; + } + + private function loadFromSource ($input) { + if (!empty($input) && strpos($input, "\n") === false && file_exists($input)) + $input = file_get_contents($input); + + return $this->loadFromString($input); + } + + private function loadFromString ($input) { + $lines = explode("\n",$input); + foreach ($lines as $k => $_) { + $lines[$k] = rtrim ($_, "\r"); + } + return $lines; + } + + /** + * Parses YAML code and returns an array for a node + * @access private + * @return array + * @param string $line A line from the YAML file + */ + private function _parseLine($line) { + if (!$line) return array(); + $line = trim($line); + if (!$line) return array(); + + $array = array(); + + $group = $this->nodeContainsGroup($line); + if ($group) { + $this->addGroup($line, $group); + $line = $this->stripGroup ($line, $group); + } + + if ($this->startsMappedSequence($line)) + return $this->returnMappedSequence($line); + + if ($this->startsMappedValue($line)) + return $this->returnMappedValue($line); + + if ($this->isArrayElement($line)) + return $this->returnArrayElement($line); + + if ($this->isPlainArray($line)) + return $this->returnPlainArray($line); + + + return $this->returnKeyValuePair($line); + + } + + /** + * Finds the type of the passed value, returns the value as the new type. + * @access private + * @param string $value + * @return mixed + */ + private function _toType($value) { + if ($value === '') return ""; + $first_character = $value[0]; + $last_character = substr($value, -1, 1); + + $is_quoted = false; + do { + if (!$value) break; + if ($first_character != '"' && $first_character != "'") break; + if ($last_character != '"' && $last_character != "'") break; + $is_quoted = true; + } while (0); + + if ($is_quoted) { + $value = str_replace('\n', "\n", $value); + if ($first_character == "'") + return strtr(substr ($value, 1, -1), array ('\'\'' => '\'', '\\\''=> '\'')); + return strtr(substr ($value, 1, -1), array ('\\"' => '"', '\\\''=> '\'')); + } + + if (strpos($value, ' #') !== false && !$is_quoted) + $value = preg_replace('/\s+#(.+)$/','',$value); + + if ($first_character == '[' && $last_character == ']') { + // Take out strings sequences and mappings + $innerValue = trim(substr ($value, 1, -1)); + if ($innerValue === '') return array(); + $explode = $this->_inlineEscape($innerValue); + // Propagate value array + $value = array(); + foreach ($explode as $v) { + $value[] = $this->_toType($v); + } + return $value; + } + + if (strpos($value,': ')!==false && $first_character != '{') { + $array = explode(': ',$value); + $key = trim($array[0]); + array_shift($array); + $value = trim(implode(': ',$array)); + $value = $this->_toType($value); + return array($key => $value); + } + + if ($first_character == '{' && $last_character == '}') { + $innerValue = trim(substr ($value, 1, -1)); + if ($innerValue === '') return array(); + // Inline Mapping + // Take out strings sequences and mappings + $explode = $this->_inlineEscape($innerValue); + // Propagate value array + $array = array(); + foreach ($explode as $v) { + $SubArr = $this->_toType($v); + if (empty($SubArr)) continue; + if (is_array ($SubArr)) { + $array[key($SubArr)] = $SubArr[key($SubArr)]; continue; + } + $array[] = $SubArr; + } + return $array; + } + + if ($value == 'null' || $value == 'NULL' || $value == 'Null' || $value == '' || $value == '~') { + return null; + } + + if ( is_numeric($value) && preg_match ('/^(-|)[1-9]+[0-9]*$/', $value) ){ + $intvalue = (int)$value; + if ($intvalue != PHP_INT_MAX && $intvalue != ~PHP_INT_MAX) + $value = $intvalue; + return $value; + } + + if ( is_string($value) && preg_match('/^0[xX][0-9a-fA-F]+$/', $value)) { + // Hexadecimal value. + return hexdec($value); + } + + $this->coerceValue($value); + + if (is_numeric($value)) { + if ($value === '0') return 0; + if (rtrim ($value, 0) === $value) + $value = (float)$value; + return $value; + } + + return $value; + } + + /** + * Used in inlines to check for more inlines or quoted strings + * @access private + * @return array + */ + private function _inlineEscape($inline) { + // There's gotta be a cleaner way to do this... + // While pure sequences seem to be nesting just fine, + // pure mappings and mappings with sequences inside can't go very + // deep. This needs to be fixed. + + $seqs = array(); + $maps = array(); + $saved_strings = array(); + $saved_empties = array(); + + // Check for empty strings + $regex = '/("")|(\'\')/'; + if (preg_match_all($regex,$inline,$strings)) { + $saved_empties = $strings[0]; + $inline = preg_replace($regex,'YAMLEmpty',$inline); + } + unset($regex); + + // Check for strings + $regex = '/(?:(")|(?:\'))((?(1)[^"]+|[^\']+))(?(1)"|\')/'; + if (preg_match_all($regex,$inline,$strings)) { + $saved_strings = $strings[0]; + $inline = preg_replace($regex,'YAMLString',$inline); + } + unset($regex); + + // echo $inline; + + $i = 0; + do { + + // Check for sequences + while (preg_match('/\[([^{}\[\]]+)\]/U',$inline,$matchseqs)) { + $seqs[] = $matchseqs[0]; + $inline = preg_replace('/\[([^{}\[\]]+)\]/U', ('YAMLSeq' . (count($seqs) - 1) . 's'), $inline, 1); + } + + // Check for mappings + while (preg_match('/{([^\[\]{}]+)}/U',$inline,$matchmaps)) { + $maps[] = $matchmaps[0]; + $inline = preg_replace('/{([^\[\]{}]+)}/U', ('YAMLMap' . (count($maps) - 1) . 's'), $inline, 1); + } + + if ($i++ >= 10) break; + + } while (strpos ($inline, '[') !== false || strpos ($inline, '{') !== false); + + $explode = explode(',',$inline); + $explode = array_map('trim', $explode); + $stringi = 0; $i = 0; + + while (1) { + + // Re-add the sequences + if (!empty($seqs)) { + foreach ($explode as $key => $value) { + if (strpos($value,'YAMLSeq') !== false) { + foreach ($seqs as $seqk => $seq) { + $explode[$key] = str_replace(('YAMLSeq'.$seqk.'s'),$seq,$value); + $value = $explode[$key]; + } + } + } + } + + // Re-add the mappings + if (!empty($maps)) { + foreach ($explode as $key => $value) { + if (strpos($value,'YAMLMap') !== false) { + foreach ($maps as $mapk => $map) { + $explode[$key] = str_replace(('YAMLMap'.$mapk.'s'), $map, $value); + $value = $explode[$key]; + } + } + } + } + + + // Re-add the strings + if (!empty($saved_strings)) { + foreach ($explode as $key => $value) { + while (strpos($value,'YAMLString') !== false) { + $explode[$key] = preg_replace('/YAMLString/',$saved_strings[$stringi],$value, 1); + unset($saved_strings[$stringi]); + ++$stringi; + $value = $explode[$key]; + } + } + } + + + // Re-add the empties + if (!empty($saved_empties)) { + foreach ($explode as $key => $value) { + while (strpos($value,'YAMLEmpty') !== false) { + $explode[$key] = preg_replace('/YAMLEmpty/', '', $value, 1); + $value = $explode[$key]; + } + } + } + + $finished = true; + foreach ($explode as $key => $value) { + if (strpos($value,'YAMLSeq') !== false) { + $finished = false; break; + } + if (strpos($value,'YAMLMap') !== false) { + $finished = false; break; + } + if (strpos($value,'YAMLString') !== false) { + $finished = false; break; + } + if (strpos($value,'YAMLEmpty') !== false) { + $finished = false; break; + } + } + if ($finished) break; + + $i++; + if ($i > 10) + break; // Prevent infinite loops. + } + + + return $explode; + } + + private function literalBlockContinues ($line, $lineIndent) { + if (!trim($line)) return true; + if (strlen($line) - strlen(ltrim($line)) > $lineIndent) return true; + return false; + } + + private function referenceContentsByAlias ($alias) { + do { + if (!isset($this->SavedGroups[$alias])) { echo "Bad group name: $alias."; break; } + $groupPath = $this->SavedGroups[$alias]; + $value = $this->result; + foreach ($groupPath as $k) { + $value = $value[$k]; + } + } while (false); + return $value; + } + + private function addArrayInline ($array, $indent) { + $CommonGroupPath = $this->path; + if (empty ($array)) return false; + + foreach ($array as $k => $_) { + $this->addArray(array($k => $_), $indent); + $this->path = $CommonGroupPath; + } + return true; + } + + private function addArray ($incoming_data, $incoming_indent) { + + // print_r ($incoming_data); + + if (count ($incoming_data) > 1) + return $this->addArrayInline ($incoming_data, $incoming_indent); + + $key = key ($incoming_data); + $value = isset($incoming_data[$key]) ? $incoming_data[$key] : null; + if ($key === '__!YAMLZero') $key = '0'; + + if ($incoming_indent == 0 && !$this->_containsGroupAlias && !$this->_containsGroupAnchor) { // Shortcut for root-level values. + if ($key || $key === '' || $key === '0') { + $this->result[$key] = $value; + } else { + $this->result[] = $value; end ($this->result); $key = key ($this->result); + } + $this->path[$incoming_indent] = $key; + return; + } + + + + $history = array(); + // Unfolding inner array tree. + $history[] = $_arr = $this->result; + foreach ($this->path as $k) { + $history[] = $_arr = $_arr[$k]; + } + + if ($this->_containsGroupAlias) { + $value = $this->referenceContentsByAlias($this->_containsGroupAlias); + $this->_containsGroupAlias = false; + } + + + // Adding string or numeric key to the innermost level or $this->arr. + if (is_string($key) && $key == '<<') { + if (!is_array ($_arr)) { $_arr = array (); } + + $_arr = array_merge ($_arr, $value); + } else if ($key || $key === '' || $key === '0') { + if (!is_array ($_arr)) + $_arr = array ($key=>$value); + else + $_arr[$key] = $value; + } else { + if (!is_array ($_arr)) { $_arr = array ($value); $key = 0; } + else { $_arr[] = $value; end ($_arr); $key = key ($_arr); } + } + + $reverse_path = array_reverse($this->path); + $reverse_history = array_reverse ($history); + $reverse_history[0] = $_arr; + $cnt = count($reverse_history) - 1; + for ($i = 0; $i < $cnt; $i++) { + $reverse_history[$i+1][$reverse_path[$i]] = $reverse_history[$i]; + } + $this->result = $reverse_history[$cnt]; + + $this->path[$incoming_indent] = $key; + + if ($this->_containsGroupAnchor) { + $this->SavedGroups[$this->_containsGroupAnchor] = $this->path; + if (is_array ($value)) { + $k = key ($value); + if (!is_int ($k)) { + $this->SavedGroups[$this->_containsGroupAnchor][$incoming_indent + 2] = $k; + } + } + $this->_containsGroupAnchor = false; + } + + } + + private static function startsLiteralBlock ($line) { + $lastChar = substr (trim($line), -1); + if ($lastChar != '>' && $lastChar != '|') return false; + if ($lastChar == '|') return $lastChar; + // HTML tags should not be counted as literal blocks. + if (preg_match ('#<.*?>$#', $line)) return false; + return $lastChar; + } + + private static function greedilyNeedNextLine($line) { + $line = trim ($line); + if (!strlen($line)) return false; + if (substr ($line, -1, 1) == ']') return false; + if ($line[0] == '[') return true; + if (preg_match ('#^[^:]+?:\s*\[#', $line)) return true; + return false; + } + + private function addLiteralLine ($literalBlock, $line, $literalBlockStyle, $indent = -1) { + $line = self::stripIndent($line, $indent); + if ($literalBlockStyle !== '|') { + $line = self::stripIndent($line); + } + $line = rtrim ($line, "\r\n\t ") . "\n"; + if ($literalBlockStyle == '|') { + return $literalBlock . $line; + } + if (strlen($line) == 0) + return rtrim($literalBlock, ' ') . "\n"; + if ($line == "\n" && $literalBlockStyle == '>') { + return rtrim ($literalBlock, " \t") . "\n"; + } + if ($line != "\n") + $line = trim ($line, "\r\n ") . " "; + return $literalBlock . $line; + } + + function revertLiteralPlaceHolder ($lineArray, $literalBlock) { + foreach ($lineArray as $k => $_) { + if (is_array($_)) + $lineArray[$k] = $this->revertLiteralPlaceHolder ($_, $literalBlock); + else if (substr($_, -1 * strlen ($this->LiteralPlaceHolder)) == $this->LiteralPlaceHolder) + $lineArray[$k] = rtrim ($literalBlock, " \r\n"); + } + return $lineArray; + } + + private static function stripIndent ($line, $indent = -1) { + if ($indent == -1) $indent = strlen($line) - strlen(ltrim($line)); + return substr ($line, $indent); + } + + private function getParentPathByIndent ($indent) { + if ($indent == 0) return array(); + $linePath = $this->path; + do { + end($linePath); $lastIndentInParentPath = key($linePath); + if ($indent <= $lastIndentInParentPath) array_pop ($linePath); + } while ($indent <= $lastIndentInParentPath); + return $linePath; + } + + + private function clearBiggerPathValues ($indent) { + + + if ($indent == 0) $this->path = array(); + if (empty ($this->path)) return true; + + foreach ($this->path as $k => $_) { + if ($k > $indent) unset ($this->path[$k]); + } + + return true; + } + + + private static function isComment ($line) { + if (!$line) return false; + if ($line[0] == '#') return true; + if (trim($line, " \r\n\t") == '---') return true; + return false; + } + + private static function isEmpty ($line) { + return (trim ($line) === ''); + } + + + private function isArrayElement ($line) { + if (!$line || !is_scalar($line)) return false; + if (substr($line, 0, 2) != '- ') return false; + if (strlen ($line) > 3) + if (substr($line,0,3) == '---') return false; + + return true; + } + + private function isHashElement ($line) { + return strpos($line, ':'); + } + + private function isLiteral ($line) { + if ($this->isArrayElement($line)) return false; + if ($this->isHashElement($line)) return false; + return true; + } + + + private static function unquote ($value) { + if (!$value) return $value; + if (!is_string($value)) return $value; + if ($value[0] == '\'') return trim ($value, '\''); + if ($value[0] == '"') return trim ($value, '"'); + return $value; + } + + private function startsMappedSequence ($line) { + return (substr($line, 0, 2) == '- ' && substr ($line, -1, 1) == ':'); + } + + private function returnMappedSequence ($line) { + $array = array(); + $key = self::unquote(trim(substr($line,1,-1))); + $array[$key] = array(); + $this->delayedPath = array(strpos ($line, $key) + $this->indent => $key); + return array($array); + } + + private function checkKeysInValue($value) { + if (strchr('[{"\'', $value[0]) === false) { + if (strchr($value, ': ') !== false) { + throw new Exception('Too many keys: '.$value); + } + } + } + + private function returnMappedValue ($line) { + $this->checkKeysInValue($line); + $array = array(); + $key = self::unquote (trim(substr($line,0,-1))); + $array[$key] = ''; + return $array; + } + + private function startsMappedValue ($line) { + return (substr ($line, -1, 1) == ':'); + } + + private function isPlainArray ($line) { + return ($line[0] == '[' && substr ($line, -1, 1) == ']'); + } + + private function returnPlainArray ($line) { + return $this->_toType($line); + } + + private function returnKeyValuePair ($line) { + $array = array(); + $key = ''; + if (strpos ($line, ': ')) { + // It's a key/value pair most likely + // If the key is in double quotes pull it out + if (($line[0] == '"' || $line[0] == "'") && preg_match('/^(["\'](.*)["\'](\s)*:)/',$line,$matches)) { + $value = trim(str_replace($matches[1],'',$line)); + $key = $matches[2]; + } else { + // Do some guesswork as to the key and the value + $explode = explode(': ', $line); + $key = trim(array_shift($explode)); + $value = trim(implode(': ', $explode)); + $this->checkKeysInValue($value); + } + // Set the type of the value. Int, string, etc + $value = $this->_toType($value); + if ($key === '0') $key = '__!YAMLZero'; + $array[$key] = $value; + } else { + $array = array ($line); + } + return $array; + + } + + + private function returnArrayElement ($line) { + if (strlen($line) <= 1) return array(array()); // Weird %) + $array = array(); + $value = trim(substr($line,1)); + $value = $this->_toType($value); + if ($this->isArrayElement($value)) { + $value = $this->returnArrayElement($value); + } + $array[] = $value; + return $array; + } + + + private function nodeContainsGroup ($line) { + $symbolsForReference = 'A-z0-9_\-'; + if (strpos($line, '&') === false && strpos($line, '*') === false) return false; // Please die fast ;-) + if ($line[0] == '&' && preg_match('/^(&['.$symbolsForReference.']+)/', $line, $matches)) return $matches[1]; + if ($line[0] == '*' && preg_match('/^(\*['.$symbolsForReference.']+)/', $line, $matches)) return $matches[1]; + if (preg_match('/(&['.$symbolsForReference.']+)$/', $line, $matches)) return $matches[1]; + if (preg_match('/(\*['.$symbolsForReference.']+$)/', $line, $matches)) return $matches[1]; + if (preg_match ('#^\s*<<\s*:\s*(\*[^\s]+).*$#', $line, $matches)) return $matches[1]; + return false; + + } + + private function addGroup ($line, $group) { + if ($group[0] == '&') $this->_containsGroupAnchor = substr ($group, 1); + if ($group[0] == '*') $this->_containsGroupAlias = substr ($group, 1); + //print_r ($this->path); + } + + private function stripGroup ($line, $group) { + $line = trim(str_replace($group, '', $line)); + return $line; + } +} +} + +// Enable use of Spyc from command line +// The syntax is the following: php Spyc.php spyc.yaml + +do { + if (PHP_SAPI != 'cli') break; + if (empty ($_SERVER['argc']) || $_SERVER['argc'] < 2) break; + if (empty ($_SERVER['PHP_SELF']) || FALSE === strpos ($_SERVER['PHP_SELF'], 'Spyc.php') ) break; + $file = $argv[1]; + echo json_encode (spyc_load_file ($file)); +} while (0); diff --git a/dev/dev.7z b/dev/dev.7z deleted file mode 100644 index f2e41eb2de9a0a08a086a7b7299c19b2ba0c8a2d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16144 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 diff --git a/dev/moddb.sh b/dev/moddb.sh new file mode 100644 index 0000000..9f27f7b --- /dev/null +++ b/dev/moddb.sh @@ -0,0 +1,80 @@ +#!/usr/bin/php += :ver'; + } + +} + +$query .= ' ORDER BY modkey ASC'; + +$statement = $db->prepare($query); +if (isset($params['ver']) && $params['ver']) { + $statement->bindParam(':ver', $params['ver']); +} + +print "Fetch $query".PHP_EOL.PHP_EOL; + +$result = $statement->execute(); +if (!$result->numColumns()) { + exit('No module data available!'.PHP_EOL.PHP_EOL); +} + +$releases = []; +while ($row = $result->fetchArray(SQLITE3_ASSOC)) { + + $releases[$row['modkey']] = [ + 'packageUrl' => $row['packageUrl'], + 'signature' => $row['signature'], + 'hash' => $row['hash'], + 'author' => $row['author'], + 'name' => $row['name'], + 'description' => $row['description'], + 'link' => $row['link'], + 'version' => $row['version'], + 'requirements' => [ + 'system' => $row['req_system'], + 'php' => $row['req_php'] + ] + ]; + +} + +$destPos = array_search('--dest', $argv); +if ($hasSystem !== false) { + $dest = $argv[$destPos+1] ?? ''; +} + +$yamlPath = __DIR__.'/release'.($dest ?? '').'.yml'; +if ( !file_put_contents($yamlPath, '## FanPress CM module package source data'.PHP_EOL.Spyc::YAMLDump($releases)) ) { + exit('Failed to create '.$yamlPath.'!'.PHP_EOL.PHP_EOL); +} + +file_put_contents(__DIR__.'/test.txt', var_export(spyc_load_file($yamlPath), true)); +exit('Release file created within '.$yamlPath.'!'.PHP_EOL.PHP_EOL); + diff --git a/dev/modules.db b/dev/modules.db new file mode 100644 index 0000000000000000000000000000000000000000..3360dffc8a624c712c568fce9995c9d794be18ec GIT binary patch literal 36864 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 literal 0 HcmV?d00001