/** * Creates a temporary image and executes the given actions. By creating a * temporary copy of the image before manipulating it, this process is atomic. */ public function process($image, $actions, $dir, $file, $render = FALSE) { // We only need the filename $image = $image['file']; // Unique temporary filename $this->tmp_image = $dir.'k2img--'.sha1(time().$dir.$file).substr($file, strrpos($file, '.')); // Copy the image to the temporary file copy($image, $this->tmp_image); // Quality change is done last $quality = (int) CArray::remove('quality', $actions); // Use 95 for the default quality empty($quality) and $quality = 95; // All calls to these will need to be escaped, so do it now $this->cmd_image = escapeshellarg($this->tmp_image); $this->new_image = ($render)? $this->cmd_image : escapeshellarg($dir.$file); if ($status = $this->execute($actions)) { // Use convert to change the image into its final version. This is // done to allow the file type to change correctly, and to handle // the quality conversion in the most effective way possible. if ($error = exec(escapeshellcmd($this->dir.'convert'.$this->ext).' -quality '.$quality.'% '.$this->cmd_image.' '.$this->new_image)) { $this->errors[] = $error; } else { // Output the image directly to the browser if ($render !== FALSE) { $contents = file_get_contents($this->tmp_image); switch (substr($file, strrpos($file, '.') + 1)) { case 'jpg': case 'jpeg': header('Content-Type: image/jpeg'); break; case 'gif': header('Content-Type: image/gif'); break; case 'png': header('Content-Type: image/png'); break; } echo $contents; } } } // Remove the temporary image unlink($this->tmp_image); $this->tmp_image = ''; return $status; }
public function process($image, $actions, $dir, $file, $render = FALSE) { // Set the "create" function switch ($image['type']) { case IMAGETYPE_JPEG: $create = 'imagecreatefromjpeg'; break; case IMAGETYPE_GIF: $create = 'imagecreatefromgif'; break; case IMAGETYPE_PNG: $create = 'imagecreatefrompng'; break; } // Set the "save" function switch (strtolower(substr(strrchr($file, '.'), 1))) { case 'jpg': case 'jpeg': $save = 'imagejpeg'; break; case 'gif': $save = 'imagegif'; break; case 'png': $save = 'imagepng'; break; } // Make sure the image type is supported for import if (empty($create) or !function_exists($create)) { throw new CException('image type not allowed'); } // Make sure the image type is supported for saving if (empty($save) or !function_exists($save)) { throw new CException('image type not allowed'); } // Load the image $this->image = $image; // Create the GD image resource $this->tmp_image = $create($image['file']); // Get the quality setting from the actions $quality = CArray::remove('quality', $actions); if ($status = $this->execute($actions)) { // Prevent the alpha from being lost imagealphablending($this->tmp_image, TRUE); imagesavealpha($this->tmp_image, TRUE); switch ($save) { case 'imagejpeg': // Default the quality to 95 $quality === NULL and $quality = 95; break; case 'imagegif': // Remove the quality setting, GIF doesn't use it unset($quality); break; case 'imagepng': // Always use a compression level of 9 for PNGs. This does not // affect quality, it only increases the level of compression! $quality = 9; break; } if ($render === FALSE) { // Set the status to the save return value, saving with the quality requested $status = isset($quality) ? $save($this->tmp_image, $dir . $file, $quality) : $save($this->tmp_image, $dir . $file); } else { // Output the image directly to the browser switch ($save) { case 'imagejpeg': header('Content-Type: image/jpeg'); break; case 'imagegif': header('Content-Type: image/gif'); break; case 'imagepng': header('Content-Type: image/png'); break; } $status = isset($quality) ? $save($this->tmp_image, NULL, $quality) : $save($this->tmp_image); } // Destroy the temporary image imagedestroy($this->tmp_image); } return $status; }
public function testRemove() { $array = CArray::fromElements("a", "b", "c", "d", "e"); CArray::remove($array, 2); $this->assertTrue(CArray::equals($array, CArray::fromElements("a", "b", "d", "e"))); }
protected function addHeaderWithoutOverriding($headers, $headerName, $value) { $headerLine; $headerName = CString::trim($headerName); $value = CString::trim($value); $foundHeaderPos; $alreadyExists = CArray::find($headers, $headerName, function ($element0, $element1) { return CRegex::find($element0, "/^\\h*" . CRegex::enterTd($element1) . "\\h*:/i"); }, $foundHeaderPos); if (!$alreadyExists) { $headerLine = "{$headerName}: {$value}"; } else { // The header already exists. Combine the header values, removing duplicates based on case-insensitive // equality. $currValue = CRegex::remove($headers[$foundHeaderPos], "/^.*?:\\h*/"); CArray::remove($headers, $foundHeaderPos); $values = CString::split("{$currValue}, {$value}", ","); $len = CArray::length($values); for ($i = 0; $i < $len; $i++) { $values[$i] = CString::trim($values[$i]); } $values = CArray::filter($values, function ($element) { return !CString::isEmpty($element); }); $values = CArray::unique($values, function ($element0, $element1) { return CString::equalsCi($element0, $element1); }); $combinedValue = CArray::join($values, ", "); $headerLine = "{$headerName}: {$combinedValue}"; } CArray::push($headers, $headerLine); }
/** * Removes an element from an array. * * @param int $elementPos The position of the element to be removed. * * @return void */ public function remove($elementPos) { CArray::remove($this->m_splArray, $elementPos); }
/** * 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(); }