コード例 #1
0
ファイル: CRegexTest.php プロジェクト: nunodotferreira/Phred
 public function testFindGroups()
 {
     // ASCII.
     $foundGroups;
     $found = CRegex::findGroups("Hello there!", "/^(\\w+) (\\w+)/", $foundGroups);
     $this->assertTrue($found && CArray::length($foundGroups) == 2 && CString::equals($foundGroups[0], "Hello") && CString::equals($foundGroups[1], "there"));
     $foundGroups;
     $foundString;
     $found = CRegex::findGroups("Hello there!", "/^(\\w+) (\\S+)/", $foundGroups, $foundString);
     $this->assertTrue($found && CArray::length($foundGroups) == 2 && CString::equals($foundGroups[0], "Hello") && CString::equals($foundGroups[1], "there!") && CString::equals($foundString, "Hello there!"));
     $foundGroups;
     $this->assertFalse(CRegex::findGroups("Hello there!", "/^(\\w+) (\\w+)\\z/", $foundGroups));
     $foundGroups;
     $found = CRegex::findGroups("Hello there!", "/^\\w+ \\w+/", $foundGroups);
     $this->assertTrue($found && CArray::isEmpty($foundGroups));
     // Unicode.
     $foundGroups;
     $found = CRegex::findGroups("¡Hello señor!", "/(\\w+) (\\w+)/u", $foundGroups);
     $this->assertTrue($found && CArray::length($foundGroups) == 2 && CUString::equals($foundGroups[0], "Hello") && CUString::equals($foundGroups[1], "señor"));
     $foundGroups;
     $foundString;
     $found = CRegex::findGroups("¡Hello señor!", "/(\\w+) (\\S+)/u", $foundGroups, $foundString);
     $this->assertTrue($found && CArray::length($foundGroups) == 2 && CUString::equals($foundGroups[0], "Hello") && CUString::equals($foundGroups[1], "señor!") && CUString::equals($foundString, "Hello señor!"));
     $foundGroups;
     $this->assertFalse(CRegex::findGroups("¡Hello señor!", "/^(\\w+) (\\w+)/u", $foundGroups));
 }
コード例 #2
0
ファイル: CFilePath.php プロジェクト: nunodotferreira/Phred
 /**
  * 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;
 }
コード例 #3
0
ファイル: CSystem.php プロジェクト: nunodotferreira/Phred
 public function leaveNode(PhpParser\Node $node)
 {
     if ($node instanceof PhpParser\Node\Stmt\Class_ || $node instanceof PhpParser\Node\Stmt\Trait_) {
         $this->m_numEnteredClassesOrTraits--;
     } else {
         if ($node instanceof PhpParser\Node\Stmt\Interface_) {
             $this->m_numEnteredInterfaces--;
         } else {
             if ($node instanceof PhpParser\Node\Stmt\ClassMethod) {
                 $numEnteredMethods = $this->m_numEnteredMethods;
                 $this->m_numEnteredMethods--;
                 if (!($this->m_numEnteredClassesOrTraits == 1 && $this->m_numEnteredInterfaces == 0 && $numEnteredMethods == 1 && $this->m_numEnteredClosures == 0 && $this->m_numEnteredFunctions == 0)) {
                     return;
                 }
                 $method = $node;
                 if ($method->isProtected() && !$this->m_wrapProtectedMethods && !$this->m_isTrait || $method->isPrivate() && !$this->m_wrapPrivateMethods && !$this->m_isTrait || $method->isAbstract()) {
                     return;
                 }
                 if (!isset($method->stmts) || CMap::isEmpty($method->stmts)) {
                     return;
                 }
                 $hasParams = false;
                 $params = CArray::make();
                 $hasParamsByRef = false;
                 $paramsByRef = CArray::make();
                 if (isset($method->params) && !CMap::isEmpty($method->params)) {
                     $hasParams = true;
                     $params = CArray::fromPArray($method->params);
                     $paramsByRef = CArray::filter($params, function ($param) {
                         return $param->byRef;
                     });
                     $hasParamsByRef = !CArray::isEmpty($paramsByRef);
                 }
                 $method->stmts[0]->setAttribute("_imFirstStmtInMethodOrFunction", true);
                 $method->stmts[CMap::length($method->stmts) - 1]->setAttribute("_imLastStmtInMethodOrFunction", true);
                 $statements = [$method];
                 $methodFirstLastStmtVisitor = new CMethodOrFunctionFirstLastStmtVisitor($hasParams, $params, $hasParamsByRef, $paramsByRef);
                 $traverser = new PhpParser\NodeTraverser();
                 $traverser->addVisitor($methodFirstLastStmtVisitor);
                 $statements = $traverser->traverse($statements);
                 $method = $statements[0];
                 $returnVisitor = new CReturnVisitor($hasParams, $params, $hasParamsByRef, $paramsByRef, $method->byRef, CReturnVisitor::SUBJ_METHOD);
                 $traverser = new PhpParser\NodeTraverser();
                 $traverser->addVisitor($returnVisitor);
                 $statements = $traverser->traverse($statements);
                 return $statements;
             } else {
                 if ($node instanceof PhpParser\Node\Expr\Closure) {
                     $this->m_numEnteredClosures--;
                 } else {
                     if ($node instanceof PhpParser\Node\Stmt\Function_) {
                         $this->m_numEnteredFunctions--;
                     }
                 }
             }
         }
     }
 }
コード例 #4
0
ファイル: CArrayTest.php プロジェクト: nunodotferreira/Phred
 public function testIsEmpty()
 {
     $array = CArray::make();
     $this->assertTrue(CArray::isEmpty($array));
     $array = CArray::make(2);
     $this->assertFalse(CArray::isEmpty($array));
 }
コード例 #5
0
 /**
  * @ignore
  */
 public function setInternalOptions(&$success, $cookiesFp = null, $newCookieSession = null)
 {
     $success = true;
     if ($this->m_hasError) {
         $success = false;
         $this->finalize();
         return;
     }
     $options = CMap::make();
     // How to deal with the response.
     if (!$this->m_echoResponse) {
         $options[CURLOPT_RETURNTRANSFER] = true;
         $this->m_isReturnTransferSet = true;
     } else {
         $options[CURLOPT_RETURNTRANSFER] = false;
         $this->m_isReturnTransferSet = false;
     }
     if (isset($this->m_verboseOutput) && $this->m_verboseOutput) {
         $options[CURLOPT_VERBOSE] = true;
     }
     // The destination URL and port.
     $options[CURLOPT_URL] = $this->m_url;
     if (isset($this->m_port)) {
         $options[CURLOPT_PORT] = $this->m_port;
     }
     // Avoid response caching and reuse, which might happen because of any unconventional caching strategies used
     // by cURL.
     $options[CURLOPT_FORBID_REUSE] = true;
     $options[CURLOPT_FRESH_CONNECT] = true;
     if ($this->m_type != self::HTTP_HEAD) {
         $options[CURLOPT_HEADER] = false;
     }
     if ($this->isHttp()) {
         if ($this->m_type == self::HTTP_GET) {
             $options[CURLOPT_HTTPGET] = true;
         } else {
             if ($this->m_type == self::HTTP_DOWNLOAD || $this->m_type == self::ANY_DOWNLOAD) {
                 $options[CURLOPT_HTTPGET] = true;
                 assert('isset($this->m_downloadDestinationFp)', vs(isset($this), get_defined_vars()));
                 $this->m_downloadFile = new CFile($this->m_downloadDestinationFp, CFile::WRITE_NEW);
                 $options[CURLOPT_FILE] = $this->m_downloadFile->systemResource();
             } else {
                 if ($this->m_type == self::HTTP_POST) {
                     // POST.
                     $options[CURLOPT_POST] = true;
                     // At least one POST variable needs to be set in order to make a POST request.
                     assert('isset($this->m_postQuery)', vs(isset($this), get_defined_vars()));
                     // POST variables use the same format as the query string (application/x-www-form-urlencoded).
                     $options[CURLOPT_POSTFIELDS] = $this->m_postQuery->queryString();
                 } else {
                     if ($this->m_type == self::HTTP_UPLOAD) {
                         // File upload via POST and using the CURLFile class.
                         $options[CURLOPT_POST] = true;
                         assert('isset($this->m_postFileUploadRecord)', vs(isset($this), get_defined_vars()));
                         $options[CURLOPT_POSTFIELDS] = $this->m_postFileUploadRecord;
                     } else {
                         if ($this->m_type == self::HTTP_PUT) {
                             // PUT.
                             assert('isset($this->m_nonPostFileUploadFp)', vs(isset($this), get_defined_vars()));
                             $options[CURLOPT_PUT] = true;
                             $this->m_uploadFile = new CFile($this->m_nonPostFileUploadFp, CFile::READ);
                             $options[CURLOPT_INFILE] = $this->m_uploadFile->systemResource();
                             $options[CURLOPT_INFILESIZE] = CFile::size($this->m_nonPostFileUploadFp);
                         } else {
                             if ($this->m_type == self::HTTP_DELETE) {
                                 // DELETE.
                                 $options[CURLOPT_CUSTOMREQUEST] = "DELETE";
                             } else {
                                 if ($this->m_type == self::HTTP_HEAD) {
                                     // HEAD.
                                     $options[CURLOPT_HEADER] = true;
                                     $options[CURLOPT_NOBODY] = true;
                                 }
                             }
                         }
                     }
                 }
             }
         }
         // HTTP redirections.
         $options[CURLOPT_FOLLOWLOCATION] = $this->m_redirection;
         if ($this->m_redirection) {
             if (isset($this->m_maxNumRedirections)) {
                 $options[CURLOPT_MAXREDIRS] = $this->m_maxNumRedirections;
             }
             if (isset($this->m_redirectionAutoReferer)) {
                 $options[CURLOPT_AUTOREFERER] = $this->m_redirectionAutoReferer;
             }
             if (isset($this->m_redirectionKeepAuth)) {
                 $options[CURLOPT_UNRESTRICTED_AUTH] = $this->m_redirectionKeepAuth;
             }
         }
         // HTTP response code treatment.
         $options[CURLOPT_FAILONERROR] = $this->m_failOn400ResponseCodeOrGreater;
         // HTTP headers.
         if ($this->m_sendDefaultAcceptEncodingHeader && !(isset($this->m_requestHeaders) && $this->hasHeader(CHttpRequest::ACCEPT_ENCODING))) {
             $options[CURLOPT_ENCODING] = "";
         }
         if ($this->m_sendDefaultUserAgentHeader && !(isset($this->m_requestHeaders) && $this->hasHeader(CHttpRequest::USER_AGENT))) {
             $userAgent = self::$ms_defaultUserAgent;
             $curlVersion = self::curlVersion();
             $sslVersion = self::openSslVersion();
             $sslVersion = CRegex::remove($sslVersion, "/OpenSSL(\\/|\\h+)/i");
             $userAgent = CString::replaceCi($userAgent, "curl/x.x.x", "curl/{$curlVersion}");
             $userAgent = CString::replaceCi($userAgent, "libcurl x.x.x", "libcurl {$curlVersion}");
             $userAgent = CString::replaceCi($userAgent, "OpenSSL x.x.x", "OpenSSL {$sslVersion}");
             $this->addHeader(CHttpRequest::USER_AGENT, $userAgent);
         }
         if (isset($this->m_requestHeaders) && !CArray::isEmpty($this->m_requestHeaders)) {
             $options[CURLOPT_HTTPHEADER] = CArray::toPArray($this->m_requestHeaders);
         }
         if (isset($this->m_requestCookies) && !CArray::isEmpty($this->m_requestCookies)) {
             // Custom HTTP cookies.
             $cookieHeaderValue = CArray::join($this->m_requestCookies, "; ");
             $options[CURLOPT_COOKIE] = $cookieHeaderValue;
         }
         if (isset($cookiesFp)) {
             $options[CURLOPT_COOKIEFILE] = $cookiesFp;
             $options[CURLOPT_COOKIEJAR] = $cookiesFp;
         }
         if (isset($newCookieSession) && $newCookieSession) {
             $options[CURLOPT_COOKIESESSION] = true;
         }
         // Needed for the retrieval of information regarding the data transfer after it is complete.
         $options[CURLINFO_HEADER_OUT] = true;
         // Needed for the retrieval of response headers.
         $options[CURLOPT_HEADERFUNCTION] = [$this, "headerFunction"];
         if (isset($this->m_userAndPassword)) {
             // HTTP authentication. Let cURL pick any authentication method it finds suitable (it will
             // automatically select the one it finds most secure).
             $options[CURLOPT_HTTPAUTH] = CURLAUTH_ANY;
         }
     } else {
         if ($this->m_type == self::FTP_LIST) {
             $options[CURLOPT_FTPLISTONLY] = true;
         } else {
             if ($this->m_type == self::FTP_DOWNLOAD || $this->m_type == self::ANY_DOWNLOAD) {
                 assert('isset($this->m_downloadDestinationFp)', vs(isset($this), get_defined_vars()));
                 $this->m_downloadFile = new CFile($this->m_downloadDestinationFp, CFile::WRITE_NEW);
                 $options[CURLOPT_FILE] = $this->m_downloadFile->systemResource();
             } else {
                 if ($this->m_type == self::FTP_UPLOAD) {
                     // File upload via FTP.
                     assert('isset($this->m_nonPostFileUploadFp)', vs(isset($this), get_defined_vars()));
                     $this->m_uploadFile = new CFile($this->m_nonPostFileUploadFp, CFile::READ);
                     $options[CURLOPT_UPLOAD] = true;
                     $options[CURLOPT_INFILE] = $this->m_uploadFile->systemResource();
                     $options[CURLOPT_INFILESIZE] = CFile::size($this->m_nonPostFileUploadFp);
                     if ($this->m_ftpCreateMissingDirectoriesForUpload) {
                         $options[CURLOPT_FTP_CREATE_MISSING_DIRS] = true;
                     }
                     if (isset($this->m_ftpAppendUpload) && $this->m_ftpAppendUpload) {
                         $options[CURLOPT_FTPAPPEND] = true;
                     }
                 }
             }
         }
         if (isset($this->m_ftpQuoteCommands) && !CArray::isEmpty($this->m_ftpQuoteCommands)) {
             $options[CURLOPT_QUOTE] = CArray::toPArray($this->m_ftpQuoteCommands);
         }
         if (isset($this->m_ftpPostQuoteCommands) && !CArray::isEmpty($this->m_ftpPostQuoteCommands)) {
             $options[CURLOPT_POSTQUOTE] = CArray::toPArray($this->m_ftpPostQuoteCommands);
         }
         if (isset($this->m_ftpUseEpsv) && !$this->m_ftpUseEpsv) {
             $options[CURLOPT_FTP_USE_EPSV] = false;
         }
         if (isset($this->m_ftpActiveModeBackAddress)) {
             $options[CURLOPT_FTPPORT] = $this->m_ftpActiveModeBackAddress;
         }
         if (isset($this->m_ftpUseEprt) && !$this->m_ftpUseEprt) {
             $options[CURLOPT_FTP_USE_EPRT] = false;
         }
     }
     // Timeouts.
     if (isset($this->m_requestTimeoutSeconds)) {
         $options[CURLOPT_TIMEOUT] = $this->m_requestTimeoutSeconds;
     }
     if (isset($this->m_connectionTimeoutSeconds)) {
         $options[CURLOPT_CONNECTTIMEOUT] = $this->m_connectionTimeoutSeconds;
     }
     if (isset($this->m_dnsCacheTimeoutSeconds)) {
         $options[CURLOPT_DNS_CACHE_TIMEOUT] = $this->m_dnsCacheTimeoutSeconds;
     }
     // The byte range(s) of interest.
     if (isset($this->m_requestedByteRange)) {
         $options[CURLOPT_RANGE] = $this->m_requestedByteRange;
     }
     // SSL certificate verification options.
     $options[CURLOPT_SSL_VERIFYPEER] = $this->m_certificateVerification;
     if (isset($this->m_alternateCertificateFpOrDp)) {
         if (CFile::isFile($this->m_alternateCertificateFpOrDp)) {
             $options[CURLOPT_CAINFO] = $this->m_alternateCertificateFpOrDp;
         } else {
             if (CFile::isDirectory($this->m_alternateCertificateFpOrDp)) {
                 $options[CURLOPT_CAPATH] = $this->m_alternateCertificateFpOrDp;
             } else {
                 assert('false', vs(isset($this), get_defined_vars()));
             }
         }
     }
     if (!$this->m_hostVerification) {
         // The default should be the highest setting, so only set this option to `0` if host verification is
         // disabled.
         $options[CURLOPT_SSL_VERIFYHOST] = 0;
     }
     if (isset($this->m_userAndPassword)) {
         $options[CURLOPT_USERPWD] = $this->m_userAndPassword;
     }
     // SSL options.
     if (isset($this->m_sslCertificateFp)) {
         $options[CURLOPT_SSLCERT] = $this->m_sslCertificateFp;
     }
     if (isset($this->m_sslPrivateKeyFp)) {
         $options[CURLOPT_SSLKEY] = $this->m_sslPrivateKeyFp;
     }
     if (isset($this->m_sslCertificateFormat)) {
         $options[CURLOPT_SSLCERTTYPE] = $this->m_sslCertificateFormat;
     }
     if (isset($this->m_sslPrivateKeyFormat)) {
         $options[CURLOPT_SSLKEYTYPE] = $this->m_sslPrivateKeyFormat;
     }
     if (isset($this->m_sslCertificatePassphrase)) {
         $options[CURLOPT_SSLCERTPASSWD] = $this->m_sslCertificatePassphrase;
     }
     if (isset($this->m_sslPrivateKeyPassphrase)) {
         $options[CURLOPT_SSLKEYPASSWD] = $this->m_sslPrivateKeyPassphrase;
     }
     if (isset($this->m_sslVersion)) {
         $options[CURLOPT_SSLVERSION] = $this->m_sslVersion;
     }
     if (isset($this->m_sslCipherList)) {
         $options[CURLOPT_SSL_CIPHER_LIST] = $this->m_sslCipherList;
     }
     if (isset($this->m_sslEngine)) {
         $options[CURLOPT_SSLENGINE] = $this->m_sslEngine;
     }
     if (isset($this->m_sslDefaultEngine)) {
         $options[CURLOPT_SSLENGINE_DEFAULT] = $this->m_sslDefaultEngine;
     }
     if (isset($this->m_useKerberos) && $this->m_useKerberos) {
         $options[CURLOPT_KRBLEVEL] = $this->m_kerberosLevel;
     }
     if (isset($this->m_proxyAddress)) {
         // Use a proxy.
         $options[CURLOPT_PROXY] = $this->m_proxyAddress;
         if (isset($this->m_proxyUserAndPassword)) {
             $options[CURLOPT_PROXYUSERPWD] = $this->m_proxyUserAndPassword;
         }
         if (isset($this->m_proxyType)) {
             $proxyType;
             switch ($this->m_proxyType) {
                 case self::PROXY_HTTP:
                     $proxyType = CURLPROXY_HTTP;
                     break;
                 case self::PROXY_SOCKS_5:
                     $proxyType = CURLPROXY_SOCKS5;
                     break;
                 default:
                     assert('false', vs(isset($this), get_defined_vars()));
                     break;
             }
             $options[CURLOPT_PROXYTYPE] = $proxyType;
         }
         if (isset($this->m_proxyPort)) {
             $options[CURLOPT_PROXYPORT] = $this->m_proxyPort;
         }
         if (isset($this->m_proxyTunneling) && $this->m_proxyTunneling) {
             $options[CURLOPT_HTTPPROXYTUNNEL] = true;
         }
         if (isset($this->m_proxyConnectOnly) && $this->m_proxyConnectOnly) {
             $options[CURLOPT_CONNECT_ONLY] = true;
         }
     }
     if (isset($this->m_outgoingInterface)) {
         $options[CURLOPT_INTERFACE] = $this->m_outgoingInterface;
     }
     // Speed limits.
     if (isset($this->m_maxDownloadSpeed)) {
         $options[CURLOPT_MAX_RECV_SPEED_LARGE] = $this->m_maxDownloadSpeed;
     }
     if (isset($this->m_maxUploadSpeed)) {
         $options[CURLOPT_MAX_SEND_SPEED_LARGE] = $this->m_maxUploadSpeed;
     }
     // Set cURL options.
     $res = curl_setopt_array($this->m_curl, $options);
     if (!$res || !CString::isEmpty(curl_error($this->m_curl))) {
         // Should never get in here as long as cURL options are being set correctly, hence the assertion.
         assert('false', vs(isset($this), get_defined_vars()));
         $this->m_hasError = true;
         $curlError = curl_error($this->m_curl);
         $this->m_errorMessage = !CString::isEmpty($curlError) ? $curlError : "The 'curl_setopt_array' function failed.";
         $success = false;
         $this->finalize();
         return;
     }
 }
コード例 #6
0
ファイル: CTimeZone.php プロジェクト: nunodotferreira/Phred
 /**
  * Returns the names of the time zones that are known for a specified country.
  *
  * If the country's code is not recognized for any reason, the entire list of the known time zone names is
  * returned.
  *
  * @param  string $countryCode The two-letter code of the country, as provided by ISO 3166.
  *
  * @return CArrayObject The known time zone names for the country specified, of type `CUStringObject`.
  */
 public static function knownNamesForCountry($countryCode)
 {
     assert('is_cstring($countryCode)', vs(isset($this), get_defined_vars()));
     $paNames = DateTimeZone::listIdentifiers(DateTimeZone::PER_COUNTRY, $countryCode);
     $paNames = CMap::filter($paNames, "CTimeZone::isNameIcuCompatible");
     $names = CArray::fromPArray($paNames);
     if (is_cmap($paNames) && !CArray::isEmpty($names)) {
         return oop_a($names);
     } else {
         return oop_a(self::knownNames());
     }
 }
コード例 #7
-1
 /**
  * Starts a session by sending out the added requests.
  *
  * @param  reference $success **OPTIONAL. OUTPUT.** After the method is called with this parameter provided, the
  * parameter's value tells whether the session was successful.
  *
  * @return void
  */
 public function start(&$success = null)
 {
     $success = true;
     if ($this->m_hasError) {
         $success = false;
         return;
     }
     if (CArray::isEmpty($this->m_requestRecordsQueue)) {
         // Nothing to do.
         return;
     }
     // Current policy is to disable HTTP pipelining.
     $res = curl_multi_setopt($this->m_multiCurl, CURLMOPT_PIPELINING, 0);
     if (!$res) {
         // Should never get in here as long as cURL options are being set correctly, hence the assertion.
         assert('false', vs(isset($this), get_defined_vars()));
         $this->m_hasError = true;
         $this->m_errorMessage = "The 'curl_multi_setopt' function failed.";
         $success = false;
         $this->finalize();
         return;
     }
     $anySuccessfulRequests = false;
     // Disable the script's execution timeout before getting into the session.
     $timeoutPause = new CTimeoutPause();
     $numRunningRequests = 0;
     // also the index of the next request to send
     while (true) {
         // From the request queue, add as many normal cURL handles to the multi cURL handle as it is allowed by the
         // maximum number of concurrent requests, priorly setting internal options for every request.
         while ($numRunningRequests < CArray::length($this->m_requestRecordsQueue) && $numRunningRequests < $this->m_maxNumConcurrentRequests) {
             $requestRecord = $this->m_requestRecordsQueue[$numRunningRequests];
             $request = $requestRecord[0];
             $onCompleteCallback = $requestRecord[1];
             $newCookieSession = $requestRecord[2];
             $requestCurl = $request->curl();
             // Set cURL options for the normal cURL handle, having created a temporary file for cookie storage if
             // needed.
             $requestSetOptSuccess;
             if ($this->m_cookiesAreEnabled && $request->isHttp()) {
                 if (!isset($this->m_cookiesFp)) {
                     $this->m_cookiesFp = CFile::createTemporary();
                 }
                 $request->setInternalOptions($requestSetOptSuccess, $this->m_cookiesFp, $newCookieSession);
             } else {
                 $request->setInternalOptions($requestSetOptSuccess);
             }
             if (!$requestSetOptSuccess) {
                 if (isset($onCompleteCallback)) {
                     call_user_func($onCompleteCallback, false, "", $request, $this);
                 }
                 CArray::remove($this->m_requestRecordsQueue, $numRunningRequests);
                 continue;
             }
             // Add the normal cURL handle to the multi cURL handle.
             $res = curl_multi_add_handle($this->m_multiCurl, $requestCurl);
             if ($res != 0) {
                 $this->m_hasError = true;
                 $curlError = curl_multi_strerror($res);
                 $this->m_errorMessage = is_cstring($curlError) && !CString::isEmpty($curlError) ? $curlError : "The 'curl_multi_add_handle' function failed.";
                 $success = false;
                 $timeoutPause->end();
                 $this->finalize();
                 return;
             }
             $numRunningRequests++;
         }
         if ($numRunningRequests == 0) {
             break;
         }
         // Process the currently added requests until complete or no more data is available. Although
         // `CURLM_CALL_MULTI_PERFORM` is deprecated since libcurl 7.20, keep it for compatibility reasons.
         $numRunningTransfers;
         do {
             $multiExecRes = curl_multi_exec($this->m_multiCurl, $numRunningTransfers);
         } while ($multiExecRes == CURLM_CALL_MULTI_PERFORM);
         if ($multiExecRes != CURLM_OK) {
             $this->m_hasError = true;
             $curlError = curl_multi_strerror($multiExecRes);
             $this->m_errorMessage = is_cstring($curlError) && !CString::isEmpty($curlError) ? $curlError : "The 'curl_multi_exec' function failed.";
             $success = false;
             $timeoutPause->end();
             $this->finalize();
             return;
         }
         // Check for completed requests, call the callback function for any completed one (if such a function is
         // defined), finalize completed requests, and remove completed requests from the queue.
         while (true) {
             $completedRequestInfo = curl_multi_info_read($this->m_multiCurl);
             if (!is_cmap($completedRequestInfo)) {
                 break;
             }
             // A request has completed.
             assert('$completedRequestInfo["msg"] == CURLMSG_DONE', vs(isset($this), get_defined_vars()));
             $requestCurl = $completedRequestInfo["handle"];
             $requestRes = $completedRequestInfo["result"];
             $requestRecordPos;
             $found = CArray::find($this->m_requestRecordsQueue, $requestCurl, function ($requestRecord, $requestCurl) {
                 $request = $requestRecord[0];
                 return $request->curl() == $requestCurl;
             }, $requestRecordPos);
             assert('$found', vs(isset($this), get_defined_vars()));
             $requestRecord = $this->m_requestRecordsQueue[$requestRecordPos];
             $request = $requestRecord[0];
             $onCompleteCallback = $requestRecord[1];
             // Remove the normal cURL handle from the multi cURL handle.
             $res = curl_multi_remove_handle($this->m_multiCurl, $requestCurl);
             if ($res != 0) {
                 $this->m_hasError = true;
                 $curlError = curl_multi_strerror($res);
                 $this->m_errorMessage = is_cstring($curlError) && !CString::isEmpty($curlError) ? $curlError : "The 'curl_multi_remove_handle' function failed.";
                 $success = false;
                 $timeoutPause->end();
                 $this->finalize();
                 return;
             }
             if ($requestRes == CURLE_OK) {
                 // The request has succeeded.
                 if (isset($onCompleteCallback)) {
                     $response;
                     if ($request->isReturnTransferSet()) {
                         $response = curl_multi_getcontent($requestCurl);
                         assert('is_cstring($response)', vs(isset($this), get_defined_vars()));
                     } else {
                         $response = "";
                     }
                     $request->onRequestCompleteOk();
                     // also close the normal cURL handle
                     call_user_func($onCompleteCallback, true, $response, $request, $this);
                 } else {
                     $request->onRequestCompleteOk();
                     // also close the normal cURL handle
                 }
                 $anySuccessfulRequests = true;
             } else {
                 // The request has failed.
                 $curlError = curl_strerror($requestRes);
                 if (!is_cstring($curlError)) {
                     $curlError = "";
                 }
                 $request->onRequestCompleteWithError($curlError);
                 // also close the normal cURL handle
                 if (isset($onCompleteCallback)) {
                     call_user_func($onCompleteCallback, false, "", $request, $this);
                 }
             }
             CArray::remove($this->m_requestRecordsQueue, $requestRecordPos);
             $numRunningRequests--;
         }
         assert('$numRunningRequests == $numRunningTransfers', vs(isset($this), get_defined_vars()));
         if ($numRunningTransfers > 0) {
             // Some requests are still being processed (by remote machines). Wait for more data to appear on
             // sockets, without getting hard on the CPU.
             do {
                 $multiSelectRes = curl_multi_select($this->m_multiCurl);
             } while ($multiSelectRes == -1);
         } else {
             // No requests are being processed. Check if any requests are pending.
             if (CArray::isEmpty($this->m_requestRecordsQueue)) {
                 // No requests are pending.
                 break;
             }
         }
     }
     // Set the script's execution time limit like the session has never happened.
     $timeoutPause->end();
     if (!$anySuccessfulRequests) {
         $this->m_hasError = true;
         $this->m_errorMessage = "None of the session's requests succeeded.";
         $success = false;
     }
     $this->finalize();
 }