Пример #1
0
 public function upload_file($source_file, $dest_filename, $dest_folder, $checkExists = true)
 {
     $out = array('success' => FALSE, 'filename' => '');
     $this->init();
     if ($dest_folder !== FALSE) {
         $dest_folder .= '/';
     } else {
         $dest_folder = '';
     }
     // Extension
     $extension = substr(strrchr($source_file, '.'), 1);
     // Subdirectory?
     $subdir = isset($this->lsettings['directory']) == TRUE && $this->lsettings['directory'] != FALSE ? $this->lsettings['directory'] . '/' : '';
     $filename_no_ext = str_replace('.' . $extension, '', $dest_filename);
     if ($checkExists) {
         // Does it already exists?
         if ($this->S3->if_object_exists($this->lsettings['bucket'], $subdir . $dest_folder . $dest_filename)) {
             for ($i = 2; $i < 30; $i++) {
                 if ($this->S3->if_object_exists($this->lsettings['bucket'], $subdir . $dest_folder . "{$filename_no_ext}_{$i}.{$extension}") == FALSE) {
                     $dest_filename = "{$filename_no_ext}_{$i}.{$extension}";
                     break;
                 }
             }
         }
     }
     // Mime type
     if (class_exists('CFMimeTypes') == FALSE) {
         include PATH_THIRD . 'channel_files/libraries/mimetypes.class.php';
     }
     $MIME = new CFMimeTypes();
     $filemime = $MIME->get_mimetype($extension);
     $upload_arr = array();
     $upload_arr['fileUpload'] = $source_file;
     $upload_arr['contentType'] = $filemime;
     $upload_arr['acl'] = $this->lsettings['acl'];
     $upload_arr['storage'] = $this->lsettings['storage'];
     $upload_arr['headers'] = array();
     if (isset($this->lsettings['force_download']) == TRUE && $this->lsettings['force_download'] == 'yes') {
         $upload_arr['headers']['Content-Disposition'] = 'attachment';
     }
     $filesize = @filesize($source_file);
     // MultiPart ?
     if ($filesize > 31457280) {
         $upload_arr['partSize'] = 6291456;
         // 6MB Part Size
         $response = $this->S3->create_mpu_object($this->lsettings['bucket'], $subdir . $dest_folder . $dest_filename, $upload_arr);
     } else {
         $response = $this->S3->create_object($this->lsettings['bucket'], $subdir . $dest_folder . $dest_filename, $upload_arr);
     }
     // Success?
     if ($response->isOK()) {
         $out['success'] = TRUE;
         $out['filename'] = $dest_filename;
     } else {
         return FALSE;
     }
     return $out;
 }
Пример #2
0
 /**
  * Authenticates a connection to Amazon S3. Do not use directly unless implementing custom methods for
  * this class.
  *
  * @param string $operation (Required) The name of the bucket to operate on (S3 Only).
  * @param array $payload (Required) An associative array of parameters for authenticating. See inline comments for allowed keys.
  * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
  * @link http://docs.amazonwebservices.com/AmazonS3/latest/dev/S3_Authentication.html REST authentication
  */
 public function authenticate($operation, $payload)
 {
     /*
      * Overriding or extending this class? You can pass the following "magic" keys into $opt.
      *
      * ## verb, resource, sub_resource and query_string ##
      * 	<verb> /<resource>?<sub_resource>&<query_string>
      * 	GET /filename.txt?versions&prefix=abc&max-items=1
      *
      * ## versionId, uploadId, partNumber, response-* ##
      * 	These don't follow the same rules as above, in that the they needs to be signed, while
      * 	other query_string values do not.
      *
      * ## curlopts ##
      * 	These values get passed directly to the cURL methods in RequestCore.
      *
      * ## fileUpload, fileDownload, seekTo ##
      * 	These are slightly modified and then passed to the cURL methods in RequestCore.
      *
      * ## headers ##
      * 	$opt['headers'] is an array, whose keys are HTTP headers to be sent.
      *
      * ## body ##
      * 	This is the request body that is sent to the server via PUT/POST.
      *
      * ## preauth ##
      * 	This is a hook that tells authenticate() to generate a pre-authenticated URL.
      *
      * ## returnCurlHandle ##
      * 	Tells authenticate() to return the cURL handle for the request instead of executing it.
      */
     // Rename variables (to overcome inheritence issues)
     $bucket = $operation;
     $opt = $payload;
     // Validate the S3 bucket name
     if (!$this->validate_bucketname_support($bucket)) {
         // @codeCoverageIgnoreStart
         throw new S3_Exception('S3 does not support "' . $bucket . '" as a valid bucket name. Review "Bucket Restrictions and Limitations" in the S3 Developer Guide for more information.');
         // @codeCoverageIgnoreEnd
     }
     // Die if $opt isn't set.
     if (!$opt) {
         return false;
     }
     $method_arguments = func_get_args();
     // Use the caching flow to determine if we need to do a round-trip to the server.
     if ($this->use_cache_flow) {
         // Generate an identifier specific to this particular set of arguments.
         $cache_id = $this->key . '_' . get_class($this) . '_' . $bucket . '_' . sha1(serialize($method_arguments));
         // Instantiate the appropriate caching object.
         $this->cache_object = new $this->cache_class($cache_id, $this->cache_location, $this->cache_expires, $this->cache_compress);
         if ($this->delete_cache) {
             $this->use_cache_flow = false;
             $this->delete_cache = false;
             return $this->cache_object->delete();
         }
         // Invoke the cache callback function to determine whether to pull data from the cache or make a fresh request.
         $data = $this->cache_object->response_manager(array($this, 'cache_callback'), $method_arguments);
         if ($this->parse_the_response) {
             // Parse the XML body
             $data = $this->parse_callback($data);
         }
         // End!
         return $data;
     }
     // If we haven't already set a resource prefix and the bucket name isn't DNS-valid...
     if (!$this->resource_prefix && !$this->validate_bucketname_create($bucket) || $this->path_style) {
         // Fall back to the older path-style URI
         $this->set_resource_prefix('/' . $bucket);
         $this->temporary_prefix = true;
     }
     // Determine hostname
     $scheme = $this->use_ssl ? 'https://' : 'http://';
     if ($this->resource_prefix || $this->path_style) {
         $hostname = $this->hostname . $this->resource_prefix . ($bucket === '' || $this->resource_prefix === '/' . $bucket ? '' : '/' . $bucket);
     } else {
         $hostname = $this->vhost ? $this->vhost : ($bucket === '' ? $this->hostname : $bucket . '.' . $this->hostname);
     }
     // Get the UTC timestamp in RFC 2616 format
     $date = gmdate(CFUtilities::DATE_FORMAT_RFC2616, time());
     // Storage for request parameters.
     $resource = '';
     $sub_resource = '';
     $querystringparams = array();
     $signable_querystringparams = array();
     $string_to_sign = '';
     $headers = array('Content-MD5' => '', 'Content-Type' => 'application/x-www-form-urlencoded', 'Date' => $date);
     /*%******************************************************************************************%*/
     // Do we have an authentication token?
     if ($this->auth_token) {
         $headers['X-Amz-Security-Token'] = $this->auth_token;
     }
     // Handle specific resources
     if (isset($opt['resource'])) {
         $resource .= $opt['resource'];
     }
     // Merge query string values
     if (isset($opt['query_string'])) {
         $querystringparams = array_merge($querystringparams, $opt['query_string']);
     }
     $query_string = $this->util->to_query_string($querystringparams);
     // Merge the signable query string values. Must be alphabetical.
     $signable_list = array('partNumber', 'response-cache-control', 'response-content-disposition', 'response-content-encoding', 'response-content-language', 'response-content-type', 'response-expires', 'uploadId', 'versionId');
     foreach ($signable_list as $item) {
         if (isset($opt[$item])) {
             $signable_querystringparams[$item] = $opt[$item];
         }
     }
     $signable_query_string = $this->util->to_query_string($signable_querystringparams);
     // Merge the HTTP headers
     if (isset($opt['headers'])) {
         $headers = array_merge($headers, $opt['headers']);
     }
     // Compile the URI to request
     $conjunction = '?';
     $signable_resource = '/' . str_replace('%2F', '/', rawurlencode($resource));
     $non_signable_resource = '';
     if (isset($opt['sub_resource'])) {
         $signable_resource .= $conjunction . rawurlencode($opt['sub_resource']);
         $conjunction = '&';
     }
     if ($signable_query_string !== '') {
         $signable_query_string = $conjunction . $signable_query_string;
         $conjunction = '&';
     }
     if ($query_string !== '') {
         $non_signable_resource .= $conjunction . $query_string;
         $conjunction = '&';
     }
     if (substr($hostname, -1) === substr($signable_resource, 0, 1)) {
         $signable_resource = ltrim($signable_resource, '/');
     }
     $this->request_url = $scheme . $hostname . $signable_resource . $signable_query_string . $non_signable_resource;
     if (isset($opt['location'])) {
         $this->request_url = $opt['location'];
     }
     // Gather information to pass along to other classes.
     $helpers = array('utilities' => $this->utilities_class, 'request' => $this->request_class, 'response' => $this->response_class);
     // Instantiate the request class
     $request = new $this->request_class($this->request_url, $this->proxy, $helpers, $this->credentials);
     // Update RequestCore settings
     $request->request_class = $this->request_class;
     $request->response_class = $this->response_class;
     $request->ssl_verification = $this->ssl_verification;
     // Pass along registered stream callbacks
     if ($this->registered_streaming_read_callback) {
         $request->register_streaming_read_callback($this->registered_streaming_read_callback);
     }
     if ($this->registered_streaming_write_callback) {
         $request->register_streaming_write_callback($this->registered_streaming_write_callback);
     }
     // Streaming uploads
     if (isset($opt['fileUpload'])) {
         if (is_resource($opt['fileUpload'])) {
             // Determine the length to read from the stream
             $length = null;
             // From current position until EOF by default, size determined by set_read_stream()
             if (isset($headers['Content-Length'])) {
                 $length = $headers['Content-Length'];
             } elseif (isset($opt['seekTo'])) {
                 // Read from seekTo until EOF by default
                 $stats = fstat($opt['fileUpload']);
                 if ($stats && $stats['size'] >= 0) {
                     $length = $stats['size'] - (int) $opt['seekTo'];
                 }
             }
             $request->set_read_stream($opt['fileUpload'], $length);
             if ($headers['Content-Type'] === 'application/x-www-form-urlencoded') {
                 $headers['Content-Type'] = 'application/octet-stream';
             }
         } else {
             $request->set_read_file($opt['fileUpload']);
             // Determine the length to read from the file
             $length = $request->read_stream_size;
             // The file size by default
             if (isset($headers['Content-Length'])) {
                 $length = $headers['Content-Length'];
             } elseif (isset($opt['seekTo']) && isset($length)) {
                 // Read from seekTo until EOF by default
                 $length -= (int) $opt['seekTo'];
             }
             $request->set_read_stream_size($length);
             // Attempt to guess the correct mime-type
             if ($headers['Content-Type'] === 'application/x-www-form-urlencoded') {
                 $extension = explode('.', $opt['fileUpload']);
                 $extension = array_pop($extension);
                 $mime_type = CFMimeTypes::get_mimetype($extension);
                 $headers['Content-Type'] = $mime_type;
             }
         }
         $headers['Content-Length'] = $request->read_stream_size;
         $headers['Content-MD5'] = '';
     }
     // Handle streaming file offsets
     if (isset($opt['seekTo'])) {
         // Pass the seek position to RequestCore
         $request->set_seek_position((int) $opt['seekTo']);
     }
     // Streaming downloads
     if (isset($opt['fileDownload'])) {
         if (is_resource($opt['fileDownload'])) {
             $request->set_write_stream($opt['fileDownload']);
         } else {
             $request->set_write_file($opt['fileDownload']);
         }
     }
     $curlopts = array();
     // Set custom CURLOPT settings
     if (isset($opt['curlopts'])) {
         $curlopts = $opt['curlopts'];
     }
     // Debug mode
     if ($this->debug_mode) {
         $curlopts[CURLOPT_VERBOSE] = true;
     }
     // Set the curl options.
     if (count($curlopts)) {
         $request->set_curlopts($curlopts);
     }
     // Do we have a verb?
     if (isset($opt['verb'])) {
         $request->set_method($opt['verb']);
         $string_to_sign .= $opt['verb'] . "\n";
     }
     // Add headers and content when we have a body
     if (isset($opt['body'])) {
         $request->set_body($opt['body']);
         $headers['Content-Length'] = strlen($opt['body']);
         if ($headers['Content-Type'] === 'application/x-www-form-urlencoded') {
             $headers['Content-Type'] = 'application/octet-stream';
         }
         if (!isset($opt['NoContentMD5']) || $opt['NoContentMD5'] !== true) {
             $headers['Content-MD5'] = $this->util->hex_to_base64(md5($opt['body']));
         }
     }
     // Handle query-string authentication
     if (isset($opt['preauth']) && (int) $opt['preauth'] > 0) {
         unset($headers['Date']);
         $headers['Content-Type'] = '';
         $headers['Expires'] = is_int($opt['preauth']) ? $opt['preauth'] : strtotime($opt['preauth']);
     }
     // Sort headers
     uksort($headers, 'strnatcasecmp');
     // Add headers to request and compute the string to sign
     foreach ($headers as $header_key => $header_value) {
         // Strip linebreaks from header values as they're illegal and can allow for security issues
         $header_value = str_replace(array("\r", "\n"), '', $header_value);
         // Add the header if it has a value
         if ($header_value !== '') {
             $request->add_header($header_key, $header_value);
         }
         // Generate the string to sign
         if (strtolower($header_key) === 'content-md5' || strtolower($header_key) === 'content-type' || strtolower($header_key) === 'date' || strtolower($header_key) === 'expires' && isset($opt['preauth']) && (int) $opt['preauth'] > 0) {
             $string_to_sign .= $header_value . "\n";
         } elseif (substr(strtolower($header_key), 0, 6) === 'x-amz-') {
             $string_to_sign .= strtolower($header_key) . ':' . $header_value . "\n";
         }
     }
     // Add the signable resource location
     $string_to_sign .= $this->resource_prefix ? $this->resource_prefix : '';
     $string_to_sign .= ($bucket === '' || $this->resource_prefix === '/' . $bucket ? '' : '/' . $bucket) . $signable_resource . urldecode($signable_query_string);
     // Hash the AWS secret key and generate a signature for the request.
     $signature = base64_encode(hash_hmac('sha1', $string_to_sign, $this->secret_key, true));
     $request->add_header('Authorization', 'AWS ' . $this->key . ':' . $signature);
     // If we're generating a URL, return the URL to the calling method.
     if (isset($opt['preauth']) && (int) $opt['preauth'] > 0) {
         $query_params = array('AWSAccessKeyId' => $this->key, 'Expires' => $headers['Expires'], 'Signature' => $signature);
         // If using short-term credentials, add the token to the query string
         if ($this->auth_token) {
             $query_params['x-amz-security-token'] = $this->auth_token;
         }
         return $this->request_url . $conjunction . http_build_query($query_params, '', '&');
     } elseif (isset($opt['preauth'])) {
         return $this->request_url;
     }
     /*%******************************************************************************************%*/
     // If our changes were temporary, reset them.
     if ($this->temporary_prefix) {
         $this->temporary_prefix = false;
         $this->resource_prefix = null;
     }
     // Manage the (newer) batch request API or the (older) returnCurlHandle setting.
     if ($this->use_batch_flow) {
         $handle = $request->prep_request();
         $this->batch_object->add($handle);
         $this->use_batch_flow = false;
         return $handle;
     } elseif (isset($opt['returnCurlHandle']) && $opt['returnCurlHandle'] === true) {
         return $request->prep_request();
     }
     // Send!
     $request->send_request();
     // Prepare the response
     $headers = $request->get_response_header();
     $headers['x-aws-request-url'] = $this->request_url;
     $headers['x-aws-redirects'] = $this->redirects;
     $headers['x-aws-stringtosign'] = $string_to_sign;
     $headers['x-aws-requestheaders'] = $request->request_headers;
     // Did we have a request body?
     if (isset($opt['body'])) {
         $headers['x-aws-requestbody'] = $opt['body'];
     }
     $data = new $this->response_class($headers, $this->parse_callback($request->get_response_body()), $request->get_response_code());
     // Did Amazon tell us to redirect? Typically happens for multiple rapid requests EU datacenters.
     // @see: http://docs.amazonwebservices.com/AmazonS3/latest/dev/Redirects.html
     // @codeCoverageIgnoreStart
     if ((int) $request->get_response_code() === 307) {
         $this->redirects++;
         $opt['location'] = $headers['location'];
         $data = $this->authenticate($bucket, $opt);
     } elseif ((int) $request->get_response_code() === 500 || (int) $request->get_response_code() === 503) {
         if ($this->redirects <= $this->max_retries) {
             // Exponential backoff
             $delay = (int) (pow(4, $this->redirects) * 100000);
             usleep($delay);
             $this->redirects++;
             $data = $this->authenticate($bucket, $opt);
         }
     }
     // @codeCoverageIgnoreEnd
     // Return!
     $this->redirects = 0;
     return $data;
 }
Пример #3
0
 /**
  * Method: authenticate()
  * 	Authenticates a connection to Amazon S3. Do not use directly unless implementing custom methods for
  * 	this class.
  *
  * Access:
  * 	public
  *
  * Parameters:
  * 	$bucket - _string_ (Required) The name of the bucket to use.
  * 	$opt - _array_ (Optional) An associative array of parameters for authenticating. See the individual methods for allowed keys.
  * 	$location - _string_ (Do Not Use) Used internally by this function on occasions when Amazon S3 returns a redirect code and it needs to call itself recursively.
  * 	$redirects - _integer_ (Do Not Use) Used internally by this function on occasions when Amazon S3 returns a redirect code and it needs to call itself recursively.
  *
  * Returns:
  * 	_CFResponse_ A <CFResponse> object containing a parsed HTTP response.
  *
  * See Also:
  * 	[REST authentication](http://docs.amazonwebservices.com/AmazonS3/latest/RESTAuthentication.html)
  */
 public function authenticate($bucket, $opt = null, $location = null, $redirects = 0, $nothing = null)
 {
     /*
      * Overriding or extending this class? You can pass the following "magic" keys into $opt.
      *
      * ## verb, resource, sub_resource and query_string ##
      * 	<verb> /<resource>?<sub_resource>&<query_string>
      * 	GET /filename.txt?versions&prefix=abc&max-items=1
      *
      * ## versionId ##
      * 	versionId doesn't follow the same rules as above, in that the versionId needs to be
      * 	signed, while other query_string values do not.
      *
      * ## curlopts, fileUpload and fileDownload ##
      * 	These values get passed directly to the cURL methods in RequestCore.
      *
      * ## headers ##
      * 	$opt['headers'] is an array, whose keys are HTTP headers to be sent.
      *
      * ## body ##
      * 	This is the request body that is sent to the server via POST.
      *
      * ## preauth ##
      * 	This is a hook that tells authenticate() to generate a pre-authenticated URL.
      *
      * ## returnCurlHandle ##
      * 	Tells authenticate() to return the cURL handle for the request instead of executing it.
      */
     /**
      * @todo: Handle duplicate headers with different values.
      */
     // Validate the S3 bucket name
     if (!$this->validate_bucketname_support($bucket)) {
         throw new S3_Exception('S3 does not support "' . $bucket . '" as a valid bucket name. Review "Bucket Restrictions and Limitations" in the S3 Developer Guide for more information.');
     }
     // Die if $opt isn't set.
     if (!$opt) {
         return false;
     }
     $method_arguments = func_get_args();
     // Use the caching flow to determine if we need to do a round-trip to the server.
     if ($this->use_cache_flow) {
         // Generate an identifier specific to this particular set of arguments.
         $cache_id = $this->key . '_' . get_class($this) . '_' . $bucket . '_' . sha1(serialize($method_arguments));
         // Instantiate the appropriate caching object.
         $this->cache_object = new $this->cache_class($cache_id, $this->cache_location, $this->cache_expires, $this->cache_compress);
         if ($this->delete_cache) {
             $this->use_cache_flow = false;
             $this->delete_cache = false;
             return $this->cache_object->delete();
         }
         // Invoke the cache callback function to determine whether to pull data from the cache or make a fresh request.
         $data = $this->cache_object->response_manager(array($this, 'cache_callback'), $method_arguments);
         // Parse the XML body
         $data = $this->parse_callback($data);
         // End!
         return $data;
     }
     // If we haven't already set a resource prefix...
     if (!$this->resource_prefix || $this->path_style) {
         // And if the bucket name isn't DNS-valid...
         if (!$this->validate_bucketname_create($bucket) || $this->path_style) {
             // Fall back to the older path-style URI
             $this->set_resource_prefix('/' . $bucket);
         }
     }
     // Determine hostname
     $scheme = $this->use_ssl ? 'https://' : 'http://';
     if ($this->resource_prefix || $this->path_style) {
         $hostname = $this->hostname . $this->resource_prefix . ($bucket === '' || $this->resource_prefix === '/' . $bucket ? '' : '/' . $bucket);
     } else {
         $hostname = $this->vhost ? $this->vhost : ($bucket === '' ? $this->hostname : $bucket . '.' . $this->hostname);
     }
     // Get the UTC timestamp in RFC 2616 format
     $date = gmdate($this->util->konst($this->util, 'DATE_FORMAT_RFC2616'), time() + (int) $this->adjust_offset);
     // Storage for request parameters.
     $resource = '';
     $sub_resource = '';
     $query_string_params = array();
     $signable_query_string_params = array();
     $string_to_sign = '';
     $headers = array('Content-MD5' => '', 'Content-Type' => 'application/x-www-form-urlencoded', 'Date' => $date);
     /*%******************************************************************************************%*/
     // Handle specific resources
     if (isset($opt['resource'])) {
         $resource .= $opt['resource'];
     }
     // Merge query string values
     if (isset($opt['query_string'])) {
         $query_string_params = array_merge($query_string_params, $opt['query_string']);
     }
     $query_string = $this->util->to_query_string($query_string_params);
     // Merge the signable query string values
     if (isset($opt['versionId'])) {
         $signable_query_string_params['versionId'] = rawurlencode($opt['versionId']);
     }
     $signable_query_string = $this->util->to_query_string($signable_query_string_params);
     // Merge the HTTP headers
     if (isset($opt['headers'])) {
         $headers = array_merge($headers, $opt['headers']);
     }
     // Compile the URI to request
     $conjunction = '?';
     $signable_resource = '/' . rawurlencode($resource);
     $non_signable_resource = '';
     if (isset($opt['sub_resource'])) {
         $signable_resource .= $conjunction . rawurlencode($opt['sub_resource']);
         $conjunction = '&';
     }
     if ($signable_query_string !== '') {
         $signable_resource .= $conjunction . $signable_query_string;
     }
     if ($query_string !== '') {
         $non_signable_resource .= $conjunction . $query_string;
     }
     $this->request_url = $scheme . $hostname . $signable_resource . $non_signable_resource;
     // Instantiate the request class
     $request = new $this->request_class($this->request_url, $this->proxy);
     // Update RequestCore settings
     $request->request_class = $this->request_class;
     $request->response_class = $this->response_class;
     // Enable debug headers
     if ($this->debug_mode) {
         $request->set_curlopts(array(CURLOPT_VERBOSE => true));
     }
     // Streaming uploads
     if (isset($opt['fileUpload'])) {
         $request->set_read_file($opt['fileUpload']);
         // Attempt to guess the correct mime-type
         if ($headers['Content-Type'] === 'application/x-www-form-urlencoded') {
             $extension = explode('.', $opt['fileUpload']);
             $extension = array_pop($extension);
             $mime_type = CFMimeTypes::get_mimetype($extension);
             $headers['Content-Type'] = $mime_type;
         }
     }
     // Streaming downloads
     if (isset($opt['fileDownload'])) {
         $request->set_write_file($opt['fileDownload']);
     }
     // Set custom CURLOPT settings
     if (isset($opt['curlopts'])) {
         $request->set_curlopts($opt['curlopts']);
         unset($opt['curlopts']);
     }
     // Do we have a verb?
     if (isset($opt['verb'])) {
         $request->set_method($opt['verb']);
         $string_to_sign .= $opt['verb'] . "\n";
     }
     // Add headers and content when we have a body
     if (isset($opt['body'])) {
         $request->set_body($opt['body']);
         $headers['Content-Length'] = strlen($opt['body']);
         $headers['Content-MD5'] = $this->util->hex_to_base64(md5($opt['body']));
     }
     // Handle query-string authentication
     if (isset($opt['preauth']) && (int) $opt['preauth'] > 0) {
         unset($headers['Date']);
         $headers['Content-Type'] = '';
         $headers['Expires'] = strtotime($opt['preauth']);
     }
     // Sort headers
     uksort($headers, 'strnatcasecmp');
     // Add headers to request and compute the string to sign
     foreach ($headers as $header_key => $header_value) {
         // Strip linebreaks from header values as they're illegal and can allow for security issues
         $header_value = str_replace(array("\r", "\n"), '', $header_value);
         // Add the header if it has a value
         if ($header_value !== '') {
             $request->add_header($header_key, $header_value);
         }
         // Generate the string to sign
         if (strtolower($header_key) === 'content-md5' || strtolower($header_key) === 'content-type' || strtolower($header_key) === 'date' || strtolower($header_key) === 'expires' && isset($opt['preauth']) && (int) $opt['preauth'] > 0) {
             $string_to_sign .= $header_value . "\n";
         } elseif (substr(strtolower($header_key), 0, 6) === 'x-amz-') {
             $string_to_sign .= strtolower($header_key) . ':' . $header_value . "\n";
         }
     }
     // Add the signable resource location
     $string_to_sign .= $this->resource_prefix ? $this->resource_prefix : '';
     $string_to_sign .= ($bucket === '' || $this->resource_prefix === '/' . $bucket ? '' : '/' . $bucket) . $signable_resource;
     // Hash the AWS secret key and generate a signature for the request.
     $signature = base64_encode(hash_hmac('sha1', $string_to_sign, $this->secret_key, true));
     $request->add_header('Authorization', 'AWS ' . $this->key . ':' . $signature);
     // If we're generating a URL, return certain data to the calling method.
     if (isset($opt['preauth']) && (int) $opt['preauth'] > 0) {
         return $this->request_url . (isset($opt['sub_resource']) ? '&' : '?') . 'AWSAccessKeyId=' . $this->key . '&Expires=' . $headers['Expires'] . '&Signature=' . rawurlencode($signature);
     } elseif (isset($opt['preauth'])) {
         return $this->request_url;
     }
     /*%******************************************************************************************%*/
     // Manage the (newer) batch request API or the (older) returnCurlHandle setting.
     if ($this->use_batch_flow) {
         $handle = $request->prep_request();
         $this->batch_object->add($handle);
         $this->use_batch_flow = false;
         return $handle;
     } elseif (isset($opt['returnCurlHandle']) && $opt['returnCurlHandle'] === true) {
         return $request->prep_request();
     }
     // Send!
     $request->send_request();
     // Prepare the response
     $headers = $request->get_response_header();
     $headers['x-aws-request-url'] = $this->request_url;
     $headers['x-aws-redirects'] = $redirects;
     $headers['x-aws-stringtosign'] = $string_to_sign;
     $headers['x-aws-requestheaders'] = $request->request_headers;
     // Did we have a request body?
     if (isset($opt['body'])) {
         $headers['x-aws-requestbody'] = $opt['body'];
     }
     $data = new $this->response_class($headers, $this->parse_callback($request->get_response_body()), $request->get_response_code());
     // Did Amazon tell us to redirect? Typically happens for multiple rapid requests EU datacenters.
     // @see: http://docs.amazonwebservices.com/AmazonS3/latest/Redirects.html
     if ((int) $request->get_response_code() === 307) {
         $data = $this->authenticate($bucket, $opt, $headers['location'], ++$redirects);
     } elseif ((int) $request->get_response_code() === 500 || (int) $request->get_response_code() === 503) {
         if ($redirects <= $this->max_retries) {
             // Exponential backoff
             $delay = (int) (pow(4, $redirects) * 100000);
             usleep($delay);
             $data = $this->authenticate($bucket, $opt, null, ++$redirects);
         }
     }
     // Return!
     return $data;
 }
Пример #4
0
 private function _process_post_save($data, $draft_action = NULL)
 {
     $this->EE->load->library('channel_files_helper');
     $this->EE->load->helper('url');
     // Are we using Better Workflow?
     if ($draft_action !== NULL) {
         $is_draft = 1;
         $entry_id = $this->settings['entry_id'];
         $field_id = $this->settings['field_id'];
         $channel_id = $this->settings['channel_id'];
         $settings = $this->EE->channel_files_helper->grab_field_settings($field_id);
     } else {
         $is_draft = 0;
         $data = isset($this->EE->session->cache['ChannelFiles']['FieldData'][$this->field_id]) ? $this->EE->session->cache['ChannelFiles']['FieldData'][$this->field_id] : FALSE;
         $entry_id = $this->settings['entry_id'];
         $channel_id = $this->EE->input->post('channel_id');
         $field_id = $this->field_id;
         // Grab Settings
         $settings = $this->settings['channel_files'];
     }
     // Moving Channels?
     if ($this->EE->input->get_post('new_channel') != FALSE) {
         $channel_id = $this->EE->input->get_post('new_channel');
     }
     // Do we need to skip?
     if (isset($data['files']) == FALSE) {
         return;
     }
     // Our Key
     $key = $data['key'];
     // Mimetype!
     if (class_exists('CFMimeTypes') == FALSE) {
         include 'libraries/mimetypes.class.php';
     }
     $MIME = new CFMimeTypes();
     // -----------------------------------------
     // Entry_id FOLDER?
     // -----------------------------------------
     $entry_id_folder = TRUE;
     $prefix_entry_id = TRUE;
     if (isset($settings['entry_id_folder']) && $settings['entry_id_folder'] == 'no') {
         $entry_id_folder = FALSE;
     }
     if (isset($settings['prefix_entry_id']) && $settings['prefix_entry_id'] == 'no') {
         $prefix_entry_id = FALSE;
     }
     // -----------------------------------------
     // Load Location
     // -----------------------------------------
     $location_type = $settings['upload_location'];
     $location_class = 'CF_Location_' . $location_type;
     $location_settings = $settings['locations'][$location_type];
     // Load Main Class
     if (class_exists('Cfile_location') == FALSE) {
         require PATH_THIRD . 'channel_files/locations/cfile_location.php';
     }
     // Try to load Location Class
     if (class_exists($location_class) == FALSE) {
         $location_file = PATH_THIRD . 'channel_files/locations/' . $location_type . '/' . $location_type . '.php';
         require $location_file;
     }
     // Init!
     $LOC = new $location_class($location_settings);
     // We only create the dir if we this is true
     if ($entry_id_folder == TRUE) {
         // Create the DIR!
         $LOC->create_dir($entry_id);
     }
     // Load the API
     if (class_exists('Channel_Files_API') != TRUE) {
         include 'api.channel_files.php';
     }
     $API = new Channel_Files_API();
     // -----------------------------------------
     // Upload all Files
     // -----------------------------------------
     $filenames = array();
     $temp_dir = APPPATH . 'cache/channel_files/field_' . $field_id . '/' . $key;
     // Loop over all files
     $tempfiles = @scandir($temp_dir);
     if (is_array($tempfiles) == TRUE) {
         $dir_entry_id = $entry_id;
         foreach ($tempfiles as $filename) {
             if ($filename == '.' or $filename == '..') {
                 continue;
             }
             $filepath = $temp_dir . '/' . $filename;
             $original_filename = $filename;
             // Entry ID as Folders?
             if ($entry_id_folder == FALSE) {
                 if ($prefix_entry_id === TRUE) {
                     $filename = $entry_id . '-' . $filename;
                 }
                 $dir_entry_id = FALSE;
             }
             // -------------------------------------------
             // 'channel_files_download_init' hook.
             //  - Executes before the the upload of a file
             //
             if ($this->EE->extensions->active_hook('channel_files_upload_start') === TRUE) {
                 $edata = $this->EE->extensions->universal_call('channel_files_upload_start', $field_id, $entry_id, $filepath, $filename, $dir_entry_id);
                 if ($this->EE->extensions->end_script === TRUE) {
                     return;
                 }
             }
             //
             // -------------------------------------------
             $res = $LOC->upload_file($filepath, $filename, $dir_entry_id);
             if (is_array($res) === TRUE && $res['success'] == TRUE) {
                 if ($res['filename'] != FALSE) {
                     $filenames[$original_filename] = $res['filename'];
                 }
             } else {
                 $filenames[$original_filename] = $filename;
             }
             @unlink($filepath);
             // -------------------------------------------
             // 'channel_files_download_init' hook.
             //  - Executes after the upload of a file, the source file already has been deleted.
             //
             if ($this->EE->extensions->active_hook('channel_files_upload_end') === TRUE) {
                 $edata = $this->EE->extensions->universal_call('channel_files_upload_end', $field_id, $entry_id, $filename, $dir_entry_id);
                 if ($this->EE->extensions->end_script === TRUE) {
                     return;
                 }
             }
             //
             // -------------------------------------------
         }
     }
     @rmdir($temp_dir);
     // -----------------------------------------
     // Grab all the files from the DB
     // -----------------------------------------
     $this->EE->db->select('*');
     $this->EE->db->from('exp_channel_files');
     $this->EE->db->where('entry_id', $entry_id);
     $this->EE->db->where('field_id', $field_id);
     if ($is_draft === 1 && $draft_action == 'update') {
         $this->EE->db->where('is_draft', 1);
     } else {
         $this->EE->db->where('is_draft', 0);
     }
     $query = $this->EE->db->get();
     // Lets create an file hash! So we can do unique image
     $dbfiles = array();
     foreach ($query->result() as $row) {
         $dbfiles[] = $row->file_id . $row->filename;
     }
     if ($is_draft === 1 && $draft_action == 'create') {
         $dbfiles = array();
     }
     // Any files?
     if (count($dbfiles) > 0) {
         // -----------------------------------------
         // Not fresh, lets see whats new.
         // -----------------------------------------
         foreach ($data['files'] as $order => $file) {
             $file = $this->EE->channel_files_helper->decode_json($file['data']);
             if (isset($file->delete) == TRUE) {
                 $API->delete_file($file);
             }
             /*
             				// If we are creating a new draft, we already copied all data.. So lets kill the ones that came through POST
             				if ($is_draft === 1 && $file->file_id > 0)
             				{
             					// -----------------------------------------
             					// Old File
             					// -----------------------------------------
             					$data = array(	'entry_id'	=>	$entry_id,
             									'field_id'	=>	$field_id,
             									'channel_id'=>	$channel_id,
             									'title'		=>	$API->process_field_string($file->title),
             									'url_title'	=>	$API->process_field_string($file->url_title),
             									'description' => $API->process_field_string($file->description),
             									'category' 	=>	(isset($file->category) == true) ? $file->category : '',
             									'cffield_1'	=>	$API->process_field_string($file->cffield_1),
             									'cffield_2'	=>	$API->process_field_string($file->cffield_2),
             									'cffield_3'	=>	$API->process_field_string($file->cffield_3),
             									'cffield_4'	=>	$API->process_field_string($file->cffield_4),
             									'cffield_5'	=>	$API->process_field_string($file->cffield_5),
             									'file_primary'	=>	$file->primary,
             									'file_order'	=>	$order,
             									'is_draft'	=>	$is_draft,
             								);
             
             					$this->EE->db->update('exp_channel_files', $data, array('file_id' => $file->file_id));
             					continue;
             				}
             */
             // Mime type
             $filemime = $MIME->get_mimetype($file->extension);
             // Check for linked_fileid
             if (isset($file->link_file_id) == FALSE) {
                 $file->link_file_id = 0;
             }
             $file->link_entry_id = 0;
             $file->link_channel_id = 0;
             $file->link_field_id = 0;
             // Is it a new file? Lets grab it's new filename
             if (isset($filenames[$file->filename]) === TRUE && $file->file_id < 1) {
                 $file->filename = $filenames[$file->filename];
             }
             if ($this->EE->channel_files_helper->in_multi_array($file->file_id . $file->filename, $dbfiles) === FALSE) {
                 // Grab MD5/Filesize
                 if ($file->link_file_id > 0) {
                     $q = $this->EE->db->select('entry_id, field_id, channel_id, md5, filesize')->from('exp_channel_files')->where('file_id', $file->link_file_id)->limit(1)->get();
                     $file->link_entry_id = $q->row('entry_id');
                     $file->link_channel_id = $q->row('channel_id');
                     $file->link_field_id = $q->row('field_id');
                     $file->filesize = $q->row('filesize');
                     $file->md5 = $q->row('md5');
                     $q->free_result();
                 }
                 // -----------------------------------------
                 // New Files
                 // -----------------------------------------
                 $data = array('site_id' => $this->site_id, 'entry_id' => $entry_id, 'field_id' => $field_id, 'channel_id' => $channel_id, 'member_id' => $this->EE->session->userdata['member_id'], 'is_draft' => $is_draft, 'link_file_id' => $file->link_file_id, 'link_entry_id' => $file->link_entry_id, 'link_channel_id' => $file->link_channel_id, 'link_field_id' => $file->link_field_id, 'filename' => $file->filename, 'extension' => $file->extension, 'mime' => $filemime, 'upload_service' => $location_type, 'title' => $API->process_field_string($file->title), 'url_title' => $API->process_field_string($file->url_title), 'description' => $API->process_field_string($file->description), 'category' => isset($file->category) == true ? $file->category : '', 'cffield_1' => $API->process_field_string($file->cffield_1), 'cffield_2' => $API->process_field_string($file->cffield_2), 'cffield_3' => $API->process_field_string($file->cffield_3), 'cffield_4' => $API->process_field_string($file->cffield_4), 'cffield_5' => $API->process_field_string($file->cffield_5), 'filesize' => $file->filesize, 'md5' => $file->md5, 'file_primary' => $file->primary, 'file_order' => $order, 'date' => $this->EE->localize->now);
                 $this->EE->db->insert('exp_channel_files', $data);
             } else {
                 // -----------------------------------------
                 // Old File
                 // -----------------------------------------
                 $data = array('entry_id' => $entry_id, 'field_id' => $field_id, 'channel_id' => $channel_id, 'title' => $API->process_field_string($file->title), 'url_title' => $API->process_field_string($file->url_title), 'description' => $API->process_field_string($file->description), 'category' => isset($file->category) == true ? $file->category : '', 'cffield_1' => $API->process_field_string($file->cffield_1), 'cffield_2' => $API->process_field_string($file->cffield_2), 'cffield_3' => $API->process_field_string($file->cffield_3), 'cffield_4' => $API->process_field_string($file->cffield_4), 'cffield_5' => $API->process_field_string($file->cffield_5), 'file_primary' => $file->primary, 'file_order' => $order, 'is_draft' => $is_draft);
                 $this->EE->db->update('exp_channel_files', $data, array('file_id' => $file->file_id));
             }
         }
     } else {
         // -----------------------------------------
         // No previous entries, fresh fresh
         // -----------------------------------------
         foreach ($data['files'] as $order => $file) {
             $file = $this->EE->channel_files_helper->decode_json($file['data']);
             ///$this->EE->firephp->log($file);
             ///$this->EE->firephp->log($draft_action);
             ///$this->EE->firephp->log($is_draft);
             // If we are creating a new draft, we already copied all data.. So lets kill the ones that came through POST
             if ($is_draft === 1 && $file->file_id > 0 && $draft_action !== 'create') {
                 // -----------------------------------------
                 // Old File
                 // -----------------------------------------
                 $data = array('entry_id' => $entry_id, 'field_id' => $field_id, 'channel_id' => $channel_id, 'title' => $API->process_field_string($file->title), 'url_title' => $API->process_field_string($file->url_title), 'description' => $API->process_field_string($file->description), 'category' => isset($file->category) == true ? $file->category : '', 'cffield_1' => $API->process_field_string($file->cffield_1), 'cffield_2' => $API->process_field_string($file->cffield_2), 'cffield_3' => $API->process_field_string($file->cffield_3), 'cffield_4' => $API->process_field_string($file->cffield_4), 'cffield_5' => $API->process_field_string($file->cffield_5), 'file_primary' => $file->primary, 'file_order' => $order, 'is_draft' => $is_draft);
                 $this->EE->db->update('exp_channel_files', $data, array('file_id' => $file->file_id));
                 continue;
             }
             if ($file->file_id > 0) {
                 continue;
             }
             // Mime type
             $filemime = $MIME->get_mimetype($file->extension);
             // Check for linked_fileid
             if (isset($file->link_file_id) == FALSE) {
                 $file->link_file_id = 0;
             }
             $file->link_entry_id = 0;
             $file->link_channel_id = 0;
             $file->link_field_id = 0;
             if ($file->link_file_id == 0) {
                 $file->filename = $filenames[$file->filename];
             }
             // Grab MD5/Filesize
             if ($file->link_file_id > 0) {
                 $q = $this->EE->db->select('entry_id, field_id, channel_id, md5, filesize')->from('exp_channel_files')->where('file_id', $file->link_file_id)->limit(1)->get();
                 $file->link_entry_id = $q->row('entry_id');
                 $file->link_channel_id = $q->row('channel_id');
                 $file->link_field_id = $q->row('field_id');
                 $file->filesize = $q->row('filesize');
                 $file->md5 = $q->row('md5');
                 $q->free_result();
             }
             // -----------------------------------------
             // New Files
             // -----------------------------------------
             $data = array('site_id' => $this->site_id, 'entry_id' => $entry_id, 'field_id' => $field_id, 'channel_id' => $channel_id, 'member_id' => $this->EE->session->userdata['member_id'], 'is_draft' => $is_draft, 'link_file_id' => $file->link_file_id, 'link_entry_id' => $file->link_entry_id, 'link_channel_id' => $file->link_channel_id, 'link_field_id' => $file->link_field_id, 'filename' => $file->filename, 'extension' => $file->extension, 'mime' => $filemime, 'upload_service' => $location_type, 'title' => $API->process_field_string($file->title), 'url_title' => $API->process_field_string($file->url_title), 'description' => $API->process_field_string($file->description), 'category' => isset($file->category) == true ? $file->category : '', 'cffield_1' => $API->process_field_string($file->cffield_1), 'cffield_2' => $API->process_field_string($file->cffield_2), 'cffield_3' => $API->process_field_string($file->cffield_3), 'cffield_4' => $API->process_field_string($file->cffield_4), 'cffield_5' => $API->process_field_string($file->cffield_5), 'filesize' => $file->filesize, 'md5' => $file->md5, 'file_primary' => $file->primary, 'file_order' => $order, 'date' => $this->EE->localize->now);
             $this->EE->db->insert('exp_channel_files', $data);
         }
     }
     // Kill Folder
     $this->EE->channel_files_helper->delete_files($temp_dir, TRUE);
     @rmdir($temp_dir);
     // -----------------------------------------
     // Delete old cache folders
     // -----------------------------------------'
     $path_temp_dir = APPPATH . 'cache/channel_files/field_' . $field_id . '/';
     $day_ago = $this->EE->localize->now - 86400;
     // Get directory contents
     $tempdirs = @scandir($path_temp_dir);
     if (is_array($tempdirs) == TRUE) {
         // Loop over all files
         foreach ($tempdirs as $tempdir) {
             // We don't want those
             if ($tempdir == '.' or $tempdir == '..' or $temp_dir == FALSE) {
                 continue;
             }
             // Is it a Directory?
             if (@is_dir($path_temp_dir . $tempdir) == TRUE) {
                 // And 24 old?
                 if ($day_ago > $tempdir) {
                     // Kill it
                     $this->EE->channel_files_helper->delete_files($path_temp_dir . $tempdir, TRUE);
                     @rmdir($path_temp_dir . $tempdir);
                 }
             }
         }
     }
     // -----------------------------------------
     // WYGWAM
     // -----------------------------------------
     // Which field_group is assigned to this channel?
     $query = $this->EE->db->select('field_group')->from('exp_channels')->where('channel_id', $channel_id)->get();
     if ($query->num_rows() == 0) {
         return;
     }
     $field_group = $query->row('field_group');
     // Which fields are WYGWAM/wyvern
     $query = $this->EE->db->select('field_id')->from('exp_channel_fields')->where('group_id', $field_group)->where('field_type', 'wygwam')->or_where('field_type', 'wyvern')->get();
     if ($query->num_rows() == 0) {
         return;
     }
     // Harvest all of them
     $fields = array();
     foreach ($query->result() as $row) {
         $fields[] = 'field_id_' . $row->field_id;
     }
     if (count($fields) > 0) {
         // Grab them!
         foreach ($fields as $field) {
             $this->EE->db->set($field, " REPLACE({$field}, 'd=CFKEYDIR&', 'd={$entry_id}&') ", FALSE);
             $this->EE->db->where('entry_id', $entry_id);
             $this->EE->db->update('exp_channel_data');
         }
     }
     // Delete old dirs
     $API->clean_temp_dirs($this->field_id);
     // -----------------------------------------
     // Just to be sure
     // -----------------------------------------
     $query = $this->EE->db->select('file_id')->from('exp_channel_files')->where('field_id', $this->field_id)->where('entry_id', $entry_id)->get();
     if ($query->num_rows() == 0) {
         $this->EE->db->set('field_id_' . $this->field_id, '');
     } else {
         $this->EE->db->set('field_id_' . $this->field_id, 'Channel Files');
     }
     $this->EE->db->where('entry_id', $entry_id);
     $this->EE->db->update('exp_channel_data');
     return;
 }
Пример #5
0
 public function upload_file($source_file, $dest_filename, $dest_folder, $checkExists = true)
 {
     $out = array('success' => FALSE, 'filename' => '');
     $this->init();
     $this->CF_CONT = $this->CF_CONN->get_container($this->lsettings['container']);
     if ($dest_folder !== FALSE) {
         $dest_folder .= '/';
     } else {
         $dest_folder = '';
     }
     // Extension
     $extension = substr(strrchr($source_file, '.'), 1);
     $filename_no_ext = str_replace('.' . $extension, '', $dest_filename);
     if ($checkExists) {
         // Does it already exists?
         try {
             $this->CF_CONT->get_object($dest_folder . $dest_filename, TRUE, TRUE);
             // It exists..
             for ($i = 2; $i < 30; $i++) {
                 try {
                     $this->CF_CONT->get_object($dest_folder . "{$filename_no_ext}_{$i}.{$extension}", TRUE, TRUE);
                 } catch (NoSuchObjectException $e) {
                     $dest_filename = "{$filename_no_ext}_{$i}.{$extension}";
                     break;
                 }
             }
         } catch (NoSuchObjectException $e) {
         }
     }
     // Mime type
     if (class_exists('CFMimeTypes') == FALSE) {
         include PATH_THIRD . 'channel_files/libraries/mimetypes.class.php';
     }
     $MIME = new CFMimeTypes();
     $filemime = $MIME->get_mimetype($extension);
     // Create Object
     $OBJECT = $this->CF_CONT->create_object($dest_folder . $dest_filename);
     $OBJECT->content_type = $filemime;
     // UPLOAD FREAKING FILE!
     $fp = fopen($source_file, "r");
     $size = (double) sprintf("%u", @filesize($source_file));
     $OBJECT->write($fp, $size, TRUE);
     fclose($fp);
     $out['success'] = TRUE;
     $out['filename'] = $dest_filename;
     return $out;
 }
Пример #6
0
 private function stream_file($dir = '', $filename = '', $file = FALSE)
 {
     if (file_exists($dir . $filename) == FALSE) {
         exit('FILE NOT FOUND!');
     }
     if (empty($file) == TRUE) {
         $file = new StdClass();
         $file->filename = $filename;
         $file->extension = substr(strrchr($file->filename, '.'), 1);
         // Mime type
         if (class_exists('CFMimeTypes') == FALSE) {
             include PATH_THIRD . 'channel_files/libraries/mimetypes.class.php';
         }
         $MIME = new CFMimeTypes();
         $file->mime = $MIME->get_mimetype($file->extension);
         $file->filesize = @filesize($dir . $filename);
     }
     /** ----------------------------------------
     		/**  For Local Files we STREAM
     		/** ----------------------------------------*/
     header('Pragma: public');
     header('Expires: 0');
     header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
     header('Cache-Control: public', FALSE);
     header('Content-Description: File Transfer');
     header('Content-Type: ' . $file->mime);
     header('Accept-Ranges: bytes');
     header('Content-Disposition: attachment; filename="' . $filename . '";');
     header('Content-Transfer-Encoding: binary');
     header('Content-Length: ' . $file->filesize);
     @ob_clean();
     @flush();
     @readfile($dir . $filename);
     exit;
 }