diff --git a/android/jni/Android.mk b/android/jni/Android.mk index b3d1193..24a635b 100644 --- a/android/jni/Android.mk +++ b/android/jni/Android.mk @@ -50,6 +50,7 @@ LOCAL_SRC_FILES := \ ../../src/foundation_pEp_jniadapter_AbstractEngine.cc \ ../../src/foundation_pEp_jniadapter_Engine.cc \ ../../src/foundation_pEp_jniadapter_Message.cc \ + ../../src/foundation_pEp_jniadapter__Blob.cc \ ../../src/throw_pEp_exception.cc \ ../../src/basic_api.cc \ ../../src/identity_api.cc \ diff --git a/src/Makefile b/src/Makefile index 38404ab..d9c6645 100644 --- a/src/Makefile +++ b/src/Makefile @@ -46,7 +46,9 @@ C_SOURCES=foundation_pEp_jniadapter_Engine.cc \ foundation_pEp_jniadapter_Message.h \ throw_pEp_exception.cc \ throw_pEp_exception.hh \ - foundation_pEp_jniadapter_AbstractEngine.h + foundation_pEp_jniadapter_AbstractEngine.h \ + foundation_pEp_jniadapter__Blob.cc \ + foundation_pEp_jniadapter__Blob.h PEP_HEADER:=$(shell $(CXX) $(CXXFLAGS) -E -M get_header.cc | grep -oe '[^[:space:]]*pEpEngine\.h' | head -1) @@ -58,7 +60,7 @@ $(JAR): status_list.yml2 $(JAVA_SOURCES) $(C_SOURCES) $(JP)/javac foundation/pEp/jniadapter/*.java $(JP)/jar cf $@ foundation/pEp/jniadapter/*.class -BLUBB=foundation_pEp_jniadapter_AbstractEngine.h foundation_pEp_jniadapter_Engine.h foundation_pEp_jniadapter_Message.h +BLUBB=foundation_pEp_jniadapter_AbstractEngine.h foundation_pEp_jniadapter_Engine.h foundation_pEp_jniadapter_Message.h foundation_pEp_jniadapter__Blob.h $(BLUBB): foundation_pEp_jniadapter_%.h: foundation/pEp/jniadapter/%.java ifdef OLD_JAVA $(JP)/javah $(subst /,.,$(subst .java,,$<)) @@ -69,10 +71,10 @@ endif foundation_pEp_jniadapter_AbstractEngine.o: %.o: %.cc %.h throw_pEp_exception.hh jniutils.hh $(CXX) $(CXXFLAGS) -c $< -o $@ -foundation_pEp_jniadapter_Engine.o foundation_pEp_jniadapter_Message.o: %.o: %.cc %.h +foundation_pEp_jniadapter_Engine.o foundation_pEp_jniadapter_Message.o foundation_pEp_jniadapter__Blob.o : %.o: %.cc %.h $(CXX) $(CXXFLAGS) -c $< -o $@ -$(LIBRARY): foundation_pEp_jniadapter_AbstractEngine.o foundation_pEp_jniadapter_Engine.o foundation_pEp_jniadapter_Message.o throw_pEp_exception.o jniutils.o basic_api.o +$(LIBRARY): foundation_pEp_jniadapter_AbstractEngine.o foundation_pEp_jniadapter_Engine.o foundation_pEp_jniadapter_Message.o throw_pEp_exception.o jniutils.o basic_api.o foundation_pEp_jniadapter__Blob.o ar -r $@ *.o $(SHARED): $(LIBRARY) diff --git a/src/foundation/pEp/jniadapter/Blob.java b/src/foundation/pEp/jniadapter/Blob.java index cd4d962..c38cda3 100644 --- a/src/foundation/pEp/jniadapter/Blob.java +++ b/src/foundation/pEp/jniadapter/Blob.java @@ -9,6 +9,22 @@ public class Blob { mime_type = "application/octet-stream"; } + /** Human readable string representation of Blob. + * The data field is ASN.1 XER decoded for mime_types: + * "application/pEp.sync" + * "application/pEp.keyreset" + * @return String Blob as String + */ + public String toString() { + _Blob _b = new _Blob(this); + String ret = ""; + ret += "mime_type: \"" + mime_type + "\"\n"; + ret += "filename: \"" + filename + "\"\n"; + ret += "data plain: \"" + AbstractEngine.toUTF16(data) + "\"\n"; + ret += "data decoded: \"" + _b.dataToXER() + "\"\n"; + return ret; + } + Blob(_Blob b) { data = b.data; mime_type = AbstractEngine.toUTF16(b.mime_type); diff --git a/src/foundation/pEp/jniadapter/_Blob.java b/src/foundation/pEp/jniadapter/_Blob.java index 406d032..4a78ea9 100644 --- a/src/foundation/pEp/jniadapter/_Blob.java +++ b/src/foundation/pEp/jniadapter/_Blob.java @@ -7,6 +7,11 @@ public class _Blob { _Blob() { } + private native byte[] _dataToXER() throws pEpException;; + public String dataToXER() { + return AbstractEngine.toUTF16(_dataToXER()); + } + _Blob(Blob b) { data = b.data; mime_type = AbstractEngine.toUTF8(b.mime_type); diff --git a/src/foundation_pEp_jniadapter__Blob.cc b/src/foundation_pEp_jniadapter__Blob.cc new file mode 100644 index 0000000..ea719bd --- /dev/null +++ b/src/foundation_pEp_jniadapter__Blob.cc @@ -0,0 +1,61 @@ +#include +#include +#include +#include + +#include "jniutils.hh" +#include "throw_pEp_exception.hh" +#include "foundation_pEp_jniadapter__Blob.h" + +namespace pEp { + namespace JNIAdapter { + static ::bloblist_t *bloblist_ptr(JNIEnv *env, jobject me) { + jfieldID handle; + + try { + handle = getFieldID(env, "foundation/pEp/jniadapter/Blob", "mime_type", "Ljava/lang/String"); + } + catch (std::exception& ex) { + assert(0); + return NULL; + } + + return (::bloblist_t *) (intptr_t) (int64_t) env->GetLongField(me, handle); + } + }; +}; + +extern "C" { + +using namespace std; +using namespace pEp::JNIAdapter; +JNIEXPORT jbyteArray JNICALL Java_foundation_pEp_jniadapter__1Blob__1dataToXER + (JNIEnv *env, jobject obj) +{ + bloblist_t *b = to_blob(env, obj); + char *out = nullptr; + + if(strcasecmp(b->mime_type, "application/pEp.sync") == 0) { + PEP_STATUS status = ::PER_to_XER_Sync_msg(b->value, (size_t) b->size, &out); + if (status) + throw_pEp_Exception(env, status); + + jbyteArray result = from_string(env, out); + free(out); + return result; + } + + if(strcasecmp(b->mime_type, "application/pEp.keyreset") == 0) { + PEP_STATUS status = ::PER_to_XER_Distribution_msg(b->value, (size_t) b->size, &out); + if (status) + throw_pEp_Exception(env, status); + + jbyteArray result = from_string(env, out); + free(out); + return result; + } + + return from_string(env,b->value); +} + +}; // extern "C" diff --git a/src/jniutils.cc b/src/jniutils.cc index f7a4e10..f2d67ed 100644 --- a/src/jniutils.cc +++ b/src/jniutils.cc @@ -1,5 +1,4 @@ #include "jniutils.hh" - #include #include #include @@ -644,6 +643,32 @@ namespace pEp { return obj; } + bloblist_t *to_blob(JNIEnv *env, jobject obj) + { + if (!obj) + return NULL; + + static const char *classname = "foundation/pEp/jniadapter/_Blob"; + jclass clazz = findClass(env, classname); + + char *mime_type = _getStringField(env, classname, obj, "mime_type"); + char *filename = _getStringField(env, classname, obj, "filename"); + + jfieldID data_id = getFieldID(env, classname, "data", "[B"); + jbyteArray _data = reinterpret_cast(env->GetObjectField(obj, data_id)); + size_t size = (size_t) env->GetArrayLength(_data); + char *b = (char *) malloc(size); + assert(b); + + env->GetByteArrayRegion(_data, 0, size, (jbyte*)b); + bloblist_t *bl = new_bloblist( b, size, mime_type, filename); + + free(mime_type); + free(filename); + return bl; + } + + bloblist_t *to_bloblist(JNIEnv *env, jobject obj) { if (!obj) @@ -653,35 +678,15 @@ namespace pEp { if (size == 0) return NULL; - static const char *classname = "foundation/pEp/jniadapter/_Blob"; - jclass clazz = findClass(env, classname); - jfieldID data_id = getFieldID(env, classname, "data", "[B"); - bloblist_t *bl = new_bloblist(NULL, 0, NULL, NULL); bloblist_t *_bl; + _bl = bl; jint i; - for (_bl = bl, i = 0; i < (int) size; i++) { + for (i = 0; i < (int) size; i++) { jobject o = callObjectMethod(env, obj, "get", i); - char *mime_type = _getStringField(env, classname, o, - "mime_type"); - char *filename = _getStringField(env, classname, o, - "filename"); - - jbyteArray _data = - reinterpret_cast(env->GetObjectField(o, - data_id)); - - size_t size = (size_t) env->GetArrayLength(_data); - char *b = (char *) malloc(size); - assert(b); - - env->GetByteArrayRegion(_data, 0, size, (jbyte*)b); - - _bl = bloblist_add(_bl, b, size, mime_type, filename); - + bloblist_t *b = to_blob(env, o); + _bl = bloblist_add(_bl, b->value, b->size, b->mime_type, b->filename); env->DeleteLocalRef(o); - free(mime_type); - free(filename); } return bl; diff --git a/src/jniutils.hh b/src/jniutils.hh index 7fb2b04..88597de 100644 --- a/src/jniutils.hh +++ b/src/jniutils.hh @@ -88,6 +88,7 @@ namespace pEp { identity_list *to_identitylist(JNIEnv *env, jobject obj); jobject from_bloblist(JNIEnv *env, bloblist_t *bl); + bloblist_t *to_blob(JNIEnv *env, jobject obj); bloblist_t *to_bloblist(JNIEnv *env, jobject obj); PEP_enc_format to_EncFormat(JNIEnv *env, jobject obj); diff --git a/test/Basic/SyncCallbacks.java b/test/Basic/SyncCallbacks.java index 3436291..0e92350 100644 --- a/test/Basic/SyncCallbacks.java +++ b/test/Basic/SyncCallbacks.java @@ -3,22 +3,23 @@ import foundation.pEp.jniadapter.*; class SyncCallbacks implements Sync.MessageToSendCallback, Sync.NotifyHandshakeCallback { public void messageToSend(Message message) { - System.out.println("================================"); - System.out.println("Message to send called"); + System.out.println("================================"); + System.out.println("Message to send called"); System.out.println("From: " + message.getFrom()); System.out.println("To: " + message.getTo()); System.out.println("Subject: " + message.getShortmsg()); - System.out.println("================================"); + System.out.println("Attachement[0]: " + message.getAttachments().get(0).toString()); + System.out.println("================================"); } public void notifyHandshake(Identity myself, Identity partner, SyncHandshakeSignal signal) { - System.out.println("================================"); - System.out.println("Notify handshake called"); - System.out.println("Myself: " + myself); - System.out.println("Partner: " + partner); - System.out.println("Signal: " + signal); - System.out.println("================================"); + System.out.println("================================"); + System.out.println("Notify handshake called"); + System.out.println("Myself: " + myself); + System.out.println("Partner: " + partner); + System.out.println("Signal: " + signal); + System.out.println("================================"); } } diff --git a/test/Basic/Testing.java b/test/Basic/Testing.java index 317eabf..8ba8abf 100644 --- a/test/Basic/Testing.java +++ b/test/Basic/Testing.java @@ -17,7 +17,7 @@ class Testing { URL[] urls = ((URLClassLoader)cl).getURLs(); for(URL url: urls){ - System.out.println(url.getFile()); + System.out.println(url.getFile()); } } @@ -83,6 +83,24 @@ class Testing { msg.setLongmsg("this is a test"); msg.setDir(Message.Direction.Outgoing); + // Test setAttachements() with nrAttachemnts + int nrAttachemnts = 3; + { + System.out.print("Adding " + String.valueOf(nrAttachemnts) + " attachements ["); + Vector attachments = new Vector<>(); + + for (int i = 0; i < nrAttachemnts; i++) { + Blob blb = new Blob(); + String dataString = "Attachement nr: " + String.valueOf(i) + " [TEST DATA]"; + blb.data = dataString.getBytes(); + blb.filename = "testfilename.txt"; + attachments.add(blb); + System.out.print("."); + } + msg.setAttachments(attachments); + System.out.println("]"); + } + Message enc = null; try { enc = e.encrypt_message(msg, null, Message.EncFormat.PEP); @@ -94,11 +112,7 @@ class Testing { } System.out.println(enc.getLongmsg()); - Vector attachments = enc.getAttachments(); - // Print msg.txt (encrypted body) contents. - System.out.println(e.toUTF16(attachments.get(1).data)); - msg.setDir(Message.Direction.Outgoing); try { System.out.println("Rating preview: " + e.outgoing_message_rating_preview(msg)); System.out.println("Rating" + e.outgoing_message_rating(msg)); @@ -117,8 +131,24 @@ class Testing { ex.printStackTrace(); } + System.out.println(result.dst.getShortmsg()); System.out.println(result.dst.getLongmsg()); + + // Test getAttachments() + { + Vector attachments = result.dst.getAttachments(); + + System.out.println("get attachement data"); + System.out.println("Attachement count: " + String.valueOf(attachments.size())); + for( Blob a: attachments) { + System.out.println("Attachement nr: " + String.valueOf(attachments.indexOf(a))); + System.out.println("["); + System.out.println(a.toString()); + System.out.println("]"); + } + } + System.out.println("TEST DONE - FINISHED"); try { @@ -126,7 +156,7 @@ class Testing { } catch (pEpException ex) { System.out.println("cannot reset all own keys"); - ex.printStackTrace(); + ex.printStackTrace(); } System.out.println("Testing.java: e.StartSync()");