Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions s3_storage/composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"name": "friendica-addons/s3_storage",
"description": "Adds the possibility to use S3 as a selectable storage backend",
"type": "friendica-addon",
"authors": [
{
"name": "Philipp Holzer",
"email": "[email protected]",
"homepage": "https://blog.philipp.info",
"role": "Developer"
}
],
"require": {
"php": ">=7.0",
"akeeba/s3": "^2.0"
},
"license": "3-clause BSD license",
"config": {
"optimize-autoloader": true,
"autoloader-suffix": "S3StorageAddon",
"preferred-install": "dist"
}
}
65 changes: 65 additions & 0 deletions s3_storage/composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

108 changes: 108 additions & 0 deletions s3_storage/lang/C/messages.po
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
# ADDON s3_storage
# Copyright (C)
# This file is distributed under the same license as the Friendica s3_storage addon package.
#
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-02-24 23:25+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <[email protected]>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"

#: src/S3Config.php:113
msgid "Access Key"
msgstr ""

#: src/S3Config.php:115
msgid "Set the Access Key of the S3 storage"
msgstr ""

#: src/S3Config.php:120
msgid "Secret Key"
msgstr ""

#: src/S3Config.php:122
msgid "Set the Secret Key of the S3 storage"
msgstr ""

#: src/S3Config.php:127
msgid "Bucket"
msgstr ""

#: src/S3Config.php:129
msgid "The S3 Bucket (name), you want to use with Friendica"
msgstr ""

#: src/S3Config.php:134
msgid "Signature Method"
msgstr ""

#: src/S3Config.php:136
msgid ""
"Set the signature method to use (BEWARE: v4 will be automatically set to v2 "
"in case the endpoint isn't amazon)"
msgstr ""

#: src/S3Config.php:141
#, php-format
msgid "Amazon S3 compatible endpoint (leave empty for '%s')"
msgstr ""

#: src/S3Config.php:143
msgid ""
"Set the S3 endpoint. Do NOT use a protocol (You can use a custom endpoint "
"with v2 signatures to access third party services which offer S3 "
"compatibility, e.g. OwnCloud, Google Storage etc.)"
msgstr ""

#: src/S3Config.php:147
#, php-format
msgid "AWS region (leave empty for '%s')"
msgstr ""

#: src/S3Config.php:149
msgid "The AWS region is mandatory for v4 signatures"
msgstr ""

#: src/S3Config.php:153
msgid "Use the dualstack URL (which will ship traffic over ipv6 in most cases)"
msgstr ""

#: src/S3Config.php:155
msgid ""
"For more information on these endpoints please read https://docs.aws.amazon."
"com/AmazonS3/latest/dev/dual-stack-endpoints.html"
msgstr ""

#: src/S3Config.php:159
msgid "Use legacy, path-style access to the bucket"
msgstr ""

#: src/S3Config.php:161
msgid ""
"When it's turned off (default) we use virtual hosting stylepaths which are "
"RECOMMENDED BY AMAZON per http://docs.aws.amazon.com/AmazonS3/latest/API/"
"APIRest.html"
msgstr ""

#: src/S3Config.php:175
msgid "Invalid input"
msgstr ""

#: src/S3Config.php:214
#, php-format
msgid "error '%s', message '%s'"
msgstr ""

#: src/S3Config.php:222
#, php-format
msgid "Bucket %s cannot be not found, possible buckets: %s"
msgstr ""
42 changes: 42 additions & 0 deletions s3_storage/s3_storage.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php
/*
* Name: S3 Storage
* Description: Adds the possibility to use Amazon S3 as a selectable storage backend
* Version: 1.0
* Author: Philipp Holzer
*/

use Friendica\Addon\s3_storage\src\S3Client;
use Friendica\Addon\s3_storage\src\S3Config;
use Friendica\App;
use Friendica\Core\Hook;
use Friendica\DI;

require_once __DIR__ . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'autoload.php';

function s3_storage_install($a)
{
Hook::register('storage_instance' , __FILE__, 's3_storage_instance');
Hook::register('storage_config' , __FILE__, 's3_storage_config');
DI::storageManager()->register(S3Client::class);
}

function s3_storage_uninstall()
{
DI::storageManager()->unregister(S3Client::class);
}

function s3_storage_instance(App $a, array &$data)
{
if ($data['name'] == S3Client::getName()) {
$config = new S3Config(DI::l10n(), DI::config());
$data['storage'] = new S3Client($config->getConfig(), $config->getBucket());
}
}

function s3_storage_config(App $a, array &$data)
{
if ($data['name'] == S3Client::getName()) {
$data['storage_config'] = new S3Config(DI::l10n(), DI::config());
}
}
101 changes: 101 additions & 0 deletions s3_storage/src/S3Client.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
<?php

namespace Friendica\Addon\s3_storage\src;

defined('AKEEBAENGINE') or define('AKEEBAENGINE', 1);

use Akeeba\Engine\Postproc\Connector\S3v4\Configuration;
use Akeeba\Engine\Postproc\Connector\S3v4\Connector;
use Akeeba\Engine\Postproc\Connector\S3v4\Exception\CannotDeleteFile;
use Akeeba\Engine\Postproc\Connector\S3v4\Input;
use Friendica\Core\Storage\Capability\ICanWriteToStorage;
use Friendica\Core\Storage\Exception\StorageException;
use Friendica\Util\Strings;

/**
* A WebDav Backend Storage class
*/
class S3Client implements ICanWriteToStorage
{
const NAME = 'S3';

/** @var Connector */
protected $connector;

/** @var string The name of the bucket used for the backend */
protected $bucket;

public function __construct(Configuration $config, string $bucket)
{
$this->connector = new Connector($config);
$this->bucket = $bucket;
}

/**
* Split data ref and return file path
*
* @param string $reference Data reference
*
* @return string
*/
private function pathForRef(string $reference): string
{
$fold1 = substr($reference, 0, 2);
$fold2 = substr($reference, 2, 2);
$file = substr($reference, 4);

return implode('/', [$fold1, $fold2, $file]);
}

/** {@inheritDoc} */
public function __toString(): string
{
return self::getName();
}

/** {@inheritDoc} */
public static function getName(): string
{
return self::NAME;
}

/** {@inheritDoc} */
public function get(string $reference): string
{
try {
return $this->connector->getObject($this->bucket, $this->pathForRef($reference), false);
} catch (\RuntimeException $exception) {
throw new StorageException(sprintf('Cannot get reference %s', $reference), $exception->getCode(), $exception);
}
}

/** {@inheritDoc} */
public function put(string $data, string $reference = ""): string
{
if ($reference === '') {
try {
$reference = Strings::getRandomHex();
} catch (\Exception $exception) {
throw new StorageException('S3 storage failed to generate a random hex', $exception->getCode(), $exception);
}
}

try {
$input = Input::createFromData($data);
$this->connector->putObject($input, $this->bucket, $this->pathForRef($reference));
return $reference;
} catch (\Exception $exception) {
throw new StorageException(sprintf('Cannot put data for reference %s', $reference), $exception->getCode(), $exception);
}
}

/** {@inheritDoc} */
public function delete(string $reference)
{
try {
$this->connector->deleteObject($this->bucket, $this->pathForRef($reference));
} catch (CannotDeleteFile $exception) {
throw new StorageException(sprintf('Cannot delete reference %s', $reference), $exception->getCode(), $exception);
}
}
}
Loading