package stego.StegoCreator;

import Main.Main;
import StegoGUI.StegoFileSelection;
import java.io.File;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import javax.imageio.ImageIO;
import stego.Drivers;
import stego.StegoCaller.Caller_Encryption_XOR;
import stego.btoS;

public class StegoExtractor
{

    File fleCarrierImage;
    int numBytesToExtract;
    int myFragmentNumber;
    int totalNumberOfFragments;
    String strBatchIdentifier;
    int fileTypeNumber;
    String strFileExtension;
    String strExtractedMessage;
    byte extractedBytes[];
    private static String strMyClassName = "StegoExtractor";
    public static final int index_ExtractedNumBytes_EMBEDDED = 0;
    public static final int index_ExtractedBatchIdentifier = 1;
    public static final int index_ExtractedFragmentIndex = 2;
    public static final int index_ExtractedTotalNumFragments = 3;
    public static final int index_ExtractedFileTypeNumber = 4;
    public static final int index_ExtractedFileExtension = 5;
    public static final int index_ExtractedMessage = 6;
    java.awt.image.BufferedImage image;
    boolean loadJPEG_TO_PNG;
    public boolean completed_SUCCESSFULLY;
    ArrayList alExtractedData;

    public StegoExtractor(boolean decryptExtractedMessage, File fleToExtrct, int numBytesRead, int fragNum, int totalCarriers, boolean thisIsExtractingOverhead_ONLY, File encryption_JAR_Path, 
            File encryptionKey)
    {
        fleCarrierImage = null;
        numBytesToExtract = 0;
        myFragmentNumber = 0;
        totalNumberOfFragments = 0;
        strBatchIdentifier = "";
        fileTypeNumber = 0;
        strFileExtension = "UKN";
        strExtractedMessage = "";
        extractedBytes = null;
        image = null;
        loadJPEG_TO_PNG = false;
        completed_SUCCESSFULLY = false;
        alExtractedData = null;
        try
        {
            if(decryptExtractedMessage)
            {
                Drivers.sop((new StringBuilder("fleEncryption_JAR == null: ")).append(encryption_JAR_Path == null).toString());
                Drivers.sop((new StringBuilder("fleEncryption_JAR.exists(): ")).append(encryption_JAR_Path.exists()).toString());
                Drivers.sop((new StringBuilder("fleEncryption_JAR.isFile(): ")).append(encryption_JAR_Path.isFile()).toString());
                Drivers.sop((new StringBuilder("decryptpKeyPath != null: ")).append(encryptionKey != null).toString());
                Drivers.sop((new StringBuilder("decryptpKeyPath.exists(): ")).append(encryptionKey.exists()).toString());
                Drivers.sop((new StringBuilder("decryptpKeyPath.isFile(): ")).append(encryptionKey.isFile()).toString());
            }
            fleCarrierImage = fleToExtrct;
            numBytesToExtract = numBytesRead;
            myFragmentNumber = fragNum;
            totalNumberOfFragments = totalCarriers;
            Drivers.sop((new StringBuilder("File: ")).append(fleToExtrct).append("Received in ").append(strMyClassName).append(".  Commencing Extraction...\n").toString());
            if(Drivers.lstSpecialFormats_jpgPngGif.contains(Drivers.getFileExtension(fleToExtrct, true).toUpperCase()))
            {
                Drivers.sop("* * * // Special Format Found in Extraction. Loading specially  // * * *");
                loadJPEG_TO_PNG = true;
            }
            extractedBytes = getExtractedBytes(fleToExtrct, numBytesRead + Drivers.numOfOverheadBytes + 1);
            Drivers.sop((new StringBuilder("\nPrinting Extracted Message: ")).append(new String(extractedBytes)).append("\n").toString());
            if(decryptExtractedMessage)
            {
                try
                {
                    Drivers.sop((new StringBuilder("Decrypting bytes... Size of extractedBytes: ")).append(extractedBytes.length).toString());
                    Drivers.writeImage_Fully("Test.txt", new File("./"), extractedBytes);
                    Drivers.sop((new StringBuilder("Encryption Encoding: ")).append(System.getProperty("file.encoding")).toString());
                    Drivers.sop("The issue is probably here with encryption! \nNeed to figure out how to get extr" +
"acted text and write out into format (unicode) XoR is expecting"
);
                    byte decryptedBytes[] = decryptByteArray(encryption_JAR_Path, true, encryptionKey, extractedBytes, Drivers.ensureTempFolderExists(fleToExtrct.getParentFile()), fleToExtrct);
                }
                catch(Exception e)
                {
                    e.printStackTrace();
                }
            } else
            {
                Drivers.sop("NOTE: Extracted bytes is not encrypted");
            }
            alExtractedData = parseExtractedData(extractedBytes, thisIsExtractingOverhead_ONLY);
            if(alExtractedData != null)
            {
                if(!thisIsExtractingOverhead_ONLY)
                {
                    Drivers.sop("\n* * * Data Parsing complete * * *");
                    Drivers.sop((new StringBuilder("\tExtracted Number of Bytes EMBEDDED: ")).append((String)alExtractedData.get(0)).toString());
                    Drivers.sop((new StringBuilder("\tExtracted Batch Identifier: ")).append((String)alExtractedData.get(1)).toString());
                    Drivers.sop((new StringBuilder("\tExtracted Fragment Number: ")).append((String)alExtractedData.get(2)).toString());
                    Drivers.sop((new StringBuilder("\tExtracted Total # of Fragments: ")).append((String)alExtractedData.get(3)).toString());
                    Drivers.sop((new StringBuilder("\tExtracted File Type Number: ")).append((String)alExtractedData.get(4)).toString());
                    Drivers.sop((new StringBuilder("\tExtracted File Extension: ")).append((String)alExtractedData.get(5)).toString());
                    Drivers.sop((new StringBuilder("\tExtracted Message: ")).append((String)alExtractedData.get(6)).toString());
                }
                saveExtractedData(alExtractedData, fleToExtrct);
                completed_SUCCESSFULLY = true;
            } else
            {
                Drivers.sop("Critical error!  Data parsing error detected!");
            }
        }
        catch(Exception e)
        {
            Drivers.eop("StegoExtractor Constructor", strMyClassName, e, "Most likely invalid file selected", false);
        }
    }

    public byte[] decryptByteArray(File fleEncryption_JAR, boolean decryptByteArray, File encrypKeyPath, byte message_To_Decrypt[], File fleOutDirectory, File carrierImage)
    {
        if(!decryptByteArray)
        {
            return message_To_Decrypt;
        }
        byte decryptedArray[];
        if(fleEncryption_JAR == null || !fleEncryption_JAR.exists() || !fleEncryption_JAR.isFile() || !decryptByteArray || encrypKeyPath == null || !encrypKeyPath.exists() || !encrypKeyPath.isFile() || !carrierImage.exists())
        {
            break MISSING_BLOCK_LABEL_272;
        }
        String strCarrierImageName = carrierImage.getName();
        String encryptedFileName = (new StringBuilder(String.valueOf(strCarrierImageName.substring(0, strCarrierImageName.lastIndexOf("."))))).append(".tmp").toString();
        File fleTempDir = Drivers.ensureTempFolderExists(fleOutDirectory);
        if(fleTempDir == null)
        {
            fleTempDir = new File("./");
        }
        File fleEncryptedText = Drivers.writeImage_Fully(encryptedFileName, fleTempDir, message_To_Decrypt);
        Drivers.sop((new StringBuilder("Temp plaintext written to: ")).append(fleEncryptedText).append(" attempting to decrypt temp file...").toString());
        File decryptedFile = Caller_Encryption_XOR.decryptFile(fleEncryptedText, fleEncryption_JAR, encrypKeyPath, fleTempDir, StegoFileSelection.jtxtpneInteractionContent);
        Drivers.sop((new StringBuilder("Encryption Enabled.  fleEncryptedText: ")).append(fleEncryptedText).append("\nfleEncryption_JAR: ").append(fleEncryption_JAR).append("\nencrypKeyPath: ").append(encrypKeyPath).append("\nfleTempDir: ").append(fleTempDir).toString());
        Drivers.sop((new StringBuilder("Decrypted Temp File Written to disk at: ")).append(decryptedFile.getCanonicalPath()).toString());
        decryptedArray = (byte[])null;
        decryptedArray = Drivers.readImage_Fully(decryptedFile);
        if(decryptedArray == null)
        {
            return message_To_Decrypt;
        }
        return decryptedArray;
        try
        {
            throw new Exception("Input parameters to decrypt carrier image was invalid");
        }
        catch(Exception e)
        {
            Drivers.eop("decryptByteArray", strMyClassName, e, e.getLocalizedMessage(), true);
        }
        Drivers.sop("Returning original message array to continue");
        return message_To_Decrypt;
    }

    private byte[] decryptByteArray_DEPRECATED(File fleEncryption_JAR, boolean decryptByteArray, File decryptpKeyPath, byte byteArrayToDecrypt[])
    {
        byte decryptedArray[];
        byte arrEncryptionKey[];
        Drivers.sop((new StringBuilder("byteArrayToDecrypt != null: ")).append(byteArrayToDecrypt != null).toString());
        Drivers.sop((new StringBuilder("byteArrayToDecrypt.length: ")).append(byteArrayToDecrypt.length).toString());
        Drivers.sop((new StringBuilder("fleEncryption_JAR != null: ")).append(fleEncryption_JAR != null).toString());
        Drivers.sop((new StringBuilder("fleEncryption_JAR.exists(): ")).append(fleEncryption_JAR.exists()).toString());
        Drivers.sop((new StringBuilder("fleEncryption_JAR.isFile(): ")).append(fleEncryption_JAR.isFile()).toString());
        Drivers.sop((new StringBuilder("decryptByteArray: ")).append(decryptByteArray).toString());
        Drivers.sop((new StringBuilder("decryptpKeyPath != null: ")).append(decryptpKeyPath != null).toString());
        Drivers.sop((new StringBuilder("decryptpKeyPath.exists(): ")).append(decryptpKeyPath.exists()).toString());
        Drivers.sop((new StringBuilder("decryptpKeyPath.isFile(): ")).append(decryptpKeyPath.isFile()).toString());
        if(byteArrayToDecrypt == null || byteArrayToDecrypt.length <= 1 || fleEncryption_JAR == null || !fleEncryption_JAR.exists() || !fleEncryption_JAR.isFile() || !decryptByteArray || decryptpKeyPath == null || !decryptpKeyPath.exists() || !decryptpKeyPath.isFile())
        {
            break MISSING_BLOCK_LABEL_518;
        }
        decryptedArray = (byte[])null;
        arrEncryptionKey = Drivers.readImage_Fully(decryptpKeyPath);
        if(arrEncryptionKey != null && arrEncryptionKey.length >= 1)
        {
            break MISSING_BLOCK_LABEL_325;
        }
        Drivers.sop((new StringBuilder("Errors in reading decryption key at path: ")).append(decryptpKeyPath).append(" decrypted array returned a null or a length < 1").toString());
        Drivers.sop("Returning original array to continue");
        return byteArrayToDecrypt;
        String stDecryptionKey_ByteArrayRep;
        stDecryptionKey_ByteArrayRep = btoS.convertByteArrayToStringRepresentation(arrEncryptionKey);
        if(stDecryptionKey_ByteArrayRep != null && stDecryptionKey_ByteArrayRep.trim().length() >= 1)
        {
            break MISSING_BLOCK_LABEL_378;
        }
        Drivers.sop((new StringBuilder("Errors in receiving the decrypted string representation on file: ")).append(decryptpKeyPath).toString());
        Drivers.sop("Returning original array to continue");
        return byteArrayToDecrypt;
        String strMessage_ByteArrayRep;
        strMessage_ByteArrayRep = btoS.convertByteArrayToStringRepresentation(byteArrayToDecrypt);
        if(strMessage_ByteArrayRep != null && strMessage_ByteArrayRep.trim().length() >= 1)
        {
            break MISSING_BLOCK_LABEL_439;
        }
        Drivers.sop((new StringBuilder("Errors in receiving the message string representation on message: ")).append(new String(byteArrayToDecrypt)).toString());
        Drivers.sop("Returning original array to continue");
        return byteArrayToDecrypt;
        String decryptedText;
        decryptedText = Caller_Encryption_XOR.decryptText(fleEncryption_JAR, strMessage_ByteArrayRep, stDecryptionKey_ByteArrayRep);
        if(decryptedText != null && decryptedText.trim().length() >= 1)
        {
            break MISSING_BLOCK_LABEL_481;
        }
        Drivers.sop("Errors in receiving the decrypted message from XOr.jar");
        Drivers.sop("Returning original array to continue");
        return byteArrayToDecrypt;
        decryptedArray = btoS.convertStringRepresentationToByteArray(decryptedText);
        if(decryptedArray != null && decryptedArray.length >= 1)
        {
            break MISSING_BLOCK_LABEL_515;
        }
        Drivers.sop("Errors in receiving the decrypted byte array from btoS.java");
        Drivers.sop("Returning original array to continue");
        return byteArrayToDecrypt;
        return decryptedArray;
        Drivers.sop("NOTE: Byte Array is not Decrypted or parameters passed in are not sufficient to " +
"decrypt byte array"
);
        Drivers.sop("Returning original array to continue");
        return byteArrayToDecrypt;
        Exception e;
        e;
        Drivers.eop("decryptByteArray", strMyClassName, e, e.getLocalizedMessage(), true);
        return byteArrayToDecrypt;
    }

    public StegoExtractor(boolean decryptExtractedMessage, File fleToExtrct, File encryptionPathTo_JAR, File encryptionPathTo_KEY)
    {
        fleCarrierImage = null;
        numBytesToExtract = 0;
        myFragmentNumber = 0;
        totalNumberOfFragments = 0;
        strBatchIdentifier = "";
        fileTypeNumber = 0;
        strFileExtension = "UKN";
        strExtractedMessage = "";
        extractedBytes = null;
        image = null;
        loadJPEG_TO_PNG = false;
        completed_SUCCESSFULLY = false;
        alExtractedData = null;
        StegoExtractor overhead = new StegoExtractor(decryptExtractedMessage, fleToExtrct, 1, 0, 1, true, encryptionPathTo_JAR, encryptionPathTo_KEY);
        ArrayList extractedData = overhead.getExtractedData();
        Drivers.sop((new StringBuilder("\n* * * Data Parsing of OVERHEAD Complete for file: ")).append(fleToExtrct).append("* * *").toString());
        Drivers.sop((new StringBuilder("\tExtracted Number of Bytes EMBEDDED_FOR OVERHEAD: ")).append((String)extractedData.get(0)).toString());
        Drivers.sop((new StringBuilder("\tExtracted Batch Identifier_FOR OVERHEAD: ")).append((String)extractedData.get(1)).toString());
        Drivers.sop((new StringBuilder("\tExtracted Current Fragment Number_FOR OVERHEAD: ")).append((String)extractedData.get(2)).toString());
        Drivers.sop((new StringBuilder("\tExtracted Total # Fragments_FOR OVERHEAD: ")).append((String)extractedData.get(3)).toString());
        Drivers.sop((new StringBuilder("\tExtracted File Type Number_FOR OVERHEAD: ")).append((String)extractedData.get(4)).toString());
        Drivers.sop((new StringBuilder("\tExtracted File Extension_FOR OVERHEAD: ")).append((String)extractedData.get(5)).toString());
        Drivers.sop((new StringBuilder("\tExtracted Message_FOR OVERHEAD: ")).append((String)extractedData.get(6)).toString());
        Drivers.sop((new StringBuilder("\n\nOverhead complete.  Calling Extractor again to extract: ")).append((String)extractedData.get(0)).append(" bytes from carrier image.\n").toString());
        try
        {
            int numBytesToRead = Integer.parseInt((String)extractedData.get(0));
            int currFragNum = Integer.parseInt((String)extractedData.get(2));
            int totNumFragments = Integer.parseInt((String)extractedData.get(3));
            completed_SUCCESSFULLY = true;
            StegoExtractor extractorFullMsg = new StegoExtractor(decryptExtractedMessage, fleToExtrct, numBytesToRead, currFragNum, totNumFragments, false, encryptionPathTo_JAR, encryptionPathTo_KEY);
            alExtractedData = extractorFullMsg.getExtractedData();
            saveExtractedData(extractorFullMsg.getExtractedData(), fleToExtrct);
        }
        catch(Exception e)
        {
            if(extractedData != null && extractedData.size() > 6)
            {
                String outputData = (new StringBuilder("\n\nExtracted Number of Bytes EMBEDDED: ")).append((String)extractedData.get(0)).append("\nExtracted Batch Identifier: ").append((String)extractedData.get(1)).append("\nExtracted Current Index: ").append((String)extractedData.get(2)).append("\nExtracted Total # w/in Batch: ").append((String)extractedData.get(3)).append("\nExtracted File Type Number: ").append((String)extractedData.get(4)).append("\nExtracted File Extension: ").append((String)extractedData.get(5)).append("\nExtracted Message: ").append((String)extractedData.get(6)).toString();
                Drivers.jop_Error((new StringBuilder("Part of data from file: ")).append(fleToExtrct).append(" was unrecoverable. \nVerify the following data: ").append(outputData).append("\n\nPerhaps this data was encrypted?").toString(), "Critical Error");
            } else
            {
                Drivers.jop_Error((new StringBuilder("Errors were discovered in file:\n")).append(fleToExtrct).append(" \n\nData was unrecoverable. ").append("\n\nPerhaps this data was encrypted?").toString(), "Critical Error");
            }
        }
    }

    private boolean saveExtractedData(ArrayList alToSave, File fleToAnalyze)
    {
        String flePath = "UNKNOWN";
        try
        {
            if(alToSave == null || alToSave.size() < 7)
            {
                Drivers.jop_Error((new StringBuilder("Errors were discovered in file:\n")).append(fleToAnalyze).append(" \n\nData was unrecoverable while attempting to save extracted information. ").append("\n\nPerhaps this data was encrypted?").toString(), "Critical Error");
                throw new Exception("alToSave was null or size < 7");
            }
            flePath = fleToAnalyze.getCanonicalPath();
            alExtractedData = alToSave;
            numBytesToExtract = Integer.parseInt((String)alToSave.get(0));
            strBatchIdentifier = (String)alToSave.get(1);
            myFragmentNumber = Integer.parseInt((String)alToSave.get(2));
            totalNumberOfFragments = Integer.parseInt((String)alToSave.get(3));
            fileTypeNumber = Integer.parseInt((String)alToSave.get(4));
            strFileExtension = (String)alToSave.get(5);
            strExtractedMessage = (String)alToSave.get(6);
            if(!Main.mode_CLI)
            {
                StegoFileSelection.setSourceText(null, strExtractedMessage);
            } else
            {
                Main.extractedMessage = strExtractedMessage;
            }
        }
        catch(Exception e)
        {
            Drivers.eop("saveExtractedData", strMyClassName, e, (new StringBuilder(String.valueOf(e.getLocalizedMessage()))).append(" This error will be dismissed.  Review if ").append(flePath).append(" was actually a carrier file created by this program of if the contents are stil" +
"l encrypted!"
).toString(), false);
            return false;
        }
        return true;
    }

    public ArrayList getExtractedData()
    {
        return alExtractedData;
    }

    public byte[] getExtractedBytes(File fleToExtract, int numBytesToExtract)
    {
        byte arrCarrierImage[];
        ArrayList alLocationToExtract;
        if(fleToExtract == null)
        {
            throw new Exception("File to extract bytes was null!");
        }
        arrCarrierImage = Drivers.readImage_Fully(fleToExtract);
        if(loadJPEG_TO_PNG)
        {
            Drivers.sop("\n \\\\ Loading special import for PNG and JPEG \\\\");
            image = ImageIO.read(fleToExtract);
            java.awt.image.WritableRaster raster = image.getRaster();
            java.awt.image.DataBufferByte buffer = (java.awt.image.DataBufferByte)raster.getDataBuffer();
            arrCarrierImage = buffer.getData();
        }
        alLocationToExtract = Drivers.populateRandomLocationToEmbedBits(numBytesToExtract * 8, arrCarrierImage.length, arrCarrierImage.length);
        if(alLocationToExtract.size() % 8 != 0)
        {
            Drivers.jop_Error("Internal Error occurred.  Location of bits to extract is not within expected len" +
"gth.\nProgramming assistance is required"
, "Critical Error");
            throw new Exception("Critical Error.  UKN reason why.  alLocationToExtract.size % 8 is not equal to 0" +
".  Stop here and figure out why because this throws off the number of bits into " +
"each byte"
);
        }
        return extractBytes_UPDATE_SHIFTING(arrCarrierImage, alLocationToExtract, numBytesToExtract);
        Exception e;
        e;
        Drivers.eop("extractBytes", strMyClassName, e, "Most likely invalid file selected", false);
        return null;
    }

    private byte[] extractBytes(byte carrierImage[], ArrayList alExtractByteLocation, int bytesToExtract)
    {
        byte arrExtratedBytes_EmbeddedMessage[];
        int extractedByteLoc_To_Save_In_arrExtratedBytes;
        String strExtractedByte_Bits;
        arrExtratedBytes_EmbeddedMessage = new byte[bytesToExtract];
        extractedByteLoc_To_Save_In_arrExtratedBytes = 0;
        byte arrCurrByte_CarrierImage[] = (byte[])null;
        String strCurrByte_Bits = "";
        strExtractedByte_Bits = "";
        byte extractedByte[] = (byte[])null;
        for(int i = 0; i < alExtractByteLocation.size(); i++)
        {
            if(strExtractedByte_Bits.length() == 8)
            {
                BigInteger bigint_strExtractedByte_Bits = new BigInteger(strExtractedByte_Bits, 2);
                byte extractedByte[] = bigint_strExtractedByte_Bits.toByteArray();
                arrExtratedBytes_EmbeddedMessage[extractedByteLoc_To_Save_In_arrExtratedBytes++] = extractedByte[0];
                strExtractedByte_Bits = "";
            } else
            if(strExtractedByte_Bits.length() > 8)
            {
                throw new Exception((new StringBuilder("strExtractedByte_Bits's length in ")).append(strMyClassName).append(" is greater than 8.  Should never happen.  Need to determine why").toString());
            }
            byte arrCurrByte_CarrierImage[] = {
                carrierImage[((Integer)alExtractByteLocation.get(i)).intValue()]
            };
            BigInteger bigint_Bits = new BigInteger(arrCurrByte_CarrierImage);
            String strCurrByte_Bits = bigint_Bits.toString(2);
            strExtractedByte_Bits = (new StringBuilder(String.valueOf(strExtractedByte_Bits))).append(strCurrByte_Bits.substring(strCurrByte_Bits.length() - 1)).toString();
        }

        return arrExtratedBytes_EmbeddedMessage;
        Exception e;
        e;
        Drivers.eop("extractBytes", strMyClassName, e, "Check sizes of bytesToExtract and size of arrExtratedBytes.  Perhaps we are over" +
"running the array."
, true);
        return null;
    }

    private ArrayList parseExtractedData(byte extractedData[], boolean thisIsToReturn_OVERHEAD_Data_ONLY)
    {
        ArrayList alParsedData = null;
        try
        {
            String numBytesEmbedded = new String(extractedData, 0, 4);
            String batchIdentifier = new String(extractedData, 4, 4);
            String currIndexNum = new String(extractedData, 8, 2);
            String totalNumFilesWithBatch = new String(extractedData, 10, 2);
            String fileTypeNumber = new String(extractedData, 12, 2);
            String fileExtension = new String(extractedData, 14, 4);
            String message = new String(extractedData, 18, extractedData.length - 19);
            alParsedData = new ArrayList();
            alParsedData.add(numBytesEmbedded);
            alParsedData.add(batchIdentifier);
            alParsedData.add(currIndexNum);
            alParsedData.add(totalNumFilesWithBatch);
            alParsedData.add(fileTypeNumber);
            alParsedData.add(fileExtension);
            if(thisIsToReturn_OVERHEAD_Data_ONLY)
            {
                alParsedData.add("OVERHEAD DATA ONLY");
            } else
            {
                alParsedData.add(message);
            }
        }
        catch(Exception e)
        {
            Drivers.eop("parseExtractedData", strMyClassName, e, "Perhaps overrunning the extrctedData array", true);
        }
        return alParsedData;
    }

    private byte[] extractBytes_UPDATED(byte carrierImage[], ArrayList alExtractByteLocation, int bytesToExtract)
    {
        byte arrExtratedBytes_EmbeddedMessage[];
        Drivers.sop("\n\n Using extractBytes_UPDATED mtd");
        arrExtratedBytes_EmbeddedMessage = new byte[bytesToExtract];
        int indexToSave_ExtractedMessage = 0;
        byte currByte_CarrierImage = 0;
        byte LSB_CarrierImage_Placed_At_Head = 0;
        byte extractedByte_Complete = 0;
        for(int i = 0; i < alExtractByteLocation.size(); i++)
        {
            if(i % 8 == 0)
            {
                arrExtratedBytes_EmbeddedMessage[indexToSave_ExtractedMessage++] = extractedByte_Complete;
                extractedByte_Complete = 0;
            }
            currByte_CarrierImage = carrierImage[((Integer)alExtractByteLocation.get(i)).intValue()];
            LSB_CarrierImage_Placed_At_Head = (byte)(currByte_CarrierImage << 7);
            if(i == 0)
            {
                extractedByte_Complete = LSB_CarrierImage_Placed_At_Head;
            } else
            {
                extractedByte_Complete |= (byte)(LSB_CarrierImage_Placed_At_Head >>> i);
            }
        }

        return arrExtratedBytes_EmbeddedMessage;
        Exception e;
        e;
        Drivers.eop("extractBytes_UPDATED", strMyClassName, e, "Check sizes of bytesToExtract and size of arrExtratedBytes.  Perhaps we are over" +
"running the array."
, true);
        return null;
    }

    private byte[] extractBytes_UPDATE_SHIFTING(byte carrierImage[], ArrayList alExtractByteLocation, int bytesToExtract)
    {
        byte arrExtratedBytes_EmbeddedMessage[];
        int extractedByteLoc_To_Save_In_arrExtratedBytes;
        byte extractedByte;
        arrExtratedBytes_EmbeddedMessage = new byte[bytesToExtract];
        extractedByteLoc_To_Save_In_arrExtratedBytes = 0;
        byte arrCurrByte_CarrierImage[] = (byte[])null;
        String strCurrByte_Bits = "";
        String strExtractedByte_Bits = "";
        extractedByte = 0;
        for(int i = 0; i < alExtractByteLocation.size(); i++)
        {
            if(i % 8 == 0 && i != 0)
            {
                arrExtratedBytes_EmbeddedMessage[extractedByteLoc_To_Save_In_arrExtratedBytes++] = extractedByte;
                extractedByte = 0;
            }
            extractedByte = (byte)(extractedByte << 1 | carrierImage[((Integer)alExtractByteLocation.get(i)).intValue()] & 1);
        }

        return arrExtratedBytes_EmbeddedMessage;
        Exception e;
        e;
        Drivers.eop("extractBytes_UPDATE_SHIFTING", strMyClassName, e, "Check sizes of bytesToExtract and size of arrExtratedBytes.  Perhaps we are over" +
"running the array."
, true);
        return null;
    }

    public int getNumBytesExtracted()
    {
        return numBytesToExtract;
    }

    public int getFragmentNumber()
    {
        return myFragmentNumber;
    }

    public int getTotalNumberOfFragments()
    {
        return totalNumberOfFragments;
    }

    public String getBatchIdentifier()
    {
        return strBatchIdentifier;
    }

    public int getFileTypeNumber()
    {
        return fileTypeNumber;
    }

    public String getFileExtension()
    {
        return strFileExtension;
    }

    public String getExtractedMessage()
    {
        return strExtractedMessage;
    }

    public String getFileExtension_WithoutSpaceFiller()
    {
        return strFileExtension.replace("0", "");
        Exception exception;
        exception;
        return strFileExtension;
    }

}
