archive file in image

Discussion in 'Scripts, 3rd Party Apps, and Programming' started by galaxyAbstractor, Oct 2, 2009.

  1. galaxyAbstractor

    galaxyAbstractor Community Advocate Community Support

    Messages:
    5,508
    Likes Received:
    35
    Trophy Points:
    48
    oh actually you're right, gonna need to check that up then
     
  2. marshian

    marshian New Member

    Messages:
    526
    Likes Received:
    9
    Trophy Points:
    0
    Good luck on that, in case you need more info just let me know.
     
  3. galaxyAbstractor

    galaxyAbstractor Community Advocate Community Support

    Messages:
    5,508
    Likes Received:
    35
    Trophy Points:
    48
    Last edited: Oct 6, 2009
  4. marshian

    marshian New Member

    Messages:
    526
    Likes Received:
    9
    Trophy Points:
    0
    Good attempt, but not entirely correct.
    Your only mistake (as far as I see) are these lines:
    Code:
    out.write('\n');
    out.write((int) imageFile.length());
    This is wrong because: you don't know the size of that integer. If the image is 10,000 bytes, it'll be represented by a 6 character string, but if the image is 100,000 bytes it would be a 7 character string. How do you know where to stop?
    An integer on the other is always 4 byte in size (in the memory). It's possible to write an object to an output stream with an ObjectOutputStream. Then reading is done with an ObjectInputStream. If you use this you'll have no problems to determine where the data of the archive ends. The '\n' isn't even required.

    I haven't tried it, but I think the following code should roughly be correct:

    Code:
    (new ObjectOutputStream((OutputStream) out)).write((int) imageFile.length());
    A bit longer (more readable):

    Code:
    outOOS = new ObjectOutputStream((OutputStream) out);
    outOOS.write((int) imageFile.length());
    Of course I'm assuming there is a constructor ObjectOutputStream(OutputStream arg1), if there isn't the code is wrong.

    It's a bit late now, but if you want more info (or more structured) just ask and I'll respond when I have some more time... (and less beer)
     
  5. galaxyAbstractor

    galaxyAbstractor Community Advocate Community Support

    Messages:
    5,508
    Likes Received:
    35
    Trophy Points:
    48
    Like http://pastebin.ca/1602112? That destroys the image but the archive works
     
  6. marshian

    marshian New Member

    Messages:
    526
    Likes Received:
    9
    Trophy Points:
    0
    It's probably a bad idea to use two OutputStreams to the same file at the same file. You should finish with the FileOutputStream before making the OOS.

    Apart from that it looks good to me. Does this really destroy the image? Adding any other data doesn't destroy it so why would this do? Have you tried a couple of variations yet?

    The code:

    Code:
    InputStream in = null;
    InputStream in2 = null;
    try {
        in = new FileInputStream(image);
        in2 = new FileInputStream(file);
        OutputStream out = new FileOutputStream(output);
        outOOS = new ObjectOutputStream((OutputStream) out);
        int nextChar;
        int nextChar2;
        while ((nextChar = in.read()) != -1) {
            out.write((char) nextChar);
        }
        while ((nextChar2 = in2.read()) != -1) {
            out.write((char) nextChar2);
        }
        out.flush();
        out.close();
        outOSS = new ObjectOutputStream((OutputStream) new FileOutputStream(output));
        outOOS.write((int) imageFile.length());
        outOOS.write(0x58); // Identify archive
        outOOS.write(0x59); // Identify archive
        outOOS.write(0x12); // Identify archive
        outOOS.write(0xA2); // Identify archive
        outOOS.flush();
    } catch (IOException ex) {
    	Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
    } catch (FileNotFoundException ex) {
        Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
    } finally {
        try {
            in.close();
            in2.close();
        } catch (IOException ex) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
     
    Last edited: Oct 7, 2009
  7. galaxyAbstractor

    galaxyAbstractor Community Advocate Community Support

    Messages:
    5,508
    Likes Received:
    35
    Trophy Points:
    48
    Yep that breaks it, Should I PM you the dist folder?
     
  8. marshian

    marshian New Member

    Messages:
    526
    Likes Received:
    9
    Trophy Points:
    0
    Yes please.
    What kind of image did you use to test? I manually tried it on a png file and the generated image was valid enough to show up in Gnome's image viewer and firefox.
     
  9. galaxyAbstractor

    galaxyAbstractor Community Advocate Community Support

    Messages:
    5,508
    Likes Received:
    35
    Trophy Points:
    48
    Sent.

    Rar file in a png
     
  10. marshian

    marshian New Member

    Messages:
    526
    Likes Received:
    9
    Trophy Points:
    0
    Aha... You noticed how the output file is 11 bytes in size?
    I forgot to append x)
    Code:
    outOSS = new ObjectOutputStream((OutputStream) new FileOutputStream(output, true));
    That should prevent the OOS from overwriting the entire file.
     
  11. galaxyAbstractor

    galaxyAbstractor Community Advocate Community Support

    Messages:
    5,508
    Likes Received:
    35
    Trophy Points:
    48
    It works now


    Now at this, this does not work. "Illegal unicode escape" and "Empty character literal"
     
    Last edited: Oct 8, 2009
  12. marshian

    marshian New Member

    Messages:
    526
    Likes Received:
    9
    Trophy Points:
    0
    I said it's me-code :p
    '\u58' + '\u59' + '\u12' + '\uA2'
    should be
    ((char) 0x58) + ((char) 0x59) + ((char) 0x12) + ((char) 0xA2)
    in Java
     
  13. galaxyAbstractor

    galaxyAbstractor Community Advocate Community Support

    Messages:
    5,508
    Likes Received:
    35
    Trophy Points:
    48

    Ooooh I thougt you meant "me code" like in "I code" with a bit of internet slangxD
     
  14. marshian

    marshian New Member

    Messages:
    526
    Likes Received:
    9
    Trophy Points:
    0
    No it's just pseudo-code used to explain the algorithm. In this case it's easier to write pseudo-code than to explain it all in text :)
     
  15. galaxyAbstractor

    galaxyAbstractor Community Advocate Community Support

    Messages:
    5,508
    Likes Received:
    35
    Trophy Points:
    48
  16. marshian

    marshian New Member

    Messages:
    526
    Likes Received:
    9
    Trophy Points:
    0
    Beware, non-tested code ahead!

    Code:
    File input = new File(output);
    InputStream inFile = null;
    //Initialise the value of 'valid' to false
    boolean valid = false;
    //This is the signature every file should have
    byte[] signature = {0x58, 0x59, 0x12, 0xA2};
    try {
        inFile = new FileInputStream(input);
        //Go to the last 4 bytes
        inFile.skip(input.length() - 4);
        //Assume the input file is valid
        valid = true;
       	//Compare each of the last 4 bytes to the expected signature
        for(int i=0; i<4; i++) {
        	if(inFile.read() != filesig[i]) {
        		//In case any of the 4 bytes fails the check, the file is invalid
        		//and the loop is aborted.
        		valid = false;
        		break;
        	}
        }
    	//Any exception assumes that the input is invalid.
    } catch (FileNotFoundException ex) {
    	Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
    	valid = false;
    } catch (IOException ex) {
        Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
        valid = false;
    }
    
    System.out.println(valid);
     
  17. galaxyAbstractor

    galaxyAbstractor Community Advocate Community Support

    Messages:
    5,508
    Likes Received:
    35
    Trophy Points:
    48
    it works! Thanks :D

    Btw, try to remember what you call your vars ;). outOOS vs outOSS and filesig vs signature

    I had to change the byte[] to int[] tho, otherwise it complained about loss of precision and incompatible types
     
  18. marshian

    marshian New Member

    Messages:
    526
    Likes Received:
    9
    Trophy Points:
    0
    It's not my fault, I was trying to set up some stuff and wanted to post that message in the least amount of time possible while still half focussing on the process...
    At least you got the point, that's good enough ;)
     
  19. galaxyAbstractor

    galaxyAbstractor Community Advocate Community Support

    Messages:
    5,508
    Likes Received:
    35
    Trophy Points:
    48
    Ok I edited the code a bit to check wether or not it's a zip or rar.

    Code:
     int a = 0;
                    while(a < jFileChooser1.getSelectedFiles().length) {
                       
                        File input = jFileChooser1.getSelectedFiles()[a];
                        InputStream inFile = null;
                        //Initialise the value of 'valid' to false
                        String valid = "false";
                        //This is the signature every file should have
                        int[] filesigrar = {0x58, 0x59, 0x12, 0xA2};
                        int[] filesigzip = {0x58, 0x59, 0x12, 0xA3};
                        try {
                            inFile = new FileInputStream(input);
                            //Go to the last 4 bytes
                            inFile.skip(input.length() - 4);
                            //Assume the input file is valid
                            valid = "true";
                                //Compare each of the last 4 bytes to the expected signature
                            for(int i=0; i<4; i++) {
                                if(inFile.read() == filesigrar[i]) {
                                        //In case any of the 4 bytes fails the check, the file is invalid
                                        //and the loop is aborted.
                                        valid = "RAR";
                                        break;
                                }
                                if(inFile.read() == filesigzip[i]) {
                                        //In case any of the 4 bytes fails the check, the file is invalid
                                        //and the loop is aborted.
                                        valid = "ZIP";
                                        break;
                                }
                                if(inFile.read() != filesigrar[i] || inFile.read() != filesigzip[i] ) {
                                        //In case any of the 4 bytes fails the check, the file is invalid
                                        //and the loop is aborted.
                                        valid = "";
                                        break;
                                }
                            }
                                //Any exception assumes that the input is invalid.
                        } catch (FileNotFoundException ex) {
                            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
                            valid = "false";
                        } catch (IOException ex) {
                            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
                            valid = "false";
                        }
                        model.addRow(new Object[]{jFileChooser1.getSelectedFiles()[a].getName(),
                        jFileChooser1.getSelectedFiles()[a].length()/1024+" kb", valid});
                        a++;
                    }
    Thing is... It returns RAR on all files including an archive, even tho I add different sigs now:

    Code:
    if(archiveType.equals("rar")){
                        outOOS.write(0x58); // Identify archive rar
                        outOOS.write(0x59); // Identify archive rar
                        outOOS.write(0x12); // Identify archive rar
                        outOOS.write(0xA2); // Identify archive rar
                    } else if(archiveType.equals("zip")) {
                        outOOS.write(0x58); // Identify archive zip
                        outOOS.write(0x59); // Identify archive zip
                        outOOS.write(0x12); // Identify archive zip
                        outOOS.write(0xA3); // Identify archive zip
                    }
    (I tested this and it works)
     
  20. marshian

    marshian New Member

    Messages:
    526
    Likes Received:
    9
    Trophy Points:
    0
    *sigh*
    You do know what break means, right? :p

    Code:
    int a = 0;
    while(a < jFileChooser1.getSelectedFiles().length) {
    	File input = jFileChooser1.getSelectedFiles()[a];
    	InputStream inFile = null;
    	//Initialise the value of 'valid' to false
    	String valid = "false";
    	//This is the signature every file should have
    	int[] filesigrar = {0x58, 0x59, 0x12, 0xA2};
    	int[] filesigzip = {0x58, 0x59, 0x12, 0xA3};
    	try {
    		inFile = new FileInputStream(input);
    		//Go to the last 4 bytes
    		inFile.skip(input.length() - 4);
    		//Compare each of the last 4 bytes to the expected signatures
    		for(int i=0; i<4; i++) {
    			if(inFile.read() == filesigrar[i]) {
    				valid = "RAR";
    			} else if(inFile.read() == filesigzip[i]) {
    				valid = "ZIP";
    			} else {
    				//In case any of the 4 bytes fails the check, the file is invalid
    				//and the loop is aborted.
    				valid = "false";
    				break;
    			}
    		}
    	//Any exception assumes that the input is invalid.
    	} catch (FileNotFoundException ex) {
    		Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
    		valid = "false";
    	} catch (IOException ex) {
    		Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
    		valid = "false";
    	}
    	model.addRow(new Object[]{jFileChooser1.getSelectedFiles()[a].getName(),
    		jFileChooser1.getSelectedFiles()[a].length()/1024+" kb", valid});
    	a++;
    }
    It's not very nice to use a string for "valid" though. You only need 3 values so it would be a better idea to use a short.
     

Share This Page