/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.redPandaLib.core.messages;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.redPandaLib.ImageTooLargeException;
import org.redPandaLib.core.Channel;
import org.redPandaLib.core.Test;
import org.redPandaLib.crypt.ECKey;
/**
*
* @author robin
*/
public class ImageMsg extends RawMsg {
private static int MAX_FILE_SIZE = 1024 * 1024 * 15;
public static final byte BYTE = (byte) 2;
protected ImageMsg(ECKey key, long timestamp, int nonce) {
super(key, timestamp, nonce);
public_type = 21; //message will be kept after each block
}
public ImageMsg(ECKey key, long timestamp, int nonce, byte[] signature, byte[] content, byte[] decryptedContent, Channel channel, boolean verified, boolean readable, int database_Id) {
super(key, timestamp, nonce, signature, content, decryptedContent, channel, verified, readable, database_Id);
public_type = 21; //message will be kept after each block
}
public static ArrayList<ImageMsg> build(Channel channel, String pathToImage, boolean lowPriority) throws ImageTooLargeException {
try {
File file = new File(pathToImage);
byte[] messageContentBytes = read(file);
if (messageContentBytes == null) {
return null;
}
System.out.println("image bytes: " + messageContentBytes.length);
ECKey key = channel.getKey();
ArrayList<ImageMsg> msgs = new ArrayList<ImageMsg>();
//
int writtenBytes = 0;
int blockSize = Math.max(1024 * 50, messageContentBytes.length / 30);
System.out.println("blocksize 1 : " + blockSize);
if (blockSize > 100 * 1024) {
blockSize = 100 * 1024;
}
int block = 0;
int blocks = messageContentBytes.length / blockSize + 1;
long timeStamp = System.currentTimeMillis();
while (writtenBytes < messageContentBytes.length) {
int bytesThisRound = 0;
if (block + 1 == blocks) {
//last block
bytesThisRound = messageContentBytes.length - writtenBytes;
} else {
bytesThisRound = blockSize;
}
System.out.println("generating Img msg of size: " + bytesThisRound + " block: " + block + " of " + blocks);
ImageMsg imgMsg = new ImageMsg(key, timeStamp, 110 + block);
if (lowPriority) {
imgMsg.public_type = 100;
}
imgMsg.channel = channel;
byte[] content = new byte[1 + 8 + 4 + 4 + bytesThisRound];
ByteBuffer wrap = ByteBuffer.wrap(content);
wrap.put(BYTE);
wrap.putLong(Test.localSettings.identity);
wrap.putInt(block);
wrap.putInt(blocks);
wrap.put(messageContentBytes, writtenBytes, bytesThisRound);
imgMsg.decryptedContent = content;
imgMsg.readable = true;
imgMsg.encrypt();
imgMsg.sign();
writtenBytes += blockSize;
block++;
msgs.add(imgMsg);
}
return msgs;
} catch (FileNotFoundException ex) {
Logger.getLogger(ImageMsg.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(ImageMsg.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
public int getPartCount() {
ByteBuffer wrap = ByteBuffer.wrap(decryptedContent);
wrap.get();
wrap.getLong();
return wrap.getInt();
}
public int getParts() {
ByteBuffer wrap = ByteBuffer.wrap(decryptedContent);
wrap.get();
wrap.getLong();
wrap.getInt();
return wrap.getInt();
}
public byte[] getImageBytes() {
ByteBuffer wrap = ByteBuffer.wrap(decryptedContent);
wrap.get();
wrap.getLong();
wrap.getInt();
wrap.getInt();
byte[] out = new byte[wrap.remaining()];
wrap.get(out);
return out;
//System.out.println("decrypted bytes: " + Msg.bytesToHexString(decryptedContent));
//
// try {
// return new String(decryptedContent, 9, decryptedContent.length - 9, "UTF-8");
// } catch (UnsupportedEncodingException ex) {
// Logger.getLogger(TextMsg.class.getName()).log(Level.SEVERE, null, ex);
// }
//
// return "charset error";
}
public long getIdentity() {
ByteBuffer wrap = ByteBuffer.wrap(decryptedContent);
wrap.get();
return wrap.getLong();
}
public static byte[] read(File file) throws IOException, ImageTooLargeException {
if (file.length() > MAX_FILE_SIZE) {
throw new ImageTooLargeException();
}
byte[] buffer = new byte[(int) file.length()];
InputStream ios = null;
try {
ios = new FileInputStream(file);
if (ios.read(buffer) == -1) {
throw new IOException("EOF reached while trying to read the whole file");
}
} finally {
try {
if (ios != null) {
ios.close();
}
} catch (IOException e) {
}
}
return buffer;
}
}