package de.stadtbote.votian; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import java.nio.file.*; import java.io.*; import java.util.*; import javax.imageio.ImageIO; import static de.stadtbote.votian.AdminSupport.bad; @Component class NewsletterImages { final Path directory; NewsletterImages(@Value("${app.form-images-directory:data/form-images}")String path){directory=Path.of(path).toAbsolutePath().normalize();} String upload(LegacyUser u,String data){u.require(0);u.require(17);if(data==null||data.length()>410000||!data.matches("data:image/(png|jpeg|gif);base64,[A-Za-z0-9+/=\\r\\n]+"))throw bad("Bitte ein PNG-, JPG- oder GIF-Bild bis 300 KB auswählen.");byte[] bytes;try{bytes=Base64.getMimeDecoder().decode(data.substring(data.indexOf(',')+1));}catch(IllegalArgumentException e){throw bad("Ungültige Bilddatei.");}if(bytes.length>300000)throw bad("Bilder dürfen höchstens 300 KB groß sein."); try(var input=ImageIO.createImageInputStream(new ByteArrayInputStream(bytes))){var readers=ImageIO.getImageReaders(input);if(!readers.hasNext())throw bad("Die Datei enthält kein unterstütztes Bild.");var reader=readers.next();try{reader.setInput(input);String format=reader.getFormatName().toLowerCase(Locale.ROOT);if(!Set.of("png","jpeg","gif").contains(format)||!data.startsWith("data:image/"+format+";"))throw bad("Bildinhalt und Dateityp stimmen nicht überein.");if(reader.getWidth(0)>8000||reader.getHeight(0)>8000||(long)reader.getWidth(0)*reader.getHeight(0)>32000000)throw bad("Die Bildabmessungen sind zu groß.");reader.read(0);String name="ng_"+UUID.randomUUID()+"."+(format.equals("jpeg")?"jpg":format);Files.createDirectories(directory);Files.write(directory.resolve(name),bytes,StandardOpenOption.CREATE_NEW);return name;}finally{reader.dispose();}}catch(IOException e){throw bad("Bild konnte nicht gespeichert werden. Bitte das konfigurierte Bildverzeichnis prüfen.");} } String data(String name){if(!name.matches("ng_[0-9a-f-]{36}\\.(png|jpg|gif)"))return null;try{Path path=directory.resolve(name);if(!Files.isRegularFile(path,LinkOption.NOFOLLOW_LINKS))return null;if(Files.size(path)>300000)throw bad("Gespeicherte Bilddatei überschreitet 300 KB.");String type=name.endsWith(".jpg")?"jpeg":name.endsWith(".gif")?"gif":"png";return "data:image/"+type+";base64,"+Base64.getEncoder().encodeToString(Files.readAllBytes(path));}catch(IOException e){throw bad("Gespeicherte Bilddatei ist nicht lesbar.");}} }