Search in sources :

Example 1 with ImageFormat

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.
}
Also used : InputStream(java.io.InputStream) OutputStream(java.io.OutputStream) FileOutputStream(java.io.FileOutputStream) ConsoleSetting(org.eclipse.kapua.app.console.setting.ConsoleSetting) IOException(java.io.IOException) URL(java.net.URL) URLConnection(java.net.URLConnection) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) GwtKapuaException(org.eclipse.kapua.app.console.shared.GwtKapuaException) IOException(java.io.IOException) ImageReadException(org.apache.sanselan.ImageReadException) ImageFormat(org.apache.sanselan.ImageFormat) FileOutputStream(java.io.FileOutputStream) File(java.io.File)

Aggregations

File (java.io.File)1 FileOutputStream (java.io.FileOutputStream)1 IOException (java.io.IOException)1 InputStream (java.io.InputStream)1 OutputStream (java.io.OutputStream)1 URL (java.net.URL)1 URLConnection (java.net.URLConnection)1 NoSuchAlgorithmException (java.security.NoSuchAlgorithmException)1 ImageFormat (org.apache.sanselan.ImageFormat)1 ImageReadException (org.apache.sanselan.ImageReadException)1 ConsoleSetting (org.eclipse.kapua.app.console.setting.ConsoleSetting)1 GwtKapuaException (org.eclipse.kapua.app.console.shared.GwtKapuaException)1