1010use OCA \Social \Entity \MediaAttachment ;
1111use OCA \Social \Service \AccountFinder ;
1212use OCP \AppFramework \Http ;
13+ use OCP \AppFramework \Http \Response ;
1314use OCP \AppFramework \Http \DataResponse ;
15+ use OCP \AppFramework \Http \DataDownloadResponse ;
16+ use OCP \AppFramework \Http \NotFoundResponse ;
1417use OCP \DB \ORM \IEntityManager ;
1518use OCP \Files \IAppData ;
1619use OCP \Files \NotFoundException ;
1720use OCP \IL10N ;
1821use OCP \AppFramework \Controller ;
19- use OCP \AppFramework \Http \DataResponse ;
2022use OCP \Files \IMimeTypeDetector ;
2123use OCP \Image ;
2224use OCP \IRequest ;
2325use OCP \IURLGenerator ;
2426use OCP \IUserSession ;
2527use OCP \Util ;
28+ use Psr \Log \LoggerInterface ;
2629
2730class MediaApiController extends Controller {
2831
@@ -34,6 +37,18 @@ class MediaApiController extends Controller {
3437 private IEntityManager $ entityManager ;
3538 private IURLGenerator $ generator ;
3639
40+ public const IMAGE_MIME_TYPES = [
41+ 'image/png ' ,
42+ 'image/jpeg ' ,
43+ 'image/jpg ' ,
44+ 'image/gif ' ,
45+ 'image/x-xbitmap ' ,
46+ 'image/x-ms-bmp ' ,
47+ 'image/bmp ' ,
48+ 'image/svg+xml ' ,
49+ 'image/webp ' ,
50+ ];
51+
3752 public function __construct (
3853 string $ appName ,
3954 IRequest $ request ,
@@ -43,7 +58,8 @@ public function __construct(
4358 IUserSession $ userSession ,
4459 AccountFinder $ accountFinder ,
4560 IEntityManager $ entityManager ,
46- IURLGenerator $ generator
61+ IURLGenerator $ generator ,
62+ LoggerInterface $ logger
4763 ) {
4864 parent ::__construct ($ appName , $ request );
4965 $ this ->l10n = $ l10n ;
@@ -53,14 +69,15 @@ public function __construct(
5369 $ this ->accountFinder = $ accountFinder ;
5470 $ this ->entityManager = $ entityManager ;
5571 $ this ->generator = $ generator ;
72+ $ this ->logger = $ logger ;
5673 }
5774
5875 /**
5976 * Creates an attachment to be used with a new status.
6077 *
6178 * @NoAdminRequired
6279 */
63- public function uploadMedia (string $ description , string $ focus = '' ): DataResponse {
80+ public function uploadMedia (? string $ description , ? string $ focus = '' ): DataResponse {
6481 try {
6582 $ file = $ this ->getUploadedFile ('file ' );
6683 if (!isset ($ file ['tmp_name ' ], $ file ['name ' ], $ file ['type ' ])) {
@@ -90,10 +107,10 @@ public function uploadMedia(string $description, string $focus = ''): DataRespon
90107 "aspect " => $ image ->width () / $ image ->height (),
91108 ];
92109
93- $ attachment = new MediaAttachment ();
110+ $ attachment = MediaAttachment:: create ();
94111 $ attachment ->setMimetype ($ file ['type ' ]);
95112 $ attachment ->setAccount ($ account );
96- $ attachment ->setDescription ($ description );
113+ $ attachment ->setDescription ($ description ?? '' );
97114 $ attachment ->setMeta ($ meta );
98115 $ this ->entityManager ->persist ($ attachment );
99116 $ this ->entityManager ->flush ();
@@ -103,10 +120,39 @@ public function uploadMedia(string $description, string $focus = ''): DataRespon
103120 } catch (NotFoundException $ e ) {
104121 $ folder = $ this ->appData ->newFolder ('media-attachments ' );
105122 }
123+ assert ($ attachment ->getId () !== '' );
106124 $ folder ->newFile ($ attachment ->getId (), $ image ->data ());
107125
108126 return new DataResponse ($ attachment ->toMastodonApi ($ this ->generator ));
109127 } catch (\Exception $ e ) {
128+ $ this ->logger ->error ($ e ->getMessage (), ['exception ' => $ e ]);
129+ return new DataResponse ([
130+ "error " => "Validation failed: File content type is invalid, File is invalid " ,
131+ ], 500 );
132+ }
133+ }
134+
135+ /**
136+ * @NoAdminRequired
137+ */
138+ public function updateMedia (string $ id , ?string $ description , ?string $ focus = '' ): Response {
139+ try {
140+ $ account = $ this ->accountFinder ->getCurrentAccount ($ this ->userSession ->getUser ());
141+ $ attachementRepository = $ this ->entityManager ->getRepository (MediaAttachment::class);
142+ $ attachement = $ attachementRepository ->findOneBy ([
143+ 'id ' => $ id ,
144+ ]);
145+ if ($ attachement ->getAccount ()->getId () !== $ account ->getId ()) {
146+ throw new NotFoundResponse ();
147+ }
148+
149+ $ attachement ->setDescription ($ description ?? '' );
150+ $ this ->entityManager ->persist ($ attachement );
151+ $ this ->entityManager ->flush ();
152+
153+ return new DataResponse ($ attachement ->toMastodonApi ($ this ->generator ));
154+ } catch (\Exception $ e ) {
155+ $ this ->logger ->error ($ e ->getMessage (), ['exception ' => $ e ]);
110156 return new DataResponse ([
111157 "error " => "Validation failed: File content type is invalid, File is invalid " ,
112158 ], 500 );
@@ -151,4 +197,60 @@ private function getUploadedFile(string $key): array {
151197 }
152198 return $ file ;
153199 }
200+
201+ /**
202+ * @NoAdminRequired
203+ * @NoCSRFRequired
204+ */
205+ public function getMedia (string $ shortcode , string $ extension ): DataDownloadResponse {
206+ try {
207+ $ folder = $ this ->appData ->getFolder ('media-attachments ' );
208+ } catch (NotFoundException $ e ) {
209+ $ folder = $ this ->appData ->newFolder ('media-attachments ' );
210+ }
211+ $ attachementRepository = $ this ->entityManager ->getRepository (MediaAttachment::class);
212+ $ attachement = $ attachementRepository ->findOneBy ([
213+ 'shortcode ' => $ shortcode ,
214+ ]);
215+ $ file = $ folder ->getFile ($ attachement ->getId ());
216+ return new DataDownloadResponse (
217+ $ file ->getContent (),
218+ (string ) Http::STATUS_OK ,
219+ $ this ->getSecureMimeType ($ file ->getMimeType ())
220+ );
221+ }
222+
223+ /**
224+ * @NoAdminRequired
225+ */
226+ public function deleteMedia (string $ id ): DataResponse {
227+ try {
228+ $ folder = $ this ->appData ->getFolder ('media-attachments ' );
229+ } catch (NotFoundException $ e ) {
230+ $ folder = $ this ->appData ->newFolder ('media-attachments ' );
231+ }
232+ $ attachementRepository = $ this ->entityManager ->getRepository (MediaAttachment::class);
233+ $ attachement = $ attachementRepository ->findOneBy ([
234+ 'id ' => $ id ,
235+ ]);
236+ $ file = $ folder ->getFile ($ attachement ->getId ());
237+ $ file ->delete ();
238+ $ this ->entityManager ->remove ($ attachement );
239+ $ this ->entityManager ->flush ();
240+ return new DataResponse (['removed ' ]);
241+ }
242+
243+ /**
244+ * Allow all supported mimetypes
245+ * Use mimetype detector for the other ones
246+ *
247+ * @param string $mimetype
248+ * @return string
249+ */
250+ private function getSecureMimeType (string $ mimetype ): string {
251+ if (in_array ($ mimetype , self ::IMAGE_MIME_TYPES )) {
252+ return $ mimetype ;
253+ }
254+ return $ this ->mimeTypeDetector ->getSecureMimeType ($ mimetype );
255+ }
154256}
0 commit comments