/*
 * Autopsy Forensic Browser
 *
 * Copyright 2011-2016 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.keywordsearch;

import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.logging.Level;
import org.apache.commons.io.IOUtils;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.datamodel.ContentUtils;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskCoreException;

/**
 * Extracts text from artifacts by concatenating the values of all of the
 * artifact's attributes.
 */
public class ArtifactTextExtractor extends TextExtractor<BlackboardArtifact> {
    static final private Logger logger = Logger.getLogger(ArtifactTextExtractor.class.getName());

    /**
     * Get the Content that is the data source for the given artifact. //JMTODO:
     * is there a prexisting method to do this?
     *
     * @param artifact
     *
     * @return The data source for the given artifact as a Content object, or
     *         null if it could not be found.
     *
     * @throws TskCoreException if there is a problem accessing the case db.
     */
    static Content getDataSource(BlackboardArtifact artifact) throws TskCoreException {

        Case currentCase;
        try {
            currentCase = Case.getCurrentCase();
        } catch (IllegalStateException ignore) {
            // thorown by Case.getCurrentCase() if currentCase is null
            return null;
        }

        SleuthkitCase sleuthkitCase = currentCase.getSleuthkitCase();
        if (sleuthkitCase == null) {
            return null;

        }
        Content dataSource;
        AbstractFile abstractFile = sleuthkitCase.getAbstractFileById(artifact.getObjectID());
        if (abstractFile != null) {
            dataSource = abstractFile.getDataSource();
        } else {
            dataSource = sleuthkitCase.getContentById(artifact.getObjectID());
        }

        if (dataSource == null) {
            return null;
        }
        return dataSource;
    }

    @Override
    boolean isDisabled() {
        return false;
    }


    @Override
    InputStream getInputStream(BlackboardArtifact artifact) {
        // Concatenate the string values of all attributes into a single
        // "content" string to be indexed.
        StringBuilder artifactContents = new StringBuilder();

        try {
            Content dataSource = getDataSource(artifact);
            if (dataSource == null) {
                return null;
            }

            for (BlackboardAttribute attribute : artifact.getAttributes()) {
                artifactContents.append(attribute.getAttributeType().getDisplayName());
                artifactContents.append(" : ");
                // We have also discussed modifying BlackboardAttribute.getDisplayString()
                // to magically format datetime attributes but that is complicated by
                // the fact that BlackboardAttribute exists in Sleuthkit data model
                // while the utility to determine the timezone to use is in ContentUtils
                // in the Autopsy datamodel.
                switch (attribute.getValueType()) {
                    case DATETIME:
                        artifactContents.append(ContentUtils.getStringTime(attribute.getValueLong(), dataSource));
                        break;
                    default:
                        artifactContents.append(attribute.getDisplayString());
                }
                artifactContents.append(System.lineSeparator());
            }
        } catch (TskCoreException ex) {
            logger.log(Level.SEVERE, "There was a problem getting the atributes for artifact " + artifact.getArtifactID(), ex);
            return null;
        }
        if (artifactContents.length() == 0) {
            return null;
        }

        return IOUtils.toInputStream(artifactContents);
    }

    @Override
    Reader getReader(InputStream stream, BlackboardArtifact source) throws Ingester.IngesterException {
        return new InputStreamReader(stream);
    }

    @Override
    long getID(BlackboardArtifact source) {
        return source.getArtifactID();
    }

    @Override
    String getName(BlackboardArtifact source) {
        return source.getDisplayName() + "_" + source.getArtifactID();
    }
}

@@ -803,32 +803,74 @@
 java.io.Reader;%0A
+import java.nio.charset.StandardCharsets;%0A
 import java.util
@@ -4732,33 +4732,32 @@
 null;%0A        %7D%0A
-%0A
         return I
@@ -4793,16 +4793,40 @@
 Contents
+, StandardCharsets.UTF_8
 );%0A    %7D
@@ -4988,16 +4988,40 @@
 r(stream
+, StandardCharsets.UTF_8
 );%0A    %7D

use UTF-8 encoding for ArtifactTextExtractor streams and readers