static jint android_nfc_NdefRecord_parseNdefRecord(JNIEnv *e, jobject o, jbyteArray array) { uint16_t status; jbyte *raw_record; jsize raw_record_size; jint ret = -1; phFriNfc_NdefRecord_t record; jfieldID mType, mId, mPayload, mTnf, mFlags; jbyteArray type = NULL; jbyteArray id = NULL; jbyteArray payload = NULL; jclass record_cls = e->GetObjectClass(o); raw_record_size = e->GetArrayLength(array); raw_record = e->GetByteArrayElements(array, NULL); if (raw_record == NULL) { goto clean_and_return; } TRACE("phFriNfc_NdefRecord_Parse()"); status = phFriNfc_NdefRecord_Parse(&record, (uint8_t *)raw_record); if (status) { LOGE("phFriNfc_NdefRecord_Parse() returned 0x%04x, failing", status); goto clean_and_return; } TRACE("phFriNfc_NdefRecord_Parse() returned 0x%04x, continuing", status); /* Set TNF field */ mTnf = e->GetFieldID(record_cls, "mTnf", "S"); e->SetShortField(o, mTnf, record.Tnf); /* Set type field */ mType = e->GetFieldID(record_cls, "mType", "[B"); type = e->NewByteArray(record.TypeLength); if (type == NULL) { goto clean_and_return; } e->SetByteArrayRegion(type, 0, record.TypeLength, (jbyte *)record.Type); e->SetObjectField(o, mType, type); /* Set id field */ mId = e->GetFieldID(record_cls, "mId", "[B"); id = e->NewByteArray(record.IdLength); if (id == NULL) { goto clean_and_return; } e->SetByteArrayRegion(id, 0, record.IdLength, (jbyte *)record.Id); e->SetObjectField(o, mId, id); /* Set payload field */ mPayload = e->GetFieldID(record_cls, "mPayload", "[B"); payload = e->NewByteArray(record.PayloadLength); if (payload == NULL) { goto clean_and_return; } e->SetByteArrayRegion(payload, 0, record.PayloadLength, (jbyte *)record.PayloadData); e->SetObjectField(o, mPayload, payload); /* Set flags field */ mFlags = e->GetFieldID(record_cls, "mFlags", "B"); e->SetByteField(o, mFlags, record.Flags); ret = 0; clean_and_return: if (type != NULL) { e->DeleteLocalRef(type); } if (id != NULL) { e->DeleteLocalRef(id); } if (payload != NULL) { e->DeleteLocalRef(payload); } if (raw_record != NULL) { e->ReleaseByteArrayElements(array, raw_record, JNI_ABORT); } return ret; }
static jint android_nfc_NdefMessage_parseNdefMessage(JNIEnv *e, jobject o, jbyteArray array) { uint16_t status; uint32_t i; jbyte *raw_msg; jsize raw_msg_size; uint32_t num_of_records = 0; uint8_t **records = NULL; uint8_t *is_chunked = NULL; jint ret = -1; phFriNfc_NdefRecord_t record; jclass record_cls; jobjectArray records_array; jmethodID ctor; jclass msg_cls; jfieldID mrecords; raw_msg_size = e->GetArrayLength(array); raw_msg = e->GetByteArrayElements(array, NULL); if (raw_msg == NULL) return -1; /* Get the number of records in the message so we can allocate buffers */ TRACE("phFriNfc_NdefRecord_GetRecords(NULL)"); status = phFriNfc_NdefRecord_GetRecords((uint8_t *)raw_msg, (uint32_t)raw_msg_size, NULL, NULL, &num_of_records); if (status) { LOGE("phFriNfc_NdefRecord_GetRecords(NULL) returned 0x%04x", status); goto end; } TRACE("phFriNfc_NdefRecord_GetRecords(NULL) returned 0x%04x, with %d records", status, num_of_records); is_chunked = (uint8_t*)malloc(num_of_records); if (is_chunked == NULL) goto end; records = (uint8_t**)malloc(num_of_records * sizeof(uint8_t *)); if (records == NULL) goto end; /* Now, actually retrieve records position in message */ TRACE("phFriNfc_NdefRecord_GetRecords()"); status = phFriNfc_NdefRecord_GetRecords((uint8_t *)raw_msg, (uint32_t)raw_msg_size, records, is_chunked, &num_of_records); if (status) { LOGE("phFriNfc_NdefRecord_GetRecords() returned 0x%04x", status); goto end; } TRACE("phFriNfc_NdefRecord_GetRecords() returned 0x%04x, with %d records", status, num_of_records); /* Build NDEF records array */ record_cls = e->FindClass("android/nfc/NdefRecord"); records_array = e->NewObjectArray((jsize)num_of_records, record_cls, NULL); if (records_array == NULL) goto end; ctor = e->GetMethodID(record_cls, "<init>", "(S[B[B[B)V"); for (i = 0; i < num_of_records; i++) { jbyteArray type, id, payload; jobject new_record; TRACE("phFriNfc_NdefRecord_Parse()"); status = phFriNfc_NdefRecord_Parse(&record, records[i]); if (status) { LOGE("phFriNfc_NdefRecord_Parse() returned 0x%04x", status); goto end; } TRACE("phFriNfc_NdefRecord_Parse() returned 0x%04x", status); // We don't exactly know what *is* a valid length, but a simple // sanity check is to make sure that the length of the header // plus all fields does not exceed raw_msg_size. The min length // of the header is 3 bytes: TNF, Type Length, Payload Length // (ID length field is optional!) uint64_t indicatedMsgLength = 3 + record.TypeLength + record.IdLength + (uint64_t)record.PayloadLength; if (indicatedMsgLength > (uint64_t)raw_msg_size) { LOGE("phFri_NdefRecord_Parse: invalid length field"); goto end; } type = e->NewByteArray(record.TypeLength); if (type == NULL) { LOGD("NFC_Set Record Type Error\n"); goto end; } id = e->NewByteArray(record.IdLength); if(id == NULL) { LOGD("NFC_Set Record ID Error\n"); goto end; } payload = e->NewByteArray(record.PayloadLength); if(payload == NULL) { LOGD("NFC_Set Record Payload Error\n"); goto end; } e->SetByteArrayRegion(type, 0, record.TypeLength, (jbyte *)record.Type); e->SetByteArrayRegion(id, 0, record.IdLength, (jbyte *)record.Id); e->SetByteArrayRegion(payload, 0, record.PayloadLength, (jbyte *)record.PayloadData); new_record = e->NewObject(record_cls, ctor, (jshort)record.Tnf, type, id, payload); e->SetObjectArrayElement(records_array, i, new_record); /* Try not to clutter the Java stack too much */ e->DeleteLocalRef(new_record); e->DeleteLocalRef(type); e->DeleteLocalRef(id); e->DeleteLocalRef(payload); } /* Store built array in our NDEFMessage instance */ msg_cls = e->GetObjectClass(o); mrecords = e->GetFieldID(msg_cls, "mRecords", "[Landroid/nfc/NdefRecord;"); e->SetObjectField(o, mrecords, (jobject)records_array); ret = 0; end: if(is_chunked) free(is_chunked); if(records) free(records); e->ReleaseByteArrayElements(array, raw_msg, JNI_ABORT); return ret; }