|
Packit |
1fb8d4 |
/**
|
|
Packit |
1fb8d4 |
* FreeRDP: A Remote Desktop Protocol Implementation
|
|
Packit |
1fb8d4 |
* Android Event System
|
|
Packit |
1fb8d4 |
*
|
|
Packit |
1fb8d4 |
* Copyright 2013 Felix Long
|
|
Packit |
1fb8d4 |
* Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
|
|
Packit |
1fb8d4 |
*
|
|
Packit |
1fb8d4 |
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
Packit |
1fb8d4 |
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
Packit |
1fb8d4 |
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
Packit |
1fb8d4 |
*/
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
#include "android_jni_utils.h"
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
#include <locale.h>
|
|
Packit |
1fb8d4 |
#include <freerdp/channels/channels.h>
|
|
Packit |
1fb8d4 |
#include <freerdp/log.h>
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
#include "android_jni_callback.h"
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
#define TAG CLIENT_TAG("android.utils")
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
JavaVM *g_JavaVm;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
JavaVM* getJavaVM()
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
return g_JavaVm;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
JNIEnv* getJNIEnv()
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
JNIEnv* env = NULL;
|
|
Packit |
1fb8d4 |
if ((*g_JavaVm)->GetEnv(g_JavaVm, (void**) &env, JNI_VERSION_1_4) != JNI_OK)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
WLog_FATAL(TAG, "Failed to obtain JNIEnv");
|
|
Packit |
1fb8d4 |
return NULL;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
return env;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
jobject create_string_builder(JNIEnv *env, char* initialStr)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
jclass cls;
|
|
Packit |
1fb8d4 |
jmethodID methodId;
|
|
Packit |
1fb8d4 |
jobject obj;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
// get class
|
|
Packit |
1fb8d4 |
cls = (*env)->FindClass(env, "java/lang/StringBuilder");
|
|
Packit |
1fb8d4 |
if(!cls)
|
|
Packit |
1fb8d4 |
return NULL;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if(initialStr)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
// get method id for constructor
|
|
Packit |
1fb8d4 |
methodId = (*env)->GetMethodID(env, cls, "<init>", "(Ljava/lang/String;)V");
|
|
Packit |
1fb8d4 |
if(!methodId)
|
|
Packit |
1fb8d4 |
return NULL;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
// create string that holds our initial string
|
|
Packit |
1fb8d4 |
jstring jstr = (*env)->NewStringUTF(env, initialStr);
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
// construct new StringBuilder
|
|
Packit |
1fb8d4 |
obj = (*env)->NewObject(env, cls, methodId, jstr);
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
else
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
// get method id for constructor
|
|
Packit |
1fb8d4 |
methodId = (*env)->GetMethodID(env, cls, "<init>", "()V");
|
|
Packit |
1fb8d4 |
if(!methodId)
|
|
Packit |
1fb8d4 |
return NULL;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
// construct new StringBuilder
|
|
Packit |
1fb8d4 |
obj = (*env)->NewObject(env, cls, methodId);
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
return obj;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
char* get_string_from_string_builder(JNIEnv* env, jobject strBuilder)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
jclass cls;
|
|
Packit |
1fb8d4 |
jmethodID methodId;
|
|
Packit |
1fb8d4 |
jstring strObj;
|
|
Packit |
1fb8d4 |
const jbyte* native_str;
|
|
Packit |
1fb8d4 |
char* result;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
// get class
|
|
Packit |
1fb8d4 |
cls = (*env)->FindClass(env, "java/lang/StringBuilder");
|
|
Packit |
1fb8d4 |
if(!cls)
|
|
Packit |
1fb8d4 |
return NULL;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
// get method id for constructor
|
|
Packit |
1fb8d4 |
methodId = (*env)->GetMethodID(env, cls, "toString", "()Ljava/lang/String;");
|
|
Packit |
1fb8d4 |
if(!methodId)
|
|
Packit |
1fb8d4 |
return NULL;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
// get jstring representation of our buffer
|
|
Packit |
1fb8d4 |
strObj = (*env)->CallObjectMethod(env, strBuilder, methodId);
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
// read string
|
|
Packit |
1fb8d4 |
native_str = (*env)->GetStringUTFChars(env, strObj, NULL);
|
|
Packit |
1fb8d4 |
if (!native_str)
|
|
Packit |
1fb8d4 |
return NULL;
|
|
Packit |
1fb8d4 |
result = strdup(native_str);
|
|
Packit |
1fb8d4 |
(*env)->ReleaseStringUTFChars(env, strObj, native_str);
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
return result;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
jstring jniNewStringUTF(JNIEnv* env, const char* in, int len)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
jstring out = NULL;
|
|
Packit |
1fb8d4 |
jchar* unicode = NULL;
|
|
Packit |
1fb8d4 |
jint result_size = 0;
|
|
Packit |
1fb8d4 |
jint i;
|
|
Packit |
1fb8d4 |
unsigned char* utf8 = (unsigned char*)in;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!in)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
return NULL;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
if (len < 0)
|
|
Packit |
1fb8d4 |
len = strlen(in);
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
unicode = (jchar*)malloc(sizeof(jchar) * (len + 1));
|
|
Packit |
1fb8d4 |
if (!unicode)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
return NULL;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
for(i = 0; i < len; i++)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
unsigned char one = utf8[i];
|
|
Packit |
1fb8d4 |
switch(one >> 4)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
case 0x00:
|
|
Packit |
1fb8d4 |
case 0x01:
|
|
Packit |
1fb8d4 |
case 0x02:
|
|
Packit |
1fb8d4 |
case 0x03:
|
|
Packit |
1fb8d4 |
case 0x04:
|
|
Packit |
1fb8d4 |
case 0x05:
|
|
Packit |
1fb8d4 |
case 0x06:
|
|
Packit |
1fb8d4 |
case 0x07:
|
|
Packit |
1fb8d4 |
unicode[result_size++] = one;
|
|
Packit |
1fb8d4 |
break;
|
|
Packit |
1fb8d4 |
case 0x08:
|
|
Packit |
1fb8d4 |
case 0x09:
|
|
Packit |
1fb8d4 |
case 0x0a:
|
|
Packit |
1fb8d4 |
case 0x0b:
|
|
Packit |
1fb8d4 |
//case 0x0f:
|
|
Packit |
1fb8d4 |
/*
|
|
Packit |
1fb8d4 |
* Bit pattern 10xx or 1111, which are illegal start bytes.
|
|
Packit |
1fb8d4 |
* Note: 1111 is valid for normal UTF-8, but not the
|
|
Packit |
1fb8d4 |
* modified UTF-8 used here.
|
|
Packit |
1fb8d4 |
*/
|
|
Packit |
1fb8d4 |
break;
|
|
Packit |
1fb8d4 |
case 0x0f:
|
|
Packit |
1fb8d4 |
case 0x0e:
|
|
Packit |
1fb8d4 |
// Bit pattern 111x, so there are two additional bytes.
|
|
Packit |
1fb8d4 |
if (i < (len - 2))
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
unsigned char two = utf8[i+1];
|
|
Packit |
1fb8d4 |
unsigned char three = utf8[i+2];
|
|
Packit |
1fb8d4 |
if ((two & 0xc0) == 0x80 && (three & 0xc0) == 0x80)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
i += 2;
|
|
Packit |
1fb8d4 |
unicode[result_size++] =
|
|
Packit |
1fb8d4 |
((one & 0x0f) << 12)
|
|
Packit |
1fb8d4 |
| ((two & 0x3f) << 6)
|
|
Packit |
1fb8d4 |
| (three & 0x3f);
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
break;
|
|
Packit |
1fb8d4 |
case 0x0c:
|
|
Packit |
1fb8d4 |
case 0x0d:
|
|
Packit |
1fb8d4 |
// Bit pattern 110x, so there is one additional byte.
|
|
Packit |
1fb8d4 |
if (i < (len - 1))
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
unsigned char two = utf8[i+1];
|
|
Packit |
1fb8d4 |
if ((two & 0xc0) == 0x80)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
i += 1;
|
|
Packit |
1fb8d4 |
unicode[result_size++] =
|
|
Packit |
1fb8d4 |
((one & 0x1f) << 6)
|
|
Packit |
1fb8d4 |
| (two & 0x3f);
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
break;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
out = (*env)->NewString(env, unicode, result_size);
|
|
Packit |
1fb8d4 |
free(unicode);
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
return out;
|
|
Packit |
1fb8d4 |
}
|