<commit_before>package lan.dk.podcastserver.manager.worker.downloader;

import lan.dk.podcastserver.business.ItemBusiness;
import lan.dk.podcastserver.business.PodcastBusiness;
import lan.dk.podcastserver.entity.Item;
import lan.dk.podcastserver.manager.ItemDownloadManager;
import lan.dk.podcastserver.utils.MimeTypeUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.concurrent.atomic.AtomicBoolean;

public abstract class AbstractDownloader implements Runnable, Downloader {

    protected final Logger logger = LoggerFactory.getLogger(this.getClass());

    public static final String WS_TOPIC_DOWNLOAD = "/topic/download";
    public static final String WS_TOPIC_PODCAST = "/topic/podcast/";

    protected Item item;
    protected String temporaryExtension = ".psdownload";
    protected File target = null;

    @Autowired protected ItemDownloadManager itemDownloadManager;
    @Autowired protected ItemBusiness itemService;
    @Resource protected PodcastBusiness podcastBusiness;
    @Resource protected SimpMessagingTemplate template;

    protected AtomicBoolean stopDownloading = new AtomicBoolean(false);

    public Item getItem() {
        return item;
    }

    public void setItem(Item item) {
        this.item = item;
    }

    @Override
    public void run() {
        logger.debug("Run");
        this.startDownload();
    }

    @Override
    public void startDownload() {
        this.item.setStatus("Started");
        stopDownloading.set(false);
        this.saveSyncWithPodcast();
        this.convertAndSaveBroadcast();
        this.download();
    }

    @Override
    public void pauseDownload() {
        this.item.setStatus("Paused");
        stopDownloading.set(true);
        this.saveSyncWithPodcast();
        this.convertAndSaveBroadcast();
    }

    @Override
    public void stopDownload() {
        this.item.setStatus("Stopped");
        stopDownloading.set(true);
        this.saveSyncWithPodcast();
        itemDownloadManager.removeACurrentDownload(item);
        if (target != null && target.exists())
            target.delete();
        this.convertAndSaveBroadcast();
    }

    @Override
    @Transactional
    public void finishDownload() {
        itemDownloadManager.removeACurrentDownload(item);
        if (target != null) {
            this.item.setStatus("Finish");
            try {

                if (target.getAbsolutePath().contains(temporaryExtension)) { // Si contient l'extention temporaire.
                    File targetWithoutExtension = new File(target.getAbsolutePath().replace(temporaryExtension, ""));
                    if (targetWithoutExtension.exists())
                        targetWithoutExtension.delete();
                    FileUtils.moveFile(target, targetWithoutExtension);
                    target = targetWithoutExtension;
                }
            } catch (IOException e) {
                e.printStackTrace();
                logger.error("IOException :", e);
            }

            this.item.setLocalUrl(itemDownloadManager.getFileContainer() + "/" + item.getPodcast().getTitle() + "/" + FilenameUtils.getName(String.valueOf(target)));
            this.item.setLocalUri(target.getAbsolutePath());
            this.item.setDownloaddate(ZonedDateTime.of(LocalDateTime.now(), ZoneId.systemDefault()));
            this.item.setLength(FileUtils.sizeOf(target));

            try {
                this.item.setMimeType(Files.probeContentType(target.toPath()));
                if (this.item.getMimeType() == null) {
                    this.item.setMimeType(MimeTypeUtils.getMimeType(FilenameUtils.getExtension(target.getAbsolutePath())));
                }
            } catch (IOException e) {
                e.printStackTrace();
                this.item.setMimeType(MimeTypeUtils.getMimeType(FilenameUtils.getExtension(target.getAbsolutePath())));
            }

            this.saveSyncWithPodcast();
            this.convertAndSaveBroadcast();
        } else {
            resetDownload();
        }


    }

    public void resetDownload() {
        this.stopDownload();
        //item.setStatus("Not Downloaded").setProgression(0);
        //itemService.save(item);
        //itemDownloadManager.addItemToQueue(item);
    }

    @Transactional
    public File getTagetFile (Item item) {

        if (target != null)
            return target;

        File finalFile = getTempFile(item);
        logger.debug("Création du fichier : {}", finalFile.getAbsolutePath());
        //logger.debug(file.getAbsolutePath());

        if (!finalFile.getParentFile().exists()) {
            finalFile.getParentFile().mkdirs();
        }

        if (finalFile.exists() || new File(finalFile.getAbsolutePath().concat(temporaryExtension)).exists()) {
            logger.info("Doublon sur le fichier en lien avec {} - {}, {}", item.getPodcast().getTitle(), item.getId(), item.getTitle() );
            try {
                finalFile  = File.createTempFile(
                        FilenameUtils.getBaseName(item.getUrl()).concat("-"),
                        ".".concat(FilenameUtils.getExtension(item.getUrl())),
                        finalFile.getParentFile());
                finalFile.delete();
            } catch (IOException e) {
                logger.error("Erreur lors du renommage d'un doublon", e);
            }
        }

        return new File(finalFile.getAbsolutePath() + temporaryExtension) ;
    }

    private File getTempFile(Item item) {
        String fileName = FilenameUtils.getName(String.valueOf(item.getUrl()));
        fileName = fileName.substring(0, fileName.lastIndexOf("?"));
        return new File(itemDownloadManager.getRootfolder() + File.separator + item.getPodcast().getTitle() + File.separator + fileName);
    }

    @Transactional
    protected Item saveSyncWithPodcast() {
        try {
            this.item.setPodcast(podcastBusiness.findOne(this.item.getPodcast().getId()));
            //this.item.getPodcast().getItems().remove(this.item);
            //this.item.getPodcast().getItems().add(this.item);

            return itemService.save(this.item);

        } catch (Exception e) {
            logger.error("Error during save and Sync of the item {}", this.item, e);
            return new Item();
        }
    }
<commit_msg>fix(downloader): out of bound string manipulation in getTargertFile<commit_after>package lan.dk.podcastserver.manager.worker.downloader;

import lan.dk.podcastserver.business.ItemBusiness;
import lan.dk.podcastserver.business.PodcastBusiness;
import lan.dk.podcastserver.entity.Item;
import lan.dk.podcastserver.manager.ItemDownloadManager;
import lan.dk.podcastserver.utils.MimeTypeUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.concurrent.atomic.AtomicBoolean;

public abstract class AbstractDownloader implements Runnable, Downloader {

    protected final Logger logger = LoggerFactory.getLogger(this.getClass());

    public static final String WS_TOPIC_DOWNLOAD = "/topic/download";
    public static final String WS_TOPIC_PODCAST = "/topic/podcast/";

    protected Item item;
    protected String temporaryExtension = ".psdownload";
    protected File target = null;

    @Autowired protected ItemDownloadManager itemDownloadManager;
    @Autowired protected ItemBusiness itemService;
    @Resource protected PodcastBusiness podcastBusiness;
    @Resource protected SimpMessagingTemplate template;

    protected AtomicBoolean stopDownloading = new AtomicBoolean(false);

    public Item getItem() {
        return item;
    }

    public void setItem(Item item) {
        this.item = item;
    }

    @Override
    public void run() {
        logger.debug("Run");
        this.startDownload();
    }

    @Override
    public void startDownload() {
        this.item.setStatus("Started");
        stopDownloading.set(false);
        this.saveSyncWithPodcast();
        this.convertAndSaveBroadcast();
        this.download();
    }

    @Override
    public void pauseDownload() {
        this.item.setStatus("Paused");
        stopDownloading.set(true);
        this.saveSyncWithPodcast();
        this.convertAndSaveBroadcast();
    }

    @Override
    public void stopDownload() {
        this.item.setStatus("Stopped");
        stopDownloading.set(true);
        this.saveSyncWithPodcast();
        itemDownloadManager.removeACurrentDownload(item);
        if (target != null && target.exists())
            target.delete();
        this.convertAndSaveBroadcast();
    }

    @Override
    @Transactional
    public void finishDownload() {
        itemDownloadManager.removeACurrentDownload(item);
        if (target != null) {
            this.item.setStatus("Finish");
            try {

                if (target.getAbsolutePath().contains(temporaryExtension)) { // Si contient l'extention temporaire.
                    File targetWithoutExtension = new File(target.getAbsolutePath().replace(temporaryExtension, ""));
                    if (targetWithoutExtension.exists())
                        targetWithoutExtension.delete();
                    FileUtils.moveFile(target, targetWithoutExtension);
                    target = targetWithoutExtension;
                }
            } catch (IOException e) {
                e.printStackTrace();
                logger.error("IOException :", e);
            }

            this.item.setLocalUrl(itemDownloadManager.getFileContainer() + "/" + item.getPodcast().getTitle() + "/" + FilenameUtils.getName(String.valueOf(target)));
            this.item.setLocalUri(target.getAbsolutePath());
            this.item.setDownloaddate(ZonedDateTime.of(LocalDateTime.now(), ZoneId.systemDefault()));
            this.item.setLength(FileUtils.sizeOf(target));

            try {
                this.item.setMimeType(Files.probeContentType(target.toPath()));
                if (this.item.getMimeType() == null) {
                    this.item.setMimeType(MimeTypeUtils.getMimeType(FilenameUtils.getExtension(target.getAbsolutePath())));
                }
            } catch (IOException e) {
                e.printStackTrace();
                this.item.setMimeType(MimeTypeUtils.getMimeType(FilenameUtils.getExtension(target.getAbsolutePath())));
            }

            this.saveSyncWithPodcast();
            this.convertAndSaveBroadcast();
        } else {
            resetDownload();
        }


    }

    public void resetDownload() {
        this.stopDownload();
        //item.setStatus("Not Downloaded").setProgression(0);
        //itemService.save(item);
        //itemDownloadManager.addItemToQueue(item);
    }

    @Transactional
    public File getTagetFile (Item item) {

        if (target != null)
            return target;

        File finalFile = getTempFile(item);
        logger.debug("Création du fichier : {}", finalFile.getAbsolutePath());
        //logger.debug(file.getAbsolutePath());

        if (!finalFile.getParentFile().exists()) {
            finalFile.getParentFile().mkdirs();
        }

        if (finalFile.exists() || new File(finalFile.getAbsolutePath().concat(temporaryExtension)).exists()) {
            logger.info("Doublon sur le fichier en lien avec {} - {}, {}", item.getPodcast().getTitle(), item.getId(), item.getTitle() );
            try {
                finalFile  = File.createTempFile(
                        FilenameUtils.getBaseName(item.getUrl()).concat("-"),
                        ".".concat(FilenameUtils.getExtension(item.getUrl())),
                        finalFile.getParentFile());
                finalFile.delete();
            } catch (IOException e) {
                logger.error("Erreur lors du renommage d'un doublon", e);
            }
        }

        return new File(finalFile.getAbsolutePath() + temporaryExtension) ;
    }

    private File getTempFile(Item item) {
        String fileName = FilenameUtils.getName(String.valueOf(item.getUrl()));

        if ( fileName.lastIndexOf("?") != -1 )
            fileName = fileName.substring(0, fileName.lastIndexOf("?"));

        return new File(itemDownloadManager.getRootfolder() + File.separator + item.getPodcast().getTitle() + File.separator + fileName);
    }

    @Transactional
    protected Item saveSyncWithPodcast() {
        try {
            this.item.setPodcast(podcastBusiness.findOne(this.item.getPodcast().getId()));
            //this.item.getPodcast().getItems().remove(this.item);
            //this.item.getPodcast().getItems().add(this.item);

            return itemService.save(this.item);

        } catch (Exception e) {
            logger.error("Error during save and Sync of the item {}", this.item, e);
            return new Item();
        }
    }

{'fraction_non_alphanumeric': 0.11566864078379761, 'fraction_numerical': 0.0006580390436499232, 'mean_word_length': 2.6108764519535375, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 61, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5835582', 'n_tokens_mistral': 3695, 'n_tokens_neox': 3576, 'n_words': 630}