Blame client/Android/android_jni_utils.c

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
}