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,29 @@ 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-
93+
8994 // If destination not provided, we use the same path
9095 // as the original file, but with the new extension
9196 if ($ destination === null ) {
@@ -94,11 +99,21 @@ public function convert(File $file, string $targetMimeType, ?string $destination
9499 $ destination = $ parent ->getFullPath ($ basename . '. ' . $ targetExtension );
95100 }
96101
102+ // If destination doesn't match the target extension, we throw an error
103+ if (pathinfo ($ destination , PATHINFO_EXTENSION ) !== $ targetExtension ) {
104+ throw new GenericFileException ($ this ->l10n ->t ('Destination does not match conversion extension ' ));
105+ }
106+
107+ // Check destination before converting
108+ $ this ->checkDestination ($ destination );
109+
110+ // Convert the file and write it to the destination
111+ $ convertedFile = $ validProvider ->convertFile ($ file , $ targetMimeType );
97112 $ convertedFile = $ this ->writeToDestination ($ destination , $ convertedFile );
98113 return $ convertedFile ->getPath ();
99114 }
100115
101- throw new RuntimeException ('Could not convert file ' );
116+ throw new RuntimeException ($ this -> l10n -> t ( 'Could not convert file ' ) );
102117 }
103118
104119 /**
@@ -127,14 +142,25 @@ private function getRegisteredProviders(): array {
127142 return array_values (array_merge ([], $ this ->preferredProviders , $ this ->providers ));
128143 }
129144
145+ private function checkDestination (string $ destination ): void {
146+ if (!$ this ->rootFolder ->nodeExists (dirname ($ destination ))) {
147+ throw new ForbiddenException ($ this ->l10n ->t ('Destination does not exist ' ));
148+ }
149+
150+ $ folder = $ this ->rootFolder ->get (dirname ($ destination ));
151+ if (!$ folder ->isCreatable ()) {
152+ throw new ForbiddenException ($ this ->l10n ->t ('Destination is not creatable ' ));
153+ }
154+ }
155+
130156 private function writeToDestination (string $ destination , mixed $ content ): File {
157+ $ this ->checkDestination ($ destination );
158+
131159 if ($ this ->rootFolder ->nodeExists ($ destination )) {
132160 $ file = $ this ->rootFolder ->get ($ destination );
133161 $ parent = $ file ->getParent ();
134- if (!$ parent ->isCreatable ()) {
135- throw new GenericFileException ('Destination is not creatable ' );
136- }
137162
163+ // Folder permissions is already checked in checkDestination method
138164 $ newName = $ parent ->getNonExistingName (basename ($ destination ));
139165 $ destination = $ parent ->getFullPath ($ newName );
140166 }
0 commit comments