Merge branch 'master' into groups

This commit is contained in:
Robin Appelman 2013-07-23 22:06:03 +02:00
commit fb40d9e1e6
1561 changed files with 93389 additions and 16205 deletions

7
.gitignore vendored
View file

@ -15,6 +15,13 @@
!/apps/files_versions
!/apps/user_ldap
!/apps/user_webdavauth
/apps/files_external/3rdparty/irodsphp/PHPUnitTest
/apps/files_external/3rdparty/irodsphp/web
/apps/files_external/3rdparty/irodsphp/prods/test
/apps/files_external/3rdparty/irodsphp/prods/tutorials
/apps/files_external/3rdparty/irodsphp/prods/test*
# ignore themes except the README
/themes/*

@ -1 +1 @@
Subproject commit 217626723957161191572ea50172a3943c30696d
Subproject commit 25e8568d41a9b9a6d1662ccf33058822a890e7f5

20
README
View file

@ -1,20 +0,0 @@
ownCloud gives you freedom and control over your own data.
A personal cloud which runs on your own server.
http://ownCloud.org
Installation instructions: http://doc.owncloud.org/server/5.0/developer_manual/app/gettingstarted.html
Contribution Guidelines: http://owncloud.org/dev/contribute/
Source code: https://github.com/owncloud
Mailing list: https://mail.kde.org/mailman/listinfo/owncloud
IRC channel: https://webchat.freenode.net/?channels=owncloud
Diaspora: https://joindiaspora.com/u/owncloud
Identi.ca: https://identi.ca/owncloud
Important notice on translations:
Please submit translations via Transifex:
https://www.transifex.com/projects/p/owncloud/
For more detailed information about translations:
http://owncloud.org/dev/translation/

26
README.md Normal file
View file

@ -0,0 +1,26 @@
# ownCloud
[ownCloud](http://ownCloud.org) gives you freedom and control over your own data.
A personal cloud which runs on your own server.
### Build Status on [Jenkins CI](https://ci.owncloud.org/)
Git master: [![Build Status](https://ci.owncloud.org/buildStatus/icon?job=ownCloud-Server%28master%29)](https://ci.owncloud.org/job/ownCloud-Server%28master%29/)
### Installation instructions
http://doc.owncloud.org/server/5.0/developer_manual/app/gettingstarted.html
### Contribution Guidelines
http://owncloud.org/dev/contribute/
### Get in touch
* [Forum](http://forum.owncloud.org)
* [Mailing list](https://mail.kde.org/mailman/listinfo/owncloud)
* [IRC channel](https://webchat.freenode.net/?channels=owncloud)
* [Twitter](https://twitter.com/ownClouders)
### Important notice on translations
Please submit translations via Transifex:
https://www.transifex.com/projects/p/owncloud/
For more detailed information about translations:
http://owncloud.org/dev/translation/

View file

@ -16,72 +16,56 @@ if (isset($_GET['users'])) {
}
$eventSource = new OC_EventSource();
ScanListener::$eventSource = $eventSource;
ScanListener::$view = \OC\Files\Filesystem::getView();
OC_Hook::connect('\OC\Files\Cache\Scanner', 'scan_folder', 'ScanListener', 'folder');
OC_Hook::connect('\OC\Files\Cache\Scanner', 'scan_file', 'ScanListener', 'file');
$listener = new ScanListener($eventSource);
foreach ($users as $user) {
$eventSource->send('user', $user);
OC_Util::tearDownFS();
OC_Util::setupFS($user);
$absolutePath = \OC\Files\Filesystem::getView()->getAbsolutePath($dir);
$mountPoints = \OC\Files\Filesystem::getMountPoints($absolutePath);
$mountPoints[] = \OC\Files\Filesystem::getMountPoint($absolutePath);
$mountPoints = array_reverse($mountPoints); //start with the mount point of $dir
foreach ($mountPoints as $mountPoint) {
$storage = \OC\Files\Filesystem::getStorage($mountPoint);
if ($storage) {
ScanListener::$mountPoints[$storage->getId()] = $mountPoint;
$scanner = $storage->getScanner();
if ($force) {
$scanner->scan('', \OC\Files\Cache\Scanner::SCAN_RECURSIVE, \OC\Files\Cache\Scanner::REUSE_ETAG);
} else {
$scanner->backgroundScan();
}
}
$scanner = new \OC\Files\Utils\Scanner($user);
$scanner->listen('\OC\Files\Utils\Scanner', 'scanFile', array($listener, 'file'));
$scanner->listen('\OC\Files\Utils\Scanner', 'scanFolder', array($listener, 'folder'));
if ($force) {
$scanner->scan($dir);
} else {
$scanner->backgroundScan($dir);
}
}
$eventSource->send('done', ScanListener::$fileCount);
$eventSource->send('done', $listener->getCount());
$eventSource->close();
class ScanListener {
static public $fileCount = 0;
static public $lastCount = 0;
/**
* @var \OC\Files\View $view
*/
static public $view;
/**
* @var array $mountPoints map storage ids to mountpoints
*/
static public $mountPoints = array();
private $fileCount = 0;
private $lastCount = 0;
/**
* @var \OC_EventSource event source to pass events to
*/
static public $eventSource;
private $eventSource;
static function folder($params) {
$internalPath = $params['path'];
$mountPoint = self::$mountPoints[$params['storage']];
$path = self::$view->getRelativePath($mountPoint . $internalPath);
self::$eventSource->send('folder', $path);
/**
* @param \OC_EventSource $eventSource
*/
public function __construct($eventSource) {
$this->eventSource = $eventSource;
}
static function file() {
self::$fileCount++;
if (self::$fileCount > self::$lastCount + 20) { //send a count update every 20 files
self::$lastCount = self::$fileCount;
self::$eventSource->send('count', self::$fileCount);
/**
* @param string $path
*/
public function folder($path) {
$this->eventSource->send('folder', $path);
}
public function file() {
$this->fileCount++;
if ($this->fileCount > $this->lastCount + 20) { //send a count update every 20 files
$this->lastCount = $this->fileCount;
$this->eventSource->send('count', $this->fileCount);
}
}
public function getCount() {
return $this->fileCount;
}
}

View file

@ -121,6 +121,10 @@ if ($needUpgrade) {
// information about storage capacities
$storageInfo=OC_Helper::getStorageInfo();
$maxUploadFilesize=OCP\Util::maxUploadFilesize($dir);
$publicUploadEnabled = \OC_Appconfig::getValue('core', 'shareapi_allow_public_upload', 'yes');
if (OC_App::isEnabled('files_encryption')) {
$publicUploadEnabled = 'no';
}
OCP\Util::addscript('files', 'fileactions');
OCP\Util::addscript('files', 'files');
@ -138,5 +142,6 @@ if ($needUpgrade) {
$tmpl->assign('allowZipDownload', intval(OCP\Config::getSystemValue('allowZipDownload', true)));
$tmpl->assign('usedSpacePercent', (int)$storageInfo['relative']);
$tmpl->assign('isPublic', false);
$tmpl->assign('publicUploadEnabled', $publicUploadEnabled);
$tmpl->printPage();
}

View file

@ -47,7 +47,7 @@ var FileList={
//size column
if(size!=t('files', 'Pending')){
simpleSize=simpleFileSize(size);
simpleSize = humanFileSize(size);
}else{
simpleSize=t('files', 'Pending');
}
@ -55,7 +55,6 @@ var FileList={
var lastModifiedTime = Math.round(lastModified.getTime() / 1000);
td = $('<td></td>').attr({
"class": "filesize",
"title": humanFileSize(size),
"style": 'color:rgb('+sizeColor+','+sizeColor+','+sizeColor+')'
}).text(simpleSize);
tr.append(td);
@ -171,6 +170,8 @@ var FileList={
}
}else if(type=='dir' && $('tr[data-file]').length>0){
$('tr[data-file]').first().before(element);
} else if(type=='file' && $('tr[data-file]').length>0) {
$('tr[data-file]').last().before(element);
}else{
$('#fileList').append(element);
}

View file

@ -756,9 +756,7 @@ function procesSelection(){
for(var i=0;i<selectedFolders.length;i++){
totalSize+=selectedFolders[i].size;
};
simpleSize=simpleFileSize(totalSize);
$('#headerSize').text(simpleSize);
$('#headerSize').attr('title',humanFileSize(totalSize));
$('#headerSize').text(humanFileSize(totalSize));
var selection='';
if(selectedFolders.length>0){
if(selectedFolders.length==1){

View file

@ -1,6 +1,8 @@
<?php $TRANSLATIONS = array(
"Could not move %s - File with this name already exists" => "Konnte %s nicht verschieben. Eine Datei mit diesem Namen existiert bereits",
"Could not move %s" => "Konnte %s nicht verschieben",
"Unable to set upload directory." => "Das Upload-Verzeichnis konnte nicht gesetzt werden.",
"Invalid Token" => "Ungültiges Merkmal",
"No file was uploaded. Unknown error" => "Keine Datei hochgeladen. Unbekannter Fehler",
"There is no error, the file uploaded with success" => "Es ist kein Fehler aufgetreten. Die Datei wurde erfolgreich hochgeladen.",
"The uploaded file exceeds the upload_max_filesize directive in php.ini: " => "Die hochgeladene Datei überschreitet die upload_max_filesize Vorgabe in php.ini",
@ -47,6 +49,7 @@
"{count} folders" => "{count} Ordner",
"1 file" => "1 Datei",
"{count} files" => "{count} Dateien",
"%s could not be renamed" => "%s konnte nicht umbenannt werden",
"Upload" => "Hochladen",
"File handling" => "Dateibehandlung",
"Maximum upload size" => "Maximale Upload-Größe",
@ -70,6 +73,8 @@
"The files you are trying to upload exceed the maximum size for file uploads on this server." => "Die Datei überschreitet die Maximalgröße für Uploads auf diesem Server.",
"Files are being scanned, please wait." => "Dateien werden gescannt, bitte warten.",
"Current scanning" => "Scanne",
"directory" => "Verzeichnis",
"directories" => "Verzeichnisse",
"file" => "Datei",
"files" => "Dateien",
"Upgrading filesystem cache..." => "Dateisystem-Cache wird aktualisiert ..."

View file

@ -1,5 +1,5 @@
<?php $TRANSLATIONS = array(
"Could not move %s - File with this name already exists" => "Konnte %s nicht verschieben. Eine Datei mit diesem Namen existiert bereits",
"Could not move %s - File with this name already exists" => "%s konnte nicht verschoben werden. Eine Datei mit diesem Namen existiert bereits.",
"Could not move %s" => "Konnte %s nicht verschieben",
"Unable to set upload directory." => "Das Upload-Verzeichnis konnte nicht gesetzt werden.",
"Invalid Token" => "Ungültiges Merkmal",

View file

@ -1,26 +1,28 @@
<?php $TRANSLATIONS = array(
"Could not move %s - File with this name already exists" => "No se pudo mover %s - Un archivo con este nombre ya existe",
"Could not move %s" => "No se pudo mover %s ",
"Unable to set upload directory." => "No fue posible crear el directorio de subida.",
"Invalid Token" => "Token Inválido",
"No file was uploaded. Unknown error" => "El archivo no fue subido. Error desconocido",
"There is no error, the file uploaded with success" => "No hay errores, el archivo fue subido con éxito",
"The uploaded file exceeds the upload_max_filesize directive in php.ini: " => "El archivo que intentás subir excede el tamaño definido por upload_max_filesize en el php.ini:",
"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "El archivo subido sobrepasa el valor MAX_FILE_SIZE especificada en el formulario HTML",
"The uploaded file was only partially uploaded" => "El archivo fue subido parcialmente",
"No file was uploaded" => "No se subió ningún archivo ",
"Missing a temporary folder" => "Error en la carpera temporal",
"Missing a temporary folder" => "Falta un directorio temporal",
"Failed to write to disk" => "Error al escribir en el disco",
"Not enough storage available" => "No hay suficiente capacidad de almacenamiento",
"Invalid directory." => "Directorio invalido.",
"Not enough storage available" => "No hay suficiente almacenamiento",
"Invalid directory." => "Directorio inválido.",
"Files" => "Archivos",
"Unable to upload your file as it is a directory or has 0 bytes" => "No fue posible subir el archivo porque es un directorio o porque su tamaño es 0 bytes",
"Not enough space available" => "No hay suficiente espacio disponible",
"Upload cancelled." => "La subida fue cancelada",
"File upload is in progress. Leaving the page now will cancel the upload." => "La subida del archivo está en proceso. Si salís de la página ahora, la subida se cancelará.",
"URL cannot be empty." => "La URL no puede estar vacía",
"Invalid folder name. Usage of 'Shared' is reserved by ownCloud" => "Nombre de carpeta inválido. El uso de \"Shared\" está reservado por ownCloud",
"Invalid folder name. Usage of 'Shared' is reserved by ownCloud" => "Nombre de directorio inválido. El uso de \"Shared\" está reservado por ownCloud",
"Error" => "Error",
"Share" => "Compartir",
"Delete permanently" => "Borrar de manera permanente",
"Delete permanently" => "Borrar permanentemente",
"Delete" => "Borrar",
"Rename" => "Cambiar nombre",
"Pending" => "Pendientes",
@ -28,9 +30,9 @@
"replace" => "reemplazar",
"suggest name" => "sugerir nombre",
"cancel" => "cancelar",
"replaced {new_name} with {old_name}" => "reemplazado {new_name} con {old_name}",
"replaced {new_name} with {old_name}" => "se reemplazó {new_name} con {old_name}",
"undo" => "deshacer",
"perform delete operation" => "Eliminar",
"perform delete operation" => "Llevar a cabo borrado",
"1 file uploading" => "Subiendo 1 archivo",
"files uploading" => "Subiendo archivos",
"'.' is an invalid file name." => "'.' es un nombre de archivo inválido.",
@ -38,7 +40,7 @@
"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Nombre invalido, '\\', '/', '<', '>', ':', '\"', '|', '?' y '*' no están permitidos.",
"Your storage is full, files can not be updated or synced anymore!" => "El almacenamiento está lleno, los archivos no se pueden seguir actualizando ni sincronizando",
"Your storage is almost full ({usedSpacePercent}%)" => "El almacenamiento está casi lleno ({usedSpacePercent}%)",
"Your download is being prepared. This might take some time if the files are big." => "Tu descarga esta siendo preparada. Esto puede tardar algun tiempo si los archivos son muy grandes.",
"Your download is being prepared. This might take some time if the files are big." => "Tu descarga se está preparando. Esto puede demorar si los archivos son muy grandes.",
"Invalid folder name. Usage of 'Shared' is reserved by Owncloud" => "Nombre de carpeta inválido. El uso de 'Shared' está reservado por ownCloud",
"Name" => "Nombre",
"Size" => "Tamaño",
@ -47,11 +49,12 @@
"{count} folders" => "{count} directorios",
"1 file" => "1 archivo",
"{count} files" => "{count} archivos",
"%s could not be renamed" => "No se pudo renombrar %s",
"Upload" => "Subir",
"File handling" => "Tratamiento de archivos",
"Maximum upload size" => "Tamaño máximo de subida",
"max. possible: " => "máx. posible:",
"Needed for multi-file and folder downloads." => "Es necesario para descargas multi-archivo y de carpetas",
"Needed for multi-file and folder downloads." => "Es necesario para descargas multi-archivo y de directorios.",
"Enable ZIP-download" => "Habilitar descarga en formato ZIP",
"0 is unlimited" => "0 significa ilimitado",
"Maximum input size for ZIP files" => "Tamaño máximo para archivos ZIP de entrada",
@ -60,7 +63,7 @@
"Text file" => "Archivo de texto",
"Folder" => "Carpeta",
"From link" => "Desde enlace",
"Deleted files" => "Archivos Borrados",
"Deleted files" => "Archivos borrados",
"Cancel upload" => "Cancelar subida",
"You dont have write permissions here." => "No tenés permisos de escritura acá.",
"Nothing in here. Upload something!" => "No hay nada. ¡Subí contenido!",
@ -70,6 +73,8 @@
"The files you are trying to upload exceed the maximum size for file uploads on this server." => "Los archivos que intentás subir sobrepasan el tamaño máximo ",
"Files are being scanned, please wait." => "Se están escaneando los archivos, por favor esperá.",
"Current scanning" => "Escaneo actual",
"directory" => "directorio",
"directories" => "directorios",
"file" => "archivo",
"files" => "archivos",
"Upgrading filesystem cache..." => "Actualizando el cache del sistema de archivos"

View file

@ -1,6 +1,8 @@
<?php $TRANSLATIONS = array(
"Could not move %s - File with this name already exists" => "Ezin da %s mugitu - Izen hau duen fitxategia dagoeneko existitzen da",
"Could not move %s" => "Ezin dira fitxategiak mugitu %s",
"Unable to set upload directory." => "Ezin da igoera direktorioa ezarri.",
"Invalid Token" => "Lekuko baliogabea",
"No file was uploaded. Unknown error" => "Ez da fitxategirik igo. Errore ezezaguna",
"There is no error, the file uploaded with success" => "Ez da errorerik egon, fitxategia ongi igo da",
"The uploaded file exceeds the upload_max_filesize directive in php.ini: " => "Igotako fitxategiak php.ini fitxategian ezarritako upload_max_filesize muga gainditu du:",
@ -17,6 +19,7 @@
"Upload cancelled." => "Igoera ezeztatuta",
"File upload is in progress. Leaving the page now will cancel the upload." => "Fitxategien igoera martxan da. Orria orain uzteak igoera ezeztatutko du.",
"URL cannot be empty." => "URLa ezin da hutsik egon.",
"Invalid folder name. Usage of 'Shared' is reserved by ownCloud" => "Karpeta izne baliogabea. \"Shared\" karpeta erabilpena OwnCloudentzat erreserbaturik dago.",
"Error" => "Errorea",
"Share" => "Elkarbanatu",
"Delete permanently" => "Ezabatu betirako",
@ -46,6 +49,7 @@
"{count} folders" => "{count} karpeta",
"1 file" => "fitxategi bat",
"{count} files" => "{count} fitxategi",
"%s could not be renamed" => "%s ezin da berrizendatu",
"Upload" => "Igo",
"File handling" => "Fitxategien kudeaketa",
"Maximum upload size" => "Igo daitekeen gehienezko tamaina",
@ -69,6 +73,8 @@
"The files you are trying to upload exceed the maximum size for file uploads on this server." => "Igotzen saiatzen ari zaren fitxategiak zerbitzari honek igotzeko onartzen duena baino handiagoak dira.",
"Files are being scanned, please wait." => "Fitxategiak eskaneatzen ari da, itxoin mezedez.",
"Current scanning" => "Orain eskaneatzen ari da",
"directory" => "direktorioa",
"directories" => "direktorioak",
"file" => "fitxategia",
"files" => "fitxategiak",
"Upgrading filesystem cache..." => "Fitxategi sistemaren katxea eguneratzen..."

View file

@ -65,6 +65,8 @@
"The files you are trying to upload exceed the maximum size for file uploads on this server." => "Lähetettäväksi valitsemasi tiedostot ylittävät palvelimen salliman tiedostokoon rajan.",
"Files are being scanned, please wait." => "Tiedostoja tarkistetaan, odota hetki.",
"Current scanning" => "Tämänhetkinen tutkinta",
"directory" => "kansio",
"directories" => "kansiota",
"file" => "tiedosto",
"files" => "tiedostoa",
"Upgrading filesystem cache..." => "Päivitetään tiedostojärjestelmän välimuistia..."

View file

@ -73,6 +73,8 @@
"The files you are trying to upload exceed the maximum size for file uploads on this server." => "Les fichiers que vous essayez d'envoyer dépassent la taille maximale permise par ce serveur.",
"Files are being scanned, please wait." => "Les fichiers sont en cours d'analyse, veuillez patienter.",
"Current scanning" => "Analyse en cours",
"directory" => "dossier",
"directories" => "dossiers",
"file" => "fichier",
"files" => "fichiers",
"Upgrading filesystem cache..." => "Mise à niveau du cache du système de fichier"

View file

@ -1,6 +1,8 @@
<?php $TRANSLATIONS = array(
"Could not move %s - File with this name already exists" => "%s áthelyezése nem sikerült - már létezik másik fájl ezzel a névvel",
"Could not move %s" => "Nem sikerült %s áthelyezése",
"Unable to set upload directory." => "Nem található a mappa, ahova feltölteni szeretne.",
"Invalid Token" => "Hibás mappacím",
"No file was uploaded. Unknown error" => "Nem történt feltöltés. Ismeretlen hiba",
"There is no error, the file uploaded with success" => "A fájlt sikerült feltölteni",
"The uploaded file exceeds the upload_max_filesize directive in php.ini: " => "A feltöltött fájl mérete meghaladja a php.ini állományban megadott upload_max_filesize paraméter értékét.",
@ -47,6 +49,7 @@
"{count} folders" => "{count} mappa",
"1 file" => "1 fájl",
"{count} files" => "{count} fájl",
"%s could not be renamed" => "%s átnevezése nem sikerült",
"Upload" => "Feltöltés",
"File handling" => "Fájlkezelés",
"Maximum upload size" => "Maximális feltölthető fájlméret",
@ -70,6 +73,8 @@
"The files you are trying to upload exceed the maximum size for file uploads on this server." => "A feltöltendő állományok mérete meghaladja a kiszolgálón megengedett maximális méretet.",
"Files are being scanned, please wait." => "A fájllista ellenőrzése zajlik, kis türelmet!",
"Current scanning" => "Ellenőrzés alatt",
"directory" => "mappa",
"directories" => "mappa",
"file" => "fájl",
"files" => "fájlok",
"Upgrading filesystem cache..." => "A fájlrendszer gyorsítótárának frissítése zajlik..."

View file

@ -1,6 +1,7 @@
<?php $TRANSLATIONS = array(
"Could not move %s - File with this name already exists" => "Kan ikke flytte %s - En fil med samme navn finnes allerede",
"Could not move %s" => "Kunne ikke flytte %s",
"Unable to set upload directory." => "Kunne ikke sette opplastingskatalog.",
"No file was uploaded. Unknown error" => "Ingen filer ble lastet opp. Ukjent feil.",
"There is no error, the file uploaded with success" => "Pust ut, ingen feil. Filen ble lastet opp problemfritt",
"The uploaded file exceeds the upload_max_filesize directive in php.ini: " => "Filstørrelsen overskrider maksgrensedirektivet upload_max_filesize i php.ini-konfigurasjonen.",
@ -70,6 +71,8 @@
"The files you are trying to upload exceed the maximum size for file uploads on this server." => "Filene du prøver å laste opp er for store for å laste opp til denne serveren.",
"Files are being scanned, please wait." => "Skanner etter filer, vennligst vent.",
"Current scanning" => "Pågående skanning",
"directory" => "katalog",
"directories" => "kataloger",
"file" => "fil",
"files" => "filer",
"Upgrading filesystem cache..." => "Oppgraderer filsystemets mellomlager..."

View file

@ -49,6 +49,7 @@
"{count} folders" => "{count} mappen",
"1 file" => "1 bestand",
"{count} files" => "{count} bestanden",
"%s could not be renamed" => "%s kon niet worden hernoemd",
"Upload" => "Uploaden",
"File handling" => "Bestand",
"Maximum upload size" => "Maximale bestandsgrootte voor uploads",
@ -72,6 +73,8 @@
"The files you are trying to upload exceed the maximum size for file uploads on this server." => "De bestanden die u probeert te uploaden zijn groter dan de maximaal toegestane bestandsgrootte voor deze server.",
"Files are being scanned, please wait." => "Bestanden worden gescand, even wachten.",
"Current scanning" => "Er wordt gescand",
"directory" => "directory",
"directories" => "directories",
"file" => "bestand",
"files" => "bestanden",
"Upgrading filesystem cache..." => "Upgraden bestandssysteem cache..."

View file

@ -1,6 +1,8 @@
<?php $TRANSLATIONS = array(
"Could not move %s - File with this name already exists" => "Não foi possível mover o ficheiro %s - Já existe um ficheiro com esse nome",
"Could not move %s" => "Não foi possível move o ficheiro %s",
"Unable to set upload directory." => "Não foi possível criar o diretório de upload",
"Invalid Token" => "Token inválido",
"No file was uploaded. Unknown error" => "Nenhum ficheiro foi carregado. Erro desconhecido",
"There is no error, the file uploaded with success" => "Não ocorreram erros, o ficheiro foi submetido com sucesso",
"The uploaded file exceeds the upload_max_filesize directive in php.ini: " => "O ficheiro enviado excede o limite permitido na directiva do php.ini upload_max_filesize",
@ -47,6 +49,7 @@
"{count} folders" => "{count} pastas",
"1 file" => "1 ficheiro",
"{count} files" => "{count} ficheiros",
"%s could not be renamed" => "%s não pode ser renomeada",
"Upload" => "Carregar",
"File handling" => "Manuseamento de ficheiros",
"Maximum upload size" => "Tamanho máximo de envio",
@ -70,6 +73,8 @@
"The files you are trying to upload exceed the maximum size for file uploads on this server." => "Os ficheiro que está a tentar enviar excedem o tamanho máximo de envio neste servidor.",
"Files are being scanned, please wait." => "Os ficheiros estão a ser analisados, por favor aguarde.",
"Current scanning" => "Análise actual",
"directory" => "diretório",
"directories" => "diretórios",
"file" => "ficheiro",
"files" => "ficheiros",
"Upgrading filesystem cache..." => "Atualizar cache do sistema de ficheiros..."

View file

@ -1,6 +1,8 @@
<?php $TRANSLATIONS = array(
"Could not move %s - File with this name already exists" => "Невозможно переместить %s - файл с таким именем уже существует",
"Could not move %s" => "Невозможно переместить %s",
"Unable to set upload directory." => "Не удалось установить каталог загрузки.",
"Invalid Token" => "Недопустимый маркер",
"No file was uploaded. Unknown error" => "Файл не был загружен. Неизвестная ошибка",
"There is no error, the file uploaded with success" => "Файл загружен успешно.",
"The uploaded file exceeds the upload_max_filesize directive in php.ini: " => "Файл превышает размер установленный upload_max_filesize в php.ini:",
@ -30,7 +32,7 @@
"cancel" => "отмена",
"replaced {new_name} with {old_name}" => "заменено {new_name} на {old_name}",
"undo" => "отмена",
"perform delete operation" => "выполняется операция удаления",
"perform delete operation" => "выполнить операцию удаления",
"1 file uploading" => "загружается 1 файл",
"files uploading" => "файлы загружаются",
"'.' is an invalid file name." => "'.' - неправильное имя файла.",
@ -47,6 +49,7 @@
"{count} folders" => "{count} папок",
"1 file" => "1 файл",
"{count} files" => "{count} файлов",
"%s could not be renamed" => "%s не может быть переименован",
"Upload" => "Загрузка",
"File handling" => "Управление файлами",
"Maximum upload size" => "Максимальный размер загружаемого файла",
@ -70,6 +73,8 @@
"The files you are trying to upload exceed the maximum size for file uploads on this server." => "Файлы, которые вы пытаетесь загрузить, превышают лимит для файлов на этом сервере.",
"Files are being scanned, please wait." => "Подождите, файлы сканируются.",
"Current scanning" => "Текущее сканирование",
"directory" => "директория",
"directories" => "директории",
"file" => "файл",
"files" => "файлы",
"Upgrading filesystem cache..." => "Обновление кэша файловой системы..."

View file

@ -1,6 +1,8 @@
<?php $TRANSLATIONS = array(
"Could not move %s - File with this name already exists" => "Nie je možné presunúť %s - súbor s týmto menom už existuje",
"Could not move %s" => "Nie je možné presunúť %s",
"Unable to set upload directory." => "Nemožno nastaviť priečinok pre nahrané súbory.",
"Invalid Token" => "Neplatný token",
"No file was uploaded. Unknown error" => "Žiaden súbor nebol odoslaný. Neznáma chyba",
"There is no error, the file uploaded with success" => "Nenastala žiadna chyba, súbor bol úspešne nahraný",
"The uploaded file exceeds the upload_max_filesize directive in php.ini: " => "Nahraný súbor predčil konfiguračnú direktívu upload_max_filesize v súbore php.ini:",
@ -10,13 +12,13 @@
"Missing a temporary folder" => "Chýba dočasný priečinok",
"Failed to write to disk" => "Zápis na disk sa nepodaril",
"Not enough storage available" => "Nedostatok dostupného úložného priestoru",
"Invalid directory." => "Neplatný priečinok",
"Invalid directory." => "Neplatný priečinok.",
"Files" => "Súbory",
"Unable to upload your file as it is a directory or has 0 bytes" => "Nedá sa odoslať Váš súbor, pretože je to priečinok, alebo je jeho veľkosť 0 bajtov",
"Not enough space available" => "Nie je k dispozícii dostatok miesta",
"Upload cancelled." => "Odosielanie zrušené",
"Upload cancelled." => "Odosielanie zrušené.",
"File upload is in progress. Leaving the page now will cancel the upload." => "Opustenie stránky zruší práve prebiehajúce odosielanie súboru.",
"URL cannot be empty." => "URL nemôže byť prázdne",
"URL cannot be empty." => "URL nemôže byť prázdne.",
"Invalid folder name. Usage of 'Shared' is reserved by ownCloud" => "Neplatný názov priečinka. Názov \"Shared\" je rezervovaný pre ownCloud",
"Error" => "Chyba",
"Share" => "Zdieľať",
@ -47,6 +49,7 @@
"{count} folders" => "{count} priečinkov",
"1 file" => "1 súbor",
"{count} files" => "{count} súborov",
"%s could not be renamed" => "%s nemohol byť premenovaný",
"Upload" => "Odoslať",
"File handling" => "Nastavenie správania sa k súborom",
"Maximum upload size" => "Maximálna veľkosť odosielaného súboru",
@ -70,6 +73,8 @@
"The files you are trying to upload exceed the maximum size for file uploads on this server." => "Súbory, ktoré sa snažíte nahrať, presahujú maximálnu veľkosť pre nahratie súborov na tento server.",
"Files are being scanned, please wait." => "Čakajte, súbory sú prehľadávané.",
"Current scanning" => "Práve prezerané",
"directory" => "priečinok",
"directories" => "priečinky",
"file" => "súbor",
"files" => "súbory",
"Upgrading filesystem cache..." => "Aktualizujem medzipamäť súborového systému..."

View file

@ -1,5 +1,5 @@
<?php $TRANSLATIONS = array(
"Could not move %s - File with this name already exists" => "Ni mogoče premakniti %s - datoteka s tem imenom že obstaja",
"Could not move %s - File with this name already exists" => "%s ni mogoče premakniti - datoteka s tem imenom že obstaja",
"Could not move %s" => "Ni mogoče premakniti %s",
"Unable to set upload directory." => "Mapo, v katero boste prenašali dokumente, ni mogoče določiti",
"Invalid Token" => "Neveljaven žeton",
@ -49,6 +49,7 @@
"{count} folders" => "{count} map",
"1 file" => "1 datoteka",
"{count} files" => "{count} datotek",
"%s could not be renamed" => "%s ni bilo mogoče preimenovati",
"Upload" => "Pošlji",
"File handling" => "Upravljanje z datotekami",
"Maximum upload size" => "Največja velikost za pošiljanja",
@ -72,6 +73,8 @@
"The files you are trying to upload exceed the maximum size for file uploads on this server." => "Datoteke, ki jih želite poslati, presegajo največjo dovoljeno velikost na strežniku.",
"Files are being scanned, please wait." => "Poteka preučevanje datotek, počakajte ...",
"Current scanning" => "Trenutno poteka preučevanje",
"directory" => "direktorij",
"directories" => "direktoriji",
"file" => "datoteka",
"files" => "datoteke",
"Upgrading filesystem cache..." => "Nadgrajevanje predpomnilnika datotečnega sistema ..."

View file

@ -1,6 +1,8 @@
<?php $TRANSLATIONS = array(
"Could not move %s - File with this name already exists" => "%s taşınamadı. Bu isimde dosya zaten var.",
"Could not move %s" => "%s taşınamadı",
"Unable to set upload directory." => "Yükleme dizini tanımlanamadı.",
"Invalid Token" => "Geçeriz simge",
"No file was uploaded. Unknown error" => "Dosya yüklenmedi. Bilinmeyen hata",
"There is no error, the file uploaded with success" => "Dosya başarıyla yüklendi, hata oluşmadı",
"The uploaded file exceeds the upload_max_filesize directive in php.ini: " => "php.ini dosyasında upload_max_filesize ile belirtilen dosya yükleme sınırııldı.",
@ -47,6 +49,7 @@
"{count} folders" => "{count} dizin",
"1 file" => "1 dosya",
"{count} files" => "{count} dosya",
"%s could not be renamed" => "%s yeniden adlandırılamadı",
"Upload" => "Yükle",
"File handling" => "Dosya taşıma",
"Maximum upload size" => "Maksimum yükleme boyutu",
@ -70,6 +73,8 @@
"The files you are trying to upload exceed the maximum size for file uploads on this server." => "Yüklemeye çalıştığınız dosyalar bu sunucudaki maksimum yükleme boyutunu aşıyor.",
"Files are being scanned, please wait." => "Dosyalar taranıyor, lütfen bekleyin.",
"Current scanning" => "Güncel tarama",
"directory" => "dizin",
"directories" => "dizinler",
"file" => "dosya",
"files" => "dosyalar",
"Upgrading filesystem cache..." => "Sistem dosyası önbelleği güncelleniyor"

View file

@ -1,18 +1,28 @@
<?php $TRANSLATIONS = array(
"Could not move %s - File with this name already exists" => "无法移动 %s - 存在同名文件",
"Could not move %s" => "无法移动 %s",
"Unable to set upload directory." => "无法设置上传文件夹",
"Invalid Token" => "非法Token",
"No file was uploaded. Unknown error" => "没有上传文件。未知错误",
"There is no error, the file uploaded with success" => "文件上传成功",
"The uploaded file exceeds the upload_max_filesize directive in php.ini: " => "上传的文件超过了php.ini指定的upload_max_filesize",
"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "上传的文件超过了 HTML 表格中指定的 MAX_FILE_SIZE 选项",
"The uploaded file was only partially uploaded" => "文件部分上传",
"No file was uploaded" => "没有上传文件",
"Missing a temporary folder" => "缺失临时文件夹",
"Failed to write to disk" => "写磁盘失败",
"Not enough storage available" => "容量不足",
"Invalid directory." => "无效文件夹",
"Files" => "文件",
"Unable to upload your file as it is a directory or has 0 bytes" => "不能上传您的文件,由于它是文件夹或者为空文件",
"Not enough space available" => "容量不足",
"Upload cancelled." => "上传取消了",
"File upload is in progress. Leaving the page now will cancel the upload." => "文件正在上传。关闭页面会取消上传。",
"URL cannot be empty." => "网址不能为空。",
"Invalid folder name. Usage of 'Shared' is reserved by ownCloud" => "无效文件夹名。“Shared”已经被系统保留。",
"Error" => "出错",
"Share" => "分享",
"Delete permanently" => "永久删除",
"Delete" => "删除",
"Rename" => "重命名",
"Pending" => "等待中",
@ -22,8 +32,16 @@
"cancel" => "取消",
"replaced {new_name} with {old_name}" => "已用 {old_name} 替换 {new_name}",
"undo" => "撤销",
"perform delete operation" => "执行删除",
"1 file uploading" => "1 个文件正在上传",
"files uploading" => "个文件正在上传",
"'.' is an invalid file name." => "'.' 文件名不正确",
"File name cannot be empty." => "文件名不能为空",
"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "文件名内不能包含以下符号:\\ / < > : \" | ?和 *",
"Your storage is full, files can not be updated or synced anymore!" => "容量已满,不能再同步/上传文件了!",
"Your storage is almost full ({usedSpacePercent}%)" => "你的空间快用满了 ({usedSpacePercent}%)",
"Your download is being prepared. This might take some time if the files are big." => "正在下载,可能会花点时间,跟文件大小有关",
"Invalid folder name. Usage of 'Shared' is reserved by Owncloud" => "不正确文件夹名。Shared是保留名不能使用。",
"Name" => "名称",
"Size" => "大小",
"Modified" => "修改日期",
@ -31,6 +49,7 @@
"{count} folders" => "{count} 个文件夹",
"1 file" => "1 个文件",
"{count} files" => "{count} 个文件",
"%s could not be renamed" => "不能重命名 %s",
"Upload" => "上传",
"File handling" => "文件处理中",
"Maximum upload size" => "最大上传大小",
@ -44,7 +63,9 @@
"Text file" => "文本文档",
"Folder" => "文件夹",
"From link" => "来自链接",
"Deleted files" => "已删除的文件",
"Cancel upload" => "取消上传",
"You dont have write permissions here." => "您没有写入权限。",
"Nothing in here. Upload something!" => "这里没有东西.上传点什么!",
"Download" => "下载",
"Unshare" => "取消分享",
@ -52,6 +73,9 @@
"The files you are trying to upload exceed the maximum size for file uploads on this server." => "你正在试图上传的文件超过了此服务器支持的最大的文件大小.",
"Files are being scanned, please wait." => "正在扫描文件,请稍候.",
"Current scanning" => "正在扫描",
"directory" => "文件夹",
"directories" => "文件夹",
"file" => "文件",
"files" => "文件"
"files" => "文件",
"Upgrading filesystem cache..." => "升级系统缓存..."
);

View file

@ -1,6 +1,8 @@
<?php $TRANSLATIONS = array(
"Could not move %s - File with this name already exists" => "無法移動 %s - 同名的檔案已經存在",
"Could not move %s" => "無法移動 %s",
"Unable to set upload directory." => "無法設定上傳目錄。",
"Invalid Token" => "無效的 token",
"No file was uploaded. Unknown error" => "沒有檔案被上傳。未知的錯誤。",
"There is no error, the file uploaded with success" => "無錯誤,檔案上傳成功",
"The uploaded file exceeds the upload_max_filesize directive in php.ini: " => "上傳的檔案大小超過 php.ini 當中 upload_max_filesize 參數的設定:",
@ -47,6 +49,7 @@
"{count} folders" => "{count} 個資料夾",
"1 file" => "1 個檔案",
"{count} files" => "{count} 個檔案",
"%s could not be renamed" => "無法重新命名 %s",
"Upload" => "上傳",
"File handling" => "檔案處理",
"Maximum upload size" => "最大上傳檔案大小",
@ -70,5 +73,9 @@
"The files you are trying to upload exceed the maximum size for file uploads on this server." => "您試圖上傳的檔案已超過伺服器的最大檔案大小限制。",
"Files are being scanned, please wait." => "正在掃描檔案,請稍等。",
"Current scanning" => "目前掃描",
"directory" => "目錄",
"directories" => "目錄",
"file" => "檔案",
"files" => "檔案",
"Upgrading filesystem cache..." => "正在升級檔案系統快取..."
);

View file

@ -61,7 +61,7 @@
<div id="emptyfolder"><?php p($l->t('Nothing in here. Upload something!'))?></div>
<?php endif; ?>
<table id="filestable">
<table id="filestable" data-allow-public-upload="<?php p($_['publicUploadEnabled'])?>">
<thead>
<tr>
<th id='headerName'>
@ -77,7 +77,7 @@
<?php endif; ?>
</span>
</th>
<th id="headerSize"><?php p($l->t( 'Size' )); ?></th>
<th id="headerSize"><?php p($l->t('Size')); ?></th>
<th id="headerDate">
<span id="modified"><?php p($l->t( 'Modified' )); ?></span>
<?php if ($_['permissions'] & OCP\PERMISSION_DELETE): ?>

View file

@ -7,8 +7,7 @@
<?php endif;?>
<?php for($i=0; $i<count($_["breadcrumb"]); $i++):
$crumb = $_["breadcrumb"][$i];
$dir = str_replace('+', '%20', urlencode($crumb["dir"]));
$dir = str_replace('%2F', '/', $dir); ?>
$dir = \OCP\Util::encodePath($crumb["dir"]); ?>
<div class="crumb <?php if($i == count($_["breadcrumb"])-1) p('last');?> svg"
data-dir='<?php p($dir);?>'>
<a href="<?php p($_['baseURL'].$dir); ?>"><?php p($crumb["name"]); ?></a>

View file

@ -9,7 +9,6 @@ $totalsize = 0; ?>
} else {
$totalfiles++;
}
$simple_file_size = OCP\simple_file_size($file['size']);
// the bigger the file, the darker the shade of grey; megabytes*2
$simple_size_color = intval(160-$file['size']/(1024*1024)*2);
if($simple_size_color<0) $simple_size_color = 0;
@ -17,10 +16,8 @@ $totalsize = 0; ?>
// the older the file, the brighter the shade of grey; days*14
$relative_date_color = round((time()-$file['mtime'])/60/60/24*14);
if($relative_date_color>160) $relative_date_color = 160;
$name = rawurlencode($file['name']);
$name = str_replace('%2F', '/', $name);
$directory = rawurlencode($file['directory']);
$directory = str_replace('%2F', '/', $directory); ?>
$name = \OCP\Util::encodePath($file['name']);
$directory = \OCP\Util::encodePath($file['directory']); ?>
<tr data-id="<?php p($file['fileid']); ?>"
data-file="<?php p($name);?>"
data-type="<?php ($file['type'] == 'dir')?p('dir'):p('file')?>"
@ -54,9 +51,8 @@ $totalsize = 0; ?>
</a>
</td>
<td class="filesize"
title="<?php p(OCP\human_file_size($file['size'])); ?>"
style="color:rgb(<?php p($simple_size_color.','.$simple_size_color.','.$simple_size_color) ?>)">
<?php print_unescaped($simple_file_size); ?>
<?php print_unescaped(OCP\human_file_size($file['size'])); ?>
</td>
<td class="date">
<span class="modified"
@ -93,7 +89,7 @@ $totalsize = 0; ?>
} ?>
</span></td>
<td class="filesize">
<?php print_unescaped(OCP\simple_file_size($totalsize)); ?>
<?php print_unescaped(OCP\human_file_size($totalsize)); ?>
</td>
<td></td>
</tr>

View file

@ -2,7 +2,7 @@
<info>
<id>files_encryption</id>
<name>Encryption</name>
<description>WARNING: This is a preview release of the new ownCloud 5 encryption system. Testing and feedback is very welcome but don't use this in production yet. After the app was enabled you need to re-login to initialize your encryption keys</description>
<description>The new ownCloud 5 files encryption system. After the app was enabled you need to re-login to initialize your encryption keys.</description>
<licence>AGPL</licence>
<author>Sam Tuke, Bjoern Schiessle, Florin Peter</author>
<require>4</require>

View file

@ -8,10 +8,13 @@
"Private key password successfully updated." => "Heslo soukromého klíče úspěšně aktualizováno.",
"Could not update the private key password. Maybe the old password was not correct." => "Nelze aktualizovat heslo soukromého klíče. Možná nebylo staré heslo správně.",
"Saving..." => "Ukládám...",
"personal settings" => "osobní nastavení",
"Encryption" => "Šifrování",
"Enabled" => "Povoleno",
"Disabled" => "Zakázáno",
"Change Password" => "Změnit heslo",
"Old log-in password" => "Staré přihlašovací heslo",
"Current log-in password" => "Aktuální přihlašovací heslo",
"Enable password recovery:" => "Povolit obnovu hesla:",
"Enabling this option will allow you to reobtain access to your encrypted files in case of password loss" => "Povolení vám umožní znovu získat přístup k vašim zašifrovaným souborům pokud ztratíte heslo",
"File recovery settings updated" => "Možnosti obnovy souborů aktualizovány",

View file

@ -6,13 +6,31 @@
"Password successfully changed." => "Dein Passwort wurde geändert.",
"Could not change the password. Maybe the old password was not correct." => "Das Passwort konnte nicht geändert werden. Vielleicht war das alte Passwort falsch.",
"Private key password successfully updated." => "Passwort des privaten Schlüssels erfolgreich aktualisiert",
"Could not update the private key password. Maybe the old password was not correct." => "Das Passwort des privaten Schlüssels konnte nicht aktualisiert werden. Eventuell war das alte Passwort falsch.",
"Your private key is not valid! Likely your password was changed outside the ownCloud system (e.g. your corporate directory). You can update your private key password in your personal settings to recover access to your encrypted files." => "Dein privater Schlüssel ist ungültig. Möglicher Weise wurde von außerhalb Dein Passwort geändert (z.B. in deinem gemeinsamen Verzeichnis). Du kannst das Passwort deines privaten Schlüssels in den persönlichen Einstellungen aktualisieren, um wieder an deine Dateien zu gelangen.",
"Missing requirements." => "Fehlende Vorraussetzungen",
"Please make sure that PHP 5.3.3 or newer is installed and that the OpenSSL PHP extension is enabled and configured properly. For now, the encryption app has been disabled." => "Bitte stellen Sie sicher, dass PHP 5.3.3 oder neuer installiert ist und die OpenSSL-PHP-Erweiterung aktiviert und richtig konfiguriert ist. Die Verschlüsselungsanwendung wurde vorerst deaktiviert.",
"Saving..." => "Speichern...",
"Your private key is not valid! Maybe the your password was changed from outside." => "Ihr privater Schlüssel ist ungültig! Eventuell wurde Ihr Passwort von außerhalb geändert.",
"You can unlock your private key in your " => "Du kannst den privaten Schlüssel ändern und zwar in deinem",
"personal settings" => "Private Einstellungen",
"Encryption" => "Verschlüsselung",
"Enable recovery key (allow to recover users files in case of password loss):" => "Wiederherstellungsschlüssel aktivieren (ermöglicht das Wiederherstellen von Dateien, falls das Passwort vergessen wurde):",
"Recovery key password" => "Wiederherstellungsschlüssel-Passwort",
"Enabled" => "Aktiviert",
"Disabled" => "Deaktiviert",
"Change recovery key password:" => "Wiederherstellungsschlüssel-Passwort ändern:",
"Old Recovery key password" => "Altes Wiederherstellungsschlüssel-Passwort",
"New Recovery key password" => "Neues Wiederherstellungsschlüssel-Passwort",
"Change Password" => "Passwort ändern",
"Your private key password no longer match your log-in password:" => "Ihr Passwort für ihren privaten Schlüssel stimmt nicht mehr mit ihrem Loginpasswort überein.",
"Set your old private key password to your current log-in password." => "Setzen Sie ihr altes Passwort für ihren privaten Schlüssel auf ihr aktuelles Login-Passwort",
" If you don't remember your old password you can ask your administrator to recover your files." => "Wenn Sie Ihr altes Passwort vergessen haben, können Sie den Administrator bitten, Ihre Daten wiederherzustellen.",
"Old log-in password" => "Altes login Passwort",
"Current log-in password" => "Aktuelles Passwort",
"File recovery settings updated" => "Einstellungen zur Wiederherstellung von Dateien wurden aktualisiert"
"Update Private Key Password" => "Passwort für den privaten Schlüssel aktualisieren",
"Enable password recovery:" => "Passwortwiederherstellung aktivvieren:",
"Enabling this option will allow you to reobtain access to your encrypted files in case of password loss" => "Wenn Sie diese Option aktivieren, können Sie Ihre verschlüsselten Dateien wiederherstellen, falls Sie Ihr Passwort vergessen",
"File recovery settings updated" => "Einstellungen zur Wiederherstellung von Dateien wurden aktualisiert",
"Could not update file recovery" => "Dateiwiederherstellung konnte nicht aktualisiert werden"
);

View file

@ -29,7 +29,7 @@
"Old log-in password" => "Altes Login-Passwort",
"Current log-in password" => "Momentanes Login-Passwort",
"Update Private Key Password" => "Das Passwort des privaten Schlüssels aktualisieren",
"Enable password recovery:" => "Passwort-Wiederherstellung aktivieren:",
"Enable password recovery:" => "Die Passwort-Wiederherstellung aktivieren:",
"Enabling this option will allow you to reobtain access to your encrypted files in case of password loss" => "Durch die Aktivierung dieser Option haben Sie die Möglichkeit, wieder auf Ihre verschlüsselten Dateien zugreifen zu können, wenn Sie Ihr Passwort verloren haben.",
"File recovery settings updated" => "Die Einstellungen für die Dateiwiederherstellung wurden aktualisiert.",
"Could not update file recovery" => "Die Dateiwiederherstellung konnte nicht aktualisiert werden."

View file

@ -6,13 +6,16 @@
"Password successfully changed." => "Tu contraseña fue cambiada",
"Could not change the password. Maybe the old password was not correct." => "No se pudo cambiar la contraseña. Comprobá que la contraseña actual sea correcta.",
"Private key password successfully updated." => "Contraseña de clave privada actualizada con éxito.",
"Could not update the private key password. Maybe the old password was not correct." => "No fue posible actualizar la contraseña de la clave privada. Tal vez la contraseña antigua no es correcta.",
"Could not update the private key password. Maybe the old password was not correct." => "No fue posible actualizar la contraseña de clave privada. Tal vez la contraseña anterior no es correcta.",
"Your private key is not valid! Likely your password was changed outside the ownCloud system (e.g. your corporate directory). You can update your private key password in your personal settings to recover access to your encrypted files." => "¡Tu clave privada no es válida! Tal vez tu contraseña fue cambiada desde fuera del sistema de ownCloud (por ej. desde tu cuenta de sistema). Podés actualizar tu clave privada en la sección de \"configuración personal\", para recuperar el acceso a tus archivos.",
"Missing requirements." => "Requisitos incompletos.",
"Please make sure that PHP 5.3.3 or newer is installed and that the OpenSSL PHP extension is enabled and configured properly. For now, the encryption app has been disabled." => "Por favor, asegurate que PHP 5.3.3 o posterior esté instalado y que la extensión OpenSSL de PHP esté habilitada y configurada correctamente. Por el momento, la aplicación de encriptación está deshabilitada.",
"Saving..." => "Guardando...",
"Your private key is not valid! Maybe the your password was changed from outside." => "¡Tu clave privada no es válida! Tal vez tu contraseña fue cambiada desde afuera.",
"You can unlock your private key in your " => "Podés desbloquear tu clave privada en tu",
"personal settings" => "Configuración personal",
"Encryption" => "Encriptación",
"Enable recovery key (allow to recover users files in case of password loss):" => "Habilitar clave de recuperación (te permite recuperar los archivos de usuario en el caso en que pierdas la contraseña):",
"Enable recovery key (allow to recover users files in case of password loss):" => "Habilitar clave de recuperación (te permite recuperar los archivos de usuario en el caso que pierdas la contraseña):",
"Recovery key password" => "Contraseña de recuperación de clave",
"Enabled" => "Habilitado",
"Disabled" => "Deshabilitado",
@ -20,14 +23,14 @@
"Old Recovery key password" => "Contraseña antigua de recuperación de clave",
"New Recovery key password" => "Nueva contraseña de recuperación de clave",
"Change Password" => "Cambiar contraseña",
"Your private key password no longer match your log-in password:" => "Tu contraseña de recuperación de clave ya no coincide con la contraseña de ingreso:",
"Set your old private key password to your current log-in password." => "Usá tu contraseña de recuperación de clave antigua para tu contraseña de ingreso actual.",
"Your private key password no longer match your log-in password:" => "Tu contraseña de clave privada ya no coincide con la contraseña de ingreso:",
"Set your old private key password to your current log-in password." => "Usá tu contraseña de clave privada antigua para tu contraseña de ingreso actual.",
" If you don't remember your old password you can ask your administrator to recover your files." => "Si no te acordás de tu contraseña antigua, pedile al administrador que recupere tus archivos",
"Old log-in password" => "Contraseña anterior",
"Current log-in password" => "Contraseña actual",
"Update Private Key Password" => "Actualizar contraseña de la clave privada",
"Enable password recovery:" => "Habilitar contraseña de recuperación:",
"Enabling this option will allow you to reobtain access to your encrypted files in case of password loss" => "Habilitando esta opción te va a permitir tener acceso a tus archivos encriptados incluso si perdés la contraseña",
"Enable password recovery:" => "Habilitar recuperación de contraseña:",
"Enabling this option will allow you to reobtain access to your encrypted files in case of password loss" => "Habilitando esta opción, vas a tener acceso a tus archivos encriptados, incluso si perdés la contraseña",
"File recovery settings updated" => "Las opciones de recuperación de archivos fueron actualizadas",
"Could not update file recovery" => "No fue posible actualizar la recuperación de archivos"
);

View file

@ -1,4 +1,36 @@
<?php $TRANSLATIONS = array(
"Recovery key successfully enabled" => "کلید بازیابی با موفقیت فعال شده است.",
"Could not enable recovery key. Please check your recovery key password!" => "کلید بازیابی نمی تواند فعال شود. لطفا رمزعبور کلید بازیابی خود را بررسی نمایید!",
"Recovery key successfully disabled" => "کلید بازیابی با موفقیت غیر فعال شده است.",
"Could not disable recovery key. Please check your recovery key password!" => "کلید بازیابی را نمی تواند غیرفعال نماید. لطفا رمزعبور کلید بازیابی خود را بررسی کنید!",
"Password successfully changed." => "رمزعبور با موفقیت تغییر یافت.",
"Could not change the password. Maybe the old password was not correct." => "رمزعبور را نمیتواند تغییر دهد. شاید رمزعبورقدیمی صحیح نمی باشد.",
"Private key password successfully updated." => "رمزعبور کلید خصوصی با موفقیت به روز شد.",
"Could not update the private key password. Maybe the old password was not correct." => "رمزعبور کلید خصوصی را نمی تواند به روز کند. شاید رمزعبور قدیمی صحیح نمی باشد.",
"Your private key is not valid! Likely your password was changed outside the ownCloud system (e.g. your corporate directory). You can update your private key password in your personal settings to recover access to your encrypted files." => "کلید خصوصی شما معتبر نمی باشد! ظاهرا رمزعبور شما بیرون از سیستم ownCloud تغییر یافته است( به عنوان مثال پوشه سازمان شما ). شما میتوانید رمزعبور کلید خصوصی خود را در تنظیمات شخصیتان به روز کنید تا بتوانید به فایل های رمزگذاری شده خود را دسترسی داشته باشید.",
"Missing requirements." => "نیازمندی های گمشده",
"Please make sure that PHP 5.3.3 or newer is installed and that the OpenSSL PHP extension is enabled and configured properly. For now, the encryption app has been disabled." => "لطفا مطمئن شوید که PHP 5.3.3 یا جدیدتر نصب شده و پسوند OpenSSL PHP فعال است و به درستی پیکربندی شده است. در حال حاضر، برنامه رمزگذاری غیر فعال شده است.",
"Saving..." => "در حال ذخیره سازی...",
"Encryption" => "رمزگذاری"
"Your private key is not valid! Maybe the your password was changed from outside." => "کلید خصوصی شما معتبر نیست! شاید رمزعبوراز بیرون تغییر یافته است.",
"You can unlock your private key in your " => "شما میتوانید کلید خصوصی خود را باز نمایید.",
"personal settings" => "تنظیمات شخصی",
"Encryption" => "رمزگذاری",
"Enable recovery key (allow to recover users files in case of password loss):" => "فعال کردن کلید بازیابی(اجازه بازیابی فایل های کاربران در صورت از دست دادن رمزعبور):",
"Recovery key password" => "رمزعبور کلید بازیابی",
"Enabled" => "فعال شده",
"Disabled" => "غیرفعال شده",
"Change recovery key password:" => "تغییر رمزعبور کلید بازیابی:",
"Old Recovery key password" => "رمزعبور قدیمی کلید بازیابی ",
"New Recovery key password" => "رمزعبور جدید کلید بازیابی",
"Change Password" => "تغییر رمزعبور",
"Your private key password no longer match your log-in password:" => "رمزعبور کلید خصوصی شما با رمزعبور شما یکسان نیست :",
"Set your old private key password to your current log-in password." => "رمزعبور قدیمی کلید خصوصی خود را با رمزعبور فعلی تنظیم نمایید.",
" If you don't remember your old password you can ask your administrator to recover your files." => "اگر رمزعبور قدیمی را فراموش کرده اید میتوانید از مدیر خود برای بازیابی فایل هایتان درخواست نمایید.",
"Old log-in password" => "رمزعبور قدیمی",
"Current log-in password" => "رمزعبور فعلی",
"Update Private Key Password" => "به روز رسانی رمزعبور کلید خصوصی",
"Enable password recovery:" => "فعال سازی بازیابی رمزعبور:",
"Enabling this option will allow you to reobtain access to your encrypted files in case of password loss" => "فعال کردن این گزینه به شما اجازه خواهد داد در صورت از دست دادن رمزعبور به فایل های رمزگذاری شده خود دسترسی داشته باشید.",
"File recovery settings updated" => "تنظیمات بازیابی فایل به روز شده است.",
"Could not update file recovery" => "به روز رسانی بازیابی فایل را نمی تواند انجام دهد."
);

View file

@ -8,6 +8,8 @@
"Private key password successfully updated." => "Mot de passe de la clé privé mis à jour avec succès.",
"Could not update the private key password. Maybe the old password was not correct." => "Impossible de mettre à jour le mot de passe de la clé privé. Peut-être que l'ancien mot de passe n'était pas correcte.",
"Your private key is not valid! Likely your password was changed outside the ownCloud system (e.g. your corporate directory). You can update your private key password in your personal settings to recover access to your encrypted files." => "Votre clé de sécurité privée n'est pas valide! Il est probable que votre mot de passe ait été changé sans passer par le système ownCloud (par éxemple: le serveur de votre entreprise). Ain d'avoir à nouveau accès à vos fichiers cryptés, vous pouvez mettre à jour votre clé de sécurité privée dans les paramètres personnels de votre compte.",
"Missing requirements." => "Système minimum requis non respecté.",
"Please make sure that PHP 5.3.3 or newer is installed and that the OpenSSL PHP extension is enabled and configured properly. For now, the encryption app has been disabled." => "Veuillez vous assurer qu'une version de PHP 5.3.3 ou plus récente est installée et que l'extension OpenSSL de PHP est activée et configurée correctement. En attendant, l'application de cryptage a été désactivée.",
"Saving..." => "Enregistrement...",
"Your private key is not valid! Maybe the your password was changed from outside." => "Votre clef privée est invalide ! Votre mot de passe a peut-être été modifié depuis l'extérieur.",
"You can unlock your private key in your " => "Vous pouvez déverrouiller votre clé privée dans votre",

View file

@ -8,6 +8,8 @@
"Private key password successfully updated." => "Password della chiave privata aggiornata correttamente.",
"Could not update the private key password. Maybe the old password was not correct." => "Impossibile aggiornare la password della chiave privata. Forse la vecchia password non era corretta.",
"Your private key is not valid! Likely your password was changed outside the ownCloud system (e.g. your corporate directory). You can update your private key password in your personal settings to recover access to your encrypted files." => "La chiave privata non è valida! Forse la password è stata cambiata esternamente al sistema di ownCloud (ad es. la directory aziendale). Puoi aggiornare la password della chiave privata nelle impostazioni personali per ottenere nuovamente l'accesso ai file.",
"Missing requirements." => "Requisiti mancanti.",
"Please make sure that PHP 5.3.3 or newer is installed and that the OpenSSL PHP extension is enabled and configured properly. For now, the encryption app has been disabled." => "Assicurati che sia installato PHP 5.3.3 o versioni successive e che l'estensione OpenSSL di PHP sia abilitata e configurata correttamente. Per ora, l'applicazione di cifratura è disabilitata.",
"Saving..." => "Salvataggio in corso...",
"Your private key is not valid! Maybe the your password was changed from outside." => "La tua chiave privata non è valida! Forse è stata modifica dall'esterno.",
"You can unlock your private key in your " => "Puoi sbloccare la chiave privata nelle tue",

View file

@ -1,4 +1,18 @@
<?php $TRANSLATIONS = array(
"Password successfully changed." => "암호가 성공적으로 변경되었습니다",
"Could not change the password. Maybe the old password was not correct." => "암호를 변경할수 없습니다. 아마도 예전 암호가 정확하지 않은것 같습니다.",
"Private key password successfully updated." => "개인키 암호가 성공적으로 업데이트 됨.",
"Saving..." => "저장 중...",
"Encryption" => "암호화"
"personal settings" => "개인 설정",
"Encryption" => "암호화",
"Recovery key password" => "키 비밀번호 복구",
"Change recovery key password:" => "복구 키 비밀번호 변경",
"Old Recovery key password" => "예전 복구 키 비밀번호",
"New Recovery key password" => "새 복구 키 비밀번호",
"Change Password" => "암호 변경",
"Old log-in password" => "예전 로그인 암호",
"Current log-in password" => "현재 로그인 암호",
"Update Private Key Password" => "개인 키 암호 업데이트",
"File recovery settings updated" => "파일 복구 설정 업데이트됨",
"Could not update file recovery" => "파일 복구를 업데이트 할수 없습니다"
);

View file

@ -5,11 +5,15 @@
"Could not disable recovery key. Please check your recovery key password!" => "Não foi possível desactivar a chave de recuperação. Por favor verifique a password da chave de recuperação.",
"Password successfully changed." => "Password alterada com sucesso.",
"Could not change the password. Maybe the old password was not correct." => "Não foi possivel alterar a password. Possivelmente a password antiga não está correcta.",
"Your private key is not valid! Likely your password was changed outside the ownCloud system (e.g. your corporate directory). You can update your private key password in your personal settings to recover access to your encrypted files." => "Chave privada não é válida! Provavelmente senha foi alterada fora do sistema ownCloud (exemplo, o diretório corporativo). Pode atualizar password da chave privada em configurações personalizadas para recuperar o acesso aos seus arquivos encriptados.",
"Please make sure that PHP 5.3.3 or newer is installed and that the OpenSSL PHP extension is enabled and configured properly. For now, the encryption app has been disabled." => "Por favor, certifique-se que PHP 5.3.3 ou mais recente está instalado e que a extensão PHP OpenSSL está ativada e corretamente configurada. Por agora, a encripitação está desativado.",
"Saving..." => "A guardar...",
"personal settings" => "configurações personalizadas ",
"Encryption" => "Encriptação",
"Enabled" => "Activado",
"Disabled" => "Desactivado",
"Change Password" => "Mudar a Password",
"Enable password recovery:" => "ativar recuperação do password:",
"File recovery settings updated" => "Actualizadas as definições de recuperação de ficheiros",
"Could not update file recovery" => "Não foi possível actualizar a recuperação de ficheiros"
);

View file

@ -7,6 +7,9 @@
"Could not change the password. Maybe the old password was not correct." => "Невозможно изменить пароль. Возможно старый пароль не был верен.",
"Private key password successfully updated." => "Пароль секретного ключа успешно обновлён.",
"Could not update the private key password. Maybe the old password was not correct." => "Невозможно обновить пароль от секретного ключа. Возможно, старый пароль указан неверно.",
"Your private key is not valid! Likely your password was changed outside the ownCloud system (e.g. your corporate directory). You can update your private key password in your personal settings to recover access to your encrypted files." => "Ваш секретный ключ не действителен! Вероятно, ваш пароль был изменен вне системы OwnCloud (например, корпоративный каталог). Вы можете обновить секретный ключ в личных настройках на странице восстановления доступа к зашифрованным файлам. ",
"Missing requirements." => "Требования отсутствуют.",
"Please make sure that PHP 5.3.3 or newer is installed and that the OpenSSL PHP extension is enabled and configured properly. For now, the encryption app has been disabled." => "Пожалуйста, убедитесь, что PHP 5.3.3 или новее установлен и что расширение OpenSSL PHP включен и настроен. В настоящее время, шифрование для приложения было отключено.",
"Saving..." => "Сохранение...",
"Your private key is not valid! Maybe the your password was changed from outside." => "Секретный ключ недействителен! Возможно, Ваш пароль был изменён в другой программе.",
"You can unlock your private key in your " => "Вы можете разблокировать закрытый ключ в своём ",

View file

@ -8,6 +8,8 @@
"Private key password successfully updated." => "Den privata lösenordsnyckeln uppdaterades utan problem.",
"Could not update the private key password. Maybe the old password was not correct." => "Kunde inte uppdatera den privata lösenordsnyckeln. Kanske var det gamla lösenordet fel.",
"Your private key is not valid! Likely your password was changed outside the ownCloud system (e.g. your corporate directory). You can update your private key password in your personal settings to recover access to your encrypted files." => "Din privata lösenordsnyckel är inte giltig! Troligen har ditt lösenord ändrats utanför ownCloud (t.ex. i företagets katalogtjänst). Du kan uppdatera den privata lösenordsnyckeln under dina personliga inställningar för att återfå tillgång till dina filer.",
"Missing requirements." => "Krav som saknas",
"Please make sure that PHP 5.3.3 or newer is installed and that the OpenSSL PHP extension is enabled and configured properly. For now, the encryption app has been disabled." => "Kontrollera att PHP 5.3.3 eller senare är installerad och att tillägget OpenSSL PHP är aktiverad och rätt inställd. Kryperingsappen är därför tillsvidare inaktiverad.",
"Saving..." => "Sparar...",
"Your private key is not valid! Maybe the your password was changed from outside." => "Din privata lösenordsnyckel är inte giltig! Kanske byttes ditt lösenord från utsidan.",
"You can unlock your private key in your " => "Du kan låsa upp din privata nyckel i dina",

View file

@ -14,6 +14,7 @@ require_once realpath(dirname(__FILE__) . '/../lib/stream.php');
require_once realpath(dirname(__FILE__) . '/../lib/util.php');
require_once realpath(dirname(__FILE__) . '/../lib/helper.php');
require_once realpath(dirname(__FILE__) . '/../appinfo/app.php');
require_once realpath(dirname(__FILE__) . '/util.php');
use OCA\Encryption;
@ -22,6 +23,8 @@ use OCA\Encryption;
*/
class Test_Encryption_Keymanager extends \PHPUnit_Framework_TestCase {
const TEST_USER = "test-keymanager-user";
public $userId;
public $pass;
public $stateFilesTrashbin;
@ -47,17 +50,9 @@ class Test_Encryption_Keymanager extends \PHPUnit_Framework_TestCase {
// disable file proxy by default
\OC_FileProxy::$enabled = false;
// setup filesystem
\OC_Util::tearDownFS();
\OC_User::setUserId('');
\OC\Files\Filesystem::tearDown();
\OC_Util::setupFS('admin');
\OC_User::setUserId('admin');
// login admin
$params['uid'] = 'admin';
$params['password'] = 'admin';
OCA\Encryption\Hooks::login($params);
// create test user
\OC_User::deleteUser(\Test_Encryption_Keymanager::TEST_USER);
\Test_Encryption_Util::loginHelper(\Test_Encryption_Keymanager::TEST_USER, true);
}
function setUp() {
@ -75,9 +70,9 @@ class Test_Encryption_Keymanager extends \PHPUnit_Framework_TestCase {
$this->view = new \OC_FilesystemView('/');
\OC_User::setUserId('admin');
$this->userId = 'admin';
$this->pass = 'admin';
\OC_User::setUserId(\Test_Encryption_Keymanager::TEST_USER);
$this->userId = \Test_Encryption_Keymanager::TEST_USER;
$this->pass = \Test_Encryption_Keymanager::TEST_USER;
$userHome = \OC_User::getHome($this->userId);
$this->dataDir = str_replace('/' . $this->userId, '', $userHome);
@ -101,6 +96,9 @@ class Test_Encryption_Keymanager extends \PHPUnit_Framework_TestCase {
public static function tearDownAfterClass() {
\OC_FileProxy::$enabled = true;
// cleanup test user
\OC_User::deleteUser(\Test_Encryption_Keymanager::TEST_USER);
}
/**
@ -226,9 +224,9 @@ class Test_Encryption_Keymanager extends \PHPUnit_Framework_TestCase {
$filename = '/tmp-' . time() . '.txt';
// create folder structure
$this->view->mkdir('/admin/files/folder1');
$this->view->mkdir('/admin/files/folder1/subfolder');
$this->view->mkdir('/admin/files/folder1/subfolder/subsubfolder');
$this->view->mkdir('/'.Test_Encryption_Keymanager::TEST_USER.'/files/folder1');
$this->view->mkdir('/'.Test_Encryption_Keymanager::TEST_USER.'/files/folder1/subfolder');
$this->view->mkdir('/'.Test_Encryption_Keymanager::TEST_USER.'/files/folder1/subfolder/subsubfolder');
// enable encryption proxy
$proxyStatus = \OC_FileProxy::$enabled;

View file

@ -751,6 +751,9 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
* @large
*/
function testRecoveryForUser() {
$this->markTestIncomplete(
'This test drives Jenkins crazy - "Cannot modify header information - headers already sent" - line 811'
);
// login as admin
\Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);

View file

@ -0,0 +1,107 @@
<?php
/**
* Copyright 2010-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
namespace Aws\Common;
use Guzzle\Service\Builder\ServiceBuilder;
use Guzzle\Service\Builder\ServiceBuilderLoader;
/**
* Base class for interacting with web service clients
*/
class Aws extends ServiceBuilder
{
/**
* @var string Current version of the SDK
*/
const VERSION = '2.4.0';
/**
* Create a new service locator for the AWS SDK
*
* You can configure the service locator is four different ways:
*
* 1. Use the default configuration file shipped with the SDK that wires class names with service short names and
* specify global parameters to add to every definition (e.g. key, secret, credentials, etc)
*
* 2. Use a custom configuration file that extends the default config and supplies credentials for each service.
*
* 3. Use a custom config file that wires services to custom short names for services.
*
* 4. If you are on Amazon EC2, you can use the default configuration file and not provide any credentials so that
* you are using InstanceProfile credentials.
*
* @param array|string $config The full path to a .php or .js|.json file, or an associative array of data
* to use as global parameters to pass to each service.
* @param array $globalParameters Global parameters to pass to every service as it is instantiated.
*
* @return Aws
*/
public static function factory($config = null, array $globalParameters = array())
{
if (!$config) {
// If nothing is passed in, then use the default configuration file with credentials from the environment
$config = self::getDefaultServiceDefinition();
} elseif (is_array($config)) {
// If an array was passed, then use the default configuration file with parameter overrides
$globalParameters = $config;
$config = self::getDefaultServiceDefinition();
}
$loader = new ServiceBuilderLoader();
$loader->addAlias('_aws', self::getDefaultServiceDefinition())
->addAlias('_sdk1', __DIR__ . '/Resources/sdk1-config.php');
return $loader->load($config, $globalParameters);
}
/**
* Get the full path to the default service builder definition file
*
* @return string
*/
public static function getDefaultServiceDefinition()
{
return __DIR__ . '/Resources/aws-config.php';
}
/**
* Returns the configuration for the service builder
*
* @return array
*/
public function getConfig()
{
return $this->builderConfig;
}
/**
* Enables the facades for the clients defined in the service builder
*
* @param string|null $namespace The namespace that the facades should be mounted to. Defaults to global namespace
*
* @return Aws
*/
public function enableFacades($namespace = null)
{
$facadeClass = 'Aws\\Common\\Facade\\Facade';
if (class_exists($facadeClass)) {
$facadeClass::mountFacades($this, $namespace);
}
return $this;
}
}

View file

@ -0,0 +1,273 @@
<?php
/**
* Copyright 2010-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
namespace Aws\Common\Client;
use Aws\Common\Aws;
use Aws\Common\Credentials\Credentials;
use Aws\Common\Credentials\CredentialsInterface;
use Aws\Common\Enum\ClientOptions as Options;
use Aws\Common\Exception\InvalidArgumentException;
use Aws\Common\Signature\EndpointSignatureInterface;
use Aws\Common\Signature\SignatureInterface;
use Aws\Common\Signature\SignatureListener;
use Aws\Common\Waiter\WaiterClassFactory;
use Aws\Common\Waiter\CompositeWaiterFactory;
use Aws\Common\Waiter\WaiterFactoryInterface;
use Aws\Common\Waiter\WaiterConfigFactory;
use Guzzle\Common\Collection;
use Guzzle\Service\Client;
use Guzzle\Service\Description\ServiceDescriptionInterface;
/**
* Abstract AWS client
*/
abstract class AbstractClient extends Client implements AwsClientInterface
{
/**
* @var CredentialsInterface AWS credentials
*/
protected $credentials;
/**
* @var SignatureInterface Signature implementation of the service
*/
protected $signature;
/**
* @var WaiterFactoryInterface Factory used to create waiter classes
*/
protected $waiterFactory;
/**
* {@inheritdoc}
*/
public static function getAllEvents()
{
return array_merge(Client::getAllEvents(), array(
'client.region_changed',
'client.credentials_changed',
));
}
/**
* @param CredentialsInterface $credentials AWS credentials
* @param SignatureInterface $signature Signature implementation
* @param Collection $config Configuration options
*
* @throws InvalidArgumentException if an endpoint provider isn't provided
*/
public function __construct(CredentialsInterface $credentials, SignatureInterface $signature, Collection $config)
{
// Bootstrap with Guzzle
parent::__construct($config->get(Options::BASE_URL), $config);
$this->credentials = $credentials;
$this->signature = $signature;
// Make sure the user agent is prefixed by the SDK version
$this->setUserAgent('aws-sdk-php2/' . Aws::VERSION, true);
// Add the event listener so that requests are signed before they are sent
$dispatcher = $this->getEventDispatcher();
$dispatcher->addSubscriber(new SignatureListener($credentials, $signature));
if ($backoff = $config->get(Options::BACKOFF)) {
$dispatcher->addSubscriber($backoff, -255);
}
}
public function __call($method, $args)
{
if (substr($method, 0, 3) === 'get' && substr($method, -8) === 'Iterator') {
// Allow magic method calls for iterators (e.g. $client->get<CommandName>Iterator($params))
$commandOptions = isset($args[0]) ? $args[0] : null;
$iteratorOptions = isset($args[1]) ? $args[1] : array();
return $this->getIterator(substr($method, 3, -8), $commandOptions, $iteratorOptions);
} elseif (substr($method, 0, 9) == 'waitUntil') {
// Allow magic method calls for waiters (e.g. $client->waitUntil<WaiterName>($params))
return $this->waitUntil(substr($method, 9), isset($args[0]) ? $args[0]: array());
} else {
return parent::__call(ucfirst($method), $args);
}
}
/**
* Get an endpoint for a specific region from a service description
*
* @param ServiceDescriptionInterface $description Service description
* @param string $region Region of the endpoint
* @param string $scheme URL scheme
*
* @return string
* @throws InvalidArgumentException
*/
public static function getEndpoint(ServiceDescriptionInterface $description, $region, $scheme)
{
$service = $description->getData('serviceFullName');
// Lookup the region in the service description
if (!($regions = $description->getData('regions'))) {
throw new InvalidArgumentException("No regions found in the {$service} description");
}
// Ensure that the region exists for the service
if (!isset($regions[$region])) {
throw new InvalidArgumentException("{$region} is not a valid region for {$service}");
}
// Ensure that the scheme is valid
if ($regions[$region][$scheme] == false) {
throw new InvalidArgumentException("{$scheme} is not a valid URI scheme for {$service} in {$region}");
}
return $scheme . '://' . $regions[$region]['hostname'];
}
/**
* {@inheritdoc}
*/
public function getCredentials()
{
return $this->credentials;
}
/**
* {@inheritdoc}
*/
public function setCredentials(CredentialsInterface $credentials)
{
$formerCredentials = $this->credentials;
$this->credentials = $credentials;
// Dispatch an event that the credentials have been changed
$this->dispatch('client.credentials_changed', array(
'credentials' => $credentials,
'former_credentials' => $formerCredentials,
));
return $this;
}
/**
* {@inheritdoc}
*/
public function getSignature()
{
return $this->signature;
}
/**
* {@inheritdoc}
*/
public function getRegions()
{
return $this->serviceDescription->getData('regions');
}
/**
* {@inheritdoc}
*/
public function getRegion()
{
return $this->getConfig(Options::REGION);
}
/**
* {@inheritdoc}
*/
public function setRegion($region)
{
$config = $this->getConfig();
$formerRegion = $config->get(Options::REGION);
$global = $this->serviceDescription->getData('globalEndpoint');
// Only change the region if the service does not have a global endpoint
if (!$global || $this->serviceDescription->getData('namespace') === 'S3') {
$baseUrl = self::getEndpoint($this->serviceDescription, $region, $config->get(Options::SCHEME));
$this->setBaseUrl($baseUrl);
$config->set(Options::BASE_URL, $baseUrl)->set(Options::REGION, $region);
// Update the signature if necessary
$signature = $this->getSignature();
if ($signature instanceof EndpointSignatureInterface) {
/** @var $signature EndpointSignatureInterface */
$signature->setRegionName($region);
}
// Dispatch an event that the region has been changed
$this->dispatch('client.region_changed', array(
'region' => $region,
'former_region' => $formerRegion,
));
}
return $this;
}
/**
* {@inheritdoc}
*/
public function waitUntil($waiter, array $input = array())
{
$this->getWaiter($waiter, $input)->wait();
return $this;
}
/**
* {@inheritdoc}
*/
public function getWaiter($waiter, array $input = array())
{
return $this->getWaiterFactory()->build($waiter)
->setClient($this)
->setConfig($input);
}
/**
* {@inheritdoc}
*/
public function setWaiterFactory(WaiterFactoryInterface $waiterFactory)
{
$this->waiterFactory = $waiterFactory;
return $this;
}
/**
* {@inheritdoc}
*/
public function getWaiterFactory()
{
if (!$this->waiterFactory) {
$clientClass = get_class($this);
// Use a composite factory that checks for classes first, then config waiters
$this->waiterFactory = new CompositeWaiterFactory(array(
new WaiterClassFactory(substr($clientClass, 0, strrpos($clientClass, '\\')) . '\\Waiter')
));
if ($this->getDescription()) {
$this->waiterFactory->addFactory(new WaiterConfigFactory($this->getDescription()->getData('waiters')));
}
}
return $this->waiterFactory;
}
/**
* {@inheritdoc}
*/
public function getApiVersion()
{
return $this->serviceDescription->getApiVersion();
}
}

View file

@ -0,0 +1,118 @@
<?php
/**
* Copyright 2010-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
namespace Aws\Common\Client;
use Aws\Common\Credentials\CredentialsInterface;
use Aws\Common\Signature\SignatureInterface;
use Aws\Common\Waiter\WaiterFactoryInterface;
use Aws\Common\Waiter\WaiterInterface;
use Guzzle\Service\ClientInterface;
/**
* Interface that all AWS clients implement
*/
interface AwsClientInterface extends ClientInterface
{
/**
* Returns the AWS credentials associated with the client
*
* @return CredentialsInterface
*/
public function getCredentials();
/**
* Sets the credentials object associated with the client
*
* @param CredentialsInterface $credentials Credentials object to use
*
* @return self
*/
public function setCredentials(CredentialsInterface $credentials);
/**
* Returns the signature implementation used with the client
*
* @return SignatureInterface
*/
public function getSignature();
/**
* Get a list of available regions and region data
*
* @return array
*/
public function getRegions();
/**
* Get the name of the region to which the client is configured to send requests
*
* @return string
*/
public function getRegion();
/**
* Change the region to which the client is configured to send requests
*
* @param string $region Name of the region
*
* @return self
*/
public function setRegion($region);
/**
* Get the waiter factory being used by the client
*
* @return WaiterFactoryInterface
*/
public function getWaiterFactory();
/**
* Set the waiter factory to use with the client
*
* @param WaiterFactoryInterface $waiterFactory Factory used to create waiters
*
* @return self
*/
public function setWaiterFactory(WaiterFactoryInterface $waiterFactory);
/**
* Wait until a resource is available or an associated waiter returns true
*
* @param string $waiter Name of the waiter
* @param array $input Values used as input for the underlying operation and to control the waiter
*
* @return self
*/
public function waitUntil($waiter, array $input = array());
/**
* Get a named waiter object
*
* @param string $waiter Name of the waiter
* @param array $input Values used as input for the underlying operation and to control the waiter
*
* @return WaiterInterface
*/
public function getWaiter($waiter, array $input = array());
/**
* Get the API version of the client (e.g. 2006-03-01)
*
* @return string
*/
public function getApiVersion();
}

View file

@ -0,0 +1,454 @@
<?php
/**
* Copyright 2010-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
namespace Aws\Common\Client;
use Aws\Common\Credentials\Credentials;
use Aws\Common\Enum\ClientOptions as Options;
use Aws\Common\Enum\Region;
use Aws\Common\Exception\ExceptionListener;
use Aws\Common\Exception\InvalidArgumentException;
use Aws\Common\Exception\NamespaceExceptionFactory;
use Aws\Common\Exception\Parser\DefaultXmlExceptionParser;
use Aws\Common\Exception\Parser\ExceptionParserInterface;
use Aws\Common\Iterator\AwsResourceIteratorFactory;
use Aws\Common\Signature\EndpointSignatureInterface;
use Aws\Common\Signature\SignatureInterface;
use Aws\Common\Signature\SignatureV2;
use Aws\Common\Signature\SignatureV3;
use Aws\Common\Signature\SignatureV3Https;
use Aws\Common\Signature\SignatureV4;
use Guzzle\Common\Collection;
use Guzzle\Plugin\Backoff\BackoffPlugin;
use Guzzle\Plugin\Backoff\CurlBackoffStrategy;
use Guzzle\Plugin\Backoff\ExponentialBackoffStrategy;
use Guzzle\Plugin\Backoff\HttpBackoffStrategy;
use Guzzle\Plugin\Backoff\TruncatedBackoffStrategy;
use Guzzle\Service\Client;
use Guzzle\Service\Description\ServiceDescription;
use Guzzle\Service\Resource\ResourceIteratorClassFactory;
use Guzzle\Log\LogAdapterInterface;
use Guzzle\Log\ClosureLogAdapter;
use Guzzle\Plugin\Backoff\BackoffLogger;
/**
* Builder for creating AWS service clients
*/
class ClientBuilder
{
/**
* @var array Default client config
*/
protected static $commonConfigDefaults = array('scheme' => 'https');
/**
* @var array Default client requirements
*/
protected static $commonConfigRequirements = array(Options::SERVICE_DESCRIPTION);
/**
* @var string The namespace of the client
*/
protected $clientNamespace;
/**
* @var array The config options
*/
protected $config = array();
/**
* @var array The config defaults
*/
protected $configDefaults = array();
/**
* @var array The config requirements
*/
protected $configRequirements = array();
/**
* @var ExceptionParserInterface The Parser interface for the client
*/
protected $exceptionParser;
/**
* @var array Array of configuration data for iterators available for the client
*/
protected $iteratorsConfig = array();
/**
* Factory method for creating the client builder
*
* @param string $namespace The namespace of the client
*
* @return ClientBuilder
*/
public static function factory($namespace = null)
{
return new static($namespace);
}
/**
* Constructs a client builder
*
* @param string $namespace The namespace of the client
*/
public function __construct($namespace = null)
{
$this->clientNamespace = $namespace;
}
/**
* Sets the config options
*
* @param array|Collection $config The config options
*
* @return ClientBuilder
*/
public function setConfig($config)
{
$this->config = $this->processArray($config);
return $this;
}
/**
* Sets the config options' defaults
*
* @param array|Collection $defaults The default values
*
* @return ClientBuilder
*/
public function setConfigDefaults($defaults)
{
$this->configDefaults = $this->processArray($defaults);
return $this;
}
/**
* Sets the required config options
*
* @param array|Collection $required The required config options
*
* @return ClientBuilder
*/
public function setConfigRequirements($required)
{
$this->configRequirements = $this->processArray($required);
return $this;
}
/**
* Sets the exception parser. If one is not provided the builder will use
* the default XML exception parser.
*
* @param ExceptionParserInterface $parser The exception parser
*
* @return ClientBuilder
*/
public function setExceptionParser(ExceptionParserInterface $parser)
{
$this->exceptionParser = $parser;
return $this;
}
/**
* Set the configuration for the client's iterators
*
* @param array $config Configuration data for client's iterators
*
* @return ClientBuilder
*/
public function setIteratorsConfig(array $config)
{
$this->iteratorsConfig = $config;
return $this;
}
/**
* Performs the building logic using all of the parameters that have been
* set and falling back to default values. Returns an instantiate service
* client with credentials prepared and plugins attached.
*
* @return AwsClientInterface
* @throws InvalidArgumentException
*/
public function build()
{
// Resolve configuration
$config = Collection::fromConfig(
$this->config,
array_merge(self::$commonConfigDefaults, $this->configDefaults),
(self::$commonConfigRequirements + $this->configRequirements)
);
// Resolve endpoint and signature from the config and service description
$description = $this->updateConfigFromDescription($config);
$signature = $this->getSignature($description, $config);
// Resolve credentials
if (!$credentials = $config->get('credentials')) {
$credentials = Credentials::factory($config);
}
// Resolve exception parser
if (!$this->exceptionParser) {
$this->exceptionParser = new DefaultXmlExceptionParser();
}
// Resolve backoff strategy
$backoff = $config->get(Options::BACKOFF);
if ($backoff === null) {
$backoff = new BackoffPlugin(
// Retry failed requests up to 3 times if it is determined that the request can be retried
new TruncatedBackoffStrategy(3,
// Retry failed requests with 400-level responses due to throttling
new ThrottlingErrorChecker($this->exceptionParser,
// Retry failed requests with 500-level responses
new HttpBackoffStrategy(array(500, 503, 509),
// Retry failed requests due to transient network or cURL problems
new CurlBackoffStrategy(null,
// Retry requests that failed due to expired credentials
new ExpiredCredentialsChecker($this->exceptionParser,
new ExponentialBackoffStrategy()
)
)
)
)
)
);
$config->set(Options::BACKOFF, $backoff);
}
if ($backoff) {
$this->addBackoffLogger($backoff, $config);
}
// Determine service and class name
$clientClass = 'Aws\Common\Client\DefaultClient';
if ($this->clientNamespace) {
$serviceName = substr($this->clientNamespace, strrpos($this->clientNamespace, '\\') + 1);
$clientClass = $this->clientNamespace . '\\' . $serviceName . 'Client';
}
/** @var $client AwsClientInterface */
$client = new $clientClass($credentials, $signature, $config);
$client->setDescription($description);
// Add exception marshaling so that more descriptive exception are thrown
if ($this->clientNamespace) {
$exceptionFactory = new NamespaceExceptionFactory(
$this->exceptionParser,
"{$this->clientNamespace}\\Exception",
"{$this->clientNamespace}\\Exception\\{$serviceName}Exception"
);
$client->addSubscriber(new ExceptionListener($exceptionFactory));
}
// Add the UserAgentPlugin to append to the User-Agent header of requests
$client->addSubscriber(new UserAgentListener());
// Filters used for the cache plugin
$client->getConfig()->set(
'params.cache.key_filter',
'header=date,x-amz-date,x-amz-security-token,x-amzn-authorization'
);
// Set the iterator resource factory based on the provided iterators config
$client->setResourceIteratorFactory(new AwsResourceIteratorFactory(
$this->iteratorsConfig,
new ResourceIteratorClassFactory($this->clientNamespace . '\\Iterator')
));
// Disable parameter validation if needed
if ($config->get(Options::VALIDATION) === false) {
$params = $config->get('command.params') ?: array();
$params['command.disable_validation'] = true;
$config->set('command.params', $params);
}
return $client;
}
/**
* Add backoff logging to the backoff plugin if needed
*
* @param BackoffPlugin $plugin Backoff plugin
* @param Collection $config Configuration settings
*
* @throws InvalidArgumentException
*/
protected function addBackoffLogger(BackoffPlugin $plugin, Collection $config)
{
// The log option can be set to `debug` or an instance of a LogAdapterInterface
if ($logger = $config->get(Options::BACKOFF_LOGGER)) {
$format = $config->get(Options::BACKOFF_LOGGER_TEMPLATE);
if ($logger === 'debug') {
$logger = new ClosureLogAdapter(function ($message) {
trigger_error($message . "\n");
});
} elseif (!($logger instanceof LogAdapterInterface)) {
throw new InvalidArgumentException(
Options::BACKOFF_LOGGER . ' must be set to `debug` or an instance of '
. 'Guzzle\\Common\\Log\\LogAdapterInterface'
);
}
// Create the plugin responsible for logging exponential backoff retries
$logPlugin = new BackoffLogger($logger);
// You can specify a custom format or use the default
if ($format) {
$logPlugin->setTemplate($format);
}
$plugin->addSubscriber($logPlugin);
}
}
/**
* Ensures that an array (e.g. for config data) is actually in array form
*
* @param array|Collection $array The array data
*
* @return array
* @throws InvalidArgumentException if the arg is not an array or Collection
*/
protected function processArray($array)
{
if ($array instanceof Collection) {
$array = $array->getAll();
}
if (!is_array($array)) {
throw new InvalidArgumentException('The config must be provided as an array or Collection.');
}
return $array;
}
/**
* Update a configuration object from a service description
*
* @param Collection $config Config to update
*
* @return ServiceDescription
* @throws InvalidArgumentException
*/
protected function updateConfigFromDescription(Collection $config)
{
$description = $config->get(Options::SERVICE_DESCRIPTION);
if (!($description instanceof ServiceDescription)) {
// Inject the version into the sprintf template if it is a string
if (is_string($description)) {
$description = sprintf($description, $config->get(Options::VERSION));
}
$description = ServiceDescription::factory($description);
$config->set(Options::SERVICE_DESCRIPTION, $description);
}
if (!$config->get(Options::SERVICE)) {
$config->set(Options::SERVICE, $description->getData('endpointPrefix'));
}
if ($iterators = $description->getData('iterators')) {
$this->setIteratorsConfig($iterators);
}
// Ensure that the service description has regions
if (!$description->getData('regions')) {
throw new InvalidArgumentException(
'No regions found in the ' . $description->getData('serviceFullName'). ' description'
);
}
// Make sure a valid region is set
$region = $config->get(Options::REGION);
$global = $description->getData('globalEndpoint');
if (!$global && !$region) {
throw new InvalidArgumentException(
'A region is required when using ' . $description->getData('serviceFullName')
. '. Set "region" to one of: ' . implode(', ', array_keys($description->getData('regions')))
);
} elseif ($global && (!$region || $description->getData('namespace') !== 'S3')) {
$region = Region::US_EAST_1;
$config->set(Options::REGION, $region);
}
if (!$config->get(Options::BASE_URL)) {
// Set the base URL using the scheme and hostname of the service's region
$config->set(Options::BASE_URL, AbstractClient::getEndpoint(
$description,
$region,
$config->get(Options::SCHEME)
));
}
return $description;
}
/**
* Return an appropriate signature object for a a client based on a description
*
* @param ServiceDescription $description Description that holds a signature option
* @param Collection $config Configuration options
*
* @return SignatureInterface
* @throws InvalidArgumentException
*/
protected function getSignature(ServiceDescription $description, Collection $config)
{
if (!$signature = $config->get(Options::SIGNATURE)) {
switch ($description->getData('signatureVersion')) {
case 'v2':
$signature = new SignatureV2();
break;
case 'v3':
$signature = new SignatureV3();
break;
case 'v3https':
$signature = new SignatureV3Https();
break;
case 'v4':
$signature = new SignatureV4();
break;
default:
throw new InvalidArgumentException('Service description does not specify a valid signatureVersion');
}
}
// Allow a custom service name or region value to be provided
if ($signature instanceof EndpointSignatureInterface) {
// Determine the service name to use when signing
if (!$service = $config->get(Options::SIGNATURE_SERVICE)) {
if (!$service = $description->getData('signingName')) {
$service = $description->getData('endpointPrefix');
}
}
$signature->setServiceName($service);
// Determine the region to use when signing requests
if (!$region = $config->get(Options::SIGNATURE_REGION)) {
$region = $config->get(Options::REGION);
}
$signature->setRegionName($region);
}
return $signature;
}
}

View file

@ -0,0 +1,76 @@
<?php
/**
* Copyright 2010-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
namespace Aws\Common\Client;
use Aws\Common\Enum\ClientOptions as Options;
use Guzzle\Common\Collection;
/**
* Generic client for interacting with an AWS service
*/
class DefaultClient extends AbstractClient
{
/**
* Factory method to create a default client using an array of configuration options.
*
* The following array keys and values are available options:
*
* - Credential options (`key`, `secret`, and optional `token` OR `credentials` is required)
* - key: AWS Access Key ID
* - secret: AWS secret access key
* - credentials: You can optionally provide a custom `Aws\Common\Credentials\CredentialsInterface` object
* - token: Custom AWS security token to use with request authentication
* - token.ttd: UNIX timestamp for when the custom credentials expire
* - credentials.cache: Used to cache credentials when using providers that require HTTP requests. Set the true
* to use the default APC cache or provide a `Guzzle\Cache\CacheAdapterInterface` object.
* - credentials.cache.key: Optional custom cache key to use with the credentials
* - credentials.client: Pass this option to specify a custom `Guzzle\Http\ClientInterface` to use if your
* credentials require a HTTP request (e.g. RefreshableInstanceProfileCredentials)
* - Region and Endpoint options (a `region` and optional `scheme` OR a `base_url` is required)
* - region: Region name (e.g. 'us-east-1', 'us-west-1', 'us-west-2', 'eu-west-1', etc...)
* - scheme: URI Scheme of the base URL (e.g. 'https', 'http').
* - service: Specify the name of the service
* - base_url: Instead of using a `region` and `scheme`, you can specify a custom base URL for the client
* - Signature options
* - signature: You can optionally provide a custom signature implementation used to sign requests
* - signature.service: Set to explicitly override the service name used in signatures
* - signature.region: Set to explicitly override the region name used in signatures
* - Exponential backoff options
* - client.backoff.logger: `Guzzle\Log\LogAdapterInterface` object used to log backoff retries. Use
* 'debug' to emit PHP warnings when a retry is issued.
* - client.backoff.logger.template: Optional template to use for exponential backoff log messages. See
* `Guzzle\Plugin\Backoff\BackoffLogger` for formatting information.
* - Generic client options
* - ssl.certificate_authority: Set to true to use the bundled CA cert (default), system to use the certificate
* bundled with your system, or pass the full path to an SSL certificate bundle. This option should be used
* when you encounter curl error code 60.
* - curl.CURLOPT_VERBOSE: Set to true to output curl debug information during transfers
* - curl.*: Prefix any available cURL option with `curl.` to add cURL options to each request.
* See: http://www.php.net/manual/en/function.curl-setopt.php
*
* @param array|Collection $config Client configuration data
*
* @return self
*/
public static function factory($config = array())
{
return ClientBuilder::factory()
->setConfig($config)
->setConfigDefaults(array(Options::SCHEME => 'https'))
->build();
}
}

View file

@ -0,0 +1,80 @@
<?php
/**
* Copyright 2010-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
namespace Aws\Common\Client;
use Aws\Common\Credentials\AbstractRefreshableCredentials;
use Aws\Common\Client\AwsClientInterface;
use Aws\Common\Exception\Parser\ExceptionParserInterface;
use Guzzle\Http\Exception\HttpException;
use Guzzle\Http\Message\RequestInterface;
use Guzzle\Http\Message\Response;
use Guzzle\Plugin\Backoff\BackoffStrategyInterface;
use Guzzle\Plugin\Backoff\AbstractBackoffStrategy;
/**
* Backoff logic that handles retrying requests when credentials expire
*/
class ExpiredCredentialsChecker extends AbstractBackoffStrategy
{
/**
* @var array Array of known retrying exception codes
*/
protected $retryable = array(
'RequestExpired' => true,
'ExpiredTokenException' => true,
'ExpiredToken' => true
);
/**
* @var ExceptionParserInterface Exception parser used to parse exception responses
*/
protected $exceptionParser;
public function __construct(ExceptionParserInterface $exceptionParser, BackoffStrategyInterface $next = null) {
$this->exceptionParser = $exceptionParser;
$this->next = $next;
}
public function makesDecision()
{
return true;
}
protected function getDelay($retries, RequestInterface $request, Response $response = null, HttpException $e = null)
{
if ($response && $response->isClientError()) {
$parts = $this->exceptionParser->parse($request, $response);
if (!isset($this->retryable[$parts['code']]) || !$request->getClient()) {
return null;
}
/** @var $client AwsClientInterface */
$client = $request->getClient();
// Only retry if the credentials can be refreshed
if (!($client->getCredentials() instanceof AbstractRefreshableCredentials)) {
return null;
}
// Resign the request using new credentials
$client->getSignature()->signRequest($request, $client->getCredentials()->setExpiration(-1));
// Retry immediately with no delay
return 0;
}
}
}

View file

@ -0,0 +1,75 @@
<?php
/**
* Copyright 2010-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
namespace Aws\Common\Client;
use Aws\Common\Exception\Parser\ExceptionParserInterface;
use Guzzle\Http\Exception\HttpException;
use Guzzle\Http\Message\RequestInterface;
use Guzzle\Http\Message\Response;
use Guzzle\Plugin\Backoff\BackoffStrategyInterface;
use Guzzle\Plugin\Backoff\AbstractBackoffStrategy;
/**
* Backoff logic that handles throttling exceptions from services
*/
class ThrottlingErrorChecker extends AbstractBackoffStrategy
{
/** @var array Whitelist of exception codes (as indexes) that indicate throttling */
protected static $throttlingExceptions = array(
'RequestLimitExceeded' => true,
'Throttling' => true,
'ThrottlingException' => true,
'ProvisionedThroughputExceededException' => true,
'RequestThrottled' => true,
);
/**
* @var ExceptionParserInterface Exception parser used to parse exception responses
*/
protected $exceptionParser;
public function __construct(ExceptionParserInterface $exceptionParser, BackoffStrategyInterface $next = null)
{
$this->exceptionParser = $exceptionParser;
if ($next) {
$this->setNext($next);
}
}
/**
* {@inheritdoc}
*/
public function makesDecision()
{
return true;
}
/**
* {@inheritdoc}
*/
protected function getDelay(
$retries,
RequestInterface $request,
Response $response = null,
HttpException $e = null
) {
if ($response && $response->isClientError()) {
$parts = $this->exceptionParser->parse($request, $response);
return isset(self::$throttlingExceptions[$parts['code']]) ? true : null;
}
}
}

View file

@ -0,0 +1,93 @@
<?php
/**
* Copyright 2010-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
namespace Aws\Common\Client;
use Guzzle\Common\Event;
use Guzzle\Http\EntityBody;
use Guzzle\Service\Command\AbstractCommand as Command;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
* Prepares the body parameter of a command such that the parameter is more flexible (e.g. accepts file handles) with
* the value it accepts but converts it to the correct format for the command. Also looks for a "Filename" parameter.
*/
class UploadBodyListener implements EventSubscriberInterface
{
/**
* @var array The names of the commands of which to modify the body parameter
*/
protected $commands;
/**
* @var string The key for the upload body parameter
*/
protected $bodyParameter;
/**
* @var string The key for the source file parameter
*/
protected $sourceParameter;
/**
* @param array $commands The commands to modify
* @param string $bodyParameter The key for the body parameter
* @param string $sourceParameter The key for the source file parameter
*/
public function __construct(array $commands, $bodyParameter = 'Body', $sourceParameter = 'SourceFile')
{
$this->commands = $commands;
$this->bodyParameter = (string) $bodyParameter;
$this->sourceParameter = (string) $sourceParameter;
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents()
{
return array('command.before_prepare' => array('onCommandBeforePrepare'));
}
/**
* Converts filenames and file handles into EntityBody objects before the command is validated
*
* @param Event $event Event emitted
*/
public function onCommandBeforePrepare(Event $event)
{
/** @var $command Command */
$command = $event['command'];
if (in_array($command->getName(), $this->commands)) {
// Get the interesting parameters
$source = $command->get($this->sourceParameter);
$body = $command->get($this->bodyParameter);
// If a file path is passed in then get the file handle
if (is_string($source) && file_exists($source)) {
$body = fopen($source, 'r');
}
if (null !== $body) {
$body = EntityBody::factory($body);
}
// Prepare the body parameter and remove the source file parameter
$command->remove($this->sourceParameter);
$command->set($this->bodyParameter, $body);
}
}
}

View file

@ -0,0 +1,61 @@
<?php
/**
* Copyright 2010-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
namespace Aws\Common\Client;
use Guzzle\Common\Event;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
* Listener used to append strings to the User-Agent header of a request based
* on the `ua.append` option. `ua.append` can contain a string or array of values.
*/
class UserAgentListener implements EventSubscriberInterface
{
/**
* @var string Option used to store User-Agent modifiers
*/
const OPTION = 'ua.append';
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents()
{
return array('command.before_send' => 'onBeforeSend');
}
/**
* Adds strings to the User-Agent header using the `ua.append` parameter of a command
*
* @param Event $event Event emitted
*/
public function onBeforeSend(Event $event)
{
$command = $event['command'];
if ($userAgentAppends = $command->get(self::OPTION)) {
$request = $command->getRequest();
$userAgent = (string) $request->getHeader('User-Agent');
foreach ((array) $userAgentAppends as $append) {
$append = ' ' . $append;
if (strpos($userAgent, $append) === false) {
$userAgent .= $append;
}
}
$request->setHeader('User-Agent', $userAgent);
}
}
}

View file

@ -0,0 +1,100 @@
<?php
namespace Aws\Common\Command;
use Guzzle\Http\Message\RequestInterface;
use Guzzle\Service\Description\Parameter;
use Guzzle\Service\Command\CommandInterface;
use Guzzle\Service\Command\LocationVisitor\Request\AbstractRequestVisitor;
/**
* Location visitor used to serialize AWS query parameters (e.g. EC2, SES, SNS, SQS, etc) as POST fields
*/
class AwsQueryVisitor extends AbstractRequestVisitor
{
/**
* {@inheritdoc}
*/
public function visit(CommandInterface $command, RequestInterface $request, Parameter $param, $value)
{
$query = array();
$this->customResolver($value, $param, $query, $param->getWireName());
$request->addPostFields($query);
}
/**
* Map nested parameters into the location_key based parameters
*
* @param array $value Value to map
* @param Parameter $param Parameter that holds information about the current key
* @param array $query Built up query string values
* @param string $prefix String to prepend to sub query values
*/
protected function customResolver($value, Parameter $param, array &$query, $prefix = '')
{
switch ($param->getType()) {
case 'object':
$this->resolveObject($param, $value, $prefix, $query);
break;
case 'array':
$this->resolveArray($param, $value, $prefix, $query);
break;
default:
$query[$prefix] = $param->filter($value);
}
}
/**
* Custom handling for objects
*
* @param Parameter $param Parameter for the object
* @param array $value Value that is set for this parameter
* @param string $prefix Prefix for the resulting key
* @param array $query Query string array passed by reference
*/
protected function resolveObject(Parameter $param, array $value, $prefix, array &$query)
{
// Maps are implemented using additional properties
$hasAdditionalProperties = ($param->getAdditionalProperties() instanceof Parameter);
$additionalPropertyCount = 0;
foreach ($value as $name => $v) {
if ($subParam = $param->getProperty($name)) {
// if the parameter was found by name as a regular property
$key = $prefix . '.' . $subParam->getWireName();
$this->customResolver($v, $subParam, $query, $key);
} elseif ($hasAdditionalProperties) {
// Handle map cases like &Attribute.1.Name=<name>&Attribute.1.Value=<value>
$additionalPropertyCount++;
$query["{$prefix}.{$additionalPropertyCount}.Name"] = $name;
$newPrefix = "{$prefix}.{$additionalPropertyCount}.Value";
if (is_array($v)) {
$this->customResolver($v, $param->getAdditionalProperties(), $query, $newPrefix);
} else {
$query[$newPrefix] = $param->filter($v);
}
}
}
}
/**
* Custom handling for arrays
*
* @param Parameter $param Parameter for the object
* @param array $value Value that is set for this parameter
* @param string $prefix Prefix for the resulting key
* @param array $query Query string array passed by reference
*/
protected function resolveArray(Parameter $param, array $value, $prefix, array &$query)
{
$offset = $param->getData('offset') ?: 1;
foreach ($value as $index => $v) {
$index += $offset;
if (is_array($v) && $items = $param->getItems()) {
$this->customResolver($v, $items, $query, $prefix . '.' . $index);
} else {
$query[$prefix . '.' . $index] = $param->filter($v);
}
}
}
}

View file

@ -0,0 +1,47 @@
<?php
/**
* Copyright 2010-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
namespace Aws\Common\Command;
use Guzzle\Service\Command\OperationCommand;
use Guzzle\Http\Curl\CurlHandle;
/**
* Adds AWS JSON body functionality to dynamically generated HTTP requests
*/
class JsonCommand extends OperationCommand
{
/**
* {@inheritdoc}
*/
protected function build()
{
parent::build();
// Ensure that the body of the request ALWAYS includes some JSON. By default, this is an empty object.
if (!$this->request->getBody()) {
$this->request->setBody('{}');
}
// Never send the Expect header when interacting with a JSON query service
$this->request->removeHeader('Expect');
// Always send JSON requests as a raw string rather than using streams to avoid issues with
// cURL error code 65: "necessary data rewind wasn't possible".
// This could be removed after PHP addresses https://bugs.php.net/bug.php?id=47204
$this->request->getCurlOptions()->set(CurlHandle::BODY_AS_STRING, true);
}
}

View file

@ -0,0 +1,53 @@
<?php
/**
* Copyright 2010-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
namespace Aws\Common\Command;
use Guzzle\Service\Command\OperationCommand;
/**
* Adds AWS Query service serialization
*/
class QueryCommand extends OperationCommand
{
/**
* @var AwsQueryVisitor
*/
protected static $queryVisitor;
/**
* @var XmlResponseLocationVisitor
*/
protected static $xmlVisitor;
/**
* Register the aws.query visitor
*/
protected function init()
{
// @codeCoverageIgnoreStart
if (!self::$queryVisitor) {
self::$queryVisitor = new AwsQueryVisitor();
}
if (!self::$xmlVisitor) {
self::$xmlVisitor = new XmlResponseLocationVisitor();
}
// @codeCoverageIgnoreEnd
$this->getRequestSerializer()->addVisitor('aws.query', self::$queryVisitor);
$this->getResponseParser()->addVisitor('xml', self::$xmlVisitor);
}
}

View file

@ -0,0 +1,74 @@
<?php
namespace Aws\Common\Command;
use Guzzle\Service\Description\Operation;
use Guzzle\Service\Command\CommandInterface;
use Guzzle\Http\Message\Response;
use Guzzle\Service\Description\Parameter;
use Guzzle\Service\Command\LocationVisitor\Response\XmlVisitor;
/**
* Class used for custom AWS XML response parsing of query services
*/
class XmlResponseLocationVisitor extends XmlVisitor
{
/**
* {@inheritdoc}
*/
public function before(CommandInterface $command, array &$result)
{
parent::before($command, $result);
// Unwrapped wrapped responses
$operation = $command->getOperation();
if ($operation->getServiceDescription()->getData('resultWrapped')) {
$wrappingNode = $operation->getName() . 'Result';
if (isset($result[$wrappingNode])) {
$result = $result[$wrappingNode] + $result;
unset($result[$wrappingNode]);
}
}
}
/**
* Accounts for wrapper nodes
* {@inheritdoc}
*/
public function visit(
CommandInterface $command,
Response $response,
Parameter $param,
&$value,
$context = null
) {
parent::visit($command, $response, $param, $value, $context);
// Account for wrapper nodes (e.g. RDS, ElastiCache, etc)
if ($param->getData('wrapper')) {
$wireName = $param->getWireName();
$value += $value[$wireName];
unset($value[$wireName]);
}
}
/**
* Filter used when converting XML maps into associative arrays in service descriptions
*
* @param array $value Value to filter
* @param string $entryName Name of each entry
* @param string $keyName Name of each key
* @param string $valueName Name of each value
*
* @return array Returns the map of the XML data
*/
public static function xmlMap($value, $entryName, $keyName, $valueName)
{
$result = array();
foreach ($value as $entry) {
$result[$entry[$keyName]] = $entry[$valueName];
}
return $result;
}
}

View file

@ -0,0 +1,136 @@
<?php
/**
* Copyright 2010-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
namespace Aws\Common\Credentials;
/**
* Abstract credentials decorator
*/
class AbstractCredentialsDecorator implements CredentialsInterface
{
/**
* @var CredentialsInterface Wrapped credentials object
*/
protected $credentials;
/**
* Constructs a new BasicAWSCredentials object, with the specified AWS
* access key and AWS secret key
*
* @param CredentialsInterface $credentials
*/
public function __construct(CredentialsInterface $credentials)
{
$this->credentials = $credentials;
}
/**
* {@inheritdoc}
*/
public function serialize()
{
return $this->credentials->serialize();
}
/**
* {@inheritdoc}
*/
public function unserialize($serialized)
{
$this->credentials = new Credentials('', '');
$this->credentials->unserialize($serialized);
}
/**
* {@inheritdoc}
*/
public function getAccessKeyId()
{
return $this->credentials->getAccessKeyId();
}
/**
* {@inheritdoc}
*/
public function getSecretKey()
{
return $this->credentials->getSecretKey();
}
/**
* {@inheritdoc}
*/
public function getSecurityToken()
{
return $this->credentials->getSecurityToken();
}
/**
* {@inheritdoc}
*/
public function getExpiration()
{
return $this->credentials->getExpiration();
}
/**
* {@inheritdoc}
*/
public function isExpired()
{
return $this->credentials->isExpired();
}
/**
* {@inheritdoc}
*/
public function setAccessKeyId($key)
{
$this->credentials->setAccessKeyId($key);
return $this;
}
/**
* {@inheritdoc}
*/
public function setSecretKey($secret)
{
$this->credentials->setSecretKey($secret);
return $this;
}
/**
* {@inheritdoc}
*/
public function setSecurityToken($token)
{
$this->credentials->setSecurityToken($token);
return $this;
}
/**
* {@inheritdoc}
*/
public function setExpiration($timestamp)
{
$this->credentials->setExpiration($timestamp);
return $this;
}
}

View file

@ -0,0 +1,76 @@
<?php
/**
* Copyright 2010-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
namespace Aws\Common\Credentials;
/**
* Abstract decorator to provide a foundation for refreshable credentials
*/
abstract class AbstractRefreshableCredentials extends AbstractCredentialsDecorator
{
/**
* {@inheritdoc}
*/
public function getAccessKeyId()
{
if ($this->credentials->isExpired()) {
$this->refresh();
}
return $this->credentials->getAccessKeyId();
}
/**
* {@inheritdoc}
*/
public function getSecretKey()
{
if ($this->credentials->isExpired()) {
$this->refresh();
}
return $this->credentials->getSecretKey();
}
/**
* {@inheritdoc}
*/
public function getSecurityToken()
{
if ($this->credentials->isExpired()) {
$this->refresh();
}
return $this->credentials->getSecurityToken();
}
/**
* {@inheritdoc}
*/
public function serialize()
{
if ($this->credentials->isExpired()) {
$this->refresh();
}
return $this->credentials->serialize();
}
/**
* Attempt to get new credentials
*/
abstract protected function refresh();
}

View file

@ -0,0 +1,73 @@
<?php
/**
* Copyright 2010-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
namespace Aws\Common\Credentials;
use Guzzle\Cache\CacheAdapterInterface;
/**
* Credentials decorator used to implement caching credentials
*/
class CacheableCredentials extends AbstractRefreshableCredentials
{
/**
* @var CacheAdapterInterface Cache adapter used to store credentials
*/
protected $cache;
/**
* @var string Cache key used to store the credentials
*/
protected $cacheKey;
/**
* CacheableCredentials is a decorator that decorates other credentials
*
* @param CredentialsInterface $credentials Credentials to adapt
* @param CacheAdapterInterface $cache Cache to use to store credentials
* @param string $cacheKey Cache key of the credentials
*/
public function __construct(CredentialsInterface $credentials, CacheAdapterInterface $cache, $cacheKey)
{
$this->credentials = $credentials;
$this->cache = $cache;
$this->cacheKey = $cacheKey;
}
/**
* Attempt to get new credentials from cache or from the adapted object
*/
protected function refresh()
{
if (!$cache = $this->cache->fetch($this->cacheKey)) {
// The credentials were not found, so try again and cache if new
$this->credentials->getAccessKeyId();
if (!$this->credentials->isExpired()) {
// The credentials were updated, so cache them
$this->cache->save($this->cacheKey, $this->credentials, $this->credentials->getExpiration() - time());
}
} else {
// The credentials were found in cache, so update the adapter object
// if the cached credentials are not expired
if (!$cache->isExpired()) {
$this->credentials->setAccessKeyId($cache->getAccessKeyId());
$this->credentials->setSecretKey($cache->getSecretKey());
$this->credentials->setSecurityToken($cache->getSecurityToken());
$this->credentials->setExpiration($cache->getExpiration());
}
}
}
}

View file

@ -0,0 +1,276 @@
<?php
/**
* Copyright 2010-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
namespace Aws\Common\Credentials;
use Aws\Common\Enum\ClientOptions as Options;
use Aws\Common\Exception\InvalidArgumentException;
use Aws\Common\Exception\RequiredExtensionNotLoadedException;
use Aws\Common\Exception\RuntimeException;
use Guzzle\Http\ClientInterface;
use Guzzle\Common\FromConfigInterface;
use Guzzle\Cache\CacheAdapterInterface;
use Guzzle\Cache\DoctrineCacheAdapter;
/**
* Basic implementation of the AWSCredentials interface that allows callers to
* pass in the AWS access key and secret access in the constructor.
*/
class Credentials implements CredentialsInterface, FromConfigInterface
{
const ENV_KEY = 'AWS_ACCESS_KEY_ID';
const ENV_SECRET = 'AWS_SECRET_KEY';
/**
* @var string AWS Access key ID
*/
protected $key;
/**
* @var string AWS Secret access key
*/
protected $secret;
/**
* @var string Security token
*/
protected $token;
/**
* @var int Time to die of token
*/
protected $ttd;
/**
* Get the available keys for the factory method
*
* @return array
*/
public static function getConfigDefaults()
{
return array(
Options::KEY => null,
Options::SECRET => null,
Options::TOKEN => null,
Options::TOKEN_TTD => null,
Options::CREDENTIALS_CACHE => null,
Options::CREDENTIALS_CACHE_KEY => null,
Options::CREDENTIALS_CLIENT => null
);
}
/**
* Factory method for creating new credentials. This factory method will
* create the appropriate credentials object with appropriate decorators
* based on the passed configuration options.
*
* @param array $config Options to use when instantiating the credentials
*
* @return CredentialsInterface
* @throws InvalidArgumentException If the caching options are invalid
* @throws RuntimeException If using the default cache and APC is disabled
*/
public static function factory($config = array())
{
// Add default key values
foreach (self::getConfigDefaults() as $key => $value) {
if (!isset($config[$key])) {
$config[$key] = $value;
}
}
// Start tracking the cache key
$cacheKey = $config[Options::CREDENTIALS_CACHE_KEY];
// Create the credentials object
if (!$config[Options::KEY] || !$config[Options::SECRET]) {
// No keys were provided, so attempt to retrieve some from the environment
$envKey = isset($_SERVER[self::ENV_KEY]) ? $_SERVER[self::ENV_KEY] : getenv(self::ENV_KEY);
$envSecret = isset($_SERVER[self::ENV_SECRET]) ? $_SERVER[self::ENV_SECRET] : getenv(self::ENV_SECRET);
if ($envKey && $envSecret) {
// Use credentials set in the environment variables
$credentials = new static($envKey, $envSecret);
} else {
// Use instance profile credentials (available on EC2 instances)
$credentials = new RefreshableInstanceProfileCredentials(
new static('', '', '', 1),
$config[Options::CREDENTIALS_CLIENT]
);
}
// If no cache key was set, use the crc32 hostname of the server
$cacheKey = $cacheKey ?: 'credentials_' . crc32(gethostname());
} else {
// Instantiate using short or long term credentials
$credentials = new static(
$config[Options::KEY],
$config[Options::SECRET],
$config[Options::TOKEN],
$config[Options::TOKEN_TTD]
);
// If no cache key was set, use the access key ID
$cacheKey = $cacheKey ?: 'credentials_' . $config[Options::KEY];
}
// Check if the credentials are refreshable, and if so, configure caching
$cache = $config[Options::CREDENTIALS_CACHE];
if ($cacheKey && $cache) {
if ($cache === 'true' || $cache === true) {
// If no cache adapter was provided, then create one for the user
// @codeCoverageIgnoreStart
if (!extension_loaded('apc')) {
throw new RequiredExtensionNotLoadedException('PHP has not been compiled with APC. Unable to cache '
. 'the credentials.');
} elseif (!class_exists('Doctrine\Common\Cache\ApcCache')) {
throw new RuntimeException(
'Cannot set ' . Options::CREDENTIALS_CACHE . ' to true because the Doctrine cache component is '
. 'not installed. Either install doctrine/cache or pass in an instantiated '
. 'Guzzle\Cache\CacheAdapterInterface object'
);
}
// @codeCoverageIgnoreEnd
$cache = new DoctrineCacheAdapter(new \Doctrine\Common\Cache\ApcCache());
} elseif (!($cache instanceof CacheAdapterInterface)) {
throw new InvalidArgumentException('Unable to utilize caching with the specified options');
}
// Decorate the credentials with a cache
$credentials = new CacheableCredentials($credentials, $cache, $cacheKey);
}
return $credentials;
}
/**
* Constructs a new BasicAWSCredentials object, with the specified AWS
* access key and AWS secret key
*
* @param string $accessKeyId AWS access key ID
* @param string $secretAccessKey AWS secret access key
* @param string $token Security token to use
* @param int $expiration UNIX timestamp for when credentials expire
*/
public function __construct($accessKeyId, $secretAccessKey, $token = null, $expiration = null)
{
$this->key = trim($accessKeyId);
$this->secret = trim($secretAccessKey);
$this->token = $token;
$this->ttd = $expiration;
}
/**
* {@inheritdoc}
*/
public function serialize()
{
return json_encode(array(
Options::KEY => $this->key,
Options::SECRET => $this->secret,
Options::TOKEN => $this->token,
Options::TOKEN_TTD => $this->ttd
));
}
/**
* {@inheritdoc}
*/
public function unserialize($serialized)
{
$data = json_decode($serialized, true);
$this->key = $data[Options::KEY];
$this->secret = $data[Options::SECRET];
$this->token = $data[Options::TOKEN];
$this->ttd = $data[Options::TOKEN_TTD];
}
/**
* {@inheritdoc}
*/
public function getAccessKeyId()
{
return $this->key;
}
/**
* {@inheritdoc}
*/
public function getSecretKey()
{
return $this->secret;
}
/**
* {@inheritdoc}
*/
public function getSecurityToken()
{
return $this->token;
}
/**
* {@inheritdoc}
*/
public function getExpiration()
{
return $this->ttd;
}
/**
* {@inheritdoc}
*/
public function isExpired()
{
return $this->ttd !== null && time() >= $this->ttd;
}
/**
* {@inheritdoc}
*/
public function setAccessKeyId($key)
{
$this->key = $key;
return $this;
}
/**
* {@inheritdoc}
*/
public function setSecretKey($secret)
{
$this->secret = $secret;
return $this;
}
/**
* {@inheritdoc}
*/
public function setSecurityToken($token)
{
$this->token = $token;
return $this;
}
/**
* {@inheritdoc}
*/
public function setExpiration($timestamp)
{
$this->ttd = $timestamp;
return $this;
}
}

View file

@ -0,0 +1,96 @@
<?php
/**
* Copyright 2010-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
namespace Aws\Common\Credentials;
/**
* Provides access to the AWS credentials used for accessing AWS services: AWS
* access key ID, secret access key, and security token. These credentials are
* used to securely sign requests to AWS services.
*/
interface CredentialsInterface extends \Serializable
{
/**
* Returns the AWS access key ID for this credentials object.
*
* @return string
*/
public function getAccessKeyId();
/**
* Returns the AWS secret access key for this credentials object.
*
* @return string
*/
public function getSecretKey();
/**
* Get the associated security token if available
*
* @return string|null
*/
public function getSecurityToken();
/**
* Get the UNIX timestamp in which the credentials will expire
*
* @return int|null
*/
public function getExpiration();
/**
* Set the AWS access key ID for this credentials object.
*
* @param string $key AWS access key ID
*
* @return self
*/
public function setAccessKeyId($key);
/**
* Set the AWS secret access key for this credentials object.
*
* @param string $secret AWS secret access key
*
* @return CredentialsInterface
*/
public function setSecretKey($secret);
/**
* Set the security token to use with this credentials object
*
* @param string $token Security token
*
* @return self
*/
public function setSecurityToken($token);
/**
* Set the UNIX timestamp in which the credentials will expire
*
* @param int $timestamp UNIX timestamp expiration
*
* @return self
*/
public function setExpiration($timestamp);
/**
* Check if the credentials are expired
*
* @return bool
*/
public function isExpired();
}

View file

@ -0,0 +1,59 @@
<?php
/**
* Copyright 2010-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
namespace Aws\Common\Credentials;
use Aws\Common\InstanceMetadata\InstanceMetadataClient;
use Aws\Common\Exception\InstanceProfileCredentialsException;
/**
* Credentials decorator used to implement retrieving credentials from the
* EC2 metadata server
*/
class RefreshableInstanceProfileCredentials extends AbstractRefreshableCredentials
{
/**
* @var InstanceMetadataClient
*/
protected $client;
/**
* Constructs a new instance profile credentials decorator
*
* @param CredentialsInterface $credentials Credentials to adapt
* @param InstanceMetadataClient $client Client used to get new credentials
*/
public function __construct(CredentialsInterface $credentials, InstanceMetadataClient $client = null)
{
$this->credentials = $credentials;
$this->client = $client ?: InstanceMetadataClient::factory();
}
/**
* Attempt to get new credentials from the instance profile
*
* @throws InstanceProfileCredentialsException On error
*/
protected function refresh()
{
$credentials = $this->client->getInstanceProfileCredentials();
// Expire the token 1 minute before it actually expires to pre-fetch before expiring
$this->credentials->setAccessKeyId($credentials->getAccessKeyId())
->setSecretKey($credentials->getSecretKey())
->setSecurityToken($credentials->getSecurityToken())
->setExpiration($credentials->getExpiration());
}
}

View file

@ -0,0 +1,55 @@
<?php
/**
* Copyright 2010-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
namespace Aws\Common;
/**
* Represents an enumerable set of values
*/
abstract class Enum
{
/**
* @var array A cache of all enum values to increase performance
*/
protected static $cache = array();
/**
* Returns the names (or keys) of all of constants in the enum
*
* @return array
*/
public static function keys()
{
return array_keys(static::values());
}
/**
* Return the names and values of all the constants in the enum
*
* @return array
*/
public static function values()
{
$class = get_called_class();
if (!isset(self::$cache[$class])) {
$reflected = new \ReflectionClass($class);
self::$cache[$class] = $reflected->getConstants();
}
return self::$cache[$class];
}
}

View file

@ -0,0 +1,146 @@
<?php
/**
* Copyright 2010-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
namespace Aws\Common\Enum;
use Aws\Common\Enum;
/**
* Contains enumerable default factory options that can be passed to a client's factory method
*/
class ClientOptions extends Enum
{
/**
* @var string AWS Access Key ID
*/
const KEY = 'key';
/**
* @var string AWS secret access key
*/
const SECRET = 'secret';
/**
* @var string You can optionally provide a custom `Aws\Common\Credentials\CredentialsInterface` object
*/
const CREDENTIALS = 'credentials';
/**
* @var string Custom AWS security token to use with request authentication
*/
const TOKEN = 'token';
/**
* @var string UNIX timestamp for when the custom credentials expire
*/
const TOKEN_TTD = 'token.ttd';
/**
* @var string Used to cache credentials when using providers that require HTTP requests. Set the trueto use the
* default APC cache or provide a `Guzzle\Cache\CacheAdapterInterface` object.
*/
const CREDENTIALS_CACHE = 'credentials.cache';
/**
* @var string Optional custom cache key to use with the credentials
*/
const CREDENTIALS_CACHE_KEY = 'credentials.cache.key';
/**
* @var string Pass this option to specify a custom `Guzzle\Http\ClientInterface` to use if your credentials require
* a HTTP request (e.g. RefreshableInstanceProfileCredentials)
*/
const CREDENTIALS_CLIENT = 'credentials.client';
/**
* @var string Region name (e.g. 'us-east-1', 'us-west-1', 'us-west-2', 'eu-west-1', etc...)
*/
const REGION = 'region';
/**
* @var string URI Scheme of the base URL (e.g. 'https', 'http').
*/
const SCHEME = 'scheme';
/**
* @var string Specify the name of the service
*/
const SERVICE = 'service';
/**
* @var string Instead of using a `region` and `scheme`, you can specify a custom base URL for the client
*/
const BASE_URL = 'base_url';
/**
* @var string You can optionally provide a custom signature implementation used to sign requests
*/
const SIGNATURE = 'signature';
/**
* @var string Set to explicitly override the service name used in signatures
*/
const SIGNATURE_SERVICE = 'signature.service';
/**
* @var string Set to explicitly override the region name used in signatures
*/
const SIGNATURE_REGION = 'signature.region';
/**
* @var string Option key holding an exponential backoff plugin
*/
const BACKOFF = 'client.backoff';
/**
* @var string `Guzzle\Log\LogAdapterInterface` object used to log backoff retries. Use 'debug' to emit PHP
* warnings when a retry is issued.
*/
const BACKOFF_LOGGER = 'client.backoff.logger';
/**
* @var string Optional template to use for exponential backoff log messages. See
* `Guzzle\Plugin\Backoff\BackoffLogger` for formatting information.
*/
const BACKOFF_LOGGER_TEMPLATE = 'client.backoff.logger.template';
/**
* @var string Set to true to use the bundled CA cert or pass the full path to an SSL certificate bundle. This
* option should be modified when you encounter curl error code 60. Set to "system" to use the cacert
* bundle on your system.
*/
const SSL_CERT = 'ssl.certificate_authority';
/**
* @var string Service description to use with the client
*/
const SERVICE_DESCRIPTION = 'service.description';
/**
* @var string Whether or not modeled responses have transformations applied to them
*/
const MODEL_PROCESSING = 'command.model_processing';
/**
* @var bool Set to false to disable validation
*/
const VALIDATION = 'validation';
/**
* @var string API version used by the client
*/
const VERSION = 'version';
}

View file

@ -0,0 +1,31 @@
<?php
/**
* Copyright 2010-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
namespace Aws\Common\Enum;
use Aws\Common\Enum;
/**
* Contains enumerable date format values used in the SDK
*/
class DateFormat extends Enum
{
const ISO8601 = 'Ymd\THis\Z';
const ISO8601_S3 = 'Y-m-d\TH:i:s\Z';
const RFC1123 = 'D, d M Y H:i:s \G\M\T';
const RFC2822 = \DateTime::RFC2822;
const SHORT = 'Ymd';
}

View file

@ -0,0 +1,57 @@
<?php
/**
* Copyright 2010-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
namespace Aws\Common\Enum;
use Aws\Common\Enum;
/**
* Contains enumerable region code values. These should be useful in most cases,
* with Amazon S3 being the most notable exception
*
* @link http://docs.amazonwebservices.com/general/latest/gr/rande.html AWS Regions and Endpoints
*/
class Region extends Enum
{
const US_EAST_1 = 'us-east-1';
const VIRGINIA = 'us-east-1';
const NORTHERN_VIRGINIA = 'us-east-1';
const US_WEST_1 = 'us-west-1';
const CALIFORNIA = 'us-west-1';
const NORTHERN_CALIFORNIA = 'us-west-1';
const US_WEST_2 = 'us-west-2';
const OREGON = 'us-west-2';
const EU_WEST_1 = 'eu-west-1';
const IRELAND = 'eu-west-1';
const AP_SOUTHEAST_1 = 'ap-southeast-1';
const SINGAPORE = 'ap-southeast-1';
const AP_SOUTHEAST_2 = 'ap-southeast-2';
const SYDNEY = 'ap-southeast-2';
const AP_NORTHEAST_1 = 'ap-northeast-1';
const TOKYO = 'ap-northeast-1';
const SA_EAST_1 = 'sa-east-1';
const SAO_PAULO = 'sa-east-1';
const US_GOV_WEST_1 = 'us-gov-west-1';
const GOV_CLOUD_US = 'us-gov-west-1';
}

View file

@ -0,0 +1,53 @@
<?php
/**
* Copyright 2010-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
namespace Aws\Common\Enum;
use Aws\Common\Enum;
/**
* Contains enumerable byte-size values
*/
class Size extends Enum
{
const B = 1;
const BYTE = 1;
const BYTES = 1;
const KB = 1024;
const KILOBYTE = 1024;
const KILOBYTES = 1024;
const MB = 1048576;
const MEGABYTE = 1048576;
const MEGABYTES = 1048576;
const GB = 1073741824;
const GIGABYTE = 1073741824;
const GIGABYTES = 1073741824;
const TB = 1099511627776;
const TERABYTE = 1099511627776;
const TERABYTES = 1099511627776;
const PB = 1125899906842624;
const PETABYTE = 1125899906842624;
const PETABYTES = 1125899906842624;
const EB = 1152921504606846976;
const EXABYTE = 1152921504606846976;
const EXABYTES = 1152921504606846976;
}

View file

@ -0,0 +1,46 @@
<?php
/**
* Copyright 2010-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
namespace Aws\Common\Enum;
use Aws\Common\Enum;
/**
* Contains enumerable time values
*/
class Time extends Enum
{
const SECOND = 1;
const SECONDS = 1;
const MINUTE = 60;
const MINUTES = 60;
const HOUR = 3600;
const HOURS = 3600;
const DAY = 86400;
const DAYS = 86400;
const WEEK = 604800;
const WEEKS = 604800;
const MONTH = 2592000;
const MONTHS = 2592000;
const YEAR = 31557600;
const YEARS = 31557600;
}

View file

@ -0,0 +1,55 @@
<?php
/**
* Copyright 2010-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
namespace Aws\Common\Enum;
use Aws\Common\Enum;
/**
* User-Agent header strings for various high level operations
*/
class UaString extends Enum
{
/**
* @var string Name of the option used to add to the UA string
*/
const OPTION = 'ua.append';
/**
* @var string Resource iterator
*/
const ITERATOR = 'ITR';
/**
* @var string Resource waiter
*/
const WAITER = 'WTR';
/**
* @var string Session handlers (e.g. Amazon DynamoDB session handler)
*/
const SESSION = 'SES';
/**
* @var string Multipart upload helper for Amazon S3
*/
const MULTIPART_UPLOAD = 'MUP';
/**
* @var string Command executed during a batch transfer
*/
const BATCH = 'BAT';
}

View file

@ -0,0 +1,30 @@
<?php
/**
* Copyright 2010-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
namespace Aws\Common\Exception;
/**
* "Marker Interface" implemented by every exception in the AWS SDK
*/
interface AwsExceptionInterface
{
public function getCode();
public function getLine();
public function getFile();
public function getMessage();
public function getPrevious();
public function getTrace();
}

View file

@ -0,0 +1,22 @@
<?php
/**
* Copyright 2010-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
namespace Aws\Common\Exception;
/**
* AWS SDK namespaced version of the SPL BadMethodCallException.
*/
class BadMethodCallException extends \BadMethodCallException implements AwsExceptionInterface {}

View file

@ -0,0 +1,22 @@
<?php
/**
* Copyright 2010-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
namespace Aws\Common\Exception;
/**
* AWS SDK namespaced version of the SPL DomainException.
*/
class DomainException extends \DomainException implements AwsExceptionInterface {}

View file

@ -0,0 +1,36 @@
<?php
/**
* Copyright 2010-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
namespace Aws\Common\Exception;
use Guzzle\Http\Message\RequestInterface;
use Guzzle\Http\Message\Response;
/**
* Interface used to create AWS exception
*/
interface ExceptionFactoryInterface
{
/**
* Returns an AWS service specific exception
*
* @param RequestInterface $request Unsuccessful request
* @param Response $response Unsuccessful response that was encountered
*
* @return \Exception|AwsExceptionInterface
*/
public function fromResponse(RequestInterface $request, Response $response);
}

View file

@ -0,0 +1,59 @@
<?php
/**
* Copyright 2010-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
namespace Aws\Common\Exception;
use Guzzle\Common\Event;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
* Converts generic Guzzle response exceptions into AWS specific exceptions
*/
class ExceptionListener implements EventSubscriberInterface
{
/**
* @var ExceptionFactoryInterface Factory used to create new exceptions
*/
protected $factory;
/**
* @param ExceptionFactoryInterface $factory Factory used to create exceptions
*/
public function __construct(ExceptionFactoryInterface $factory)
{
$this->factory = $factory;
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents()
{
return array('request.error' => array('onRequestError', -1));
}
/**
* Throws a more meaningful request exception if available
*
* @param Event $event Event emitted
*/
public function onRequestError(Event $event)
{
$e = $this->factory->fromResponse($event['request'], $event['response']);
$event->stopPropagation();
throw $e;
}
}

View file

@ -0,0 +1,50 @@
<?php
/**
* Copyright 2010-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
namespace Aws\Common\Exception;
use Aws\Common\Exception\RuntimeException;
/**
* Exception thrown when an error occurs with instance profile credentials
*/
class InstanceProfileCredentialsException extends RuntimeException
{
/**
* @var string
*/
protected $statusCode;
/**
* Set the error response code received from the instance metadata
*
* @param string $code Response code
*/
public function setStatusCode($code)
{
$this->statusCode = $code;
}
/**
* Get the error response code from the service
*
* @return string|null
*/
public function getStatusCode()
{
return $this->statusCode;
}
}

View file

@ -0,0 +1,22 @@
<?php
/**
* Copyright 2010-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
namespace Aws\Common\Exception;
/**
* AWS SDK namespaced version of the SPL InvalidArgumentException.
*/
class InvalidArgumentException extends \InvalidArgumentException implements AwsExceptionInterface {}

View file

@ -0,0 +1,22 @@
<?php
/**
* Copyright 2010-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
namespace Aws\Common\Exception;
/**
* AWS SDK namespaced version of the SPL LogicException.
*/
class LogicException extends \LogicException implements AwsExceptionInterface {}

View file

@ -0,0 +1,55 @@
<?php
/**
* Copyright 2010-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
namespace Aws\Common\Exception;
use Aws\Common\Model\MultipartUpload\TransferStateInterface;
/**
* Thrown when a {@see Aws\Common\MultipartUpload\TransferInterface} object encounters an error during transfer
*/
class MultipartUploadException extends RuntimeException
{
/**
* @var TransferStateInterface State of the transfer when the error was encountered
*/
protected $state;
/**
* @param TransferStateInterface $state Transfer state
* @param \Exception $exception Last encountered exception
*/
public function __construct(TransferStateInterface $state, \Exception $exception = null)
{
parent::__construct(
'An error was encountered while performing a multipart upload: ' . $exception->getMessage(),
0,
$exception
);
$this->state = $state;
}
/**
* Get the state of the transfer
*
* @return TransferStateInterface
*/
public function getState()
{
return $this->state;
}
}

View file

@ -0,0 +1,103 @@
<?php
/**
* Copyright 2010-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
namespace Aws\Common\Exception;
use Aws\Common\Exception\Parser\ExceptionParserInterface;
use Guzzle\Http\Message\RequestInterface;
use Guzzle\Http\Message\Response;
/**
* Attempts to create exceptions by inferring the name from the code and a base
* namespace that contains exceptions. Exception classes are expected to be in
* upper camelCase and always end in 'Exception'. 'Exception' will be appended
* if it is not present in the exception code.
*/
class NamespaceExceptionFactory implements ExceptionFactoryInterface
{
/**
* @var ExceptionParserInterface $parser Parser used to parse responses
*/
protected $parser;
/**
* @var string Base namespace containing exception classes
*/
protected $baseNamespace;
/**
* @var string Default class to instantiate if a match is not found
*/
protected $defaultException;
/**
* @param ExceptionParserInterface $parser Parser used to parse exceptions
* @param string $baseNamespace Namespace containing exceptions
* @param string $defaultException Default class to use if one is not mapped
*/
public function __construct(
ExceptionParserInterface $parser,
$baseNamespace,
$defaultException = 'Aws\Common\Exception\ServiceResponseException'
) {
$this->parser = $parser;
$this->baseNamespace = $baseNamespace;
$this->defaultException = $defaultException;
}
/**
* {@inheritdoc}
*/
public function fromResponse(RequestInterface $request, Response $response)
{
$parts = $this->parser->parse($request, $response);
// Removing leading 'AWS.' and embedded periods
$className = $this->baseNamespace . '\\' . str_replace(array('AWS.', '.'), '', $parts['code']);
if (substr($className, -9) !== 'Exception') {
$className .= 'Exception';
}
$className = class_exists($className) ? $className : $this->defaultException;
return $this->createException($className, $request, $response, $parts);
}
/**
* Create an prepare an exception object
*
* @param string $className Name of the class to create
* @param RequestInterface $request Request
* @param Response $response Response received
* @param array $parts Parsed exception data
*
* @return \Exception
*/
protected function createException($className, RequestInterface $request, Response $response, array $parts)
{
$class = new $className($parts['message']);
if ($class instanceof ServiceResponseException) {
$class->setExceptionCode($parts['code']);
$class->setExceptionType($parts['type']);
$class->setResponse($response);
$class->setRequest($request);
$class->setRequestId($parts['request_id']);
}
return $class;
}
}

View file

@ -0,0 +1,22 @@
<?php
/**
* Copyright 2010-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
namespace Aws\Common\Exception;
/**
* AWS SDK namespaced version of the SPL OverflowException.
*/
class OutOfBoundsException extends \OutOfBoundsException implements AwsExceptionInterface {}

View file

@ -0,0 +1,22 @@
<?php
/**
* Copyright 2010-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
namespace Aws\Common\Exception;
/**
* AWS SDK namespaced version of the SPL OverflowException.
*/
class OverflowException extends \OverflowException implements AwsExceptionInterface {}

View file

@ -0,0 +1,66 @@
<?php
/**
* Copyright 2010-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
namespace Aws\Common\Exception\Parser;
use Guzzle\Http\Message\RequestInterface;
use Guzzle\Http\Message\Response;
/**
* Parses JSON encoded exception responses
*/
abstract class AbstractJsonExceptionParser implements ExceptionParserInterface
{
/**
* {@inheritdoc}
*/
public function parse(RequestInterface $request, Response $response)
{
// Build array of default error data
$data = array(
'code' => null,
'message' => null,
'type' => $response->isClientError() ? 'client' : 'server',
'request_id' => (string) $response->getHeader('x-amzn-RequestId'),
'parsed' => null
);
// Parse the json and normalize key casings
if (null !== $json = json_decode($response->getBody(true), true)) {
$data['parsed'] = array_change_key_case($json);
}
// Do additional, protocol-specific parsing and return the result
$data = $this->doParse($data, $response);
// Remove "Fault" suffix from exception names
if (isset($data['code']) && strpos($data['code'], 'Fault')) {
$data['code'] = preg_replace('/^([a-zA-Z]+)Fault$/', '$1', $data['code']);
}
return $data;
}
/**
* Pull relevant exception data out of the parsed json
*
* @param array $data The exception data
* @param Response $response The response from the service containing the error
*
* @return array
*/
abstract protected function doParse(array $data, Response $response);
}

View file

@ -0,0 +1,100 @@
<?php
/**
* Copyright 2010-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
namespace Aws\Common\Exception\Parser;
use Guzzle\Http\Message\RequestInterface;
use Guzzle\Http\Message\Response;
/**
* Parses default XML exception responses
*/
class DefaultXmlExceptionParser implements ExceptionParserInterface
{
/**
* {@inheritdoc}
*/
public function parse(RequestInterface $request, Response $response)
{
$data = array(
'code' => null,
'message' => null,
'type' => $response->isClientError() ? 'client' : 'server',
'request_id' => null,
'parsed' => null
);
if ($body = $response->getBody(true)) {
$this->parseBody(new \SimpleXMLElement($body), $data);
} else {
$this->parseHeaders($request, $response, $data);
}
return $data;
}
/**
* Parses additional exception information from the response headers
*
* @param RequestInterface $request Request that was issued
* @param Response $response The response from the request
* @param array $data The current set of exception data
*/
protected function parseHeaders(RequestInterface $request, Response $response, array &$data)
{
$data['message'] = $response->getStatusCode() . ' ' . $response->getReasonPhrase();
if ($requestId = $response->getHeader('x-amz-request-id')) {
$data['request_id'] = $requestId;
$data['message'] .= " (Request-ID: $requestId)";
}
}
/**
* Parses additional exception information from the response body
*
* @param \SimpleXMLElement $body The response body as XML
* @param array $data The current set of exception data
*/
protected function parseBody(\SimpleXMLElement $body, array &$data)
{
$data['parsed'] = $body;
$namespaces = $body->getDocNamespaces();
if (isset($namespaces[''])) {
// Account for the default namespace being defined and PHP not being able to handle it :(
$body->registerXPathNamespace('ns', $namespaces['']);
$prefix = 'ns:';
} else {
$prefix = '';
}
if ($tempXml = $body->xpath("//{$prefix}Code[1]")) {
$data['code'] = (string) $tempXml[0];
}
if ($tempXml = $body->xpath("//{$prefix}Message[1]")) {
$data['message'] = (string) $tempXml[0];
}
$tempXml = $body->xpath("//{$prefix}RequestId[1]");
if (empty($tempXml)) {
$tempXml = $body->xpath("//{$prefix}RequestID[1]");
}
if (isset($tempXml[0])) {
$data['request_id'] = (string) $tempXml[0];
}
}
}

View file

@ -0,0 +1,42 @@
<?php
/**
* Copyright 2010-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
namespace Aws\Common\Exception\Parser;
use Guzzle\Http\Message\RequestInterface;
use Guzzle\Http\Message\Response;
/**
* Interface used to parse exceptions into an associative array of data
*/
interface ExceptionParserInterface
{
/**
* Parses an exception into an array of data containing at minimum the
* following array keys:
* - type: Exception type
* - code: Exception code
* - message: Exception message
* - request_id: Request ID
* - parsed: The parsed representation of the data (array, SimpleXMLElement, etc)
*
* @param RequestInterface $request
* @param Response $response Unsuccessful response
*
* @return array
*/
public function parse(RequestInterface $request, Response $response);
}

View file

@ -0,0 +1,39 @@
<?php
/**
* Copyright 2010-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
namespace Aws\Common\Exception\Parser;
use Guzzle\Http\Message\Response;
/**
* Parses JSON encoded exception responses from query services
*/
class JsonQueryExceptionParser extends AbstractJsonExceptionParser
{
/**
* {@inheritdoc}
*/
protected function doParse(array $data, Response $response)
{
if ($json = $data['parsed']) {
$parts = explode('#', $json['__type']);
$data['code'] = isset($parts[1]) ? $parts[1] : $parts[0];
$data['message'] = isset($json['message']) ? $json['message'] : null;
}
return $data;
}
}

View file

@ -0,0 +1,48 @@
<?php
/**
* Copyright 2010-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
namespace Aws\Common\Exception\Parser;
use Guzzle\Http\Message\Response;
/**
* Parses JSON encoded exception responses from REST services
*/
class JsonRestExceptionParser extends AbstractJsonExceptionParser
{
/**
* {@inheritdoc}
*/
protected function doParse(array $data, Response $response)
{
// Merge in error data from the JSON body
if ($json = $data['parsed']) {
$data = array_replace($data, $json);
}
// Correct error type from services like Amazon Glacier
if (!empty($data['type'])) {
$data['type'] = strtolower($data['type']);
}
// Retrieve the error code from services like Amazon Elastic Transcoder
if ($code = (string) $response->getHeader('x-amzn-ErrorType')) {
$data['code'] = substr($code, 0, strpos($code, ':'));
}
return $data;
}
}

View file

@ -0,0 +1,22 @@
<?php
/**
* Copyright 2010-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
namespace Aws\Common\Exception;
/**
* Thrown when a particular PHP extension is required to execute the guarded logic, but the extension is not loaded
*/
class RequiredExtensionNotLoadedException extends RuntimeException {}

View file

@ -0,0 +1,22 @@
<?php
/**
* Copyright 2010-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
namespace Aws\Common\Exception;
/**
* AWS SDK namespaced version of the SPL RuntimeException.
*/
class RuntimeException extends \RuntimeException implements AwsExceptionInterface {}

View file

@ -0,0 +1,183 @@
<?php
/**
* Copyright 2010-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
namespace Aws\Common\Exception;
use Guzzle\Http\Message\RequestInterface;
use Guzzle\Http\Message\Response;
/**
* Default AWS exception
*/
class ServiceResponseException extends RuntimeException
{
/**
* @var Response Response
*/
protected $response;
/**
* @var RequestInterface Request
*/
protected $request;
/**
* @var string Request ID
*/
protected $requestId;
/**
* @var string Exception type (client / server)
*/
protected $exceptionType;
/**
* @var string Exception code
*/
protected $exceptionCode;
/**
* Set the exception code
*
* @param string $code Exception code
*/
public function setExceptionCode($code)
{
$this->exceptionCode = $code;
}
/**
* Get the exception code
*
* @return string|null
*/
public function getExceptionCode()
{
return $this->exceptionCode;
}
/**
* Set the exception type
*
* @param string $type Exception type
*/
public function setExceptionType($type)
{
$this->exceptionType = $type;
}
/**
* Get the exception type (one of client or server)
*
* @return string|null
*/
public function getExceptionType()
{
return $this->exceptionType;
}
/**
* Set the request ID
*
* @param string $id Request ID
*/
public function setRequestId($id)
{
$this->requestId = $id;
}
/**
* Get the Request ID
*
* @return string|null
*/
public function getRequestId()
{
return $this->requestId;
}
/**
* Set the associated response
*
* @param Response $response Response
*/
public function setResponse(Response $response)
{
$this->response = $response;
}
/**
* Get the associated response object
*
* @return Response|null
*/
public function getResponse()
{
return $this->response;
}
/**
* Set the associated request
*
* @param RequestInterface $request
*/
public function setRequest(RequestInterface $request)
{
$this->request = $request;
}
/**
* Get the associated request object
*
* @return RequestInterface|null
*/
public function getRequest()
{
return $this->request;
}
/**
* Get the status code of the response
*
* @return int|null
*/
public function getStatusCode()
{
return $this->response ? $this->response->getStatusCode() : null;
}
/**
* Cast to a string
*
* @return string
*/
public function __toString()
{
$message = get_class($this) . ': '
. 'AWS Error Code: ' . $this->getExceptionCode() . ', '
. 'Status Code: ' . $this->getStatusCode() . ', '
. 'AWS Request ID: ' . $this->getRequestId() . ', '
. 'AWS Error Type: ' . $this->getExceptionType() . ', '
. 'AWS Error Message: ' . $this->getMessage();
// Add the User-Agent if available
if ($this->request) {
$message .= ', ' . 'User-Agent: ' . $this->request->getHeader('User-Agent');
}
return $message;
}
}

View file

@ -0,0 +1,22 @@
<?php
/**
* Copyright 2010-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
namespace Aws\Common\Exception;
/**
* AWS SDK namespaced version of the SPL UnexpectedValueException.
*/
class UnexpectedValueException extends \UnexpectedValueException implements AwsExceptionInterface {}

View file

@ -0,0 +1,67 @@
<?php
/**
* Copyright 2010-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
namespace Aws\Common\Facade;
use Aws\Common\Aws;
/**
* Base facade class that handles the delegation logic
*/
abstract class Facade implements FacadeInterface
{
/** @var Aws */
protected static $serviceBuilder;
/**
* Mounts the facades by extracting information from the service builder config and using creating class aliases
*
* @param string|null $targetNamespace Namespace that the facades should be mounted to. Defaults to global namespace
*
* @param Aws $serviceBuilder
*/
public static function mountFacades(Aws $serviceBuilder, $targetNamespace = null)
{
self::$serviceBuilder = $serviceBuilder;
require_once __DIR__ . '/facade-classes.php';
foreach ($serviceBuilder->getConfig() as $service) {
if (isset($service['alias'], $service['class'])) {
$facadeClass = __NAMESPACE__ . '\\' . $service['alias'];
$facadeAlias = ltrim($targetNamespace . '\\' . $service['alias'], '\\');
if (!class_exists($facadeAlias)) {
// @codeCoverageIgnoreStart
class_alias($facadeClass, $facadeAlias);
// @codeCoverageIgnoreEnd
}
}
}
}
/**
* Returns the instance of the client that the facade operates on
*
* @return \Aws\Common\Client\AwsClientInterface
*/
public static function getClient()
{
return self::$serviceBuilder->get(static::getServiceBuilderKey());
}
public static function __callStatic($method, $args)
{
return call_user_func_array(array(self::getClient(), $method), $args);
}
}

View file

@ -0,0 +1,32 @@
<?php
/**
* Copyright 2010-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
namespace Aws\Common\Facade;
/**
* Interface that defines a client facade. Facades are convenient static classes that allow you to run client methods
* statically on a default instance from the service builder. The facades themselves are aliased into the global
* namespace for ease of use.
*/
interface FacadeInterface
{
/**
* Returns the key used to access the client instance from the Service Builder
*
* @return string
*/
public static function getServiceBuilderKey();
}

View file

@ -0,0 +1,267 @@
<?php
/**
* Copyright 2010-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
namespace Aws\Common\Facade;
/**
* The following classes are used to implement the static client facades and are aliased into the global namespaced. We
* discourage the use of these classes directly by their full namespace since they are not autoloaded and are considered
* an implementation detail that could possibly be changed in the future.
*/
// @codeCoverageIgnoreStart
class AutoScaling extends Facade
{
public static function getServiceBuilderKey()
{
return 'autoscaling';
}
}
class CloudFormation extends Facade
{
public static function getServiceBuilderKey()
{
return 'cloudformation';
}
}
class CloudFront extends Facade
{
public static function getServiceBuilderKey()
{
return 'cloudfront';
}
}
class CloudSearch extends Facade
{
public static function getServiceBuilderKey()
{
return 'cloudsearch';
}
}
class CloudWatch extends Facade
{
public static function getServiceBuilderKey()
{
return 'cloudwatch';
}
}
class DataPipeline extends Facade
{
public static function getServiceBuilderKey()
{
return 'datapipeline';
}
}
class DirectConnect extends Facade
{
public static function getServiceBuilderKey()
{
return 'directconnect';
}
}
class DynamoDb extends Facade
{
public static function getServiceBuilderKey()
{
return 'dynamodb';
}
}
class Ec2 extends Facade
{
public static function getServiceBuilderKey()
{
return 'ec2';
}
}
class ElastiCache extends Facade
{
public static function getServiceBuilderKey()
{
return 'elasticache';
}
}
class ElasticBeanstalk extends Facade
{
public static function getServiceBuilderKey()
{
return 'elasticbeanstalk';
}
}
class ElasticLoadBalancing extends Facade
{
public static function getServiceBuilderKey()
{
return 'elasticloadbalancing';
}
}
class ElasticTranscoder extends Facade
{
public static function getServiceBuilderKey()
{
return 'elastictranscoder';
}
}
class Emr extends Facade
{
public static function getServiceBuilderKey()
{
return 'emr';
}
}
class Glacier extends Facade
{
public static function getServiceBuilderKey()
{
return 'glacier';
}
}
class Iam extends Facade
{
public static function getServiceBuilderKey()
{
return 'iam';
}
}
class ImportExport extends Facade
{
public static function getServiceBuilderKey()
{
return 'importexport';
}
}
class OpsWorks extends Facade
{
public static function getServiceBuilderKey()
{
return 'opsworks';
}
}
class Rds extends Facade
{
public static function getServiceBuilderKey()
{
return 'rds';
}
}
class Redshift extends Facade
{
public static function getServiceBuilderKey()
{
return 'redshift';
}
}
class Route53 extends Facade
{
public static function getServiceBuilderKey()
{
return 'route53';
}
}
class S3 extends Facade
{
public static function getServiceBuilderKey()
{
return 's3';
}
}
class SimpleDb extends Facade
{
public static function getServiceBuilderKey()
{
return 'sdb';
}
}
class Ses extends Facade
{
public static function getServiceBuilderKey()
{
return 'ses';
}
}
class Sns extends Facade
{
public static function getServiceBuilderKey()
{
return 'sns';
}
}
class Sqs extends Facade
{
public static function getServiceBuilderKey()
{
return 'sqs';
}
}
class StorageGateway extends Facade
{
public static function getServiceBuilderKey()
{
return 'storagegateway';
}
}
class Sts extends Facade
{
public static function getServiceBuilderKey()
{
return 'sts';
}
}
class Support extends Facade
{
public static function getServiceBuilderKey()
{
return 'support';
}
}
class Swf extends Facade
{
public static function getServiceBuilderKey()
{
return 'swf';
}
}
// @codeCoverageIgnoreEnd

View file

@ -0,0 +1,87 @@
<?php
/**
* Copyright 2010-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
namespace Aws\Common\Hash;
use Aws\Common\Exception\LogicException;
/**
* Encapsulates the creation of a hash from streamed chunks of data
*/
class ChunkHash implements ChunkHashInterface
{
/**
* @var resource The hash context as created by `hash_init()`
*/
protected $context;
/**
* @var string The resulting hash in hex form
*/
protected $hash;
/**
* @var string The resulting hash in binary form
*/
protected $hashRaw;
/**
* {@inheritdoc}
*/
public function __construct($algorithm = self::DEFAULT_ALGORITHM)
{
HashUtils::validateAlgorithm($algorithm);
$this->context = hash_init($algorithm);
}
/**
* {@inheritdoc}
*/
public function addData($data)
{
if (!$this->context) {
throw new LogicException('You may not add more data to a finalized chunk hash.');
}
hash_update($this->context, $data);
return $this;
}
/**
* {@inheritdoc}
*/
public function getHash($returnBinaryForm = false)
{
if (!$this->hash) {
$this->hashRaw = hash_final($this->context, true);
$this->hash = HashUtils::binToHex($this->hashRaw);
$this->context = null;
}
return $returnBinaryForm ? $this->hashRaw : $this->hash;
}
/**
* {@inheritdoc}
*/
public function __clone()
{
if ($this->context) {
$this->context = hash_copy($this->context);
}
}
}

View file

@ -0,0 +1,52 @@
<?php
/**
* Copyright 2010-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
namespace Aws\Common\Hash;
/**
* Interface for objects that encapsulate the creation of a hash from streamed chunks of data
*/
interface ChunkHashInterface
{
const DEFAULT_ALGORITHM = 'sha256';
/**
* Constructs the chunk hash and sets the algorithm to use for hashing
*
* @param string $algorithm A valid hash algorithm name as returned by `hash_algos()`
*
* @return self
*/
public function __construct($algorithm = 'sha256');
/**
* Add a chunk of data to be hashed
*
* @param string $data Data to be hashed
*
* @return self
*/
public function addData($data);
/**
* Return the results of the hash
*
* @param bool $returnBinaryForm If true, returns the hash in binary form instead of hex form
*
* @return string
*/
public function getHash($returnBinaryForm = false);
}

View file

@ -0,0 +1,72 @@
<?php
/**
* Copyright 2010-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
namespace Aws\Common\Hash;
use Aws\Common\Exception\InvalidArgumentException;
/**
* Contains hashing utilities
*/
class HashUtils
{
/**
* Converts a hash in hex form to binary form
*
* @param string $hash Hash in hex form
*
* @return string Hash in binary form
*/
public static function hexToBin($hash)
{
// If using PHP 5.4, there is a native function to convert from hex to binary
static $useNative;
if ($useNative === null) {
$useNative = function_exists('hex2bin');
}
return $useNative ? hex2bin($hash) : pack("H*", $hash);
}
/**
* Converts a hash in binary form to hex form
*
* @param string $hash Hash in binary form
*
* @return string Hash in hex form
*/
public static function binToHex($hash)
{
return bin2hex($hash);
}
/**
* Checks if the algorithm specified exists and throws an exception if it does not
*
* @param string $algorithm Name of the algorithm to validate
*
* @return bool
* @throws InvalidArgumentException if the algorithm doesn't exist
*/
public static function validateAlgorithm($algorithm)
{
if (!in_array($algorithm, hash_algos(), true)) {
throw new InvalidArgumentException("The hashing algorithm specified ({$algorithm}) does not exist.");
}
return true;
}
}

View file

@ -0,0 +1,195 @@
<?php
/**
* Copyright 2010-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
namespace Aws\Common\Hash;
use Aws\Common\Enum\Size;
use Aws\Common\Exception\InvalidArgumentException;
use Aws\Common\Exception\LogicException;
use Guzzle\Http\EntityBody;
/**
* Encapsulates the creation of a tree hash from streamed chunks of data
*/
class TreeHash implements ChunkHashInterface
{
/**
* @var string The algorithm used for hashing
*/
protected $algorithm;
/**
* @var array Set of binary checksums from which the tree hash is derived
*/
protected $checksums = array();
/**
* @var string The resulting hash in hex form
*/
protected $hash;
/**
* @var string The resulting hash in binary form
*/
protected $hashRaw;
/**
* Create a tree hash from an array of existing tree hash checksums
*
* @param array $checksums Set of checksums
* @param bool $inBinaryForm Whether or not the checksums are already in binary form
* @param string $algorithm A valid hash algorithm name as returned by `hash_algos()`
*
* @return TreeHash
*/
public static function fromChecksums(array $checksums, $inBinaryForm = false, $algorithm = self::DEFAULT_ALGORITHM)
{
$treeHash = new self($algorithm);
// Convert checksums to binary form if provided in hex form and add them to the tree hash
$treeHash->checksums = $inBinaryForm ? $checksums : array_map('Aws\Common\Hash\HashUtils::hexToBin', $checksums);
// Pre-calculate hash
$treeHash->getHash();
return $treeHash;
}
/**
* Create a tree hash from a content body
*
* @param string|resource|EntityBody $content Content to create a tree hash for
* @param string $algorithm A valid hash algorithm name as returned by `hash_algos()`
*
* @return TreeHash
*/
public static function fromContent($content, $algorithm = self::DEFAULT_ALGORITHM)
{
$treeHash = new self($algorithm);
// Read the data in 1MB chunks and add to tree hash
$content = EntityBody::factory($content);
while ($data = $content->read(Size::MB)) {
$treeHash->addData($data);
}
// Pre-calculate hash
$treeHash->getHash();
return $treeHash;
}
/**
* Validates an entity body with a tree hash checksum
*
* @param string|resource|EntityBody $content Content to create a tree hash for
* @param string $checksum The checksum to use for validation
* @param string $algorithm A valid hash algorithm name as returned by `hash_algos()`
*
* @return bool
*/
public static function validateChecksum($content, $checksum, $algorithm = self::DEFAULT_ALGORITHM)
{
$treeHash = self::fromContent($content, $algorithm);
return ($checksum === $treeHash->getHash());
}
/**
* {@inheritdoc}
*/
public function __construct($algorithm = self::DEFAULT_ALGORITHM)
{
HashUtils::validateAlgorithm($algorithm);
$this->algorithm = $algorithm;
}
/**
* {@inheritdoc}
* @throws LogicException if the root tree hash is already calculated
* @throws InvalidArgumentException if the data is larger than 1MB
*/
public function addData($data)
{
// Error if hash is already calculated
if ($this->hash) {
throw new LogicException('You may not add more data to a finalized tree hash.');
}
// Make sure that only 1MB chunks or smaller get passed in
if (strlen($data) > Size::MB) {
throw new InvalidArgumentException('The chunk of data added is too large for tree hashing.');
}
// Store the raw hash of this data segment
$this->checksums[] = hash($this->algorithm, $data, true);
return $this;
}
/**
* Add a checksum to the tree hash directly
*
* @param string $checksum The checksum to add
* @param bool $inBinaryForm Whether or not the checksum is already in binary form
*
* @return self
* @throws LogicException if the root tree hash is already calculated
*/
public function addChecksum($checksum, $inBinaryForm = false)
{
// Error if hash is already calculated
if ($this->hash) {
throw new LogicException('You may not add more checksums to a finalized tree hash.');
}
// Convert the checksum to binary form if necessary
$this->checksums[] = $inBinaryForm ? $checksum : HashUtils::hexToBin($checksum);
return $this;
}
/**
* {@inheritdoc}
*/
public function getHash($returnBinaryForm = false)
{
if (!$this->hash) {
// Perform hashes up the tree to arrive at the root checksum of the tree hash
$hashes = $this->checksums;
while (count($hashes) > 1) {
$sets = array_chunk($hashes, 2);
$hashes = array();
foreach ($sets as $set) {
$hashes[] = (count($set) === 1) ? $set[0] : hash($this->algorithm, $set[0] . $set[1], true);
}
}
$this->hashRaw = $hashes[0];
$this->hash = HashUtils::binToHex($this->hashRaw);
}
return $returnBinaryForm ? $this->hashRaw : $this->hash;
}
/**
* @return array Array of raw checksums composing the tree hash
*/
public function getChecksums()
{
return $this->checksums;
}
}

View file

@ -0,0 +1,85 @@
<?php
/**
* Copyright 2010-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
namespace Aws\Common;
use Guzzle\Http\Url;
/**
* Utility class for parsing regions and services from URLs
*/
class HostNameUtils
{
const DEFAULT_REGION = 'us-east-1';
const DEFAULT_GOV_REGION = 'us-gov-west-1';
/**
* Parse the AWS region name from a URL
*
*
* @param Url $url HTTP URL
*
* @return string
* @link http://docs.amazonwebservices.com/general/latest/gr/rande.html
*/
public static function parseRegionName(Url $url)
{
// If we don't recognize the domain, just return the default
if (substr($url->getHost(), -14) != '.amazonaws.com') {
return self::DEFAULT_REGION;
}
$serviceAndRegion = substr($url->getHost(), 0, -14);
// Special handling for S3 regions
$separator = strpos($serviceAndRegion, 's3') === 0 ? '-' : '.';
$separatorPos = strpos($serviceAndRegion, $separator);
// If don't detect a separator, then return the default region
if ($separatorPos === false) {
return self::DEFAULT_REGION;
}
$region = substr($serviceAndRegion, $separatorPos + 1);
// All GOV regions currently use the default GOV region
if ($region == 'us-gov') {
return self::DEFAULT_GOV_REGION;
}
return $region;
}
/**
* Parse the AWS service name from a URL
*
* @param Url $url HTTP URL
*
* @return string Returns a service name (or empty string)
* @link http://docs.amazonwebservices.com/general/latest/gr/rande.html
*/
public static function parseServiceName(Url $url)
{
// The service name is the first part of the host
$parts = explode('.', $url->getHost(), 2);
// Special handling for S3
if (stripos($parts[0], 's3') === 0) {
return 's3';
}
return $parts[0];
}
}

View file

@ -0,0 +1,99 @@
<?php
/**
* Copyright 2010-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
namespace Aws\Common\InstanceMetadata;
use Aws\Common\Enum\ClientOptions as Options;
use Aws\Common\Exception\InstanceProfileCredentialsException;
use Aws\Common\Credentials\Credentials;
use Aws\Common\Client\AbstractClient;
use Guzzle\Common\Collection;
use Guzzle\Http\Message\RequestFactory;
/**
* Client used for interacting with the Amazon EC2 instance metadata server
*/
class InstanceMetadataClient extends AbstractClient
{
/**
* Factory method to create a new InstanceMetadataClient using an array
* of configuration options.
*
* The configuration options accepts the following array keys and values:
* - base_url: Override the base URL of the instance metadata server
* - version: Version of the metadata server to interact with
*
* @param array|Collection $config Configuration options
*
* @return InstanceMetadataClient
*/
public static function factory($config = array())
{
$config = Collection::fromConfig($config, array(
Options::BASE_URL => 'http://169.254.169.254/{version}/',
'version' => 'latest',
), array('base_url', 'version'));
return new self($config);
}
/**
* Constructor override
*/
public function __construct(Collection $config)
{
$this->setConfig($config);
$this->setBaseUrl($config->get(Options::BASE_URL));
$this->defaultHeaders = new Collection();
$this->setRequestFactory(RequestFactory::getInstance());
}
/**
* Get instance profile credentials
*
* @return Credentials
* @throws InstanceProfileCredentialsException
*/
public function getInstanceProfileCredentials()
{
try {
$request = $this->get('meta-data/iam/security-credentials/');
$request->getCurlOptions()->set(CURLOPT_TIMEOUT, 1)->set(CURLOPT_CONNECTTIMEOUT, 1);
$credentials = trim($request->send()->getBody(true));
$result = $this->get("meta-data/iam/security-credentials/{$credentials}")->send()->json();
} catch (\Exception $e) {
$message = 'Error retrieving credentials from the instance profile metadata server. When you are not'
. ' running inside of Amazon EC2, you must provide your AWS access key ID and secret access key in'
. ' the "key" and "secret" options when creating a client or provide an instantiated'
. ' Aws\\Common\\Credentials\\CredentialsInterface object.';
throw new InstanceProfileCredentialsException($message, $e->getCode(), $e);
}
// Ensure that the status code was successful
if ($result['Code'] !== 'Success') {
$e = new InstanceProfileCredentialsException('Unexpected response code: ' . $result['Code']);
$e->setStatusCode($result['Code']);
throw $e;
}
return new Credentials(
$result['AccessKeyId'],
$result['SecretAccessKey'],
$result['Token'],
strtotime($result['Expiration'])
);
}
}

View file

@ -0,0 +1,50 @@
<?php
/**
* Copyright 2010-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
namespace Aws\Common\InstanceMetadata\Waiter;
use Aws\Common\Waiter\AbstractResourceWaiter;
use Guzzle\Http\Exception\CurlException;
/**
* Waits until the instance metadata service is responding. Will send up to
* 4 requests with a 5 second delay between each try. Each try can last up to
* 11 seconds to complete if the service is not responding.
*
* @codeCoverageIgnore
*/
class ServiceAvailable extends AbstractResourceWaiter
{
protected $interval = 5;
protected $maxAttempts = 4;
/**
* {@inheritdoc}
*/
public function doWait()
{
$request = $this->client->get();
try {
$request->getCurlOptions()->set(CURLOPT_CONNECTTIMEOUT, 10)
->set(CURLOPT_TIMEOUT, 10);
$request->send();
return true;
} catch (CurlException $e) {
return false;
}
}
}

View file

@ -0,0 +1,149 @@
<?php
/**
* Copyright 2010-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
namespace Aws\Common\Iterator;
use Aws\Common\Enum\UaString as Ua;
use Aws\Common\Exception\RuntimeException;
Use Guzzle\Service\Resource\Model;
use Guzzle\Service\Resource\ResourceIterator;
/**
* Iterate over a client command
*/
class AwsResourceIterator extends ResourceIterator
{
/**
* @var Model Result of a command
*/
protected $lastResult = null;
/**
* Provides access to the most recent result obtained by the iterator.
*
* @return Model|null
*/
public function getLastResult()
{
return $this->lastResult;
}
/**
* {@inheritdoc}
* This AWS specific version of the resource iterator provides a default implementation of the typical AWS iterator
* process. It relies on configuration and extension to implement the operation-specific logic of handling results
* and nextTokens. This method will loop until resources are acquired or there are no more iterations available.
*/
protected function sendRequest()
{
do {
// Prepare the request including setting the next token
$this->prepareRequest();
if ($this->nextToken) {
$this->applyNextToken();
}
// Execute the request and handle the results
$this->command->add(Ua::OPTION, Ua::ITERATOR);
$this->lastResult = $this->command->getResult();
$resources = $this->handleResults($this->lastResult);
$this->determineNextToken($this->lastResult);
// If no resources collected, prepare to reiterate before yielding
if ($reiterate = empty($resources) && $this->nextToken) {
$this->command = clone $this->originalCommand;
}
} while ($reiterate);
return $resources;
}
/**
* {@inheritdoc}
*/
protected function prepareRequest()
{
// Get the limit parameter key to set
$param = $this->get('limit_param');
if ($param && ($limit = $this->command->get($param))) {
$pageSize = $this->calculatePageSize();
// If the limit of the command is different than the pageSize of the iterator, use the smaller value
if ($limit && $pageSize) {
$this->command->set('limit', min($limit, $pageSize));
}
}
}
/**
* {@inheritdoc}
*/
protected function handleResults(Model $result)
{
$results = array();
// Get the result key that contains the results
if ($resultKey = $this->get('result_key')) {
$results = $result->getPath($resultKey) ?: array();
}
return $results;
}
/**
* {@inheritdoc}
*/
protected function applyNextToken()
{
// Get the token parameter key to set
if ($tokenParam = $this->get('token_param')) {
// Set the next token. Works with multi-value tokens
if (is_array($tokenParam)) {
if (is_array($this->nextToken) && count($tokenParam) === count($this->nextToken)) {
foreach (array_combine($tokenParam, $this->nextToken) as $param => $token) {
$this->command->set($param, $token);
}
} else {
throw new RuntimeException('The definition of the iterator\'s token parameter and the actual token '
. 'value are not compatible.');
}
} else {
$this->command->set($tokenParam, $this->nextToken);
}
}
}
/**
* {@inheritdoc}
*/
protected function determineNextToken(Model $result)
{
$this->nextToken = null;
// If the value of "more key" is true or there is no "more key" to check, then try to get the next token
$moreKey = $this->get('more_key');
if ($moreKey === null || $result->getPath($moreKey)) {
// Get the token key to check
if ($tokenKey = $this->get('token_key')) {
// Get the next token's value. Works with multi-value tokens
$getToken = function ($key) use ($result) {
return $result->getPath((string) $key);
};
$this->nextToken = is_array($tokenKey) ? array_map($getToken, $tokenKey) : $getToken($tokenKey);
}
}
}
}

View file

@ -0,0 +1,101 @@
<?php
namespace Aws\Common\Iterator;
use Aws\Common\Exception\InvalidArgumentException;
use Guzzle\Common\Collection;
use Guzzle\Service\Command\CommandInterface;
use Guzzle\Service\Resource\ResourceIteratorFactoryInterface;
/**
* Resource iterator factory used to instantiate the default AWS resource iterator with the correct configuration or
* use a concrete iterator class if one exists
*/
class AwsResourceIteratorFactory implements ResourceIteratorFactoryInterface
{
/**
* @var array Default configuration values for iterators
*/
protected static $defaultConfig = array(
'limit_key' => null,
'limit_param' => null,
'more_key' => null,
'token_key' => null,
'token_param' => null,
'operations' => array(),
);
/**
* @var Collection The configuration for the iterators
*/
protected $config;
/**
* @var Collection Additional configurations for specific iterators
*/
protected $operations;
/**
* @var ResourceIteratorFactoryInterface Another factory that will be used first to instantiate the iterator
*/
protected $primaryIteratorFactory;
/**
* @param array $config An array of configuration values for the factory
* @param ResourceIteratorFactoryInterface $primaryIteratorFactory Another factory to use for chain of command
*
* @throws InvalidArgumentException
*/
public function __construct(array $config, ResourceIteratorFactoryInterface $primaryIteratorFactory = null)
{
$this->primaryIteratorFactory = $primaryIteratorFactory;
// Set up the config with default values
$this->config = Collection::fromConfig($config, self::$defaultConfig);
// Pull out the operation-specific configurations
$this->operations = new Collection();
$potentialOperations = $this->config->get('operations') ?: array();
$this->config->remove('operations');
foreach ($potentialOperations as $key => $value) {
if (is_int($key) && is_string($value)) {
$this->operations->set($value, array());
} elseif (is_string($key) && is_array($value)) {
$this->operations->set($key, $value);
} else {
throw new InvalidArgumentException('The iterator factory configuration was invalid.');
}
}
}
/**
* {@inheritdoc}
*/
public function build(CommandInterface $command, array $options = array())
{
// Get the configuration data for the command
$commandName = $command->getName();
$iteratorConfig = $this->operations->get($commandName) ?: array();
$options = array_replace($this->config->getAll(), $iteratorConfig, $options);
// Instantiate the iterator using the primary factory (if there is one)
if ($this->primaryIteratorFactory && $this->primaryIteratorFactory->canBuild($command)) {
$iterator = $this->primaryIteratorFactory->build($command, $options);
} elseif (!$this->operations->hasKey($commandName)) {
throw new InvalidArgumentException("Iterator was not found for {$commandName}.");
} else {
// Fallback to this factory for creating the iterator if the primary factory did not work
$iterator = new AwsResourceIterator($command, $options);
}
return $iterator;
}
/**
* {@inheritdoc}
*/
public function canBuild(CommandInterface $command)
{
return ($this->primaryIteratorFactory && $this->primaryIteratorFactory->canBuild($command))
|| $this->operations->hasKey($command->getName());
}
}

Some files were not shown because too many files have changed in this diff Show more