Exemplo n.º 1
0
 public function testEnterTd()
 {
     // ASCII.
     $res = CRegex::enterTd(".(]/", "/");
     $this->assertTrue(CString::equals($res, "\\.\\(\\]\\/"));
     $res = CRegex::enterTd(".(]#", "#");
     $this->assertTrue(CString::equals($res, "\\.\\(\\]\\#"));
     // Unicode.
     $res = CRegex::enterTd(".(señor]/", "/");
     $this->assertTrue(CString::equals($res, "\\.\\(señor\\]\\/"));
     $res = CRegex::enterTd(".(señor]#", "#");
     $this->assertTrue(CString::equals($res, "\\.\\(señor\\]\\#"));
 }
Exemplo n.º 2
0
 /**
  * Normalizes a path by removing any trailing slashes, any redundant slashes, any references to the current
  * directory, and any references to the parent directory where possible, and returns the new path.
  *
  * For example, "/path//./dir-a/.././to//../dir-b/" is normalized to "/path/dir-b".
  *
  * @param  string $path The path to be normalized (can be absolute or relative).
  * @param  bool $targetIsExecutable **OPTIONAL. Default is** `false`. Tells whether the path's target should be
  * treated as an executable so that, if the path starts with ".", the resulting path will start with "." too and
  * the "." will not be removed as a reference to the current directory.
  *
  * @return CUStringObject The normalized path.
  */
 public static function normalize($path, $targetIsExecutable = false)
 {
     assert('is_cstring($path) && is_bool($targetIsExecutable)', vs(isset($this), get_defined_vars()));
     assert('!CString::isEmpty($path)', vs(isset($this), get_defined_vars()));
     $path = CRegex::replace($path, "/\\/{2,}/", "/");
     // normalize consecutive slashes
     $path = CString::stripEnd($path, "/");
     // remove the trailing slash, if any
     if (CString::isEmpty($path)) {
         return "/";
     }
     $path = CRegex::remove($path, "/\\/\\.(?=\\/|\\z)/");
     // remove any "/." followed by a slash or at the end
     if (CString::isEmpty($path)) {
         return "/";
     }
     if (!$targetIsExecutable) {
         $path = CString::stripStart($path, "./");
     }
     $pathIsAbsolute;
     if (!CString::startsWith($path, "/")) {
         $pathIsAbsolute = false;
     } else {
         $pathIsAbsolute = true;
         $path = CString::substr($path, 1);
     }
     if (!CString::find($path, "/")) {
         if ($pathIsAbsolute) {
             if (!CString::equals($path, "..")) {
                 $path = "/{$path}";
             } else {
                 $path = "/";
             }
         }
         return $path;
     }
     // Recompose the path.
     $components = CString::split($path, "/");
     $newComponents = CArray::make();
     $len = CArray::length($components);
     for ($i = 0; $i < $len; $i++) {
         $comp = $components[$i];
         $lastAddedComp = "";
         $noCompsAddedYet = CArray::isEmpty($newComponents);
         if (!$noCompsAddedYet) {
             $lastAddedComp = CArray::last($newComponents);
         }
         if (CString::equals($comp, "..")) {
             if ($noCompsAddedYet || CString::equals($lastAddedComp, "..") || CString::equals($lastAddedComp, ".")) {
                 if (!($noCompsAddedYet && $pathIsAbsolute)) {
                     CArray::push($newComponents, $comp);
                 }
             } else {
                 CArray::pop($newComponents);
             }
         } else {
             CArray::push($newComponents, $comp);
         }
     }
     $path = CArray::join($newComponents, "/");
     if ($pathIsAbsolute) {
         $path = "/{$path}";
     } else {
         if (CString::isEmpty($path)) {
             $path = ".";
         }
     }
     return $path;
 }
Exemplo n.º 3
0
 /**
  * Determines if a URL is equal to another URL, comparing them by normalized URL strings.
  *
  * @param  CUrl $toUrl The second URL for comparison.
  * @param  bool $ignoreFragmentId **OPTIONAL. Default is** `true`. Tells whether the fragment IDs of the URLs, if
  * any, should be ignored during the comparison.
  *
  * @return bool `true` if *this* URL is equal to the second URL, `false` otherwise.
  */
 public function equals($toUrl, $ignoreFragmentId = true)
 {
     assert('$toUrl instanceof CUrl && is_bool($ignoreFragmentId)', vs(isset($this), get_defined_vars()));
     if ($ignoreFragmentId) {
         return CString::equals($this->m_normUrlWithoutFragmentId, $toUrl->m_normUrlWithoutFragmentId);
     } else {
         return CString::equals($this->m_normUrl, $toUrl->m_normUrl);
     }
 }
Exemplo n.º 4
0
 /**
  * Returns the HTTP method of the request, as an enumerand.
  *
  * @return enum The HTTP method of the request (see [Summary](#summary)).
  */
 public static function method()
 {
     $method = $_SERVER["REQUEST_METHOD"];
     $method = CString::toUpperCase($method);
     if (CString::equals($method, "GET")) {
         return self::GET;
     }
     if (CString::equals($method, "HEAD")) {
         return self::HEAD;
     }
     if (CString::equals($method, "POST")) {
         return self::POST;
     }
     if (CString::equals($method, "PUT")) {
         return self::PUT;
     }
     if (CString::equals($method, "DELETE")) {
         return self::DELETE;
     }
     if (CString::equals($method, "OPTIONS")) {
         return self::OPTIONS;
     }
     if (CString::equals($method, "TRACE")) {
         return self::TRACE;
     }
     if (CString::equals($method, "CONNECT")) {
         return self::CONNECT;
     }
     return self::UNKNOWN;
 }
Exemplo n.º 5
0
 /**
  * Wraps the text in a string to a specified width and returns the new string.
  *
  * @param  string $string The string with the text to be wrapped.
  * @param  int $width The wrapping width, in characters.
  * @param  bitfield $wrappingFlags **OPTIONAL. Default is** `WRAPPING_DEFAULT`. The wrapping option(s). The
  * available options are `WRAPPING_BREAK_SPACELESS_LINES`, `WRAPPING_ALLOW_TRAILING_SPACES`,
  * `WRAPPING_DISALLOW_LEADING_SPACES`, and `WRAPPING_DONT_BREAK_SPACELESS_CJK_ENDING_LINES`
  * (see [Summary](#summary)).
  * @param  string $newline **OPTIONAL. Default is** LF (U+000A). The newline character(s) to be used for making
  * new lines in the process of wrapping.
  *
  * @return string The wrapped text.
  */
 public static function wordWrap($string, $width, $wrappingFlags = self::WRAPPING_DEFAULT, $newline = self::NEWLINE)
 {
     assert('is_cstring($string) && is_int($width) && is_bitfield($wrappingFlags) && is_cstring($newline)', vs(isset($this), get_defined_vars()));
     assert('$width > 0', vs(isset($this), get_defined_vars()));
     // Constant. Newline character that is used by the input string (after newline normalization).
     $normNl = self::NEWLINE;
     // Constant. Determines what characters should be considered spaces.
     // A character in the "Zs" Unicode category, an HT, or a Zero Width Space, except No-break Space and Narrow
     // No-break Space.
     $spaceSubjectRe = "(\\p{Zs}|\\x{0009}|\\x{200B})(?<!\\x{00A0}|\\x{202F})";
     // Break enabling characters.
     // Soft Hyphen or Tibetan Mark Intersyllabic Tsheg.
     $breakAllowCharSubjectRe = "\\x{00AD}|\\x{0F0B}";
     // Retrieve the wrapping options.
     $breakSpacelessLines = CBitField::isBitSet($wrappingFlags, self::WRAPPING_BREAK_SPACELESS_LINES);
     $allowTrailingSpaces = CBitField::isBitSet($wrappingFlags, self::WRAPPING_ALLOW_TRAILING_SPACES);
     $disallowLeadingSpaces = CBitField::isBitSet($wrappingFlags, self::WRAPPING_DISALLOW_LEADING_SPACES);
     $dontBreakSpacelessCjkEndingLines = CBitField::isBitSet($wrappingFlags, self::WRAPPING_DONT_BREAK_SPACELESS_CJK_ENDING_LINES);
     // Normalize newlines in the input string.
     $string = self::normNewlines($string, $normNl);
     $normNlLength = self::length($normNl);
     $newString = "";
     $pos = 0;
     $bytePos = 0;
     $sLength = self::length($string);
     while (true) {
         $numCharsLeft = $sLength - $pos;
         // A portion begins at the very start or right after a newline, either it is native or added. The length of
         // a portion is the wrapping width or less.
         $portionLength = CMathi::min($width, $numCharsLeft);
         $portion = self::substr($string, $pos, $portionLength);
         $portionByteLength = CString::length($portion);
         if ($portionLength == $numCharsLeft) {
             // All done.
             $newString .= $portion;
             break;
         }
         // The starting position of the next portion.
         $nextPos = $pos + $portionLength;
         $nextBytePos = $bytePos + $portionByteLength;
         // Look for the first occurrence of a newline in the portion.
         $nlPos = self::indexOf($portion, $normNl);
         if ($nlPos != -1) {
             // This portion contains a newline, so the next portion is going to start right after this first found
             // newline.
             $subPLength = $nlPos + $normNlLength;
             $subP = self::substr($portion, 0, $subPLength);
             $newString .= $subP;
             $pos += $subPLength;
             $bytePos += CString::length($subP);
             continue;
         }
         // There are no newlines in this portion. Before the next step, make sure that the next portion is not
         // going to start with a newline.
         if ($numCharsLeft - $portionLength >= $normNlLength) {
             $nextPortionBeginning = self::substr($string, $nextPos, $normNlLength);
             if (self::indexOf($nextPortionBeginning, $normNl) == 0) {
                 // The next portion is going to start with a newline, so no need to break this one, regardless of
                 // whether or not it contains any spaces.
                 $newString .= $portion;
                 $pos = $nextPos;
                 $bytePos = $nextBytePos;
                 continue;
             }
         }
         // The next portion is not going to start with a newline. Look for the last occurrence of a space or
         // break-allow character in this portion.
         $lastSubjectBytePos = CRegex::lastIndexOf($portion, "/({$spaceSubjectRe})|({$breakAllowCharSubjectRe})/u", 0, $foundString);
         if ($lastSubjectBytePos != -1) {
             // Add a newline right after this last occurring space or break-allow character.
             $subP = CString::substring($portion, 0, $lastSubjectBytePos + CString::length($foundString));
             $newString .= $subP;
             $newString .= $newline;
             $pos += self::length($subP);
             $bytePos += CString::length($subP);
             continue;
         }
         // There are no spaces or break-allow characters in this portion. Consider adding a newline right after the
         // portion.
         if ($breakSpacelessLines || !$dontBreakSpacelessCjkEndingLines && self::hasCjkChar(self::charAt($portion, $portionLength - 1))) {
             $newString .= $portion;
             $newString .= $newline;
             $pos = $nextPos;
             $bytePos = $nextBytePos;
             continue;
         }
         // There are no spaces or break-allow characters in this portion and it should go adjacent to the upcoming
         // text. Look for the first newline, space, or break-allow character in the upcoming text.
         $nextSubjectBytePos = CRegex::indexOf($string, "/{$normNl}|(({$spaceSubjectRe})|({$breakAllowCharSubjectRe}))(?!{$normNl})/u", $nextBytePos, $foundString);
         if ($nextSubjectBytePos != -1) {
             // Found a newline, space, or a break-allow character, so the next portion is going to start right
             // after it.
             $afterP = CString::substring($string, $nextBytePos, $nextSubjectBytePos + CString::length($foundString));
             $newString .= $portion;
             $newString .= $afterP;
             if (!CString::equals($foundString, $normNl)) {
                 // It is a space or break-allow character that was found, so add a newline after it.
                 $newString .= $newline;
             }
             $pos += $portionLength + self::length($afterP);
             $bytePos += $portionByteLength + CString::length($afterP);
             continue;
         }
         // There are no spaces, newlines, or break-allow characters in the upcoming text. Finalize according to the
         // breaking options.
         if (!$breakSpacelessLines) {
             $newString .= $portion;
             $newString .= self::substr($string, $nextPos);
         } else {
             $newString .= $portion;
             $newString .= $newline;
             $pos = $nextPos;
             while (true) {
                 $numCharsLeft = $sLength - $pos;
                 $portionLength = CMathi::min($width, $numCharsLeft);
                 $newString .= self::substr($string, $pos, $portionLength);
                 if ($portionLength == $numCharsLeft) {
                     break;
                 }
                 $newString .= $newline;
                 $pos += $portionLength;
             }
         }
         break;
     }
     if (!$allowTrailingSpaces) {
         // Remove trailing spaces.
         $newString = CRegex::remove($newString, "/({$spaceSubjectRe})+(?={$normNl}|\\z)/u");
     }
     if ($disallowLeadingSpaces) {
         // Remove leading spaces.
         $newString = CRegex::remove($newString, "/(?<={$normNl}|^)({$spaceSubjectRe})+/u");
     }
     return $newString;
 }
Exemplo n.º 6
0
 /**
  * @ignore
  */
 public static function onThirdPartyUpdateByPackageManager()
 {
     if (!self::isInCliMode()) {
         // This method can be run in CLI mode only.
         assert('false', vs(isset($this), get_defined_vars()));
     }
     $timeoutPause = new CTimeoutPause();
     CShell::speak("Processing third-party components ...");
     $tpDps = CFile::listDirectories(CFilePath::absolute($GLOBALS["PHRED_PATH_TO_THIRD_PARTY"]));
     $ignorePackages = CConfiguration::option("upd.thirdPartyOopWrappingIgnorePackages");
     $ignorePackagesL2 = CArray::filter($ignorePackages, function ($package) {
         return CString::find($package, "/");
     });
     $newTpDps = CArray::make();
     $len = CArray::length($tpDps);
     for ($i = 0; $i < $len; $i++) {
         $tpDp = $tpDps[$i];
         $dirName = CFilePath::name($tpDp);
         if (!CArray::find($ignorePackages, $dirName)) {
             $dpHasL2DirsToIgnore = CArray::find($ignorePackagesL2, $dirName, function ($packageL2, $dirName) {
                 return CString::equals(CFilePath::directory($packageL2), $dirName);
             });
             if (!$dpHasL2DirsToIgnore) {
                 CArray::push($newTpDps, $tpDp);
             } else {
                 $tpSubDps = CFile::listDirectories($tpDp);
                 $tpSubDps = CArray::filter($tpSubDps, function ($subDp) use($ignorePackagesL2) {
                     return !CArray::find($ignorePackagesL2, $subDp, function ($packageL2, $subDp) {
                         return CString::endsWith($subDp, $packageL2);
                     });
                 });
                 CArray::pushArray($newTpDps, $tpSubDps);
             }
         }
     }
     $tpDps = $newTpDps;
     $wrapProtectedMethods = CConfiguration::option("upd.thirdPartyOopWrappingInProtectedMethods");
     $wrapPrivateMethods = CConfiguration::option("upd.thirdPartyOopWrappingInPrivateMethods");
     static $s_stdPhpTag = "<?php";
     static $s_progressResolution = 0.05;
     $prevProgressDivR = 0;
     $tpDpsLen = CArray::length($tpDps);
     for ($i0 = 0; $i0 < $tpDpsLen; $i0++) {
         $tpFps = CFile::reFindFilesRecursive($tpDps[$i0], "/\\.php\\d?\\z/");
         $tpFpsLen = CArray::length($tpFps);
         for ($i1 = 0; $i1 < $tpFpsLen; $i1++) {
             $fileCode = CFile::read($tpFps[$i1]);
             if (!CString::find($fileCode, self::$ms_thirdPartyAlreadyOopWrappedMark)) {
                 $parser = new PhpParser\Parser(new PhpParser\Lexer());
                 try {
                     // Parse the code.
                     $statements = $parser->parse($fileCode);
                     // Wrap the code into OOP.
                     $traverser = new PhpParser\NodeTraverser();
                     $mainVisitor = new CMainVisitor($wrapProtectedMethods, $wrapPrivateMethods);
                     $traverser->addVisitor($mainVisitor);
                     $statements = $traverser->traverse($statements);
                     $wrappedCode = (new PhpParser\PrettyPrinter\Standard())->prettyPrint($statements);
                     $phpTagPos = CString::indexOf($wrappedCode, $s_stdPhpTag);
                     if ($phpTagPos == -1) {
                         $wrappedCode = "{$s_stdPhpTag}\n\n{$wrappedCode}";
                         $phpTagPos = 0;
                     }
                     $wrappedCode = CString::insert($wrappedCode, $phpTagPos + CString::length($s_stdPhpTag), "\n\n" . self::$ms_thirdPartyAlreadyOopWrappedMark);
                     // Save.
                     CFile::write($tpFps[$i1], $wrappedCode);
                 } catch (PhpParser\Error $parserError) {
                     CShell::say("\nPhpParser: " . $tpFps[$i1] . ", at line " . $parserError->getRawLine() . ": " . $parserError->getRawMessage());
                 }
             }
             $progress = (double) ($i0 / $tpDpsLen + 1 / $tpDpsLen * $i1 / $tpFpsLen);
             $progressDivR = CMathi::floor($progress / $s_progressResolution);
             if ($progressDivR != $prevProgressDivR) {
                 $perc = CMathi::round($progressDivR * $s_progressResolution * 100);
                 CShell::speak("{$perc}%");
             }
             $prevProgressDivR = $progressDivR;
         }
     }
     CShell::speak("100%");
     CShell::say("Done.");
     $timeoutPause->end();
 }
Exemplo n.º 7
0
 /**
  * Exits the script issuing an error message if the script's user is lacking root privileges.
  *
  * @return void
  */
 public static function exitIfNotRoot()
 {
     $user = self::user();
     if (!CString::equals($user, "root")) {
         $message = "This script requires root privileges to run, while the current user is {$user}.";
         self::onError(true, $message);
     }
 }
Exemplo n.º 8
0
 /**
  * Sends a message to the recipient(s).
  *
  * @param  reference $failedAddresses **OPTIONAL. OUTPUT.** After the method is called with this parameter
  * provided, the parameter's value, which is of type `CArrayObject`, is an array containing the email addresses of
  * the recipients who failed to receive the message.
  *
  * @return int The number of recipients who have successfully received the message.
  */
 public function send(&$failedAddresses = null)
 {
     assert('isset($this->m_swiftMailer) && isset($this->m_swiftMessage)', vs(isset($this), get_defined_vars()));
     assert('(isset($this->m_from) || isset($this->m_sender) || isset($this->m_returnAddress)) && ' . '(isset($this->m_to) || isset($this->m_cc) || isset($this->m_bcc))', vs(isset($this), get_defined_vars()));
     $message = $this->m_swiftMessage;
     if (isset($this->m_from)) {
         $message->setFrom($this->m_from);
     }
     if (isset($this->m_to)) {
         $message->setTo($this->m_to);
     }
     if (isset($this->m_cc)) {
         $message->setCc($this->m_cc);
     }
     if (isset($this->m_bcc)) {
         $message->setBcc($this->m_bcc);
     }
     if (isset($this->m_sender)) {
         $message->setSender($this->m_sender);
     }
     if (isset($this->m_returnAddress)) {
         $message->setReturnPath($this->m_returnAddress);
     }
     if (isset($this->m_replyAddress)) {
         $message->setReplyTo($this->m_replyAddress);
     }
     if (isset($this->m_body)) {
         if (CString::equals($this->m_bodyType, CMimeType::PLAIN_TEXT)) {
             $this->m_body = $this->maybeWrapText($this->m_body);
         }
         $message->setBody($this->m_body, $this->m_bodyType);
     }
     if (isset($this->m_altBodiesAndTypes)) {
         $len = CArray::length($this->m_altBodiesAndTypes);
         for ($i = 0; $i < $len; $i++) {
             $bodyAndType = $this->m_altBodiesAndTypes[$i];
             $body = $bodyAndType[0];
             $type = $bodyAndType[1];
             if (CString::equals($type, CMimeType::PLAIN_TEXT)) {
                 $body = $this->maybeWrapText($body);
             }
             $message->addPart($body, $type);
         }
     }
     $paFailedAddresses;
     $res = $this->m_swiftMailer->send($message, $paFailedAddresses);
     if (is_cmap($paFailedAddresses)) {
         $failedAddresses = oop_a(CArray::fromPArray($paFailedAddresses));
     }
     $res = is_int($res) ? $res : 0;
     return $res;
 }
Exemplo n.º 9
0
 /**
  * @ignore
  */
 public static function isNameIcuCompatible($name)
 {
     assert('is_cstring($name)', vs(isset($this), get_defined_vars()));
     $itz = IntlTimeZone::createTimeZone($name);
     return CString::equals($name, $itz->getID());
 }
Exemplo n.º 10
0
 protected static function basicProtocol($protocol)
 {
     $protocol = CString::toLowerCase($protocol);
     if (CString::equals($protocol, "https")) {
         $protocol = "http";
     } else {
         if (CString::equals($protocol, "ftps")) {
             $protocol = "ftp";
         }
     }
     return $protocol;
 }
Exemplo n.º 11
0
 protected static function recurseCopy($fileOrDirectoryPath, $copyPath, $copyPermissions)
 {
     if (is_link($fileOrDirectoryPath)) {
         // The source is a symlink, so make another symlink.
         $symlinkTargetPath = readlink($fileOrDirectoryPath);
         assert('is_cstring($symlinkTargetPath)', vs(isset($this), get_defined_vars()));
         $res = symlink($symlinkTargetPath, $copyPath);
         assert('$res', vs(isset($this), get_defined_vars()));
         return;
     }
     if ($copyPermissions) {
         clearstatcache(true, $fileOrDirectoryPath);
     }
     if (is_file($fileOrDirectoryPath)) {
         // A file.
         $res = copy($fileOrDirectoryPath, $copyPath);
         assert('$res', vs(isset($this), get_defined_vars()));
         if ($copyPermissions) {
             $res = chmod($copyPath, fileperms($fileOrDirectoryPath));
             assert('$res', vs(isset($this), get_defined_vars()));
         }
     } else {
         // A directory.
         if (!is_dir($copyPath)) {
             // Create the destination directory.
             $res = mkdir($copyPath);
             assert('$res', vs(isset($this), get_defined_vars()));
         }
         if ($copyPermissions) {
             $res = chmod($copyPath, fileperms($fileOrDirectoryPath));
             assert('$res', vs(isset($this), get_defined_vars()));
         }
         // Iterate through contained items.
         $dir = dir($fileOrDirectoryPath);
         assert('is_object($dir)', vs(isset($this), get_defined_vars()));
         while (false !== ($item = $dir->read())) {
             if (CString::equals($item, ".") || CString::equals($item, "..")) {
                 continue;
             }
             self::recurseCopy("{$fileOrDirectoryPath}/{$item}", "{$copyPath}/{$item}", $copyPermissions);
         }
         $dir->close();
     }
 }
Exemplo n.º 12
0
 /**
  * Determines if an ASCII string or binary data is equal to another ASCII string or binary data.
  *
  * This method is suitable for binary-safe comparison of strings and runs faster than `equals` method when
  * comparing strings known to contain no Unicode characters and is the method to be preferred for comparison of
  * binary data.
  *
  * @param  string $toString The second string for comparison.
  *
  * @return bool `true` if the two strings are equal, comparing them byte-to-byte, and `false` otherwise.
  */
 public function equalsBi($toString)
 {
     return CString::equals($this, $toString);
 }
Exemplo n.º 13
0
 /**
  * @ignore
  */
 public static function initialize()
 {
     $configDp = CFilePath::add($GLOBALS["PHRED_PATH_TO_APP"], "Configuration");
     $configEnvsDp = CFilePath::add($configDp, "Environments");
     $configs = CArray::make();
     $currEnv;
     if ($GLOBALS["PHRED_TESTS"]) {
         $currEnv = "tst";
     }
     // Main configuration files.
     $configFps = CFile::findFiles(CFilePath::add($configDp, "*.json"));
     $numConfigs = CArray::length($configFps);
     for ($i = 0; $i < $numConfigs; $i++) {
         $configFp = $configFps[$i];
         $configName = CFilePath::nameOnly($configFp);
         self::readAndAddConfig($configFp, $configName, $configs);
         if (!isset($currEnv) && CString::equals($configName, "Application")) {
             $config = CArray::last($configs);
             $currEnv = $config[self::$ms_configAliases["Application"]]["environment"];
         }
     }
     assert('is_cstring($currEnv)', vs(isset($this), get_defined_vars()));
     // The configuration files from the current environment's directory.
     $currEnvDp = CFilePath::add($configEnvsDp, $currEnv);
     assert('CFile::exists($currEnvDp)', vs(isset($this), get_defined_vars()));
     $configFps = CFile::findFiles(CFilePath::add($currEnvDp, "*.json"));
     $numConfigs = CArray::length($configFps);
     for ($i = 0; $i < $numConfigs; $i++) {
         $configFp = $configFps[$i];
         $configName = CFilePath::nameOnly($configFp);
         self::readAndAddConfig($configFp, $configName, $configs);
     }
     self::$ms_config = call_user_func_array("CMap::merge", CArray::toPArray($configs));
     self::$ms_isInitialized = true;
 }
Exemplo n.º 14
0
 /**
  * Filters a string or a collection of strings according to the expected output type(s) and returns the output
  * value(s).
  *
  * @param  mixed $inputStringOrDecodedCollection The string to be filtered or the array or map containing the
  * strings to be filtered. If the parameter's value is a JSON-encoded string, the output value is going to be
  * either an array or map.
  * @param  reference $success **OUTPUT.** After the method is called, the value of this parameter tells whether
  * the filtering was successful.
  *
  * @return mixed The output value or a collection of values of the expected type(s) after having been put through
  * the filter.
  */
 public function filter($inputStringOrDecodedCollection, &$success)
 {
     assert('is_cstring($inputStringOrDecodedCollection) || is_collection($inputStringOrDecodedCollection)', vs(isset($this), get_defined_vars()));
     $success = true;
     if ($this->m_expectedType != self::CARRAY && $this->m_expectedType != self::CMAP) {
         // The expected output type is not a collection; the input value must be of string type.
         if (!is_cstring($inputStringOrDecodedCollection)) {
             $success = false;
             return oop_x($this->m_defaultValue);
         }
         $inputString = $inputStringOrDecodedCollection;
         if ($this->m_expectedType == self::BOOL || $this->m_expectedType == self::INT || $this->m_expectedType == self::FLOAT || $this->m_expectedType == self::EMAIL || $this->m_expectedType == self::URL || $this->m_expectedType == self::IP) {
             // Trim the input string on both sides from whitespace, including Unicode whitespace and control
             // characters.
             $trimmingSubjectRe = CUString::TRIMMING_AND_SPACING_NORM_SUBJECT_RE;
             $inputString = CRegex::remove($inputString, "/^({$trimmingSubjectRe})+|({$trimmingSubjectRe})+\\z/u");
         }
         // Pre-process the string for integer and floating-point types.
         $looksLikeHex;
         if ($this->m_expectedType == self::INT || $this->m_expectedType == self::FLOAT) {
             if (CString::startsWith($inputString, "+")) {
                 // Remove the plus sign.
                 $inputString = CString::substr($inputString, 1);
             }
             $looksLikeHex = CRegex::find($inputString, "/^-?0x/i");
             if ($this->m_allowLeadingZeros && !($this->m_expectedType == self::INT && $this->m_allowHex && $looksLikeHex)) {
                 // Remove any leading zeros (except for special cases).
                 $inputString = CRegex::replace($inputString, "/^(\\D*)0*(?!\\b)/", "\$1");
             }
             if ($this->m_allowComma) {
                 $inputString = CRegex::remove($inputString, "/,(?=\\d{3}\\b)/");
             }
         }
         // Validate and sanitize the value according to its expected type.
         if ($this->m_expectedType == self::BOOL) {
             if (!CRegex::find($inputString, "/^(1|true|yes|on|0|false|no|off)\\z/i")) {
                 $success = false;
                 return $this->m_defaultValue;
             }
             return CString::equals($inputString, "1") || CString::equalsCi($inputString, "true") || CString::equalsCi($inputString, "yes") || CString::equalsCi($inputString, "on");
         }
         if ($this->m_expectedType == self::INT) {
             $value;
             if (!($this->m_allowHex && $looksLikeHex)) {
                 // Regular.
                 if (!CRegex::find($inputString, "/^-?(?!0(?!\\b))\\d+\\z/")) {
                     $success = false;
                     return $this->m_defaultValue;
                 }
                 $value = CString::toInt($inputString);
             } else {
                 // Hex.
                 if (!CRegex::find($inputString, "/^-?0x[0-9A-F]+\\z/i")) {
                     $success = false;
                     return $this->m_defaultValue;
                 }
                 $value = CString::toIntFromHex($inputString);
             }
             if (isset($this->m_intValidMin) && $value < $this->m_intValidMin || isset($this->m_intValidMax) && $value > $this->m_intValidMax) {
                 $success = false;
                 return $this->m_defaultValue;
             }
             if (isset($this->m_intClampingMin) && $value < $this->m_intClampingMin) {
                 $value = $this->m_intClampingMin;
             }
             if (isset($this->m_intClampingMax) && $value > $this->m_intClampingMax) {
                 $value = $this->m_intClampingMax;
             }
             return $value;
         }
         if ($this->m_expectedType == self::FLOAT) {
             if (!CRegex::find($inputString, "/^-?(?!0(?!\\b))\\d*\\.?\\d+(e[\\-+]?\\d+)?\\z/i")) {
                 $success = false;
                 return $this->m_defaultValue;
             }
             $value = CString::toFloat($inputString);
             if (isset($this->m_floatValidMin) && $value < $this->m_floatValidMin || isset($this->m_floatValidMax) && $value > $this->m_floatValidMax) {
                 $success = false;
                 return $this->m_defaultValue;
             }
             if (isset($this->m_floatClampingMin) && $value < $this->m_floatClampingMin) {
                 $value = $this->m_floatClampingMin;
             }
             if (isset($this->m_floatClampingMax) && $value > $this->m_floatClampingMax) {
                 $value = $this->m_floatClampingMax;
             }
             return $value;
         }
         if ($this->m_expectedType == self::CSTRING) {
             $value = $inputString;
             if (!CString::isValid($value)) {
                 $success = false;
                 return $this->m_defaultValue;
             }
             if (!$this->m_keepAbnormalNewlines) {
                 $value = CString::normNewlines($value);
             }
             if (!$this->m_keepNonPrintable) {
                 if (!$this->m_keepTabsAndNewlines) {
                     $value = CRegex::remove($value, "/[\\x00-\\x1F\\x7F-\\xFF]/");
                 } else {
                     $value = CRegex::remove($value, "/[\\x00-\\x1F\\x7F-\\xFF](?<![\\x09\\x0A\\x0D])/");
                 }
             } else {
                 if (!$this->m_keepTabsAndNewlines) {
                     $value = CRegex::remove($value, "/[\\x09\\x0A\\x0D]/");
                 }
             }
             if (!$this->m_keepSideSpacing) {
                 $value = CString::trim($value);
             }
             if (!$this->m_keepExtraSpacing) {
                 $value = CString::normSpacing($value);
             }
             return $value;
         }
         if ($this->m_expectedType == self::CUSTRING) {
             $value = $inputString;
             if (!CUString::isValid($value)) {
                 $success = false;
                 return $this->m_defaultValue;
             }
             if (!$this->m_keepAbnormalNewlines) {
                 $value = CUString::normNewlines($value);
             }
             if (!$this->m_keepNonPrintable) {
                 if (!$this->m_keepTabsAndNewlines) {
                     $value = CRegex::remove($value, "/\\p{C}|\\p{Zl}|\\p{Zp}/u");
                 } else {
                     $value = CRegex::remove($value, "/\\p{C}(?<!\\x{0009}|\\x{000A}|\\x{000D})/u");
                 }
             } else {
                 if (!$this->m_keepTabsAndNewlines) {
                     $value = CRegex::remove($value, "/\\x{0009}|\\x{000A}|\\x{000D}|\\p{Zl}|\\p{Zp}/u");
                 }
             }
             if (!$this->m_keepSideSpacing) {
                 $value = CUString::trim($value);
             }
             if (!$this->m_keepExtraSpacing) {
                 $value = CUString::normSpacing($value);
             }
             return $value;
         }
         if ($this->m_expectedType == self::EMAIL) {
             $value = filter_var($inputString, FILTER_VALIDATE_EMAIL);
             if (!is_cstring($value)) {
                 $success = false;
                 return $this->m_defaultValue;
             }
             return $value;
         }
         if ($this->m_expectedType == self::URL) {
             $value = $inputString;
             if (!CUrl::isValid($value, $this->m_ignoreProtocolAbsence)) {
                 $success = false;
                 return $this->m_defaultValue;
             }
             if ($this->m_ignoreProtocolAbsence) {
                 $value = CUrl::ensureProtocol($value);
             }
             return $value;
         }
         if ($this->m_expectedType == self::IP) {
             $value = $inputString;
             $options = CBitField::ALL_UNSET;
             if (!$this->m_allowPrivateRange) {
                 $options |= CIp::DISALLOW_PRIVATE_RANGE;
             }
             if (!$this->m_allowReservedRange) {
                 $options |= CIp::DISALLOW_RESERVED_RANGE;
             }
             $isValid;
             if (!$this->m_ipV6 && !$this->m_ipV4OrV6) {
                 $isValid = CIp::isValidV4($value, $options);
             } else {
                 if (!$this->m_ipV4OrV6) {
                     $isValid = CIp::isValidV6($value, $options);
                 } else {
                     $isValid = CIp::isValidV4($value, $options) || CIp::isValidV6($value, $options);
                 }
             }
             if (!$isValid) {
                 $success = false;
                 return $this->m_defaultValue;
             }
             return $value;
         }
     } else {
         if ($this->m_expectedType == self::CARRAY) {
             if (!is_cstring($inputStringOrDecodedCollection) && !is_carray($inputStringOrDecodedCollection)) {
                 $success = false;
                 return oop_x($this->m_defaultValue);
             }
             $value;
             if (is_cstring($inputStringOrDecodedCollection)) {
                 // Assume JSON format for the input string.
                 $json = new CJson($inputStringOrDecodedCollection, $this->m_jsonStrictness);
                 $value = $json->decode($success);
                 if (!$success) {
                     return oop_x($this->m_defaultValue);
                 }
                 if (!is_carray($value)) {
                     $success = false;
                     return oop_x($this->m_defaultValue);
                 }
             } else {
                 $value = $inputStringOrDecodedCollection;
             }
             $value = self::recurseCollectionFiltering($value, $this->m_collectionInputFilters, $success, 0);
             if (!$success) {
                 return oop_x($this->m_defaultValue);
             }
             return $value;
         } else {
             if (!is_cstring($inputStringOrDecodedCollection) && !is_cmap($inputStringOrDecodedCollection)) {
                 $success = false;
                 return oop_x($this->m_defaultValue);
             }
             $value;
             if (is_cstring($inputStringOrDecodedCollection)) {
                 // Assume JSON format for the input string.
                 $json = new CJson($inputStringOrDecodedCollection, $this->m_jsonStrictness);
                 $value = $json->decode($success);
                 if (!$success) {
                     return oop_x($this->m_defaultValue);
                 }
                 if (!is_cmap($value)) {
                     $success = false;
                     return oop_x($this->m_defaultValue);
                 }
             } else {
                 $value = $inputStringOrDecodedCollection;
             }
             $value = self::recurseCollectionFiltering($value, $this->m_collectionInputFilters, $success, 0);
             if (!$success) {
                 return oop_x($this->m_defaultValue);
             }
             return $value;
         }
     }
 }
Exemplo n.º 15
0
 /**
  * Decodes the JSON-encoded string provided earlier to the decoder and returns the result.
  *
  * @param  reference $success **OPTIONAL. OUTPUT.** After the method is called with this parameter provided, the
  * parameter's value tells whether the decoding was successful.
  *
  * @return mixed The decoded value of type `CMapObject` or `CArrayObject`.
  */
 public function decode(&$success = null)
 {
     assert('is_cstring($this->m_source)', vs(isset($this), get_defined_vars()));
     $success = true;
     $source = $this->m_source;
     if ($this->m_decodingStrictness == self::LENIENT && !CUString::isValid($source)) {
         // Change the character encoding or try fixing it.
         if (CEString::looksLikeLatin1($source)) {
             $source = CEString::convertLatin1ToUtf8($source);
         } else {
             $source = CEString::fixUtf8($source);
         }
     }
     if ($this->m_decodingStrictness == self::STRICT_WITH_COMMENTS || $this->m_decodingStrictness == self::LENIENT) {
         if (CRegex::find($source, "/\\/\\/|\\/\\*/u")) {
             // Remove "//..." and "/*...*/" comments.
             $source = CRegex::remove($source, "/(?<!\\\\)\"(?:[^\\\\\"]++|\\\\{2}|\\\\\\C)*\"(*SKIP)(*FAIL)|" . "\\/\\/.*|\\/\\*\\C*?\\*\\//u");
         }
     }
     if ($this->m_decodingStrictness == self::LENIENT) {
         if (CRegex::find($source, "/[:\\[,]\\s*'([^\\\\']++|\\\\{2}|\\\\\\C)*'(?=\\s*[,}\\]])/u")) {
             // Convert single-quoted string values into double-quoted, taking care of double quotes within such
             // strings before and single quotes after. This needs to go in front of the rest of the leniency fixes.
             while (true) {
                 $prevSource = $source;
                 $source = CRegex::replace($source, "/(?<!\\\\)\"(?:[^\\\\\"]++|\\\\{2}|\\\\\\C)*\"(*SKIP)(*FAIL)|" . "([:\\[,]\\s*'(?:[^\\\\'\"]++|\\\\{2}|\\\\\\C)*)\"((?:[^\\\\']++|\\\\{2}|\\\\\\C)*')/u", "\$1\\\"\$2");
                 if (CString::equals($source, $prevSource) || is_null($source)) {
                     break;
                 }
             }
             if (is_null($source)) {
                 $source = "";
             }
             $source = CRegex::replace($source, "/(?<!\\\\)\"(?:[^\\\\\"]++|\\\\{2}|\\\\\\C)*\"(*SKIP)(*FAIL)|" . "([:\\[,]\\s*)'((?:[^\\\\']++|\\\\{2}|\\\\\\C)*)'(?=\\s*[,}\\]])/u", "\$1\"\$2\"");
             while (true) {
                 $prevSource = $source;
                 $source = CRegex::replace($source, "/([:\\[,]\\s*\"(?:[^\\\\\"]++|\\\\{2}|\\\\[^'])*)\\\\'((?:[^\\\\\"]++|\\\\{2}|\\\\\\C)*\")" . "(?=\\s*[,}\\]])/u", "\$1'\$2");
                 if (CString::equals($source, $prevSource) || is_null($source)) {
                     break;
                 }
             }
             if (is_null($source)) {
                 $source = "";
             }
         }
         if (CRegex::find($source, "/[{,]\\s*[\\w\\-.]+\\s*:/u")) {
             // Put property names in double quotes.
             $source = CRegex::replace($source, "/(?<!\\\\)\"(?:[^\\\\\"]++|\\\\{2}|\\\\\\C)*\"(*SKIP)(*FAIL)|" . "([{,]\\s*)([\\w\\-.]+)(\\s*:)/u", "\$1\"\$2\"\$3");
         }
         if (CRegex::find($source, "/[{,]\\s*'[\\w\\-.]+'\\s*:/u")) {
             // Put property names that are in single quotes in double quotes.
             $source = CRegex::replace($source, "/(?<!\\\\)\"(?:[^\\\\\"]++|\\\\{2}|\\\\\\C)*\"(*SKIP)(*FAIL)|" . "([{,]\\s*)'([\\w\\-.]+)'(\\s*:)/u", "\$1\"\$2\"\$3");
         }
         if (CRegex::find($source, "/,\\s*[}\\]]/u")) {
             // Remove trailing commas.
             $source = CRegex::remove($source, "/(?<!\\\\)\"(?:[^\\\\\"]++|\\\\{2}|\\\\\\C)*\"(*SKIP)(*FAIL)|" . ",(?=\\s*[}\\]])/u");
         }
         // Within string values, convert byte values for BS, FF, LF, CR, and HT, which are prohibited in JSON,
         // to their escaped equivalents.
         $stringValueSubjectRe = "/(?<!\\\\)\"(?:[^\\\\\"]++|\\\\{2}|\\\\\\C)*\"/u";
         $source = CRegex::replaceWithCallback($source, $stringValueSubjectRe, function ($matches) {
             return CRegex::replace($matches[0], "/\\x{0008}/u", "\\b");
         });
         $source = CRegex::replaceWithCallback($source, $stringValueSubjectRe, function ($matches) {
             return CRegex::replace($matches[0], "/\\x{000C}/u", "\\f");
         });
         $source = CRegex::replaceWithCallback($source, $stringValueSubjectRe, function ($matches) {
             return CRegex::replace($matches[0], "/\\x{000A}/u", "\\n");
         });
         $source = CRegex::replaceWithCallback($source, $stringValueSubjectRe, function ($matches) {
             return CRegex::replace($matches[0], "/\\x{000D}/u", "\\r");
         });
         $source = CRegex::replaceWithCallback($source, $stringValueSubjectRe, function ($matches) {
             return CRegex::replace($matches[0], "/\\x{0009}/u", "\\t");
         });
     }
     $decodedValue = @json_decode($source, false, self::$ms_maxRecursionDepth);
     if (is_null($decodedValue)) {
         if ($this->m_decodingStrictness == self::STRICT || $this->m_decodingStrictness == self::STRICT_WITH_COMMENTS) {
             $success = false;
         } else {
             if (CRegex::find($source, "/^\\s*[\\w.]+\\s*\\(/u")) {
                 // The source string appears to be a JSONP. Extract the function's argument and try decoding again.
                 $source = CRegex::replace($source, "/^\\s*[\\w.]+\\s*\\((\\C+)\\)/u", "\$1");
                 $decodedValue = @json_decode($source, false, self::$ms_maxRecursionDepth);
                 if (is_null($decodedValue)) {
                     $success = false;
                 }
             }
         }
     }
     if (!$success) {
         return;
     }
     if ($this->m_decodingStrictness == self::STRICT || $this->m_decodingStrictness == self::STRICT_WITH_COMMENTS) {
         if (!is_object($decodedValue) && !is_array($decodedValue)) {
             $success = false;
             return;
         }
     }
     // Recursively convert any object into a CMapObject/CMap and any PHP array into a CArrayObject/CArray.
     $decodedValue = self::recurseValueAfterDecoding($decodedValue, 0);
     return $decodedValue;
 }