/**
	 * 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;
	}
예제 #2
0
 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;
 }
예제 #3
0
 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")));
 }
예제 #4
0
 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);
 }
예제 #5
0
 /**
  * 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);
 }
예제 #6
-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();
 }