1010namespace OC \Files \Conversion ;
1111
1212use OC \AppFramework \Bootstrap \Coordinator ;
13+ use OC \ForbiddenException ;
1314use OC \SystemConfig ;
1415use OCP \Files \Conversion \IConversionManager ;
1516use OCP \Files \Conversion \IConversionProvider ;
1617use OCP \Files \File ;
1718use OCP \Files \GenericFileException ;
1819use OCP \Files \IRootFolder ;
20+ use OCP \IL10N ;
1921use OCP \ITempManager ;
22+ use OCP \L10N \IFactory ;
2023use OCP \PreConditionNotMetException ;
2124use Psr \Container \ContainerExceptionInterface ;
2225use Psr \Container \ContainerInterface ;
@@ -37,14 +40,17 @@ class ConversionManager implements IConversionManager {
3740 /** @var list<IConversionProvider> */
3841 private array $ providers = [];
3942
43+ private IL10N $ l10n ;
4044 public function __construct (
4145 private Coordinator $ coordinator ,
4246 private ContainerInterface $ serverContainer ,
4347 private IRootFolder $ rootFolder ,
4448 private ITempManager $ tempManager ,
4549 private LoggerInterface $ logger ,
4650 private SystemConfig $ config ,
51+ IFactory $ l10nFactory ,
4752 ) {
53+ $ this ->l10n = $ l10nFactory ->get ('files ' );
4854 }
4955
5056 public function hasProviders (): bool {
@@ -62,30 +68,28 @@ public function getProviders(): array {
6268
6369 public function convert (File $ file , string $ targetMimeType , ?string $ destination = null ): string {
6470 if (!$ this ->hasProviders ()) {
65- throw new PreConditionNotMetException ('No file conversion providers available ' );
71+ throw new PreConditionNotMetException ($ this -> l10n -> t ( 'No file conversion providers available ' ) );
6672 }
6773
6874 // Operate in mebibytes
6975 $ fileSize = $ file ->getSize () / (1024 * 1024 );
7076 $ threshold = $ this ->config ->getValue ('max_file_conversion_filesize ' , 100 );
7177 if ($ fileSize > $ threshold ) {
72- throw new GenericFileException ('File is too large to convert ' );
78+ throw new GenericFileException ($ this -> l10n -> t ( 'File is too large to convert ' ) );
7379 }
7480
7581 $ fileMimeType = $ file ->getMimetype ();
7682 $ validProvider = $ this ->getValidProvider ($ fileMimeType , $ targetMimeType );
7783
7884 if ($ validProvider !== null ) {
79- $ convertedFile = $ validProvider ->convertFile ($ file , $ targetMimeType );
80-
85+ // Get the target extension given by the provider
8186 $ targetExtension = '' ;
8287 foreach ($ validProvider ->getSupportedMimeTypes () as $ mimeProvider ) {
8388 if ($ mimeProvider ->getTo () === $ targetMimeType ) {
8489 $ targetExtension = $ mimeProvider ->getExtension ();
8590 break ;
8691 }
8792 }
88-
8993 // If destination not provided, we use the same path
9094 // as the original file, but with the new extension
9195 if ($ destination === null ) {
@@ -94,11 +98,21 @@ public function convert(File $file, string $targetMimeType, ?string $destination
9498 $ destination = $ parent ->getFullPath ($ basename . '. ' . $ targetExtension );
9599 }
96100
101+ // If destination doesn't match the target extension, we throw an error
102+ if (pathinfo ($ destination , PATHINFO_EXTENSION ) !== $ targetExtension ) {
103+ throw new GenericFileException ($ this ->l10n ->t ('Destination does not match conversion extension ' ));
104+ }
105+
106+ // Check destination before converting
107+ $ this ->checkDestination ($ destination );
108+
109+ // Convert the file and write it to the destination
110+ $ convertedFile = $ validProvider ->convertFile ($ file , $ targetMimeType );
97111 $ convertedFile = $ this ->writeToDestination ($ destination , $ convertedFile );
98112 return $ convertedFile ->getPath ();
99113 }
100114
101- throw new RuntimeException ('Could not convert file ' );
115+ throw new RuntimeException ($ this -> l10n -> t ( 'Could not convert file ' ) );
102116 }
103117
104118 /**
@@ -127,14 +141,25 @@ private function getRegisteredProviders(): array {
127141 return array_values (array_merge ([], $ this ->preferredProviders , $ this ->providers ));
128142 }
129143
144+ private function checkDestination (string $ destination ): void {
145+ if (!$ this ->rootFolder ->nodeExists (dirname ($ destination ))) {
146+ throw new ForbiddenException ($ this ->l10n ->t ('Destination does not exist ' ));
147+ }
148+
149+ $ folder = $ this ->rootFolder ->get (dirname ($ destination ));
150+ if (!$ folder ->isCreatable ()) {
151+ throw new ForbiddenException ($ this ->l10n ->t ('Destination is not creatable ' ));
152+ }
153+ }
154+
130155 private function writeToDestination (string $ destination , mixed $ content ): File {
156+ $ this ->checkDestination ($ destination );
157+
131158 if ($ this ->rootFolder ->nodeExists ($ destination )) {
132159 $ file = $ this ->rootFolder ->get ($ destination );
133160 $ parent = $ file ->getParent ();
134- if (!$ parent ->isCreatable ()) {
135- throw new GenericFileException ('Destination is not creatable ' );
136- }
137161
162+ // Folder permissions is already checked in checkDestination method
138163 $ newName = $ parent ->getNonExistingName (basename ($ destination ));
139164 $ destination = $ parent ->getFullPath ($ newName );
140165 }
0 commit comments