protected static function recurseValueBeforeFiltering($value, $inputFilterOrFilterCollection, &$success, $currDepth) { assert('$inputFilterOrFilterCollection instanceof CInputFilter || ' . 'is_collection($inputFilterOrFilterCollection)', vs(isset($this), get_defined_vars())); if ($currDepth == self::$ms_maxRecursionDepth) { $success = false; return; } $currDepth++; if (!is_cmap($value)) { // Only interested in PHP arrays. return $value; } if (is_carray($inputFilterOrFilterCollection)) { // The output value is expected to be a CArray; the keys in the arrived PHP array should be sequential. if (!CMap::areKeysSequential($value)) { $success = false; return; } $value = CArray::fromPArray($value); $len = CArray::length($value); if ($len != CArray::length($inputFilterOrFilterCollection)) { $success = false; return; } for ($i = 0; $i < $len; $i++) { $inputValue = $value[$i]; $inputFilterElement = $inputFilterOrFilterCollection[$i]; $inputValue = self::recurseValueBeforeFiltering($inputValue, $inputFilterElement, $success, $currDepth); if (!$success) { return; } $value[$i] = $inputValue; } } else { if (is_cmap($inputFilterOrFilterCollection)) { // The output value is expected to be a CMap; already got one. foreach ($value as $inputKey => &$inputValue) { if (!CMap::hasKey($inputFilterOrFilterCollection, $inputKey)) { $success = false; return; } $inputFilterElement = $inputFilterOrFilterCollection[$inputKey]; $inputValue = self::recurseValueBeforeFiltering($inputValue, $inputFilterElement, $success, $currDepth); if (!$success) { return; } } unset($inputValue); } else { $success = false; return; } } return $value; }
/** * Determines if the URL in a specified string is valid. * * @param string $url The URL string to be looked into. * @param bool $ignoreProtocolAbsence **OPTIONAL. Default is** `false`. Tells whether the URL in the string may * still be considered valid even if it does not indicate any protocol. * * @return bool `true` if the URL in the string is valid, `false` otherwise. */ public static function isValid($url, $ignoreProtocolAbsence = false) { assert('is_cstring($url) && is_bool($ignoreProtocolAbsence)', vs(isset($this), get_defined_vars())); $parsedUrl = parse_url($url); if (!is_cmap($parsedUrl)) { return false; } if ($ignoreProtocolAbsence && !CMap::hasKey($parsedUrl, "scheme")) { // No protocol seems to be specified, try with the default one. $url = self::DEFAULT_PROTOCOL . "://{$url}"; $parsedUrl = parse_url($url); if (!is_cmap($parsedUrl)) { return false; } if (!CMap::hasKey($parsedUrl, "scheme")) { return false; } } if (is_cstring(filter_var($url, FILTER_VALIDATE_URL))) { return true; } else { if (CMap::hasKey($parsedUrl, "host")) { // The `filter_var` function could fail to recognize an IPv6 as the URL's host (enclosed in square // brackets), so, in case of a valid IPv6 being the host, replace it with an IPv4 and give the URL another // try. $host = $parsedUrl["host"]; if (CRegex::find($host, "/^\\[.*\\]\\z/")) { $host = CString::substr($host, 1, CString::length($host) - 2); if (CIp::isValidV6($host)) { // Should not influence the validity if the string is present anywhere else. $url = CString::replace($url, "[{$host}]", "127.0.0.1"); if (is_cstring(filter_var($url, FILTER_VALIDATE_URL)) && is_cmap(parse_url($url))) { return true; } } } } } return false; }
/** * Determines if a country/region code is known. * * @param string $code The two-letter ISO 3166 (or ISO 639) country/region code to be looked for * . * * @return bool `true` if the country/region code is known, `false` otherwise. */ public static function isCountryCodeKnown($code) { assert('is_cstring($code)', vs(isset($this), get_defined_vars())); return CMap::hasKey(DULocale::$CountryCodeToInfo, CString::toUpperCase($code)); }
/** * Determines if the script was run with a specified long option and the option had a value assigned to it, * e.g. "--option=value". * * @param string $optionName The name of the option, excluding "-". * * @return bool `true` if the script was run with the option specified and the option had a value assigned to it, * `false` otherwise. */ public static function hasLongOptionWithValue($optionName) { assert('is_cstring($optionName)', vs(isset($this), get_defined_vars())); $opt = getopt("", ["{$optionName}:"]); return is_cmap($opt) && CMap::hasKey($opt, $optionName) && $opt[$optionName] !== false; }
/** * @ignore */ public static function maybeUpdateThirdParty() { if (!self::isInCliMode()) { // This method can be run in CLI mode only. assert('false', vs(isset($this), get_defined_vars())); return false; } $updates = CConfiguration::option("updates"); $updatesAreEnabled = $updates["enable"]; if ($updatesAreEnabled) { $minTimeBetweenDoUpdatesDays = $updates["minTimeBetweenDoUpdatesDays"]; $components = $updates["components"]; assert('is_int($minTimeBetweenDoUpdatesDays)', vs(isset($this), get_defined_vars())); // Logging. $logging = $updates["logging"]; $loggingIsEnabled = $logging["enable"]; $logFp = $logging["logFilePath"]; if ($loggingIsEnabled) { assert('!CString::isEmpty($logFp)', vs(isset($this), get_defined_vars())); $logFp = CFilePath::frameworkPath($logFp); CShell::setLogging($logFp); } // Mailing. $mailing = $updates["mailing"]; $mailingIsEnabled = $mailing["enable"]; if ($mailingIsEnabled) { $adminMail = CConfiguration::option("admin.mail"); $to = $adminMail["to"]; $from = $adminMail["from"]; $transport = $adminMail["transport"]; assert('!CString::isEmpty($to) && !CString::isEmpty($from) && !CString::isEmpty($transport)', vs(isset($this), get_defined_vars())); $mail; if (CString::equalsCi($transport, "smtp")) { $smtpOutgoingServer = $adminMail["smtpOutgoingServer"]; $smtpUsername = $adminMail["smtpUsername"]; $smtpPassword = $adminMail["smtpPassword"]; assert('!CString::isEmpty($smtpOutgoingServer) && !CString::isEmpty($smtpUsername) && ' . '!CString::isEmpty($smtpPassword)', vs(isset($this), get_defined_vars())); $mail = CMail::makeSmtp($smtpOutgoingServer, $smtpUsername, $smtpPassword, $from, $to); } else { if (CString::equalsCi($transport, "system")) { $mail = CMail::makeSystem($from, $to); } else { assert('false', vs(isset($this), get_defined_vars())); } } CShell::setMailing($mail); } $thirdPartyDp = $GLOBALS["PHRED_PATH_TO_THIRD_PARTY"]; $lastUpdateTimeFp = CFilePath::add($thirdPartyDp, self::$ms_thirdPartyLastUpdateTimeFn); // Read the file containing the Unix seconds of the last update time stamp (if exists) and compare that // time with the current time. $numDaysSinceLastUpdate; if (CFile::exists($lastUpdateTimeFp)) { $lastUpdateTime = new CTime(CString::toInt(CFile::read($lastUpdateTimeFp))); $currTime = CTime::now(); if ($lastUpdateTime->isBefore($currTime)) { $numDaysSinceLastUpdate = $currTime->diffInDays($lastUpdateTime); if ($numDaysSinceLastUpdate < $minTimeBetweenDoUpdatesDays) { // It is too early for updates yet. return false; } } else { assert('false', vs(isset($this), get_defined_vars())); } } $date = CShell::currentDate(); CShell::say("Started on {$date}."); if (isset($numDaysSinceLastUpdate)) { CShell::say("It has been {$numDaysSinceLastUpdate} day(s) since last successful update."); } $concurrLockFp = CFilePath::add($thirdPartyDp, self::$ms_thirdPartyConcurrLockFn); // Try locking the operation. if (!self::setLock($concurrLockFp, false)) { assert('false', vs(isset($this), get_defined_vars())); CShell::onError(false, "Could not obtain a lock on the operation."); CShell::writeToLog("\n"); return false; } $phpConfigNeedsReload = false; $totalNumComponents = CMap::length($components); $numComponentsUpdated = 0; // The Browser Capabilities Project (BrowsCap). if (CMap::hasKey($components, "browsCap")) { $browsCap = $components["browsCap"]; $skip = $browsCap["skip"]; if (!$skip) { CShell::say("Updating the Browser Capabilities Project (BrowsCap) ..."); $lookupFileUrl = $browsCap["lookupFileUrl"]; assert('!CString::isEmpty($lookupFileUrl)', vs(isset($this), get_defined_vars())); // Component-related constants. static $s_configOptName = "browscap"; static $s_lookupFileDownloadTimeoutSeconds = 120; if (self::hasConfigOption($s_configOptName)) { $browsCapLookupFp = CString::trim(self::configOption($s_configOptName)); if (!CString::isEmpty($browsCapLookupFp)) { $browsCapDp = CFilePath::directory($browsCapLookupFp); CShell::say("Downloading a BrowsCap lookup file from '{$lookupFileUrl}' ..."); $temporaryFp = CFile::createTemporary($browsCapDp); $downloadRes = CInetRequest::downloadFile($lookupFileUrl, $temporaryFp, $s_lookupFileDownloadTimeoutSeconds); if ($downloadRes) { // After the file is downloaded into a temporary one, move it to the destination, // safely replacing the existing file, if any. CFile::move($temporaryFp, $browsCapLookupFp); $numComponentsUpdated++; $phpConfigNeedsReload = true; $downloadedFileSizeKB = CUUnit::convertStoragef((double) CFile::size($browsCapLookupFp), CUUnit::BYTE, CUUnit::KILOBYTE); $downloadedFileSizeKB = CMathf::round($downloadedFileSizeKB, 2); CShell::say("Done. The downloaded file is {$downloadedFileSizeKB} KB in size."); } else { CShell::onError(false, "Could not download a BrowsCap lookup file from '{$lookupFileUrl}'."); } // Just in case, check for any temporary files that could have been left by any previous // operations in the directory. $leftoverFiles = CFile::findFiles(CFilePath::add($browsCapDp, CFile::DEFAULT_TEMPORARY_FILE_PREFIX . "*")); if (!CArray::isEmpty($leftoverFiles)) { // Cleanup the directory from the temporary files. $len = CArray::length($leftoverFiles); for ($i = 0; $i < $len; $i++) { CFile::delete($leftoverFiles[$i]); } } } else { CShell::onError(false, "Could not read the value of '{$s_configOptName}' option " . "in the PHP CLI configuration file."); } } else { CShell::onError(false, "Could not find '{$s_configOptName}' option in the PHP CLI configuration file."); } } else { CShell::say("Skipping the Browser Capabilities Project (BrowsCap)."); } } // All the components have been processed. Unlock the operation. self::unsetLock($concurrLockFp); $date = CShell::currentDate(); if ($numComponentsUpdated != 0) { // One or more third-party components have been updated. Put a time stamp on the directory where the // components are located. CFile::write($lastUpdateTimeFp, CString::fromInt(CTime::currentUTime())); if ($numComponentsUpdated == $totalNumComponents) { CShell::speak("Success. All {$totalNumComponents} third-party component(s)"); } else { CShell::speak("Partial success. {$numComponentsUpdated} out of {$totalNumComponents} third-party component(s)"); } CShell::say("have been updated. Completed on {$date}."); } else { CShell::say("No third-party components have been updated. Completed on {$date}."); } return $phpConfigNeedsReload; } else { return false; } }
/** * Returns the HTTP request line and the headers that were sent out with the request. * * @return CUStringObject The HTTP request line and the headers that were sent out with the request. */ public function requestHeadersString() { assert('$this->isHttp() && $this->m_done', vs(isset($this), get_defined_vars())); $key = "request_header"; if (CMap::hasKey($this->m_requestSummary, $key)) { return $this->m_requestSummary[$key]; } else { return ""; } }
public function testHasKey() { $map = ["one" => "a", "two" => "b", "three" => "c"]; $this->assertTrue(CMap::hasKey($map, "two")); $this->assertFalse(CMap::hasKey($map, "four")); $map = ["one" => "a", "two" => null, "three" => "c"]; $this->assertTrue(CMap::hasKey($map, "two")); }
/** * Determines if a URL query contains a field with a specified name. * * In case of nested fields, i.e. multi-dimensional values, the method only looks into the fields that belong to * the topmost level. * * @param string $fieldName The name of the field to be looked for. The characters in the string should be * represented literally and no characters should be percent-encoded. * * @return bool `true` if the URL query contains a field with the name specified, `false` otherwise. */ public function hasField($fieldName) { assert('is_cstring($fieldName)', vs(isset($this), get_defined_vars())); return CMap::hasKey($this->m_query, $fieldName); }
protected static function readAndAddConfig($configFp, $configName, $configs) { if (CMap::hasKey(self::$ms_configAliases, $configName)) { $configName = self::$ms_configAliases[$configName]; } $configName = CString::toLowerCase($configName); $configJson = CFile::read($configFp); $configJson = CRegex::remove($configJson, "/^\\h*\\/\\/.*/m"); // remove comments $configJson = "{\"{$configName}\": {$configJson}}"; $json = new CJson($configJson); $success; $config = $json->decode($success); assert('$success', vs(isset($this), get_defined_vars())); CArray::push($configs, $config); }
protected static function recurseCollectionFiltering($inputCollection, $filterOrFilterCollection, &$success, $currDepth) { assert('is_a($filterOrFilterCollection, get_called_class()) || is_collection($filterOrFilterCollection)', vs(isset($this), get_defined_vars())); if ($currDepth == self::$ms_maxRecursionDepth) { $success = false; return; } $currDepth++; if (is_carray($inputCollection)) { if (!is_carray($filterOrFilterCollection)) { $success = false; return; } $len = CArray::length($inputCollection); if ($len != CArray::length($filterOrFilterCollection)) { $success = false; return; } for ($i = 0; $i < $len; $i++) { $inputValue = $inputCollection[$i]; $filterElement = $filterOrFilterCollection[$i]; if (!is_collection($inputValue)) { $strInputValue = self::collectionElementToString($inputValue, $success); if (!$success) { return; } if (!is_a($filterElement, get_called_class())) { $success = false; return; } $inputValue = $filterElement->filter($strInputValue, $success); if (!$success) { return; } } else { $inputValue = self::recurseCollectionFiltering($inputValue, $filterElement, $success, $currDepth); if (!$success) { return; } } $inputCollection[$i] = $inputValue; } } else { if (!is_cmap($filterOrFilterCollection)) { $success = false; return; } foreach ($inputCollection as $inputKey => &$inputValue) { if (!CMap::hasKey($filterOrFilterCollection, $inputKey)) { $success = false; return; } $filterElement = $filterOrFilterCollection[$inputKey]; if (!is_collection($inputValue)) { $strInputValue = self::collectionElementToString($inputValue, $success); if (!$success) { return; } if (!is_a($filterElement, get_called_class())) { $success = false; return; } $inputValue = $filterElement->filter($strInputValue, $success); if (!$success) { return; } } else { $inputValue = self::recurseCollectionFiltering($inputValue, $filterElement, $success, $currDepth); if (!$success) { return; } } } unset($inputValue); } return $inputCollection; }