use of org.apache.sanselan.ImageFormat in project kapua by eclipse.
the class GwtDeviceManagementServiceImpl method checkIconResource.
/**
* Checks the source of the icon.
* The component config icon can be one of the well known icon (i.e. MqttDataTransport icon)
* as well as an icon loaded from external source with an HTTP link.
*
* We need to filter HTTP link to protect the console page and also to have content always served from
* EC console. Otherwise browsers can alert the user that content is served from domain different from
* *.everyware-cloud.com and over insicure connection.
*
* To avoid this we will download the image locally on the server temporary directory and give back the page
* a token URL to get the file.
*
* @param icon
* The icon from the OCD of the component configuration.
* @throws IOException
* @throws NoSuchAlgorithmException
* @throws ImageReadException
*/
private void checkIconResource(KapuaTicon icon) {
ConsoleSetting config = ConsoleSetting.getInstance();
String iconResource = icon.getResource();
// Check if the resource is an HTTP URL or not
if (iconResource != null && (iconResource.toLowerCase().startsWith("http://") || iconResource.toLowerCase().startsWith("https://"))) {
File tmpFile = null;
try {
logger.info("Got configuration component icon from URL: {}", iconResource);
//
// Tmp file name creation
String systemTmpDir = System.getProperty("java.io.tmpdir");
String iconResourcesTmpDir = config.getString(ConsoleSettingKeys.DEVICE_CONFIGURATION_ICON_FOLDER);
String tmpFileName = Base64.encodeBase64String(MessageDigest.getInstance("MD5").digest(iconResource.getBytes("UTF-8")));
// Conversions needed got security reasons!
// On the file servlet we use the regex [0-9A-Za-z]{1,} to validate the given file id.
// This validation prevents the caller of the file servlet to try to move out of the directory where the icons are stored.
tmpFileName = tmpFileName.replaceAll("/", "a");
tmpFileName = tmpFileName.replaceAll("\\+", "m");
tmpFileName = tmpFileName.replaceAll("=", "z");
//
// Tmp dir check and creation
StringBuilder tmpDirPathSb = new StringBuilder().append(systemTmpDir);
if (!systemTmpDir.endsWith("/")) {
tmpDirPathSb.append("/");
}
tmpDirPathSb.append(iconResourcesTmpDir);
File tmpDir = new File(tmpDirPathSb.toString());
if (!tmpDir.exists()) {
logger.info("Creating tmp dir on path: {}", tmpDir.toString());
tmpDir.mkdir();
}
//
// Tmp file check and creation
tmpDirPathSb.append("/").append(tmpFileName);
tmpFile = new File(tmpDirPathSb.toString());
// Check date of modification to avoid caching forever
if (tmpFile.exists()) {
long lastModifiedDate = tmpFile.lastModified();
long maxCacheTime = config.getLong(ConsoleSettingKeys.DEVICE_CONFIGURATION_ICON_CACHE_TIME);
if (System.currentTimeMillis() - lastModifiedDate > maxCacheTime) {
logger.info("Deleting old cached file: {}", tmpFile.toString());
tmpFile.delete();
}
}
// If file is not cached, download it.
if (!tmpFile.exists()) {
// Url connection
URL iconUrl = new URL(iconResource);
URLConnection urlConnection = iconUrl.openConnection();
urlConnection.setConnectTimeout(2000);
urlConnection.setReadTimeout(2000);
// Length check
String contentLengthString = urlConnection.getHeaderField("Content-Length");
long maxLength = config.getLong(ConsoleSettingKeys.DEVICE_CONFIGURATION_ICON_SIZE_MAX);
try {
Long contentLength = Long.parseLong(contentLengthString);
if (contentLength > maxLength) {
logger.warn("Content lenght exceeded ({}/{}) for URL: {}", new Object[] { contentLength, maxLength, iconResource });
throw new IOException("Content-Length reported a length of " + contentLength + " which exceeds the maximum allowed size of " + maxLength);
}
} catch (NumberFormatException nfe) {
logger.warn("Cannot get Content-Length header!");
}
logger.info("Creating file: {}", tmpFile.toString());
tmpFile.createNewFile();
// Icon download
InputStream is = urlConnection.getInputStream();
OutputStream os = new FileOutputStream(tmpFile);
byte[] buffer = new byte[4096];
try {
int len;
while ((len = is.read(buffer)) > 0) {
os.write(buffer, 0, len);
maxLength -= len;
if (maxLength < 0) {
logger.warn("Maximum content lenght exceeded ({}) for URL: {}", new Object[] { maxLength, iconResource });
throw new IOException("Maximum content lenght exceeded (" + maxLength + ") for URL: " + iconResource);
}
}
} finally {
os.close();
}
logger.info("Downloaded file: {}", tmpFile.toString());
// Image metadata content checks
ImageFormat imgFormat = Sanselan.guessFormat(tmpFile);
if (imgFormat.equals(ImageFormat.IMAGE_FORMAT_BMP) || imgFormat.equals(ImageFormat.IMAGE_FORMAT_GIF) || imgFormat.equals(ImageFormat.IMAGE_FORMAT_JPEG) || imgFormat.equals(ImageFormat.IMAGE_FORMAT_PNG)) {
logger.info("Detected image format: {}", imgFormat.name);
} else if (imgFormat.equals(ImageFormat.IMAGE_FORMAT_UNKNOWN)) {
logger.error("Unknown file format for URL: {}", iconResource);
throw new IOException("Unknown file format for URL: " + iconResource);
} else {
logger.error("Usupported file format ({}) for URL: {}", imgFormat, iconResource);
throw new IOException("Unknown file format for URL: {}" + iconResource);
}
logger.info("Image validation passed for URL: {}", iconResource);
} else {
logger.info("Using cached file: {}", tmpFile.toString());
}
//
// Injecting new URL for the icon resource
String newResourceURL = new StringBuilder().append("img://console/file/icons?id=").append(tmpFileName).toString();
logger.info("Injecting configuration component icon: {}", newResourceURL);
icon.setResource(newResourceURL);
} catch (Exception e) {
if (tmpFile != null && tmpFile.exists()) {
tmpFile.delete();
}
icon.setResource("Default");
logger.error("Error while checking component configuration icon. Using the default plugin icon.", e);
}
}
//
// If not, all is fine.
}
Aggregations