package com.faforever.client.uploader.imgur; import com.faforever.client.i18n.I18n; import com.faforever.client.io.ByteCopier; import com.faforever.client.task.CompletableTask; import com.faforever.client.task.ResourceLocks; import com.google.common.io.BaseEncoding; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import javafx.embed.swing.SwingFXUtils; import javafx.scene.image.Image; import org.springframework.core.env.Environment; import javax.annotation.PostConstruct; import javax.annotation.Resource; import javax.imageio.ImageIO; import java.awt.image.BufferedImage; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import static com.faforever.client.io.Bytes.formatSize; public class ImgurUploadTask extends CompletableTask<String> { private final Gson gson; @Resource I18n i18n; @Resource Environment environment; private Image image; private int maxUploadSize; private String baseUrl; private String clientId; public ImgurUploadTask() { super(Priority.HIGH); gson = new GsonBuilder().create(); } @PostConstruct void postConstruct() { updateTitle(i18n.get("chat.imageUploadTask.title")); maxUploadSize = environment.getProperty("imgur.upload.maxSize", int.class); baseUrl = environment.getProperty("imgur.upload.baseUrl"); clientId = environment.getProperty("imgur.upload.clientId"); } @Override protected String call() throws Exception { ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); BufferedImage bufferedImage = SwingFXUtils.fromFXImage(image, null); ImageIO.write(bufferedImage, "png", byteArrayOutputStream); if (byteArrayOutputStream.size() > maxUploadSize) { throw new IllegalArgumentException("Image exceeds max upload size of " + formatSize(maxUploadSize, i18n.getLocale())); } String dataImage = BaseEncoding.base64().encode(byteArrayOutputStream.toByteArray()); String data = URLEncoder.encode("image", "UTF-8") + "=" + URLEncoder.encode(dataImage, "UTF-8"); URL url = new URL(baseUrl); HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection(); urlConnection.setDoOutput(true); urlConnection.setDoInput(true); urlConnection.setRequestMethod("POST"); urlConnection.setRequestProperty("Authorization", "Client-ID " + clientId); urlConnection.setRequestMethod("POST"); urlConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); urlConnection.connect(); ResourceLocks.acquireUploadLock(); try (OutputStream outputStream = urlConnection.getOutputStream()) { byte[] bytes = data.getBytes(StandardCharsets.UTF_8); ByteCopier.from(new ByteArrayInputStream(bytes)) .to(outputStream) .totalBytes(bytes.length) .listener(this::updateProgress) .copy(); } finally { ResourceLocks.freeUploadLock(); } StringBuilder stringBuilder = new StringBuilder(); try (BufferedReader reader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()))) { String line; while ((line = reader.readLine()) != null) { stringBuilder.append(line).append("\n"); } } ImgurRestResponse imgurRestResponse = gson.fromJson(stringBuilder.toString(), ImgurRestResponse.class); if (!imgurRestResponse.success) { throw new RuntimeException("Image upload failed, status code: " + imgurRestResponse.status); } return imgurRestResponse.data.link; } public void setImage(Image image) { this.image = image; } }