package org.witness.informacam.models.media;
import info.guardianproject.iocipher.File;
import info.guardianproject.iocipher.FileWriter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.NoSuchProviderException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.io.output.ByteArrayOutputStream;
import org.spongycastle.openpgp.PGPException;
import org.witness.informacam.InformaCam;
import org.witness.informacam.R;
import org.witness.informacam.crypto.EncryptionUtility;
import org.witness.informacam.json.JSONObject;
import org.witness.informacam.models.j3m.IDCIMEntry;
import org.witness.informacam.models.notifications.INotification;
import org.witness.informacam.models.organizations.IOrganization;
import org.witness.informacam.models.transport.ITransportStub;
import org.witness.informacam.storage.IOUtility;
import org.witness.informacam.transport.TransportUtility;
import org.witness.informacam.utils.Constants.App;
import org.witness.informacam.utils.Constants.App.Storage;
import org.witness.informacam.utils.Constants.App.Storage.Type;
import org.witness.informacam.utils.Constants.Codes;
import org.witness.informacam.utils.Constants.Logger;
import org.witness.informacam.utils.Constants.Models;
import org.witness.informacam.utils.Constants.Models.IMedia.MimeType;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.util.Base64;
import android.util.Base64OutputStream;
import android.util.Log;
public class ILog extends IMedia {
public long autoLogInterval = 10 * (60 * 1000); // 10 minutes?
public boolean shouldAutoLog = false;
public long startTime = 0L;
public long endTime = 0L;
public List<String> attachedMedia = new ArrayList<String>();
private Map<String, InputStream> j3mZip;
public ILog() {
super();
_id = generateId("log_" + System.currentTimeMillis());
dcimEntry = new IDCIMEntry();
dcimEntry.mediaType = MimeType.LOG;
info.guardianproject.iocipher.File rootFolder = new info.guardianproject.iocipher.File(_id);
if(!rootFolder.exists()) {
rootFolder.mkdir();
}
this.rootFolder = rootFolder.getAbsolutePath();
}
public ILog(IMedia media) throws InstantiationException, IllegalAccessException {
super();
inflate(media.asJson());
}
public java.io.File sealLog(boolean doLocalShare, IOrganization organization, INotification notification) throws IOException, NoSuchProviderException, PGPException, InstantiationException, IllegalAccessException {
InformaCam informaCam = InformaCam.getInstance();
java.io.File log = null;
// zip up everything, encrypt if required
String logName = ("log_" + System.currentTimeMillis() + ".zip");
if(doLocalShare) {
log = new java.io.File(Storage.EXTERNAL_DIR, logName);
IOUtility.zipFiles(j3mZip, log.getAbsolutePath(), Type.FILE_SYSTEM);
if(organization != null) {
//we can't read form a file and write to it simultaneously
java.io.File logEncrypted = new java.io.File(Storage.EXTERNAL_DIR, logName + ".pgp"); //add pgp encryption extension
EncryptionUtility.encrypt(informaCam.ioService.getStream(log.getAbsolutePath(), Type.FILE_SYSTEM), new FileOutputStream(logEncrypted),Base64.encode(informaCam.ioService.getBytes(organization.publicKey, Type.IOCIPHER), Base64.DEFAULT));
log.delete();//delete unecrypted export
log = logEncrypted;
}
} else {
log = new info.guardianproject.iocipher.File(rootFolder, logName);
IOUtility.zipFiles(j3mZip, log.getAbsolutePath(), Type.IOCIPHER);
if(organization != null) {
info.guardianproject.iocipher.File logEncrypted = new info.guardianproject.iocipher.File(rootFolder, logName + ".pgp"); //add pgp encryption extension
OutputStream os = new info.guardianproject.iocipher.FileOutputStream(logEncrypted.getAbsolutePath());
os = new Base64OutputStream(os, Base64.DEFAULT);
EncryptionUtility.encrypt(informaCam.ioService.getStream(log.getAbsolutePath(), Type.IOCIPHER), os,Base64.encode(informaCam.ioService.getBytes(organization.publicKey, Type.IOCIPHER), Base64.DEFAULT));
os.flush();
os.close();
log.delete();
log = logEncrypted;
ITransportStub submission = new ITransportStub(organization, notification);
submission.setAsset(log.getName(), log.getAbsolutePath(), MimeType.LOG, Storage.Type.IOCIPHER);
TransportUtility.initTransport(submission);
}
}
reset();
return log;
}
@Override
public IAsset export(final Context context, Handler h, final IOrganization organization, final boolean includeSensorLogs, final boolean isLocalShare, final boolean doSubmission)
throws FileNotFoundException, InstantiationException, IllegalAccessException {
InformaCam informaCam = InformaCam.getInstance();
j3mZip = new HashMap<String, InputStream>();
final INotification notification = new INotification();
int progress = 0;
// append its data sensory data, form data, etc.
mungeData();
if (includeSensorLogs)
mungeSensorLogs(h);
progress += 5;
sendMessage(Codes.Keys.UI.PROGRESS, progress, h);
mungeGenealogyAndIntent();
genealogy.dateCreated = this.startTime;
progress += 5;
sendMessage(Codes.Keys.UI.PROGRESS, progress, h);
notification.label = context.getString(R.string.export);
notification.mediaId = this._id;
notification.content = context.getString(R.string.you_exported_this_x, "log");
if(organization != null) {
intent.intendedDestination = organization.organizationName;
notification.content = context.getString(R.string.you_exported_this_x_to_x, "log", organization.organizationName);
}
progress += 5;
sendMessage(Codes.Keys.UI.PROGRESS, progress, h);
JSONObject j3mObject = null;
try {
j3mObject = new JSONObject();
JSONObject j3m = new JSONObject();
j3m.put(Models.IMedia.j3m.DATA, data.asJson());
j3m.put(Models.IMedia.j3m.GENEALOGY, genealogy.asJson());
j3m.put(Models.IMedia.j3m.INTENT, intent.asJson());
info.guardianproject.iocipher.File fileTmp = new info.guardianproject.iocipher.File("tmp-export");
info.guardianproject.iocipher.FileWriter fwTmp = new info.guardianproject.iocipher.FileWriter(fileTmp);
j3m.write(fwTmp);
fwTmp.flush();
fwTmp.close();
ByteArrayOutputStream bSig = new ByteArrayOutputStream();
informaCam.signatureService.signData(new info.guardianproject.iocipher.FileInputStream(fileTmp),bSig);
fileTmp.delete();
j3mObject.put(Models.IMedia.j3m.SIGNATURE, new String(bSig.toByteArray()));
j3mObject.put(Models.IMedia.j3m.J3M, j3m);
fwTmp = new info.guardianproject.iocipher.FileWriter(fileTmp);
j3mObject.write(fwTmp);
fwTmp.flush();
fwTmp.close();
j3mZip.put("log.j3m", new info.guardianproject.iocipher.FileInputStream(fileTmp));
progress += 5;
sendMessage(Codes.Keys.UI.PROGRESS, progress, h);
notification.generateId();
notification.taskComplete = false;
informaCam.addNotification(notification, h);
if(attachedMedia != null && attachedMedia.size() > 0) {
data.attachments = getAttachedMediaIds();
int progressIncrement = (int) (50/(attachedMedia.size() * 2));
boolean doMediaSubmission = false; //don't submit media individually
boolean includeMediaSensorLogs = false; //we have all the sensor data in the main log
for(final String s : attachedMedia) {
IMedia m = InformaCam.getInstance().mediaManifest.getById(s);
if(m.associatedCaches == null) {
m.associatedCaches = new ArrayList<String>();
}
if (associatedCaches != null)
m.associatedCaches.addAll(associatedCaches);
try {
IAsset assetExport = m.export(context, h, organization, includeMediaSensorLogs, isLocalShare, doMediaSubmission);
if (assetExport.source == Type.IOCIPHER)
{
info.guardianproject.iocipher.File fileMedia = new info.guardianproject.iocipher.File(assetExport.path);
j3mZip.put(fileMedia.getName(),new info.guardianproject.iocipher.FileInputStream(fileMedia));
}
else if (assetExport.source == Type.FILE_SYSTEM)
{
File fileMedia = new File(assetExport.path);
j3mZip.put(fileMedia.getName(),new FileInputStream(fileMedia));
}
} catch (FileNotFoundException e) {
Logger.e(App.LOG,e);
}
progress += progressIncrement;
sendMessage(Codes.Keys.UI.PROGRESS, progress, h);
}
}
java.io.File fileExport = sealLog(isLocalShare, organization, notification);
if (h != null)
{
Message msgExportComplete = new Message();
msgExportComplete.what = 999;
msgExportComplete.getData().putString("file", fileExport.getAbsolutePath());
msgExportComplete.getData().putBoolean("localShare", isLocalShare);
h.sendMessage(msgExportComplete);
}
IAsset assetExport = new IAsset();
assetExport.path = fileExport.getAbsolutePath();
assetExport.source = Type.FILE_SYSTEM;
return assetExport;
} catch(Exception e) {
Log.e(LOG, e.toString(),e);
return null;
}
}
private List<String> getAttachedMediaIds() {
return attachedMedia;
}
}