File indexing completed on 2024-11-24 05:19:04

0001 <?php
0002 /**
0003  * file server - part of Opendesktop.org platform project <https://www.opendesktop.org>.
0004  *
0005  * Copyright (c) 2016 pling GmbH.
0006  *
0007  * This program is free software: you can redistribute it and/or modify
0008  * it under the terms of the GNU Affero General Public License as
0009  * published by the Free Software Foundation, either version 3 of the
0010  * License, or (at your option) any later version.
0011  *
0012  * This program is distributed in the hope that it will be useful,
0013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0015  * GNU Affero General Public License for more details.
0016  *
0017  * You should have received a copy of the GNU Affero General Public License
0018  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
0019  */
0020 
0021 namespace Ocs\Storage;
0022 
0023 use Aws\Credentials\Credentials;
0024 use Aws\S3\S3Client;
0025 use finfo;
0026 
0027 class S3Adapter implements AdapterInterface
0028 {
0029     private object $appConfig;
0030     private S3Client $s3Client;
0031 
0032     public function __construct(object $appConfig)
0033     {
0034         $this->appConfig = $appConfig;
0035     }
0036 
0037     /**
0038      * @inheritDoc
0039      */
0040     public function moveUploadedFile(string $from, string $to): bool
0041     {
0042         error_log("from=$from, to=$to");
0043         $finfo = new finfo(FILEINFO_MIME_TYPE);
0044         $type = $finfo->file($from);
0045         $md5sum = md5_file($from);
0046 
0047         $bucketKey = $this->getBucketKey($to);
0048 
0049         $awsClient = $this->getAwsClient();
0050         $awsResult = $awsClient->putObject(['Bucket'      => $this->appConfig->awss3['bucket'],
0051                                             'Key'         => $bucketKey,
0052                                             'SourceFile'  => $from,
0053                                             'ACL'         => 'private',
0054                                             'ContentType' => $type,//            'ContentMD5' => base64_encode($md5sum),
0055                                            ]);
0056 
0057         if (is_object($awsResult)) {
0058             if ($awsResult->get('@metadata')['statusCode'] != 200) {
0059                 error_log(print_r($awsResult, true));
0060 
0061                 return false;
0062             }
0063             if (trim($awsResult->get('ETag'), '"') != $md5sum) {
0064                 error_log(__METHOD__ . ' - upload failure: checksum different');
0065                 error_log(print_r($awsResult, true));
0066 
0067                 return false;
0068             }
0069         }
0070         error_log(print_r($awsResult, true));
0071 
0072         return true;
0073     }
0074 
0075     /**
0076      * @param string $to
0077      *
0078      * @return string
0079      */
0080     public function getBucketKey(string $to): string
0081     {
0082         $bucketPathPrefix = $this->appConfig->awss3['bucketPathPrefix'];
0083         $pos = strpos($to, $bucketPathPrefix);
0084 
0085         return ltrim(substr($to, $pos), " /");
0086     }
0087 
0088     private function getAwsClient(): S3Client
0089     {
0090         if (!empty($this->s3Client)) {
0091             return $this->s3Client;
0092         }
0093         // Instantiate an Amazon S3 client.
0094         if (empty($this->appConfig->awss3['endpoint'])) {
0095             $this->s3Client = new S3Client(['credentials' => new Credentials($this->appConfig->awss3['key'], $this->appConfig->awss3['secret']),
0096                                             'version'     => 'latest',
0097                                             'region'      => $this->appConfig->awss3['region'],]);
0098         } else {
0099             $this->s3Client = new S3Client(['credentials' => new Credentials($this->appConfig->awss3['key'], $this->appConfig->awss3['secret']),
0100                                             'version'     => 'latest',
0101                                             'region'      => $this->appConfig->awss3['region'],
0102                                             'endpoint'    => $this->appConfig->awss3['endpoint'],]);
0103         }
0104 
0105         return $this->s3Client;
0106     }
0107 
0108     public function fixFilename(string $name, string $collectionPath): string
0109     {
0110         $awsClient = $this->getAwsClient();
0111         $counter = 0;
0112         while ($counter < 5) {
0113             $bucketName = $this->appConfig->awss3['bucketPathPrefix'] . '/' . $collectionPath . '/' . $name;
0114             $awsObjectExists = $awsClient->doesObjectExist($this->appConfig->awss3['bucket'], $bucketName);
0115             if (!$awsObjectExists) {
0116                 break;
0117             }
0118             $counter++;
0119             $fix = date('YmdHis');
0120             if (preg_match("/^([^.]+)(\..+)/", $name, $matches)) {
0121                 $name = $matches[1] . '-' . $fix . $matches[2];
0122             } else {
0123                 $name = $name . '-' . $fix;
0124             }
0125         }
0126 
0127         return $name;
0128     }
0129 
0130     public function prepareCollectionPath(string $collectionName, string $filePath): bool
0131     {
0132         return true;
0133     }
0134 
0135     public function testAndCreate(string $dir): bool
0136     {
0137         return true;
0138     }
0139 
0140     public function moveFile($from, $to): bool
0141     {
0142         $awsClient = $this->getAwsClient();
0143         $destKey = $this->getBucketKey($to);
0144         $srcKey = $this->getBucketKey($from);
0145 //        $awsResult = $awsClient->headObject([
0146 //            'Bucket'     => $this->appConfig->awss3['bucket'],
0147 //            'Key'        => $srcKey,
0148 //        ]);
0149         $awsResult = $awsClient->copyObject(['Bucket'     => $this->appConfig->awss3['bucket'],
0150                                              'Key'        => $destKey,
0151                                              'CopySource' => $this->appConfig->awss3['bucket'] . '/' . $srcKey,]);
0152         error_log(__METHOD__ . ' - ' . 'copyObject: ' . print_r($awsResult, true));
0153         if (is_object($awsResult)) {
0154             $responseCode = $awsResult->get('@metadata')['statusCode'];
0155             if (false == in_array($responseCode, [200, 201, 202, 204])) {
0156                 error_log(print_r($awsResult, true));
0157 
0158                 return false;
0159             }
0160         }
0161 
0162         $awsResult = $awsClient->deleteObject(['Bucket' => $this->appConfig->awss3['bucket'],
0163                                                'Key'    => $srcKey,]);
0164         error_log(__METHOD__ . ' - ' . 'copyObject: ' . print_r($awsResult, true));
0165 
0166         return true;
0167     }
0168 
0169     public function copyFile($from, $to): bool
0170     {
0171         $awsClient = $this->getAwsClient();
0172         $destKey = $this->getBucketKey($to);
0173         $srcKey = $this->getBucketKey($from);
0174         $awsResult = $awsClient->copyObject(['Bucket'     => $this->appConfig->awss3['bucket'],
0175                                              'Key'        => $destKey,
0176                                              'CopySource' => $this->appConfig->awss3['bucket'] . '/' . $srcKey,]);
0177         error_log(__METHOD__ . ' - ' . 'copyObject: ' . print_r($awsResult, true));
0178         if (is_object($awsResult)) {
0179             $responseCode = $awsResult->get('@metadata')['statusCode'];
0180             if (false == in_array($responseCode, [200, 201, 202, 204])) {
0181                 error_log(print_r($awsResult, true));
0182 
0183                 return false;
0184             }
0185         }
0186         error_log(__METHOD__ . ' - ' . 'copyObject: ' . print_r($awsResult, true));
0187 
0188         return true;
0189     }
0190 
0191     public function isFile($from): bool
0192     {
0193         $bucketName = $this->appConfig->awss3['bucketPathPrefix'] . '/' . $from;
0194         $awsClient = $this->getAwsClient();
0195 
0196         return $awsClient->doesObjectExist($this->appConfig->awss3['bucket'], $bucketName);
0197     }
0198 
0199 }