View source
<?php
define('VIDEO_S3_PENDING', 1);
define('VIDEO_S3_ACTIVE', 5);
define('VIDEO_S3_COMPLETE', 10);
define('VIDEO_S3_FAILED', 20);
class video_amazon_s3 {
private $access_key;
private $secret_key;
private $ssl;
private $bucket;
private $libfile;
public $s3;
public function __construct() {
$libpath = libraries_get_path('awssdk');
$this->libfile = $libpath . '/sdk.class.php';
if (!file_exists($this->libfile)) {
drupal_set_message(t('The Amazon SDK for PHP has not been installed correctly. See the <a href="@drupal-status-page">Drupal status page</a> for more information.', array(
'@drupal-status-page' => url('admin/reports/status'),
)), 'error');
return;
}
$this->access_key = variable_get('amazon_s3_access_key', '');
$this->secret_key = variable_get('amazon_s3_secret_access_key', '');
$this->ssl = variable_get('amazon_s3_ssl', FALSE);
$this->bucket = variable_get('amazon_s3_bucket', '');
}
public function connect($access_key = '', $secret_key = '', $ssl = FALSE) {
$access_key = $access_key ? $access_key : $this->access_key;
$secret_key = $secret_key ? $secret_key : $this->secret_key;
$ssl = $ssl ? $ssl : $this->ssl;
require_once $this->libfile;
$credential = new stdClass();
$credential->key = $access_key;
$credential->secret = $secret_key;
$credential->token = NULL;
CFCredentials::set(array(
$credential,
));
$this->s3 = new AmazonS3();
$this->s3->use_ssl = $ssl;
}
public function verify($fid) {
return db_fetch_object(db_query('SELECT * FROM {video_s3} WHERE fid = %d', $fid));
}
public function get($fid) {
return db_fetch_object(db_query('SELECT * FROM {video_s3} WHERE fid = %d AND status = %d', $fid, VIDEO_S3_COMPLETE));
}
public function pushFile(stdClass $file, $keeplocal = FALSE) {
$expires_offset = variable_get('amazon_s3_expires_offset', 604800);
$perm = variable_get('amazon_s3_private', FALSE) ? AmazonS3::ACL_PRIVATE : AmazonS3::ACL_PUBLIC;
$cc = variable_get('amazon_s3_cache_control_max_age', 'none');
$headers = array();
if ($expires_offset !== 'none') {
$headers['Expires'] = gmdate('r', $expires_offset == 0 ? 0 : time() + $expires_offset);
}
if ($cc !== 'none') {
$headers['Cache-Control'] = 'max-age=' . $cc;
}
_video_db_increase_timeout();
$dstfilepath = ltrim($file->filepath, '/');
$response = $this->s3
->create_object($this->bucket, $dstfilepath, array(
'fileUpload' => $file->filepath,
'acl' => $perm,
'contentType' => $file->filemime,
'headers' => $headers,
));
if ($response
->isOK()) {
if ($perm == AmazonS3::ACL_PRIVATE) {
$this
->setZencoderAccessPolicy($this->bucket, $dstfilepath);
}
$file->bucket = $this->bucket;
if (!$keeplocal) {
file_delete($file->filepath);
}
$this
->watchdog('Successfully uploaded %file to Amazon S3 location <a href="@s3-url">@s3-path</a> and permission %permission.', array(
'%file' => $file->filename,
'@s3-url' => 'http://' . $file->bucket . '.s3.amazonaws.com/' . drupal_urlencode($dstfilepath),
'@s3-path' => $dstfilepath,
'%permission' => $perm,
), WATCHDOG_INFO, $file);
return $file;
}
$this
->watchdog('Failed to upload %file to Amazon S3.', array(
'%file' => $file->filepath,
), WATCHDOG_ERROR, $file);
return NULL;
}
public function getVideoUrl($filepath, $bucket = NULL) {
if (variable_get('amazon_s3_private', FALSE)) {
return $this
->get_authenticated_url($filepath, $bucket);
}
$cfdomain = variable_get('amazon_s3_cf_domain', FALSE);
$bucket = $bucket == NULL ? $this->bucket : $bucket;
return ($this->ssl ? 'https://' : 'http://') . ($cfdomain ? $cfdomain . '/' : $bucket . '.s3.amazonaws.com/') . drupal_urlencode($filepath);
}
public function get_object_info($filepath) {
return $this->s3
->get_object_headers($this->bucket, $filepath)
->isOK();
}
public function get_authenticated_url($filepath, $bucket = NULL) {
$lifetime = (int) variable_get('amazon_s3_lifetime', 1800);
$bucket = $bucket == NULL ? $this->bucket : $bucket;
$url = $this->s3
->get_object_url($bucket, $filepath, time() + $lifetime);
if ($this->ssl) {
$url = 'https://' . drupal_substr($url, 7);
}
return $url;
}
public function get_object($filepath, $saveTo = FALSE) {
return $this->s3
->get_object($this->bucket, $filepath, array(
'fileDownload' => $saveTo,
));
}
public function updateAllExpiresHeaders() {
$expires_offset = variable_get('amazon_s3_expires_offset', 604800);
if ($expires_offset === 'none' || $expires_offset === 0) {
return;
}
if (variable_get('amazon_s3_expires_last_cron', 0) + $expires_offset > time()) {
return;
}
$active = db_query('SELECT bucket, filename, filepath, filemime FROM {video_s3} WHERE status = %d', VIDEO_S3_COMPLETE);
$permission = variable_get('amazon_s3_private', FALSE) ? AmazonS3::ACL_PRIVATE : AmazonS3::ACL_PUBLIC;
$headers = array(
'Expires' => gmdate('r', time() + $expires_offset),
);
$cc = variable_get('amazon_s3_cache_control_max_age', 'none');
if ($cc !== 'none') {
$headers['Cache-Control'] = 'max-age=' . $cc;
}
while ($file = db_fetch_object($active)) {
$this
->update_headers($file, $permission, $headers);
}
variable_set('amazon_s3_expires_last_cron', time());
}
private function update_headers($file, $permission, $headers) {
$filepath = ltrim($file->filepath, '/');
if (strpos('/', $file->filename) !== FALSE) {
$filepath = $file->filename;
}
$headers['Content-Type'] = $file->filemime;
$item = array(
'bucket' => $file->bucket,
'filename' => $filepath,
);
return $this->s3
->copy_object($item, $item, array(
'acl' => $permission,
'headers' => $headers,
))
->isOK();
}
public function setZencoderAccessPolicy($bucket, $filepath = '', $perm = 'auto') {
if (!module_exists('video_zencoder')) {
return NULL;
}
if ($perm == 'auto') {
$perm = empty($filepath) ? AmazonS3::GRANT_WRITE : AmazonS3::GRANT_READ;
}
if (empty($filepath)) {
$acp = $this->s3
->get_bucket_acl($bucket);
}
else {
$acp = $this->s3
->get_object_acl($bucket, $filepath);
}
$acl = array();
foreach ($acp->body->AccessControlList->Grant as $grant) {
if ($grant->Grantee->DisplayName == 'zencodertv' && $grant->Permission == $perm) {
return NULL;
}
$acl[] = array(
'id' => isset($grant->Grantee->URI) ? (string) $grant->Grantee->URI : (string) $grant->Grantee->ID,
'permission' => (string) $grant->Permission,
);
}
$acl[] = array(
'id' => 'aws@zencoder.com',
'permission' => $perm,
);
if (empty($filepath)) {
return $this->s3
->set_bucket_acl($bucket, $acl)
->isOK();
}
else {
return $this->s3
->set_object_acl($bucket, $filepath, $acl)
->isOK();
}
}
private function watchdog($message, $variables = array(), $severity = WATCHDOG_NOTICE, $nid = NULL) {
$link = NULL;
if (is_object($nid)) {
if (isset($nid->nid) && $nid->nid > 0) {
$link = l(t('view node'), 'node/' . intval($nid->nid));
}
}
elseif ($nid > 0) {
$link = l(t('view node'), 'node/' . intval($nid));
}
watchdog('amazon_s3', $message, $variables, $severity, $link);
}
public function replaceLocalFile($filepath, $s3url) {
if (file_delete($filepath) !== FALSE) {
$fp = fopen($filepath, 'w+');
if (!$fp) {
return FALSE;
}
fwrite($fp, 'Moved to ' . $s3url);
fclose($fp);
chmod($filepath, 0644);
}
}
}