/*
 * Autopsy Forensic Browser
 *
 * Copyright 2013 Basis Technology Corp.
 * Contact: carrier <at> sleuthkit <dot> org
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.sleuthkit.autopsy.scalpel.jni;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.logging.Level;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.scalpel.jni.ScalpelOutputParser.CarvedFileMeta;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.ReadContentInputStream;

/**
 * JNI wrapper over libscalpel and library loader
 */
public class ScalpelCarver {

    private static final String SCALPEL_JNI_LIB = "libscalpel_jni";
    private static final String SCALPEL_OUTPUT_FILE_NAME = "audit.txt";
    private static boolean initialized = false;
    private static final Logger logger = Logger.getLogger(ScalpelCarver.class.getName());

    private static native void carveNat(String carverInputId, ReadContentInputStream input, String configFilePath, String outputFolderPath) throws ScalpelException;

    public  ScalpelCarver() {
        
    }

    public static boolean init() {
        if (initialized) {
            return true;
        }
        initialized = true;
        for (String library : Arrays.asList("libtre-4", "pthreadGC2", SCALPEL_JNI_LIB)) {
            if (!loadLib(library)) {
                initialized = false;
                logger.log(Level.SEVERE, "Failed initializing " + ScalpelCarver.class.getName() + " due to failure loading library: " + library);
                break;
            }
        }
        
        if (initialized) {
            logger.log(Level.INFO, ScalpelCarver.class.getName() + " JNI initialized successfully. ");
        }
        
        return initialized;
    }

    /**
     * initialize, load dynamic libraries
     */
    private static boolean loadLib(String id) {
        boolean success = false;
        try {
            //rely on netbeans / jna to locate the lib variation for architecture/OS
            System.loadLibrary(id);
            success = true;
        } catch (UnsatisfiedLinkError ex) {
            String msg = "Could not load library " + id + " for your environment ";
            System.out.println(msg + ex.toString());
            logger.log(Level.SEVERE, msg, ex);
        } catch (Exception ex) {
            String msg = "Could not load library " + id + " for your environment ";
            System.out.println(msg + ex.toString());
            logger.log(Level.SEVERE, msg, ex);
        }

        return success;
    }


    /**
     * Check if initialized
     *
     * @return true if library has been initialized properly, false otherwise
     */
    public boolean isInitialized() {
        return initialized;
    }

    /**
     * Carve the file passed in as an argument and save the results.
     * Requires prior call to ScalpelCarver.init()
     *
     *
     * @param file File to carve 
     * @param configFilePath file path to scalpel
     * configuration file with signatures, such as scalpel.conf
     * @param outputFolder Location to save the reults to (should be in the case
     * folder)
     * @return list of carved files info
     * @throws ScalpelException on errors
     */
    public List<CarvedFileMeta> carve(AbstractFile file, String configFilePath, String outputFolderPath) throws ScalpelException {
        if (!initialized) {
            throw new ScalpelException("Scalpel library is not fully initialized. ");
        }

        //basic check of arguments before going to jni land
        if (file == null || configFilePath == null || configFilePath.isEmpty()
                || outputFolderPath == null || outputFolderPath.isEmpty()) {
            throw new ScalpelException("Invalid arguments for scalpel carving. ");
        }
        
        //validate the paths passed in
        File config = new File(configFilePath);
        if (! config.exists() || ! config.canRead()) {
            throw new ScalpelException("Cannot read libscalpel config file: " + configFilePath);
        }
        
        File outDir = new File(outputFolderPath);
        if (! outDir.exists() || ! outDir.canWrite()) {
            throw new ScalpelException("Cannot write to libscalpel output dir: " + outputFolderPath);
        }

        final String carverInputId = file.getId() + ": " + file.getName();
        final ReadContentInputStream carverInput = new ReadContentInputStream(file);
        

        try {
            carveNat(carverInputId, carverInput, configFilePath, outputFolderPath);
        }
        catch (Exception e) {
            logger.log(Level.SEVERE, "Error while caving file " + file, e);
            throw new ScalpelException(e);
        }
        finally {
            try {
                carverInput.close();
            } catch (IOException ex) {
                logger.log(Level.SEVERE, "Error closing input stream after carving, file: " + file, ex);
            }
        }
        
        // create a file object for the output
        File outputFile = new File(outputFolderPath, SCALPEL_OUTPUT_FILE_NAME);
        
        // parse the output
        List<CarvedFileMeta> output = Collections.EMPTY_LIST;
        try {
            output = ScalpelOutputParser.parse(outputFile);
        } catch (FileNotFoundException ex) {
            logger.log(Level.SEVERE, "Could not find scalpel output file.", ex);
        } catch (IOException ex) {
            logger.log(Level.SEVERE, "IOException while processing scalpel output file.", ex);
        }
        
        return output;
    }
}

@@ -5819,18 +5819,35 @@
 ons.
-EMPTY_LIST
+%3CCarvedFileMeta%3EemptyList()
 ;%0A  

fix scalpel module build warning