@Override
    protected Void doInBackground() {
        final int BUFFER_SIZE = 1024;

        // 1. Download image
        BufferedInputStream bis = null;
        ByteArrayOutputStream baos = null;
        try {
            URL url = new URL(imageUrl);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setRequestProperty("User-Agent", "User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:27.0) Gecko/20100101 Firefox/27.0");

            this.totalProgressValue = connection.getContentLength();

            int totalDataRead = 0;
            bis = new BufferedInputStream(connection.getInputStream());
            baos = new ByteArrayOutputStream();
            try (BufferedOutputStream bos = new BufferedOutputStream(baos, BUFFER_SIZE)) {
                byte[] data = new byte[BUFFER_SIZE];
                int i = 0;

                while ((i = bis.read(data)) != -1) {
                    totalDataRead = totalDataRead + i;
                    baos.write(data, 0, i);
                    publish(new SyncTaskState(rule, imageUrl, "Downloading", totalDataRead));
                }

                publish(new SyncTaskState(rule, imageUrl, "Processing", this.totalProgressValue));

                byte[] imageBytes = baos.toByteArray();
                try {
                    byte[] imageSteganoBytes = ImageUtils.tryToDecodeSteganoImage(imageBytes, boardCode);

                    if (imageSteganoBytes != null) {
                        try {
                            NanoPost np = NanoPostFactory.getNanoPostFromBytes(imageSteganoBytes, false);
                            np.setSourceImageData(imageBytes);
                            
                            if (!np.isAlreadyDownloaded()) {
                                publish(new SyncTaskState(rule, imageUrl, "NEW NANOPOST", this.totalProgressValue));
                                np.setOutbox(false);
                                np.saveToFile(false);
                            } else {
                                publish(new SyncTaskState(rule, imageUrl, "IN SYNC", this.totalProgressValue));
                            }
                            
                            imageSteganoBytes = null;
                            imageBytes = null;
                            np.clearAllBinaryData();
                            nbf.addNanoPostToList(np);
                        } catch (IOException | MalformedNanoPostException ex) {
                            publish(new SyncTaskState(rule, imageUrl, "Not an NanoPost", this.totalProgressValue));
                        }
                    } else {
                        publish(new SyncTaskState(rule, imageUrl, "Not an NanoPost", this.totalProgressValue));
                    }
                } catch (Exception ex) {
                    //ex.printStackTrace();
                    publish(new SyncTaskState(rule, imageUrl, "Not an NanoPost", this.totalProgressValue));
                }
            }
        } catch (IOException ex) {
            ex.printStackTrace();
            
            publish(new SyncTaskState(rule, imageUrl, "IO Error", 0));
        } finally {
            try {
                bis.close();
            } catch (IOException ex) {
                publish(new SyncTaskState(rule, imageUrl, "IO Error", 0));
            }
        }
        
        return null;
    }