summaryrefslogtreecommitdiffstats
path: root/media/libdrm/mobile1
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2008-10-21 07:00:00 -0700
committerThe Android Open Source Project <initial-contribution@android.com>2008-10-21 07:00:00 -0700
commit54b6cfa9a9e5b861a9930af873580d6dc20f773c (patch)
tree35051494d2af230dce54d6b31c6af8fc24091316 /media/libdrm/mobile1
downloadframeworks_base-54b6cfa9a9e5b861a9930af873580d6dc20f773c.zip
frameworks_base-54b6cfa9a9e5b861a9930af873580d6dc20f773c.tar.gz
frameworks_base-54b6cfa9a9e5b861a9930af873580d6dc20f773c.tar.bz2
Initial Contribution
Diffstat (limited to 'media/libdrm/mobile1')
-rw-r--r--media/libdrm/mobile1/Android.mk81
-rw-r--r--media/libdrm/mobile1/include/drm_common_types.h45
-rw-r--r--media/libdrm/mobile1/include/jni/drm1_jni.h242
-rw-r--r--media/libdrm/mobile1/include/objmng/drm_decoder.h55
-rw-r--r--media/libdrm/mobile1/include/objmng/drm_file.h296
-rw-r--r--media/libdrm/mobile1/include/objmng/drm_i18n.h107
-rw-r--r--media/libdrm/mobile1/include/objmng/drm_inner.h90
-rw-r--r--media/libdrm/mobile1/include/objmng/drm_rights_manager.h183
-rw-r--r--media/libdrm/mobile1/include/objmng/drm_time.h77
-rw-r--r--media/libdrm/mobile1/include/objmng/svc_drm.h376
-rw-r--r--media/libdrm/mobile1/include/parser/parser_dcf.h91
-rw-r--r--media/libdrm/mobile1/include/parser/parser_dm.h101
-rw-r--r--media/libdrm/mobile1/include/parser/parser_rel.h123
-rw-r--r--media/libdrm/mobile1/include/xml/wbxml_tinyparser.h52
-rw-r--r--media/libdrm/mobile1/include/xml/xml_tinyParser.h171
-rw-r--r--media/libdrm/mobile1/src/jni/drm1_jni.c1175
-rw-r--r--media/libdrm/mobile1/src/objmng/drm_api.c1944
-rw-r--r--media/libdrm/mobile1/src/objmng/drm_decoder.c96
-rw-r--r--media/libdrm/mobile1/src/objmng/drm_file.c694
-rw-r--r--media/libdrm/mobile1/src/objmng/drm_i18n.c444
-rw-r--r--media/libdrm/mobile1/src/objmng/drm_rights_manager.c688
-rw-r--r--media/libdrm/mobile1/src/objmng/drm_time.c52
-rw-r--r--media/libdrm/mobile1/src/parser/parser_dcf.c125
-rw-r--r--media/libdrm/mobile1/src/parser/parser_dm.c271
-rw-r--r--media/libdrm/mobile1/src/parser/parser_rel.c663
-rw-r--r--media/libdrm/mobile1/src/xml/xml_tinyparser.c834
26 files changed, 9076 insertions, 0 deletions
diff --git a/media/libdrm/mobile1/Android.mk b/media/libdrm/mobile1/Android.mk
new file mode 100644
index 0000000..2065cd2
--- /dev/null
+++ b/media/libdrm/mobile1/Android.mk
@@ -0,0 +1,81 @@
+LOCAL_PATH := $(call my-dir)
+
+# ---------------------------------------
+# First project
+#
+# Build DRM1 core library
+#
+# Output: libdrm1.so
+# ---------------------------------------
+include $(CLEAR_VARS)
+
+ifeq ($(TARGET_ARCH), arm)
+LOCAL_DRM_CFLAG = -DDRM_DEVICE_ARCH_ARM
+endif
+
+ifeq ($(TARGET_ARCH), x86)
+LOCAL_DRM_CFLAG = -DDRM_DEVICE_ARCH_X86
+endif
+
+# DRM 1.0 core source files
+LOCAL_SRC_FILES := \
+ src/objmng/drm_decoder.c \
+ src/objmng/drm_file.c \
+ src/objmng/drm_i18n.c \
+ src/objmng/drm_time.c \
+ src/objmng/drm_api.c \
+ src/objmng/drm_rights_manager.c \
+ src/parser/parser_dcf.c \
+ src/parser/parser_dm.c \
+ src/parser/parser_rel.c \
+ src/xml/xml_tinyparser.c
+
+# Header files path
+LOCAL_C_INCLUDES := \
+ $(LOCAL_PATH)/include \
+ $(LOCAL_PATH)/include/objmng \
+ $(LOCAL_PATH)/include/parser \
+ $(LOCAL_PATH)/include/xml \
+ external/aes \
+ $(call include-path-for, system-core)/cutils
+
+LOCAL_CFLAGS := $(LOCAL_DRM_CFLAG)
+
+LOCAL_SHARED_LIBRARIES := \
+ libaes \
+ libutils \
+ libcutils
+
+LOCAL_MODULE := libdrm1
+
+include $(BUILD_SHARED_LIBRARY)
+
+# ---------------------------------------
+# Second project
+#
+# Build DRM1 Java Native Interface(JNI) library
+#
+# Output: libdrm1_jni.so
+# ------------------------------------------------
+include $(CLEAR_VARS)
+
+# Source files of DRM1 Java Native Interfaces
+LOCAL_SRC_FILES := \
+ src/jni/drm1_jni.c
+
+# Header files path
+LOCAL_C_INCLUDES := \
+ $(LOCAL_PATH)/include \
+ $(LOCAL_PATH)/include/parser \
+ $(JNI_H_INCLUDE) \
+ $(call include-path-for, system-core)/cutils \
+ external/aes
+
+
+LOCAL_SHARED_LIBRARIES := libdrm1 \
+ libutils \
+ libcutils
+
+LOCAL_MODULE := libdrm1_jni
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libdrm/mobile1/include/drm_common_types.h b/media/libdrm/mobile1/include/drm_common_types.h
new file mode 100644
index 0000000..c6bea61
--- /dev/null
+++ b/media/libdrm/mobile1/include/drm_common_types.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __COMMON_TYPES_H__
+#define __COMMON_TYPES_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <assert.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#define Trace(...)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __COMMON_TYPES_H__ */
diff --git a/media/libdrm/mobile1/include/jni/drm1_jni.h b/media/libdrm/mobile1/include/jni/drm1_jni.h
new file mode 100644
index 0000000..64e78ad
--- /dev/null
+++ b/media/libdrm/mobile1/include/jni/drm1_jni.h
@@ -0,0 +1,242 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __DRM1_JNI_H__
+#define __DRM1_JNI_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class android_drm_mobile1_DrmRawContent */
+
+#undef android_drm_mobile1_DrmRawContent_DRM_FORWARD_LOCK
+#define android_drm_mobile1_DrmRawContent_DRM_FORWARD_LOCK 1L
+#undef android_drm_mobile1_DrmRawContent_DRM_COMBINED_DELIVERY
+#define android_drm_mobile1_DrmRawContent_DRM_COMBINED_DELIVERY 2L
+#undef android_drm_mobile1_DrmRawContent_DRM_SEPARATE_DELIVERY
+#define android_drm_mobile1_DrmRawContent_DRM_SEPARATE_DELIVERY 3L
+#undef android_drm_mobile1_DrmRawContent_DRM_SEPARATE_DELIVERY_DM
+#define android_drm_mobile1_DrmRawContent_DRM_SEPARATE_DELIVERY_DM 4L
+#undef android_drm_mobile1_DrmRawContent_DRM_MIMETYPE_MESSAGE
+#define android_drm_mobile1_DrmRawContent_DRM_MIMETYPE_MESSAGE 1L
+#undef android_drm_mobile1_DrmRawContent_DRM_MIMETYPE_CONTENT
+#define android_drm_mobile1_DrmRawContent_DRM_MIMETYPE_CONTENT 2L
+#undef android_drm_mobile1_DrmRawContent_JNI_DRM_SUCCESS
+#define android_drm_mobile1_DrmRawContent_JNI_DRM_SUCCESS 0L
+#undef android_drm_mobile1_DrmRawContent_JNI_DRM_FAILURE
+#define android_drm_mobile1_DrmRawContent_JNI_DRM_FAILURE -1L
+#undef android_drm_mobile1_DrmRawContent_JNI_DRM_EOF
+#define android_drm_mobile1_DrmRawContent_JNI_DRM_EOF -2L
+#undef android_drm_mobile1_DrmRawContent_JNI_DRM_UNKNOWN_DATA_LEN
+#define android_drm_mobile1_DrmRawContent_JNI_DRM_UNKNOWN_DATA_LEN -3L
+/*
+ * Class: android_drm_mobile1_DrmRawContent
+ * Method: nativeConstructDrmContent
+ * Signature: (Ljava/io/InputStream;II)I
+ */
+JNIEXPORT jint JNICALL Java_android_drm_mobile1_DrmRawContent_nativeConstructDrmContent
+ (JNIEnv *, jobject, jobject, jint, jint);
+
+/*
+ * Class: android_drm_mobile1_DrmRawContent
+ * Method: nativeGetRightsAddress
+ * Signature: ()Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_android_drm_mobile1_DrmRawContent_nativeGetRightsAddress
+ (JNIEnv *, jobject);
+
+/*
+ * Class: android_drm_mobile1_DrmRawContent
+ * Method: nativeGetDeliveryMethod
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_android_drm_mobile1_DrmRawContent_nativeGetDeliveryMethod
+ (JNIEnv *, jobject);
+
+/*
+ * Class: android_drm_mobile1_DrmRawContent
+ * Method: nativeReadPieceOfContent
+ * Signature: ([BIII)I
+ */
+JNIEXPORT jint JNICALL Java_android_drm_mobile1_DrmRawContent_nativeReadContent
+ (JNIEnv *, jobject, jbyteArray, jint, jint, jint);
+
+/*
+ * Class: android_drm_mobile1_DrmRawContent
+ * Method: nativeGetContentType
+ * Signature: ()Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_android_drm_mobile1_DrmRawContent_nativeGetContentType
+ (JNIEnv *, jobject);
+
+/*
+ * Class: android_drm_mobile1_DrmRawContent
+ * Method: nativeGetContentLength
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_android_drm_mobile1_DrmRawContent_nativeGetContentLength
+ (JNIEnv *, jobject);
+
+/*
+ * Class: android_drm_mobile1_DrmRawContent
+ * Method: finalize
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_android_drm_mobile1_DrmRawContent_finalize
+ (JNIEnv *, jobject);
+
+/* Header for class android_drm_mobile1_DrmRights */
+
+#undef android_drm_mobile1_DrmRights_DRM_PERMISSION_PLAY
+#define android_drm_mobile1_DrmRights_DRM_PERMISSION_PLAY 1L
+#undef android_drm_mobile1_DrmRights_DRM_PERMISSION_DISPLAY
+#define android_drm_mobile1_DrmRights_DRM_PERMISSION_DISPLAY 2L
+#undef android_drm_mobile1_DrmRights_DRM_PERMISSION_EXECUTE
+#define android_drm_mobile1_DrmRights_DRM_PERMISSION_EXECUTE 3L
+#undef android_drm_mobile1_DrmRights_DRM_PERMISSION_PRINT
+#define android_drm_mobile1_DrmRights_DRM_PERMISSION_PRINT 4L
+#undef android_drm_mobile1_DrmRights_DRM_CONSUME_RIGHTS_SUCCESS
+#define android_drm_mobile1_DrmRights_DRM_CONSUME_RIGHTS_SUCCESS 0L
+#undef android_drm_mobile1_DrmRights_DRM_CONSUME_RIGHTS_FAILURE
+#define android_drm_mobile1_DrmRights_DRM_CONSUME_RIGHTS_FAILURE -1L
+#undef android_drm_mobile1_DrmRights_JNI_DRM_SUCCESS
+#define android_drm_mobile1_DrmRights_JNI_DRM_SUCCESS 0L
+#undef android_drm_mobile1_DrmRights_JNI_DRM_FAILURE
+#define android_drm_mobile1_DrmRights_JNI_DRM_FAILURE -1L
+/*
+ * Class: android_drm_mobile1_DrmRights
+ * Method: nativeGetConstraintInfo
+ * Signature: (ILandroid/drm/mobile1/DrmConstraintInfo;)I
+ */
+JNIEXPORT jint JNICALL Java_android_drm_mobile1_DrmRights_nativeGetConstraintInfo
+ (JNIEnv *, jobject, jint, jobject);
+
+/*
+ * Class: android_drm_mobile1_DrmRights
+ * Method: nativeConsumeRights
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL Java_android_drm_mobile1_DrmRights_nativeConsumeRights
+ (JNIEnv *, jobject, jint);
+
+/* Header for class android_drm_mobile1_DrmRightsManager */
+
+#undef android_drm_mobile1_DrmRightsManager_DRM_MIMETYPE_RIGHTS_XML
+#define android_drm_mobile1_DrmRightsManager_DRM_MIMETYPE_RIGHTS_XML 3L
+#undef android_drm_mobile1_DrmRightsManager_DRM_MIMETYPE_RIGHTS_WBXML
+#define android_drm_mobile1_DrmRightsManager_DRM_MIMETYPE_RIGHTS_WBXML 4L
+#undef android_drm_mobile1_DrmRightsManager_DRM_MIMETYPE_MESSAGE
+#define android_drm_mobile1_DrmRightsManager_DRM_MIMETYPE_MESSAGE 1L
+#undef android_drm_mobile1_DrmRightsManager_JNI_DRM_SUCCESS
+#define android_drm_mobile1_DrmRightsManager_JNI_DRM_SUCCESS 0L
+#undef android_drm_mobile1_DrmRightsManager_JNI_DRM_FAILURE
+#define android_drm_mobile1_DrmRightsManager_JNI_DRM_FAILURE -1L
+/* Inaccessible static: singleton */
+/*
+ * Class: android_drm_mobile1_DrmRightsManager
+ * Method: nativeInstallDrmRights
+ * Signature: (Ljava/io/InputStream;IILandroid/drm/mobile1/DrmRights;)I
+ */
+JNIEXPORT jint JNICALL Java_android_drm_mobile1_DrmRightsManager_nativeInstallDrmRights
+ (JNIEnv *, jobject, jobject, jint, jint, jobject);
+
+/*
+ * Class: android_drm_mobile1_DrmRightsManager
+ * Method: nativeQueryRights
+ * Signature: (Landroid/drm/mobile1/DrmRawContent;Landroid/drm/mobile1/DrmRights;)I
+ */
+JNIEXPORT jint JNICALL Java_android_drm_mobile1_DrmRightsManager_nativeQueryRights
+ (JNIEnv *, jobject, jobject, jobject);
+
+/*
+ * Class: android_drm_mobile1_DrmRightsManager
+ * Method: nativeGetRightsNumber
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_android_drm_mobile1_DrmRightsManager_nativeGetNumOfRights
+ (JNIEnv *, jobject);
+
+/*
+ * Class: android_drm_mobile1_DrmRightsManager
+ * Method: nativeGetRightsList
+ * Signature: ([Landroid/drm/mobile1/DrmRights;I)I
+ */
+JNIEXPORT jint JNICALL Java_android_drm_mobile1_DrmRightsManager_nativeGetRightsList
+ (JNIEnv *, jobject, jobjectArray, jint);
+
+/*
+ * Class: android_drm_mobile1_DrmRightsManager
+ * Method: nativeDeleteRights
+ * Signature: (Landroid/drm/mobile1/DrmRights;)I
+ */
+JNIEXPORT jint JNICALL Java_android_drm_mobile1_DrmRightsManager_nativeDeleteRights
+ (JNIEnv *, jobject, jobject);
+
+/**
+ * DRM return value defines
+ */
+#define JNI_DRM_SUCCESS \
+ android_drm_mobile1_DrmRawContent_JNI_DRM_SUCCESS /**< Successful operation */
+#define JNI_DRM_FAILURE \
+ android_drm_mobile1_DrmRawContent_JNI_DRM_FAILURE /**< General failure */
+#define JNI_DRM_EOF \
+ android_drm_mobile1_DrmRawContent_JNI_DRM_EOF /**< Indicates the end of the DRM content is reached */
+#define JNI_DRM_UNKNOWN_DATA_LEN \
+ android_drm_mobile1_DrmRawContent_JNI_DRM_UNKNOWN_DATA_LEN /**< Indicates the data length is unknown */
+
+/**
+ * DRM MIME type defines
+ */
+#define JNI_DRM_MIMETYPE_MESSAGE \
+ android_drm_mobile1_DrmRawContent_DRM_MIMETYPE_MESSAGE /**< The "application/vnd.oma.drm.message" MIME type */
+#define JNI_DRM_MIMETYPE_CONTENT \
+ android_drm_mobile1_DrmRawContent_DRM_MIMETYPE_CONTENT /**< The "application/vnd.oma.drm.content" MIME type */
+#define JNI_DRM_MIMETYPE_RIGHTS_XML \
+ android_drm_mobile1_DrmRightsManager_DRM_MIMETYPE_RIGHTS_XML /**< The "application/vnd.oma.drm.rights+xml" MIME type */
+#define JNI_DRM_MIMETYPE_RIGHTS_WBXML \
+ android_drm_mobile1_DrmRightsManager_DRM_MIMETYPE_RIGHTS_WBXML /**< The "application/vnd.oma.drm.rights+wbxml" MIME type */
+
+/**
+ * DRM permission defines
+ */
+#define JNI_DRM_PERMISSION_PLAY \
+ android_drm_mobile1_DrmRights_DRM_PERMISSION_PLAY /**< The permission to play */
+#define JNI_DRM_PERMISSION_DISPLAY \
+ android_drm_mobile1_DrmRights_DRM_PERMISSION_DISPLAY /**< The permission to display */
+#define JNI_DRM_PERMISSION_EXECUTE \
+ android_drm_mobile1_DrmRights_DRM_PERMISSION_EXECUTE /**< The permission to execute */
+#define JNI_DRM_PERMISSION_PRINT \
+ android_drm_mobile1_DrmRights_DRM_PERMISSION_PRINT /**< The permission to print */
+
+/**
+ * DRM delivery type defines
+ */
+#define JNI_DRM_FORWARD_LOCK \
+ android_drm_mobile1_DrmRawContent_DRM_FORWARD_LOCK /**< forward lock */
+#define JNI_DRM_COMBINED_DELIVERY \
+ android_drm_mobile1_DrmRawContent_DRM_COMBINED_DELIVERY /**< combined delivery */
+#define JNI_DRM_SEPARATE_DELIVERY \
+ android_drm_mobile1_DrmRawContent_DRM_SEPARATE_DELIVERY /**< separate delivery */
+#define JNI_DRM_SEPARATE_DELIVERY_DM \
+ android_drm_mobile1_DrmRawContent_DRM_SEPARATE_DELIVERY_DM /**< separate delivery DRM message */
+#ifdef __cplusplus
+}
+#endif
+#endif /* __DRM1_JNI_H__ */
+
diff --git a/media/libdrm/mobile1/include/objmng/drm_decoder.h b/media/libdrm/mobile1/include/objmng/drm_decoder.h
new file mode 100644
index 0000000..a769c81
--- /dev/null
+++ b/media/libdrm/mobile1/include/objmng/drm_decoder.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file drm_decoder.h
+ *
+ * provide service to decode base64 data.
+ *
+ * <!-- #interface list begin -->
+ * \section drm decoder interface
+ * - drm_decodeBase64()
+ * <!-- #interface list end -->
+ */
+
+#ifndef __DRM_DECODER_H__
+#define __DRM_DECODER_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <drm_common_types.h>
+
+/**
+ * Decode base64
+ * \param dest dest buffer to save decode base64 data
+ * \param destLen dest buffer length
+ * \param src source data to be decoded
+ * \param srcLen source buffer length, and when return, give out how many bytes has been decoded
+ * \return
+ * -when success, return a positive integer of dest buffer length,
+ * if input dest buffer is NULL or destLen is 0,
+ * return dest buffer length that user should allocate to save decoding data
+ * -when failed, return -1
+ */
+int32_t drm_decodeBase64(uint8_t * dest, int32_t destLen, uint8_t * src, int32_t * srcLen);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __DRM_DECODER_H__ */
diff --git a/media/libdrm/mobile1/include/objmng/drm_file.h b/media/libdrm/mobile1/include/objmng/drm_file.h
new file mode 100644
index 0000000..b94ddd0
--- /dev/null
+++ b/media/libdrm/mobile1/include/objmng/drm_file.h
@@ -0,0 +1,296 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+/**
+ * File Porting Layer.
+ */
+#ifndef __DRM_FILE_H__
+#define __DRM_FILE_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <drm_common_types.h>
+
+/** Type value of a regular file or file name. */
+#define DRM_FILE_ISREG 1
+/** Type value of a directory or directory name. */
+#define DRM_FILE_ISDIR 2
+/** Type value of a filter name */
+#define DRM_FILE_ISFILTER 3
+
+
+/** Return code that indicates successful completion of an operation. */
+#define DRM_FILE_SUCCESS 0
+/** Indicates that an operation failed. */
+#define DRM_FILE_FAILURE -1
+/** Indicates that the a DRM_file_read() call reached the end of the file. */
+#define DRM_FILE_EOF -2
+
+
+/** Open for read access. */
+#define DRM_FILE_MODE_READ 1
+/** Open for write access. */
+#define DRM_FILE_MODE_WRITE 2
+
+
+#ifndef MAX_FILENAME_LEN
+/** Maximum number of characters that a filename may have. By default assumes
+ * that the entry results of DRM_file_listNextEntry() are returned in the async state
+ * buffer, after the #DRM_file_result_s, and calculates the maximum name
+ * from that.
+ */
+#define MAX_FILENAME_LEN 1024
+#endif
+
+
+/**
+ * Performs one-time initialization of the File System (FS).
+ * This function is called once during the lifetime of an application,
+ * and before any call to <code>DRM_file_*</code> functions by this application.
+ * When several applications are using the file interface, this function may be called
+ * several times, once per application.
+ *
+ * @return #DRM_FILE_SUCCESS, #DRM_FILE_FAILURE.
+ */
+int32_t DRM_file_startup(void);
+
+/**
+ * Returns the length of a file (by name, opened or unopened).
+ *
+ * @param name Name of the file, UCS-2 encoded.
+ * @param nameChars Number characters encoded in name.
+ * asynchronous operation returns #DRM_FILE_WOULDBLOCK.
+ * @return #DRM_FILE_WOULDBLOCK, #DRM_FILE_FAILURE or the file length.
+ */
+int32_t DRM_file_getFileLength(const uint16_t* name,
+ int32_t nameChars);
+
+/**
+ * Initializes a list iteration session.
+ *
+ * @param prefix Prefix that must be matched, UCS-2 encoded. *
+ * @param prefixChars Number characters encoded in prefix.
+ * @param session List session identifier.
+ * @param iteration List iteration identifier.
+ *
+ * @return #DRM_FILE_WOULDBLOCK, #DRM_FILE_SUCCESS, #DRM_FILE_FAILURE.
+ */
+int32_t DRM_file_listOpen(const uint16_t* prefix,
+ int32_t prefixChars,
+ int32_t* session,
+ int32_t* iteration);
+
+/**
+ * Used to fetch a list of file names that match a given name prefix.
+ *
+ * @param prefix See DRM_file_listOpen(). This does not change during the
+ * iteration session.
+ * @param prefixChars See DRM_file_listOpen(). This does not change during
+ * the iteration session.
+ * @param entry Buffer parameter to return the next file name that matches the
+ * #prefix parameter, if any, when the function returns a positive number of
+ * characters.
+ * @param entryBytes Size of entry in bytes.
+ * @param session See DRM_file_listOpen().
+ * @param iteration See DRM_file_listOpen().
+ * @return #DRM_FILE_WOULDBLOCK, #DRM_FILE_FAILURE or the number of
+ * characters encoded in entry. Returns 0 when the end of the list is reached.
+ */
+int32_t DRM_file_listNextEntry(const uint16_t* prefix,
+ int32_t prefixChars,
+ uint16_t* entry,
+ int32_t entryBytes,
+ int32_t* session,
+ int32_t* iteration);
+
+/**
+ * Ends a list iteration session. Notifies the implementation
+ * that the list session is over and that any session resources
+ * can be released.
+ *
+ * @param session See DRM_file_listOpen().
+ * @param iteration See DRM_file_listOpen().
+ * @return #DRM_FILE_WOULDBLOCK, #DRM_FILE_SUCCESS, #DRM_FILE_FAILURE.
+ */
+int32_t DRM_file_listClose(int32_t session, int32_t iteration);
+
+/**
+ * Renames a file, given its old name. The file or directory is renamed
+ * immediately on the actual file system upon invocation of this method.
+ * Any open handles on the file specified by oldName become invalid after
+ * this method has been called.
+ *
+ * @param oldName Current file name (unopened), UCS-2 encoded.
+ * @param oldNameChars Number of characters encoded on oldName.
+ * @param newName New name for the file (unopened), UCS-2 encoded.
+ * @param newNameChars Number of characters encoded on newName.
+ * @return #DRM_FILE_WOULDBLOCK, #DRM_FILE_SUCCESS, #DRM_FILE_FAILURE. In particular,
+ * #DRM_FILE_FAILURE if a file or directory already exists with the new name.
+ */
+int32_t DRM_file_rename(const uint16_t* oldName,
+ int32_t oldNameChars,
+ const uint16_t* newName,
+ int32_t newNameChars);
+
+/**
+ * Tests if a file exists given its name.
+ *
+ * @param name Name of the file, UCS-2 encoded.
+ * @param nameChars Number of characters encoded in name.
+ * @return #DRM_FILE_WOULDBLOCK, #DRM_FILE_ISREG, #DRM_FILE_ISDIR, #DRM_FILE_FAILURE. If name
+ * exists, returns #DRM_FILE_ISREG if it is a regular file and #DRM_FILE_ISDIR if it is a directory.
+ * Returns #DRM_FILE_FAILURE in all other cases, including those where name exists but is neither
+ * a regular file nor a directory. Platforms that do not support directories MUST NOT return
+ * #DRM_FILE_ISDIR.
+ */
+int32_t DRM_file_exists(const uint16_t* name,
+ int32_t nameChars);
+
+/**
+ * Opens a file with the given name and returns its file handle.
+ *
+ * @param name Name of the file, UCS-2 encoded.
+ * @param nameChars Number of characters encoded in name.
+ * @param mode Any combination of the #DRM_FILE_MODE_READ and
+ * #DRM_FILE_MODE_WRITE flags. If the file does not exist and mode contains the
+ * #DRM_FILE_MODE_WRITE flag, then the file is automatically created. If the
+ * file exists and the mode contains the #DRM_FILE_MODE_WRITE flag, the file is
+ * opened so it can be modified, but the data is not modified by the open call.
+ * In all cases the current position is set to the start of the file.
+ * The following table shows how to map the mode semantics above to UNIX
+ * fopen-style modes. For brevity in the table, R=#DRM_FILE_MODE_READ,
+ * W=#DRM_FILE_MODE_WRITE, E=File exists:
+ * <table>
+ * <tr><td>RW</td><td>E</td><td>Maps-to</td></tr>
+ * <tr><td>00</td><td>0</td><td>Return #DRM_FILE_FAILURE</td></tr>
+ * <tr><td>00</td><td>1</td><td>Return #DRM_FILE_FAILURE</td></tr>
+ * <tr><td>01</td><td>0</td><td>Use fopen mode "w"</td></tr>
+ * <tr><td>01</td><td>1</td><td>Use fopen mode "a" and fseek to the start</td></tr>
+ * <tr><td>10</td><td>0</td><td>Return #DRM_FILE_FAILURE</td></tr>
+ * <tr><td>10</td><td>1</td><td>Use fopen mode "r"</td></tr>
+ * <tr><td>11</td><td>0</td><td>Use fopen mode "w+"</td></tr>
+ * <tr><td>11</td><td>1</td><td>Use fopen mode "r+"</td></tr>
+ * </table>
+ * @param handle Pointer where the result handle value is placed when the function
+ * is called synchronously.
+ * @return #DRM_FILE_WOULDBLOCK, #DRM_FILE_SUCCESS, #DRM_FILE_FAILURE.
+ */
+int32_t DRM_file_open(const uint16_t* name,
+ int32_t nameChars,
+ int32_t mode,
+ int32_t* handle);
+
+/**
+ * Deletes a file given its name, UCS-2 encoded. The file or directory is
+ * deleted immediately on the actual file system upon invocation of this
+ * method. Any open handles on the file specified by name become invalid
+ * after this method has been called.
+ *
+ * If the port needs to ensure that a specific application does not exceed a given storage
+ * space quota, then the bytes freed by the deletion must be added to the available space for
+ * that application.
+ *
+ * @param name Name of the file, UCS-2 encoded.
+ * @param nameChars Number of characters encoded in name.
+ * @return #DRM_FILE_WOULDBLOCK, #DRM_FILE_SUCCESS, #DRM_FILE_FAILURE.
+ */
+int32_t DRM_file_delete(const uint16_t* name,
+ int32_t nameChars);
+
+/**
+ * Read bytes from a file at the current position to a buffer. Afterwards the
+ * new file position is the byte after the last byte read.
+ * DRM_FILE_FAILURE is returned if the handle is invalid (e.g., as a
+ * consquence of DRM_file_delete, DRM_file_rename, or DRM_file_close).
+ *
+ * @param handle File handle as returned by DRM_file_open().
+ * @param dst Buffer where the data is to be copied.
+ * @param length Number of bytes to be copied.
+ * @return #DRM_FILE_WOULDBLOCK, #DRM_FILE_SUCCESS, #DRM_FILE_FAILURE, #DRM_FILE_EOF
+ * or the number of bytes that were read, i.e. in the range 0..length.
+ */
+int32_t DRM_file_read(int32_t handle,
+ uint8_t* dst,
+ int32_t length);
+
+/**
+ * Write bytes from a buffer to the file at the current position. If the
+ * current position + number of bytes written > current size of the file,
+ * then the file is grown. Afterwards the new file position is the byte
+ * after the last byte written.
+ * DRM_FILE_FAILURE is returned if the handle is invalid (e.g., as a
+ * consquence of DRM_file_delete, DRM_file_rename, or DRM_file_close).
+ *
+ * @param handle File handle as returned by DRM_file_open().
+ * @param src Buffer that contains the bytes to be written.
+ * @param length Number of bytes to be written.
+ * If the port needs to ensure that a specific application does not exceed a given storage
+ * space quota, the implementation must make sure the call does not violate that invariant.
+ * @return #DRM_FILE_WOULDBLOCK, #DRM_FILE_FAILURE or the number of bytes
+ * that were written. This number must be in the range 0..length.
+ * Returns #DRM_FILE_FAILURE when storage is full or exceeds quota.
+ */
+int32_t DRM_file_write(int32_t handle,
+ const uint8_t* src,
+ int32_t length);
+
+/**
+ * Closes a file.
+ * DRM_FILE_SUCCESS is returned if the handle is invalid (e.g., as a
+ * consquence of DRM_file_delete or DRM_file_rename).
+ *
+ * @param handle File handle as returned by DRM_file_open().
+ * @return #DRM_FILE_WOULDBLOCK, #DRM_FILE_SUCCESS, #DRM_FILE_FAILURE.
+ */
+int32_t DRM_file_close(int32_t handle);
+
+/**
+ * Sets the current position in an opened file.
+ * DRM_FILE_FAILURE is returned if the handle is invalid (e.g., as a
+ * consquence of DRM_file_delete, DRM_file_rename, or DRM_file_close).
+ *
+ * @param handle File handle as returned by DRM_file_open().
+ * @param value The new current position of the file. If value is greater
+ * than the length of the file then the file should be extended. The contents
+ * of the newly extended portion of the file is undefined.
+ * If the port needs to ensure that a specific application does not exceed a given storage
+ * space quota, the implementation must make sure the call does not violate that invariant.
+ * @return #DRM_FILE_WOULDBLOCK, #DRM_FILE_SUCCESS, #DRM_FILE_FAILURE.
+ * Returns #DRM_FILE_FAILURE when storage is full or exceeds quota.
+ */
+int32_t DRM_file_setPosition(int32_t handle, int32_t value);
+
+/**
+ * Creates a directory with the assigned name and full file permissions on
+ * the file system. The full path to the new directory must already exist.
+ * The directory is created immediately on the actual file system upon
+ * invocation of this method.
+ *
+ * @param name Name of the directory, UCS-2 encoded.
+ * @param nameChars Number of characters encoded in name.
+ * @return #DRM_FILE_WOULDBLOCK, #DRM_FILE_SUCCESS, #DRM_FILE_FAILURE.
+ */
+int32_t DRM_file_mkdir(const uint16_t* name,
+ int32_t nameChars);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __DRM_FILE_H__ */
diff --git a/media/libdrm/mobile1/include/objmng/drm_i18n.h b/media/libdrm/mobile1/include/objmng/drm_i18n.h
new file mode 100644
index 0000000..7487e9b
--- /dev/null
+++ b/media/libdrm/mobile1/include/objmng/drm_i18n.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#ifndef __DRM_I18N_H__
+#define __DRM_I18N_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <drm_common_types.h>
+
+/**
+ * @name Charset value defines
+ * @ingroup i18n
+ *
+ * Charset value defines
+ * see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/intl/unicode_81rn.asp
+ */
+typedef enum {
+ DRM_CHARSET_GBK = 936, /** Simplified Chinese GBK (CP936) */
+ DRM_CHARSET_GB2312 = 20936, /** Simplified Chinese GB2312 (CP936) */
+ DRM_CHARSET_BIG5 = 950, /** BIG5 (CP950) */
+ DRM_CHARSET_LATIN1 = 28591, /** ISO 8859-1, Latin 1 */
+ DRM_CHARSET_LATIN2 = 28592, /** ISO 8859-2, Latin 2 */
+ DRM_CHARSET_LATIN3 = 28593, /** ISO 8859-3, Latin 3 */
+ DRM_CHARSET_LATIN4 = 28594, /** ISO 8859-4, Latin 4 */
+ DRM_CHARSET_CYRILLIC = 28595, /** ISO 8859-5, Cyrillic */
+ DRM_CHARSET_ARABIC = 28596, /** ISO 8859-6, Arabic */
+ DRM_CHARSET_GREEK = 28597, /** ISO 8859-7, Greek */
+ DRM_CHARSET_HEBREW = 28598, /** ISO 8859-8, Hebrew */
+ DRM_CHARSET_LATIN5 = 28599, /** ISO 8859-9, Latin 5 */
+ DRM_CHARSET_LATIN6 = 865, /** ISO 8859-10, Latin 6 (not sure here) */
+ DRM_CHARSET_THAI = 874, /** ISO 8859-11, Thai */
+ DRM_CHARSET_LATIN7 = 1257, /** ISO 8859-13, Latin 7 (not sure here) */
+ DRM_CHARSET_LATIN8 = 38598, /** ISO 8859-14, Latin 8 (not sure here) */
+ DRM_CHARSET_LATIN9 = 28605, /** ISO 8859-15, Latin 9 */
+ DRM_CHARSET_LATIN10 = 28606, /** ISO 8859-16, Latin 10 */
+ DRM_CHARSET_UTF8 = 65001, /** UTF-8 */
+ DRM_CHARSET_UTF16LE = 1200, /** UTF-16 LE */
+ DRM_CHARSET_UTF16BE = 1201, /** UTF-16 BE */
+ DRM_CHARSET_HINDI = 57002, /** Hindi/Mac Devanagari */
+ DRM_CHARSET_UNSUPPORTED = -1
+} DRM_Charset_t;
+
+/**
+ * Convert multibyte string of specified charset to unicode string.
+ * Note NO terminating '\0' will be appended to the output unicode string.
+ *
+ * @param charset Charset of the multibyte string.
+ * @param mbs Multibyte string to be converted.
+ * @param mbsLen Number of the bytes (in mbs) to be converted.
+ * @param wcsBuf Buffer for the converted unicode characters.
+ * If wcsBuf is NULL, the function returns the number of unicode
+ * characters required for the buffer.
+ * @param bufSizeInWideChar The size (in wide char) of wcsBuf
+ * @param bytesConsumed The number of bytes in mbs that have been successfully
+ * converted. The value of *bytesConsumed is undefined
+ * if wcsBuf is NULL.
+ *
+ * @return Number of the successfully converted unicode characters if wcsBuf
+ * is not NULL. If wcsBuf is NULL, returns required unicode buffer
+ * size. -1 for unrecoverable errors.
+ */
+int32_t DRM_i18n_mbsToWcs(DRM_Charset_t charset,
+ const uint8_t *mbs, int32_t mbsLen,
+ uint16_t *wcsBuf, int32_t bufSizeInWideChar,
+ int32_t *bytesConsumed);
+
+/**
+ * Convert unicode string to multibyte string with specified charset.
+ * Note NO terminating '\0' will be appended to the output multibyte string.
+ *
+ * @param charset Charset of the multibyte string to be converted to.
+ * @param wcs Unicode string to be converted.
+ * @param wcsLen Number of the unicode characters (in wcs) to be converted.
+ * @param mbsBuf Buffer for converted multibyte characters.
+ * If mbsBuf is NULL, the function returns the number of bytes
+ * required for the buffer.
+ * @param bufSizeInByte The size (in byte) of mbsBuf.
+ *
+ * @return Number of the successfully converted bytes.
+ */
+int32_t DRM_i18n_wcsToMbs(DRM_Charset_t charset,
+ const uint16_t *wcs, int32_t wcsLen,
+ uint8_t *mbsBuf, int32_t bufSizeInByte);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/media/libdrm/mobile1/include/objmng/drm_inner.h b/media/libdrm/mobile1/include/objmng/drm_inner.h
new file mode 100644
index 0000000..55234f8
--- /dev/null
+++ b/media/libdrm/mobile1/include/objmng/drm_inner.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __DRM_INNER_H__
+#define __DRM_INNER_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <drm_common_types.h>
+
+#define INT_2_YMD_HMS(year, mon, day, date, hour, min, sec, time) do{\
+ year = date / 10000;\
+ mon = date % 10000 / 100;\
+ day = date %100;\
+ hour = time / 10000;\
+ min = time % 10000 / 100;\
+ sec = time % 100;\
+}while(0)
+
+/**
+ * Define the max malloc length for a DRM.
+ */
+#define DRM_MAX_MALLOC_LEN (50 * 1024) /* 50K */
+
+#define DRM_ONE_AES_BLOCK_LEN 16
+#define DRM_TWO_AES_BLOCK_LEN 32
+
+typedef struct _T_DRM_DM_Binary_Node {
+ uint8_t boundary[256];
+} T_DRM_DM_Binary_Node;
+
+typedef struct _T_DRM_DM_Base64_Node {
+ uint8_t boundary[256];
+ uint8_t b64DecodeData[4];
+ int32_t b64DecodeDataLen;
+} T_DRM_DM_Base64_Node;
+
+typedef struct _T_DRM_Dcf_Node {
+ uint8_t rightsIssuer[256];
+ int32_t encContentLength;
+ uint8_t aesDecData[16];
+ int32_t aesDecDataLen;
+ int32_t aesDecDataOff;
+ uint8_t aesBackupBuf[16];
+ int32_t bAesBackupBuf;
+} T_DRM_Dcf_Node;
+
+typedef struct _T_DRM_Session_Node {
+ int32_t sessionId;
+ int32_t inputHandle;
+ int32_t mimeType;
+ int32_t (*getInputDataLengthFunc)(int32_t inputHandle);
+ int32_t (*readInputDataFunc)(int32_t inputHandle, uint8_t* buf, int32_t bufLen);
+ int32_t (*seekInputDataFunc)(int32_t inputHandle, int32_t offset);
+ int32_t deliveryMethod;
+ int32_t transferEncoding;
+ uint8_t contentType[64];
+ int32_t contentLength;
+ int32_t contentOffset;
+ uint8_t contentID[256];
+ uint8_t* rawContent;
+ int32_t rawContentLen;
+ int32_t bEndData;
+ uint8_t* readBuf;
+ int32_t readBufLen;
+ int32_t readBufOff;
+ void* infoStruct;
+ struct _T_DRM_Session_Node* next;
+} T_DRM_Session_Node;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __DRM_INNER_H__ */
diff --git a/media/libdrm/mobile1/include/objmng/drm_rights_manager.h b/media/libdrm/mobile1/include/objmng/drm_rights_manager.h
new file mode 100644
index 0000000..dd2116c
--- /dev/null
+++ b/media/libdrm/mobile1/include/objmng/drm_rights_manager.h
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __DRM_RIGHTS_MANAGER_H__
+#define __DRM_RIGHTS_MANAGER_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <drm_common_types.h>
+#include <parser_rel.h>
+#include <aes.h>
+
+#ifdef DRM_DEVICE_ARCH_ARM
+#define ANDROID_DRM_CORE_PATH "/data/drm/rights/"
+#define DRM_UID_FILE_PATH "/data/drm/rights/uid.txt"
+#else
+#define ANDROID_DRM_CORE_PATH "/home/user/golf/esmertec/device/out/debug/host/linux-x86/product/sim/data/data/com.android.drm.mobile1/"
+#define DRM_UID_FILE_PATH "/home/user/golf/esmertec/device/out/debug/host/linux-x86/product/sim/data/data/com.android.drm.mobile1/uid.txt"
+#endif
+
+#define EXTENSION_NAME_INFO ".info"
+
+#define GET_ID 1
+#define GET_UID 2
+
+#define GET_ROAMOUNT 1
+#define GET_ALL_RO 2
+#define SAVE_ALL_RO 3
+#define GET_A_RO 4
+#define SAVE_A_RO 5
+
+/**
+ * Get the id or uid from the "uid.txt" file.
+ *
+ * \param Uid The content id for a specially DRM object.
+ * \param id The id number managed by DRM engine for a specially DRM object.
+ * \param option The option to get id or uid, the value includes: GET_ID, GET_UID.
+ *
+ * \return
+ * -TRUE, if the operation successfully.
+ * -FALSE, if the operation failed.
+ */
+int32_t drm_readFromUidTxt(uint8_t* Uid, int32_t* id, int32_t option);
+
+/**
+ * Save or read the rights information on the "id.info" file.
+ *
+ * \param id The id number managed by DRM engine for a specially DRM object.
+ * \param Ro The rights structure to save the rights information.
+ * \param RoAmount The number of rights for this DRM object.
+ * \param option The option include: GET_ROAMOUNT, GET_ALL_RO, SAVE_ALL_RO, GET_A_RO, SAVE_A_RO.
+ *
+ * \return
+ * -TRUE, if the operation successfully.
+ * -FALSE, if the operation failed.
+ */
+int32_t drm_writeOrReadInfo(int32_t id, T_DRM_Rights* Ro, int32_t* RoAmount, int32_t option);
+
+/**
+ * Append a rights information to DRM engine storage.
+ *
+ * \param Ro The rights structure to save the rights information.
+ *
+ * return
+ * -TRUE, if the operation successfully.
+ * -FALSE, if the operation failed.
+ */
+int32_t drm_appendRightsInfo(T_DRM_Rights* rights);
+
+/**
+ * Get the mex id number from the "uid.txt" file.
+ *
+ * \return
+ * -an integer to indicate the max id number.
+ * -(-1), if the operation failed.
+ */
+int32_t drm_getMaxIdFromUidTxt();
+
+/**
+ * Remove the "id.info" file if all the rights for this DRM object has been deleted.
+ *
+ * \param id The id number managed by DRM engine for a specially DRM object.
+ *
+ * \return
+ * -TRUE, if the operation successfully.
+ * -FALSE, if the operation failed.
+ */
+int32_t drm_removeIdInfoFile(int32_t id);
+
+/**
+ * Update the "uid.txt" file when delete the rights object.
+ *
+ * \param id The id number managed by DRM engine for a specially DRM object.
+ *
+ * \return
+ * -TRUE, if the operation successfully.
+ * -FALSE, if the operation failed.
+ */
+int32_t drm_updateUidTxtWhenDelete(int32_t id);
+
+/**
+ * Get the CEK according the given content id.
+ *
+ * \param uid The content id for a specially DRM object.
+ * \param KeyValue The buffer to save the CEK.
+ *
+ * \return
+ * -TRUE, if the operation successfully.
+ * -FALSE, if the operation failed.
+ */
+int32_t drm_getKey(uint8_t* uid, uint8_t* KeyValue);
+
+/**
+ * Discard the padding bytes in DCF decrypted data.
+ *
+ * \param decryptedBuf The aes decrypted data buffer to be scanned.
+ * \param decryptedBufLen The length of the buffer. And save the output result.
+ *
+ * \return
+ * -0
+ */
+void drm_discardPaddingByte(uint8_t *decryptedBuf, int32_t *decryptedBufLen);
+
+/**
+ * Decrypt the media data according the CEK.
+ *
+ * \param Buffer The buffer to decrypted and also used to save the output data.
+ * \param BufferLen The length of the buffer data and also save the output data length.
+ * \param ctx The structure of the CEK.
+ *
+ * \return
+ * -0
+ */
+int32_t drm_aesDecBuffer(uint8_t * Buffer, int32_t * BufferLen, aes_decrypt_ctx ctx[1]);
+
+/**
+ * Update the DCF data length according the CEK.
+ *
+ * \param pDcfLastData The last several byte for the DCF.
+ * \param keyValue The CEK of the DRM content.
+ * \param moreBytes Output the more bytes for discarded.
+ *
+ * \return
+ * -TRUE, if the operation successfully.
+ * -FALSE, if the operation failed.
+ */
+int32_t drm_updateDcfDataLen(uint8_t* pDcfLastData, uint8_t* keyValue, int32_t* moreBytes);
+
+/**
+ * Check and update the rights for a specially DRM content.
+ *
+ * \param id The id number managed by DRM engine for a specially DRM object.
+ * \param permission The permission to be check and updated.
+ *
+ * \return
+ * -DRM_SUCCESS, if there is a valid rights and update it successfully.
+ * -DRM_NO_RIGHTS, if there is no rights for this content.
+ * -DRM_RIGHTS_PENDING, if the rights is pending.
+ * -DRM_RIGHTS_EXPIRED, if the rights has expired.
+ * -DRM_RIGHTS_FAILURE, if there is some other error occur.
+ */
+int32_t drm_checkRoAndUpdate(int32_t id, int32_t permission);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __DRM_RIGHTS_MANAGER_H__ */
diff --git a/media/libdrm/mobile1/include/objmng/drm_time.h b/media/libdrm/mobile1/include/objmng/drm_time.h
new file mode 100644
index 0000000..9b013e6
--- /dev/null
+++ b/media/libdrm/mobile1/include/objmng/drm_time.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+/**
+ * @file
+ * Time Porting Layer
+ *
+ * Basic support functions that are needed by time.
+ *
+ * <!-- #interface list begin -->
+ * \section drm_time Interface
+ * - DRM_time_getElapsedSecondsFrom1970()
+ * - DRM_time_sleep()
+ * - DRM_time_getSysTime()
+ * <!-- #interface list end -->
+ */
+
+#ifndef __DRM_TIME_H__
+#define __DRM_TIME_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <time.h>
+#include <drm_common_types.h>
+
+/** the time format */
+typedef struct __db_system_time_
+{
+ uint16_t year;
+ uint16_t month;
+ uint16_t day;
+ uint16_t hour;
+ uint16_t min;
+ uint16_t sec;
+} T_DB_TIME_SysTime;
+
+/**
+ * Get the system time.it's up to UTC
+ * \return Return the time in elapsed seconds.
+ */
+uint32_t DRM_time_getElapsedSecondsFrom1970(void);
+
+/**
+ * Suspend the execution of the current thread for a specified interval
+ * \param ms suspended time by millisecond
+ */
+void DRM_time_sleep(uint32_t ms);
+
+/**
+ * function: get current system time
+ * \param time_ptr[OUT] the system time got
+ * \attention
+ * time_ptr must not be NULL
+ */
+void DRM_time_getSysTime(T_DB_TIME_SysTime *time_ptr);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __DRM_TIME_H__ */
diff --git a/media/libdrm/mobile1/include/objmng/svc_drm.h b/media/libdrm/mobile1/include/objmng/svc_drm.h
new file mode 100644
index 0000000..789343f
--- /dev/null
+++ b/media/libdrm/mobile1/include/objmng/svc_drm.h
@@ -0,0 +1,376 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __SVC_DRM_NEW_H__
+#define __SVC_DRM_NEW_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <drm_common_types.h>
+
+/**
+ * Define the mime type of DRM data.
+ */
+#define TYPE_DRM_MESSAGE 0x48 /**< The mime type is "application/vnd.oma.drm.message" */
+#define TYPE_DRM_CONTENT 0x49 /**< The mime type is "application/vnd.oma.drm.content" */
+#define TYPE_DRM_RIGHTS_XML 0x4a /**< The mime type is "application/vnd.oma.drm.rights+xml" */
+#define TYPE_DRM_RIGHTS_WBXML 0x4b /**< The mime type is "application/vnd.oma.drm.rights+wbxml" */
+#define TYPE_DRM_UNKNOWN 0xff /**< The mime type is unknown */
+
+/**
+ * Define the delivery methods.
+ */
+#define FORWARD_LOCK 1 /**< Forward_lock */
+#define COMBINED_DELIVERY 2 /**< Combined delivery */
+#define SEPARATE_DELIVERY 3 /**< Separate delivery */
+#define SEPARATE_DELIVERY_FL 4 /**< Separate delivery but DCF is forward-lock */
+
+/**
+ * Define the permissions.
+ */
+#define DRM_PERMISSION_PLAY 0x01 /**< Play */
+#define DRM_PERMISSION_DISPLAY 0x02 /**< Display */
+#define DRM_PERMISSION_EXECUTE 0x04 /**< Execute */
+#define DRM_PERMISSION_PRINT 0x08 /**< Print */
+#define DRM_PERMISSION_FORWARD 0x10 /**< Forward */
+
+/**
+ * Define the constraints.
+ */
+#define DRM_NO_CONSTRAINT 0x80 /**< Indicate have no constraint, it can use freely */
+#define DRM_END_TIME_CONSTRAINT 0x08 /**< Indicate have end time constraint */
+#define DRM_INTERVAL_CONSTRAINT 0x04 /**< Indicate have interval constraint */
+#define DRM_COUNT_CONSTRAINT 0x02 /**< Indicate have count constraint */
+#define DRM_START_TIME_CONSTRAINT 0x01 /**< Indicate have start time constraint */
+#define DRM_NO_PERMISSION 0x00 /**< Indicate no rights */
+
+/**
+ * Define the return values for those interface.
+ */
+#define DRM_SUCCESS 0
+#define DRM_FAILURE -1
+#define DRM_MEDIA_EOF -2
+#define DRM_RIGHTS_DATA_INVALID -3
+#define DRM_MEDIA_DATA_INVALID -4
+#define DRM_SESSION_NOT_OPENED -5
+#define DRM_NO_RIGHTS -6
+#define DRM_NOT_SD_METHOD -7
+#define DRM_RIGHTS_PENDING -8
+#define DRM_RIGHTS_EXPIRED -9
+#define DRM_UNKNOWN_DATA_LEN -10
+
+/**
+ * The input DRM data structure, include DM, DCF, DR, DRC.
+ */
+typedef struct _T_DRM_Input_Data {
+ /**
+ * The handle of the input DRM data.
+ */
+ int32_t inputHandle;
+
+ /**
+ * The mime type of the DRM data, if the mime type set to unknown, DRM engine
+ * will try to scan the input data to confirm the mime type, but we must say that
+ * the scan and check of mime type is not strictly precise.
+ */
+ int32_t mimeType;
+
+ /**
+ * The function to get input data length, this function should be implement by out module,
+ * and DRM engine will call-back it.
+ *
+ * \param inputHandle The handle of the DRM data.
+ *
+ * \return
+ * -A positive integer indicate the length of input data.
+ * -0, if some error occurred.
+ */
+ int32_t (*getInputDataLength)(int32_t inputHandle);
+
+ /**
+ * The function to read the input data, this function should be implement by out module,
+ * and DRM engine will call-back it.
+ *
+ * \param inputHandle The handle of the DRM data.
+ * \param buf The buffer mallocced by DRM engine to save the data.
+ * \param bufLen The length of the buffer.
+ *
+ * \return
+ * -A positive integer indicate the actually length of byte has been read.
+ * -0, if some error occurred.
+ * -(-1), if reach to the end of the data.
+ */
+ int32_t (*readInputData)(int32_t inputHandle, uint8_t* buf, int32_t bufLen);
+
+ /**
+ * The function to seek the current file pointer, this function should be implement by out module,
+ * and DRM engine will call-back it.
+ *
+ * \param inputHandle The handle of the DRM data.
+ * \param offset The offset from the start position to be seek.
+ *
+ * \return
+ * -0, if seek operation success.
+ * -(-1), if seek operation fail.
+ */
+ int32_t (*seekInputData)(int32_t inputHandle, int32_t offset);
+} T_DRM_Input_Data;
+
+/**
+ * The constraint structure.
+ */
+typedef struct _T_DRM_Constraint_Info {
+ uint8_t indicator; /**< Whether there is a right */
+ uint8_t unUsed[3];
+ int32_t count; /**< The constraint of count */
+ int32_t startDate; /**< The constraint of start date */
+ int32_t startTime; /**< The constraint of start time */
+ int32_t endDate; /**< The constraint of end date */
+ int32_t endTime; /**< The constraint of end time */
+ int32_t intervalDate; /**< The constraint of interval date */
+ int32_t intervalTime; /**< The constraint of interval time */
+} T_DRM_Constraint_Info;
+
+/**
+ * The rights permission and constraint information structure.
+ */
+typedef struct _T_DRM_Rights_Info {
+ uint8_t roId[256]; /**< The unique id for a specially rights object */
+ T_DRM_Constraint_Info playRights; /**< Constraint of play */
+ T_DRM_Constraint_Info displayRights; /**< Constraint of display */
+ T_DRM_Constraint_Info executeRights; /**< Constraint of execute */
+ T_DRM_Constraint_Info printRights; /**< Constraint of print */
+} T_DRM_Rights_Info;
+
+/**
+ * The list node of the Rights information structure.
+ */
+typedef struct _T_DRM_Rights_Info_Node {
+ T_DRM_Rights_Info roInfo;
+ struct _T_DRM_Rights_Info_Node *next;
+} T_DRM_Rights_Info_Node;
+
+/**
+ * Install a rights object to DRM engine, include the rights in Combined Delivery cases.
+ * Because all the rights object is managed by DRM engine, so every incoming rights object
+ * must be install to the engine first, or the DRM engine will not recognize it.
+ *
+ * \param data The rights object data or Combined Delivery case data.
+ * \param pRightsInfo The structure to save this rights information.
+ *
+ * \return
+ * -DRM_SUCCESS, when install successfully.
+ * -DRM_RIGHTS_DATA_INVALID, when the input rights data is invalid.
+ * -DRM_FAILURE, when some other error occur.
+ */
+int32_t SVC_drm_installRights(T_DRM_Input_Data data, T_DRM_Rights_Info* pRightsInfo);
+
+/**
+ * Open a session for a special DRM object, it will parse the input DRM data, and then user
+ * can try to get information for this DRM object, or try to use it if the rights is valid.
+ *
+ * \param data The DRM object data, DM or DCF.
+ *
+ * \return
+ * -A handle for this opened DRM object session.
+ * -DRM_MEDIA_DATA_INVALID, when the input DRM object data is invalid.
+ * -DRM_FAILURE, when some other error occurred.
+ */
+int32_t SVC_drm_openSession(T_DRM_Input_Data data);
+
+/**
+ * Get the delivery method of the DRM object.
+ *
+ * \param session The handle for this DRM object session.
+ *
+ * \return
+ * -The delivery method of this DRM object, include: FORWARD_LOCK, COMBINED_DELIVERY, SEPARATE_DELIVERY, SEPARATE_DELIVERY_FL.
+ * -DRM_FAILURE, when some other error occurred.
+ */
+int32_t SVC_drm_getDeliveryMethod(int32_t session);
+
+/**
+ * Get DRM object media object content type.
+ *
+ * \param session The handle for this DRM object session.
+ * \param mediaType The buffer to save the media type string, 64 bytes is enough.
+ *
+ * \return
+ * -DRM_SUCCESS, when get the media object content type successfully.
+ * -DRM_SESSION_NOT_OPENED, when the session is not opened or has been closed.
+ * -DRM_FAILURE, when some other error occured.
+ */
+int32_t SVC_drm_getContentType(int32_t session, uint8_t* mediaType);
+
+/**
+ * Check whether a specific DRM object has the specific permission rights or not.
+ *
+ * \param session The handle for this DRM object session.
+ * \param permission Specify the permission to be checked.
+ *
+ * \return
+ * -DRM_SUCCESS, when it has the rights for the permission.
+ * -DRM_SESSION_NOT_OPENED, when the session is not opened or has been closed.
+ * -DRM_NO_RIGHTS, when it has no rights.
+ * -DRM_RIGHTS_PENDING, when it has the rights, but currently it is pending.
+ * -DRM_RIGHTS_EXPIRED, when the rights has expired.
+ * -DRM_FAILURE, when some other error occured.
+ */
+int32_t SVC_drm_checkRights(int32_t session, int32_t permission);
+
+/**
+ * Consume the rights when try to use the DRM object.
+ *
+ * \param session The handle for this DRM object session.
+ * \param permission Specify the permission to be checked.
+ *
+ * \return
+ * -DRM_SUCCESS, when consume rights successfully.
+ * -DRM_SESSION_NOT_OPENED, when the session is not opened or has been closed.
+ * -DRM_NO_RIGHTS, when it has no rights.
+ * -DRM_RIGHTS_PENDING, when it has the rights, but currently it is pending.
+ * -DRM_RIGHTS_EXPIRED, when the rights has expired.
+ * -DRM_FAILURE, when some other error occured.
+ */
+int32_t SVC_drm_consumeRights(int32_t session, int32_t permission);
+
+/**
+ * Get DRM media object content data length.
+ *
+ * \param session The handle for this DRM object session.
+ *
+ * \return
+ * -A positive integer indicate the length of the media object content data.
+ * -DRM_SESSION_NOT_OPENED, when the session is not opened or has been closed.
+ * -DRM_NO_RIGHTS, when the rights object is not existed.
+ * -DRM_UNKNOWN_DATA_LEN, when DRM object media data length is unknown in case of DCF has no rights.
+ * -DRM_FAILURE, when some other error occured.
+ */
+int32_t SVC_drm_getContentLength(int32_t session);
+
+/**
+ * Get DRM media object content data. Support get the data piece by piece if the content is too large.
+ *
+ * \param session The handle for this DRM object session.
+ * \param offset The offset to start to get content.
+ * \param mediaBuf The buffer to save media object data.
+ * \param mediaBufLen The length of the buffer.
+ *
+ * \return
+ * -A positive integer indicate the actually length of the data has been got.
+ * -DRM_SESSION_NOT_OPENED, when the session is not opened or has been closed.
+ * -DRM_NO_RIGHTS, when the rights object is not existed.
+ * -DRM_MEDIA_EOF, when reach to the end of the media data.
+ * -DRM_FAILURE, when some other error occured.
+ */
+int32_t SVC_drm_getContent(int32_t session, int32_t offset, uint8_t* mediaBuf, int32_t mediaBufLen);
+
+/**
+ * Get the rights issuer address, this interface is specially for Separate Delivery method.
+ *
+ * \param session The handle for this DRM object session.
+ * \param rightsIssuer The buffer to save rights issuer, 256 bytes are enough.
+ *
+ * \return
+ * -DRM_SUCCESS, when get the rights issuer successfully.
+ * -DRM_SESSION_NOT_OPENED, when the session is not opened or has been closed.
+ * -DRM_NOT_SD_METHOD, when it is not a Separate Delivery DRM object.
+ * -DRM_FAILURE, when some other error occured.
+ */
+int32_t SVC_drm_getRightsIssuer(int32_t session, uint8_t* rightsIssuer);
+
+/**
+ * Get DRM object constraint informations.
+ *
+ * \param session The handle for this DRM object session.
+ * \param rights The structue to save the rights object information.
+ *
+ * \return
+ * -DRM_SUCCESS, when get the rights information successfully.
+ * -DRM_SESSION_NOT_OPENED, when the session is not opened or has been closed.
+ * -DRM_NO_RIGHTS, when this DRM object has not rights.
+ * -DRM_FAILURE, when some other error occured.
+ */
+int32_t SVC_drm_getRightsInfo(int32_t session, T_DRM_Rights_Info* rights);
+
+/**
+ * Close the opened session, after closed, the handle become invalid.
+ *
+ * \param session The handle for this DRM object session.
+ *
+ * \return
+ * -DRM_SUCCESS, when close operation success.
+ * -DRM_SESSION_NOT_OPENED, when the session is not opened or has been closed.
+ * -DRM_FAILURE, when some other error occured.
+ */
+int32_t SVC_drm_closeSession(int32_t session);
+
+/**
+ * Check and update the given rights according the given permission.
+ *
+ * \param contentID The unique id of the rights object.
+ * \param permission The permission to be updated.
+ *
+ * \return
+ * -DRM_SUCCESS, when update operation success.
+ * -DRM_NO_RIGHTS, when it has no rights.
+ * -DRM_RIGHTS_PENDING, when it has the rights, but currently it is pending.
+ * -DRM_RIGHTS_EXPIRED, when the rights has expired.
+ * -DRM_FAILURE, when some other error occured.
+ */
+int32_t SVC_drm_updateRights(uint8_t* contentID, int32_t permission);
+
+/**
+ * Scan all the rights object in current DRM engine, and get all their information.
+ *
+ * \param ppRightsInfo The pointer to the list structure to save rights info.
+ *
+ * \return
+ * -DRM_SUCCESS, when get information successfully.
+ * -DRM_FAILURE, when some other error occured.
+ */
+int32_t SVC_drm_viewAllRights(T_DRM_Rights_Info_Node **ppRightsInfo);
+
+/**
+ * Free the allocated memory when call "SVC_drm_viewAllRights".
+ *
+ * \param pRightsHeader The header pointer of the list to be free.
+ *
+ * \return
+ * -DRM_SUCCESS, when free operation successfully.
+ * -DRM_FAILURE, when some other error occured.
+ */
+int32_t SVC_drm_freeRightsInfoList(T_DRM_Rights_Info_Node *pRightsHeader);
+
+/**
+ * Delete a specify rights.
+ *
+ * \param roId The unique id of the rights.
+ *
+ * \return
+ * -DRM_SUCCESS, when free operation successfully.
+ * -DRM_NO_RIGHTS, when there is not this rights object.
+ * -DRM_FAILURE, when some other error occured.
+ */
+int32_t SVC_drm_deleteRights(uint8_t* roId);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __SVC_DRM_NEW_H__ */
diff --git a/media/libdrm/mobile1/include/parser/parser_dcf.h b/media/libdrm/mobile1/include/parser/parser_dcf.h
new file mode 100644
index 0000000..c63a195
--- /dev/null
+++ b/media/libdrm/mobile1/include/parser/parser_dcf.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __PARSER_DCF_H__
+#define __PARSER_DCF_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <drm_common_types.h>
+
+#define MAX_ENCRYPTION_METHOD_LEN 64
+#define MAX_RIGHTS_ISSUER_LEN 256
+#define MAX_CONTENT_NAME_LEN 64
+#define MAX_CONTENT_DESCRIPTION_LEN 256
+#define MAX_CONTENT_VENDOR_LEN 256
+#define MAX_ICON_URI_LEN 256
+#define MAX_CONTENT_TYPE_LEN 64
+#define MAX_CONTENT_URI_LEN 256
+
+#define HEADER_ENCRYPTION_METHOD "Encryption-Method: "
+#define HEADER_RIGHTS_ISSUER "Rights-Issuer: "
+#define HEADER_CONTENT_NAME "Content-Name: "
+#define HEADER_CONTENT_DESCRIPTION "Content-Description: "
+#define HEADER_CONTENT_VENDOR "Content-Vendor: "
+#define HEADER_ICON_URI "Icon-Uri: "
+
+#define HEADER_ENCRYPTION_METHOD_LEN 19
+#define HEADER_RIGHTS_ISSUER_LEN 15
+#define HEADER_CONTENT_NAME_LEN 14
+#define HEADER_CONTENT_DESCRIPTION_LEN 21
+#define HEADER_CONTENT_VENDOR_LEN 16
+#define HEADER_ICON_URI_LEN 10
+
+#define UINT_VAR_FLAG 0x80
+#define UINT_VAR_DATA 0x7F
+#define MAX_UINT_VAR_BYTE 5
+#define DRM_UINT_VAR_ERR -1
+
+typedef struct _T_DRM_DCF_Info {
+ uint8_t Version;
+ uint8_t ContentTypeLen; /**< Length of the ContentType field */
+ uint8_t ContentURILen; /**< Length of the ContentURI field */
+ uint8_t unUsed;
+ uint8_t ContentType[MAX_CONTENT_TYPE_LEN]; /**< The MIME media type of the plaintext data */
+ uint8_t ContentURI[MAX_CONTENT_URI_LEN]; /**< The unique identifier of this content object */
+ int32_t HeadersLen; /**< Length of the Headers field */
+ int32_t EncryptedDataLen; /**< Length of the encrypted data field */
+ int32_t DecryptedDataLen; /**< Length of the decrypted data field */
+ uint8_t Encryption_Method[MAX_ENCRYPTION_METHOD_LEN]; /**< Encryption method */
+ uint8_t Rights_Issuer[MAX_RIGHTS_ISSUER_LEN]; /**< Rights issuer */
+ uint8_t Content_Name[MAX_CONTENT_NAME_LEN]; /**< Content name */
+ uint8_t ContentDescription[MAX_CONTENT_DESCRIPTION_LEN]; /**< Content description */
+ uint8_t ContentVendor[MAX_CONTENT_VENDOR_LEN]; /**< Content vendor */
+ uint8_t Icon_URI[MAX_ICON_URI_LEN]; /**< Icon URI */
+} T_DRM_DCF_Info;
+
+/**
+ * Parse the DRM content format data
+ *
+ * \param buffer (in)Input the DCF format data
+ * \param bufferLen (in)The input buffer length
+ * \param pDcfInfo (out)A structure pointer which contain information of DCF headers
+ * \param ppEncryptedData (out)The location of encrypted data
+ *
+ * \return
+ * -TRUE, when success
+ * -FALSE, when failed
+ */
+int32_t drm_dcfParser(uint8_t *buffer, int32_t bufferLen, T_DRM_DCF_Info *pDcfInfo,
+ uint8_t **ppEncryptedData);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __PARSER_DCF_H__ */
diff --git a/media/libdrm/mobile1/include/parser/parser_dm.h b/media/libdrm/mobile1/include/parser/parser_dm.h
new file mode 100644
index 0000000..ec8b6b2
--- /dev/null
+++ b/media/libdrm/mobile1/include/parser/parser_dm.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __PARSER_DM_H__
+#define __PARSER_DM_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <drm_common_types.h>
+
+#define MAX_CONTENT_TYPE_LEN 64
+#define MAX_CONTENT_ID 256
+#define MAX_CONTENT_BOUNDARY_LEN 256
+#define MAX_RIGHTS_ISSUER_LEN 256
+
+#define DRM_MIME_TYPE_RIGHTS_XML "application/vnd.oma.drm.rights+xml"
+#define DRM_MIME_TYPE_CONTENT "application/vnd.oma.drm.content"
+
+#define HEADERS_TRANSFER_CODING "Content-Transfer-Encoding:"
+#define HEADERS_CONTENT_TYPE "Content-Type:"
+#define HEADERS_CONTENT_ID "Content-ID:"
+
+#define TRANSFER_CODING_TYPE_7BIT "7bit"
+#define TRANSFER_CODING_TYPE_8BIT "8bit"
+#define TRANSFER_CODING_TYPE_BINARY "binary"
+#define TRANSFER_CODING_TYPE_BASE64 "base64"
+
+#define DRM_UID_TYPE_FORWORD_LOCK "forwardlock"
+#define DRM_NEW_LINE_CRLF "\r\n"
+
+#define HEADERS_TRANSFER_CODING_LEN 26
+#define HEADERS_CONTENT_TYPE_LEN 13
+#define HEADERS_CONTENT_ID_LEN 11
+
+#define DRM_MESSAGE_CODING_7BIT 0 /* default */
+#define DRM_MESSAGE_CODING_8BIT 1
+#define DRM_MESSAGE_CODING_BINARY 2
+#define DRM_MESSAGE_CODING_BASE64 3
+
+#define DRM_B64_DEC_BLOCK 3
+#define DRM_B64_ENC_BLOCK 4
+
+typedef struct _T_DRM_DM_Info {
+ uint8_t contentType[MAX_CONTENT_TYPE_LEN]; /**< Content type */
+ uint8_t contentID[MAX_CONTENT_ID]; /**< Content ID */
+ uint8_t boundary[MAX_CONTENT_BOUNDARY_LEN]; /**< DRM message's boundary */
+ uint8_t deliveryType; /**< The Delivery type */
+ uint8_t transferEncoding; /**< Transfer encoding type */
+ int32_t contentOffset; /**< The offset of the media content from the original DRM data */
+ int32_t contentLen; /**< The length of the media content */
+ int32_t rightsOffset; /**< The offset of the rights object in case of combined delivery */
+ int32_t rightsLen; /**< The length of the rights object in case of combined delivery */
+ uint8_t rightsIssuer[MAX_RIGHTS_ISSUER_LEN];/**< The rights issuer address in case of separate delivery */
+} T_DRM_DM_Info;
+
+/**
+ * Search the string in a limited length.
+ *
+ * \param str The original string
+ * \param strSearch The sub-string to be searched
+ * \param len The length limited
+ *
+ * \return
+ * -NULL, when there is not the searched string in length
+ * -The pointer of this sub-string
+ */
+const uint8_t* drm_strnstr(const uint8_t* str, const uint8_t* strSearch, int32_t len);
+
+/**
+ * Parse the DRM message format data.
+ *
+ * \param buffer (in)Input the DRM message format data
+ * \param bufferLen (in)The input buffer length
+ * \param pDmInfo (out)A structure pointer which contain information of DRM message headers
+ *
+ * \return
+ * -TRUE, when success
+ * -FALSE, when failed
+ */
+int32_t drm_parseDM(const uint8_t* buffer, int32_t bufferLen, T_DRM_DM_Info* pDmInfo);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __PARSER_DM_H__ */
diff --git a/media/libdrm/mobile1/include/parser/parser_rel.h b/media/libdrm/mobile1/include/parser/parser_rel.h
new file mode 100644
index 0000000..8def199
--- /dev/null
+++ b/media/libdrm/mobile1/include/parser/parser_rel.h
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __PARSER_REL_H__
+#define __PARSER_REL_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <drm_common_types.h>
+
+#define WRITE_RO_FLAG(whoIsAble, boolValue, Indicator, RIGHTS) do{\
+ whoIsAble = boolValue;\
+ Indicator |= RIGHTS;\
+}while(0)
+
+#define CHECK_VALIDITY(ret) do{\
+ if(ret == NULL){\
+ if(XML_ERROR_NO_SUCH_NODE != xml_errno)\
+ return FALSE;\
+ }\
+ else\
+ {\
+ if(XML_ERROR_OK != xml_errno)\
+ return FALSE;\
+ }\
+}while(0)
+
+#define YMD_HMS_2_INT(year, mon, day, date, hour, min, sec, time) do{\
+ date = year * 10000 + mon * 100 + day;\
+ time = hour * 10000 + min * 100 + sec;\
+}while(0)
+
+#define DRM_UID_LEN 256
+#define DRM_KEY_LEN 16
+
+#define XML_DOM_PARSER
+
+typedef struct _T_DRM_DATETIME {
+ int32_t date; /**< year * 10000 + mon *100 + day */
+ int32_t time; /**< hour * 10000 + min *100 + sec */
+} T_DRM_DATETIME;
+
+typedef struct _T_DRM_Rights_Constraint {
+ uint8_t Indicator; /**< Indicate which is constrainted, the first one indicate 0001, second one indicate 0010 */
+ uint8_t unUsed[3];
+ int32_t Count; /**< The times that can be used */
+ T_DRM_DATETIME StartTime; /**< The starting time */
+ T_DRM_DATETIME EndTime; /**< The ending time */
+ T_DRM_DATETIME Interval; /**< The interval time */
+} T_DRM_Rights_Constraint;
+
+typedef struct _T_DRM_Rights {
+ uint8_t Version[8]; /**< Version number */
+ uint8_t uid[256]; /**< record the rights object name */
+ uint8_t KeyValue[16]; /**< Decode base64 */
+ int32_t bIsPlayable; /**< Is playable */
+ int32_t bIsDisplayable; /**< Is displayable */
+ int32_t bIsExecuteable; /**< Is executeable */
+ int32_t bIsPrintable; /**< Is printable */
+ T_DRM_Rights_Constraint PlayConstraint; /**< Play constraint */
+ T_DRM_Rights_Constraint DisplayConstraint; /**< Display constraint */
+ T_DRM_Rights_Constraint ExecuteConstraint; /**< Execute constraint */
+ T_DRM_Rights_Constraint PrintConstraint; /**< Print constraint */
+} T_DRM_Rights;
+
+/**
+ * Input year and month, return how many days that month have
+ * \param year (in)Input the year
+ * \param month (in)Input the month
+ * \return
+ * -A positive integer, which is how many days that month have
+ * -When wrong input, return -1
+ */
+int32_t drm_monthDays(int32_t year, int32_t month);
+
+/**
+ * Check whether the date and time is valid.
+ * \param year year of the date
+ * \param month month of the date
+ * \param day day of the date
+ * \param hour hour of the time
+ * \param min minute of the time
+ * \param sec second of the time
+ * \return
+ * -when it is a valid time, return 0
+ * -when it is a invalid time, return -1
+ */
+int32_t drm_checkDate(int32_t year, int32_t month, int32_t day, int32_t hour, int32_t min, int32_t sec);
+
+/**
+ * Parse the rights object include xml format and wbxml format data
+ *
+ * \param buffer (in)Input the DRM rights object data
+ * \param bufferLen (in)The buffer length
+ * \param format (in)Which format, xml or wbxml
+ * \param pRights (out)A structure pointer which save the rights information
+ *
+ * \return
+ * -TRUE, when success
+ * -FALSE, when failed
+ */
+int32_t drm_relParser(uint8_t* buffer, int32_t bufferLen, int32_t Format, T_DRM_Rights* pRights);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __PARSER_REL_H__ */
diff --git a/media/libdrm/mobile1/include/xml/wbxml_tinyparser.h b/media/libdrm/mobile1/include/xml/wbxml_tinyparser.h
new file mode 100644
index 0000000..1c40467
--- /dev/null
+++ b/media/libdrm/mobile1/include/xml/wbxml_tinyparser.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __WBXML_TINYPARSER_H__
+#define __WBXML_TINYPARSER_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <drm_common_types.h>
+
+#define REL_TAG_RIGHTS 0x05
+#define REL_TAG_CONTEXT 0x06
+#define REL_TAG_VERSION 0x07
+#define REL_TAG_UID 0x08
+#define REL_TAG_AGREEMENT 0x09
+#define REL_TAG_ASSET 0x0A
+#define REL_TAG_KEYINFO 0x0B
+#define REL_TAG_KEYVALUE 0x0C
+#define REL_TAG_PERMISSION 0x0D
+#define REL_TAG_PLAY 0x0E
+#define REL_TAG_DISPLAY 0x0F
+#define REL_TAG_EXECUTE 0x10
+#define REL_TAG_PRINT 0x11
+#define REL_TAG_CONSTRAINT 0x12
+#define REL_TAG_COUNT 0x13
+#define REL_TAG_DATETIME 0x14
+#define REL_TAG_START 0x15
+#define REL_TAG_END 0x16
+#define REL_TAG_INTERVAL 0x17
+
+#define REL_CHECK_WBXML_HEADER(x) ((x != NULL) && (x[0] == 0x03) && (x[1] == 0x0E) && (x[2] == 0x6A))
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __WBXML_TINYPARSER_H__ */
diff --git a/media/libdrm/mobile1/include/xml/xml_tinyParser.h b/media/libdrm/mobile1/include/xml/xml_tinyParser.h
new file mode 100644
index 0000000..4ad65b8
--- /dev/null
+++ b/media/libdrm/mobile1/include/xml/xml_tinyParser.h
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __XML_TINYPARSER_H__
+#define __XML_TINYPARSER_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <drm_common_types.h>
+
+#define XML_DOM_PARSER
+#define WBXML_DOM_PARSER
+#define XML_DOM_CHECK_ENDTAG
+#define XML_ENABLE_ERRNO
+#define WBXML_OLD_VERSION /* for drm only */
+
+#ifdef DEBUG_MODE
+void XML_PrintMallocInfo();
+#endif /* DEBUG_MODE */
+
+#define XML_TRUE 1
+#define XML_FALSE 0
+#define XML_EOF 0
+#define XML_TAG_START 0
+#define XML_TAG_END 1
+#define XML_TAG_SELF 2
+
+#define XML_MAX_PROPERTY_LEN 256
+#define XML_MAX_ATTR_NAME_LEN 256
+#define XML_MAX_ATTR_VALUE_LEN 256
+#define XML_MAX_VALUE_LEN 256
+
+#define XML_ERROR_OK 0
+#define XML_ERROR_BUFFER_NULL -1
+#define XML_ERROR_ATTR_NAME -2
+#define XML_ERROR_ATTR_MISSED_EQUAL -3
+#define XML_ERROR_PROPERTY_NAME -4
+#define XML_ERROR_ATTR_VALUE -5
+#define XML_ERROR_ENDTAG -6
+#define XML_ERROR_NO_SUCH_NODE -7
+#define XML_ERROR_PROPERTY_END -8
+#define XML_ERROR_VALUE -9
+#define XML_ERROR_NO_START_TAG -14
+#define XML_ERROR_NOVALUE -15
+
+#define WBXML_ERROR_MISSED_CONTENT -10
+#define WBXML_ERROR_MBUINT32 -11
+#define WBXML_ERROR_MISSED_STARTTAG -12
+#define WBXML_ERROR_MISSED_ENDTAG -13
+
+#ifdef XML_ENABLE_ERRNO
+extern int32_t xml_errno;
+#define XML_ERROR(x) do { xml_errno = x; } while (0)
+#else /* XML_ENABLE_ERRNO */
+#define XML_ERROR
+#endif /* XML_ENABLE_ERRNO */
+
+#ifdef XML_DOM_PARSER
+uint8_t *XML_DOM_getNode(uint8_t *buffer, const uint8_t *const node);
+uint8_t *XML_DOM_getNodeValue(uint8_t *buffer, uint8_t *node,
+ uint8_t **value, int32_t *valueLen);
+
+uint8_t *XML_DOM_getValue(uint8_t *buffer, uint8_t **pValue, int32_t *valueLen);
+uint8_t *XML_DOM_getAttr(uint8_t *buffer, uint8_t **pName, int32_t *nameLen,
+ uint8_t **pValue, int32_t *valueLen);
+
+uint8_t *XML_DOM_getNextNode(uint8_t *buffer, uint8_t **pNodeName,
+ int32_t *nodenameLen);
+
+uint8_t *XML_DOM_getTag(uint8_t *buffer, int32_t *tagLen, int32_t *tagType);
+#endif /* XML_DOM_PARSER */
+
+#ifdef WBXML_DOM_PARSER
+
+#define WBXML_WITH_ATTR 0x80
+#define WBXML_WITH_CONTENT 0x40
+#define WBXML_ATTR_END 0x01
+#define WBXML_CONTENT_END 0x01
+
+#define WBXML_SWITCH_PAGE 0x00
+#define WBXML_STR_I 0x03
+#define WBXML_END 0x00
+#define WBXML_OPAUE 0xC3
+#define WBXML_STR_T 0x83
+#define WBXML_OPAQUE 0xC3
+
+#define WBXML_GET_TAG(x) ((x) & 0x3F) /* get 6-digits */
+#define WBXML_HAS_ATTR(x) ((x) & WBXML_WITH_ATTR)
+#define WBXML_HAS_CONTENT(x) ((x) & WBXML_WITH_CONTENT)
+
+typedef struct _WBXML {
+ uint8_t version;
+ uint8_t unUsed[3];
+ uint32_t publicid;
+ uint32_t charset;
+ int32_t strTableLen;
+ uint8_t *strTable;
+ uint8_t *Content;
+ uint8_t *End;
+ uint8_t *curPtr;
+ int32_t depth;
+} WBXML;
+
+typedef int32_t XML_BOOL;
+
+#ifdef WBXML_OLD_VERSION
+uint8_t *WBXML_DOM_getNode(uint8_t *buffer, int32_t bufferLen,
+ uint8_t *node);
+uint8_t *WBXML_DOM_getNodeValue(uint8_t *buffer, int32_t bufferLen,
+ uint8_t *node,
+ uint8_t **value,
+ int32_t *valueLen);
+#endif /* WBXML_OLD_VERSION */
+
+XML_BOOL WBXML_DOM_Init(WBXML * pWbxml, uint8_t *buffer,
+ int32_t bufferLen);
+XML_BOOL WBXML_DOM_Eof(WBXML * pWbxml);
+uint8_t WBXML_DOM_GetTag(WBXML * pWbxml);
+uint8_t WBXML_DOM_GetChar(WBXML * pWbxml);
+uint8_t WBXML_DOM_GetUIntVar(WBXML * pWbxml);
+void WBXML_DOM_Rewind(WBXML * pWbxml);
+void WBXML_DOM_Seek(WBXML * pWbxml, int32_t offset);
+int32_t WBXML_GetUintVar(const uint8_t *const buffer, int32_t *len);
+
+#endif /* WBXML_DOM_PARSER */
+
+#ifdef XML_TREE_STRUCTURE
+
+typedef struct _XML_TREE_ATTR XML_TREE_ATTR;
+struct _XML_TREE_ATTR {
+ uint8_t name[XML_MAX_ATTR_VALUE_LEN];
+ uint8_t value[XML_MAX_ATTR_VALUE_LEN];
+ XML_TREE_ATTR *next;
+};
+
+typedef struct _XML_TREE XML_TREE;
+struct _XML_TREE {
+ uint8_t tag[XML_MAX_PROPERTY_LEN];
+ uint8_t value[XML_MAX_VALUE_LEN];
+ XML_TREE_ATTR *attr;
+ XML_TREE_ATTR *last_attr;
+ XML_TREE *brother;
+ XML_TREE *last_brother;
+ XML_TREE *child;
+};
+
+XML_TREE *XML_makeTree(uint8_t **buf);
+void XML_freeTree(XML_TREE * pTree);
+
+#endif /* XML_TREE_STRUCTURE */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __XML_TINYPARSER_H__ */
diff --git a/media/libdrm/mobile1/src/jni/drm1_jni.c b/media/libdrm/mobile1/src/jni/drm1_jni.c
new file mode 100644
index 0000000..d0fca54
--- /dev/null
+++ b/media/libdrm/mobile1/src/jni/drm1_jni.c
@@ -0,0 +1,1175 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file drm1_jni.c
+ *
+ * This file implement the Java Native Interface
+ * for supporting OMA DRM 1.0
+ */
+
+#include <jni/drm1_jni.h>
+#include <objmng/svc_drm.h>
+#include "log.h"
+
+
+#define MS_PER_SECOND 1000 /* Milliseconds per second */
+#define MS_PER_MINUTE 60 * MS_PER_SECOND /* Milliseconds per minute */
+#define MS_PER_HOUR 60 * MS_PER_MINUTE /* Milliseconds per hour */
+#define MS_PER_DAY 24 * MS_PER_HOUR /* Milliseconds per day */
+
+#define SECONDS_PER_MINUTE 60 /* Seconds per minute*/
+#define SECONDS_PER_HOUR 60 * SECONDS_PER_MINUTE /* Seconds per hour */
+#define SECONDS_PER_DAY 24 * SECONDS_PER_HOUR /* Seconds per day */
+
+#define DAY_PER_MONTH 30 /* Days per month */
+#define DAY_PER_YEAR 365 /* Days per year */
+
+/** Nonzero if 'y' is a leap year, else zero. */
+#define leap(y) (((y) % 4 == 0 && (y) % 100 != 0) || (y) % 400 == 0)
+
+/** Number of leap years from 1970 to 'y' (not including 'y' itself). */
+#define nleap(y) (((y) - 1969) / 4 - ((y) - 1901) / 100 + ((y) - 1601) / 400)
+
+/** Accumulated number of days from 01-Jan up to start of current month. */
+static const int32_t ydays[] = {
+ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
+};
+
+#define int64_const(s) (s)
+#define int64_add(dst, s1, s2) ((void)((dst) = (s1) + (s2)))
+#define int64_mul(dst, s1, s2) ((void)((dst) = (int64_t)(s1) * (int64_t)(s2)))
+
+/**
+ * DRM data structure
+ */
+typedef struct _DrmData {
+ /**
+ * The id of the DRM content.
+ */
+ int32_t id;
+
+ /**
+ * The pointer of JNI interface.
+ */
+ JNIEnv* env;
+
+ /**
+ * The pointer of DRM raw content InputStream object.
+ */
+ jobject* pInData;
+
+ /**
+ * The len of the InputStream object.
+ */
+ int32_t len;
+
+ /**
+ * The next DRM data.
+ */
+ struct _DrmData *next;
+} DrmData;
+
+/** The table to hold all the DRM data. */
+static DrmData *drmTable = NULL;
+
+/**
+ * Allocate a new item of DrmData.
+ *
+ * \return a pointer to a DrmData item if allocate successfully,
+ * otherwise return NULL
+ */
+static DrmData * newItem(void)
+{
+ DrmData *d = (DrmData *)malloc(sizeof(DrmData));
+
+ if (d != NULL) {
+ d->id = -1;
+ d->next = NULL;
+ }
+
+ return d;
+}
+
+/**
+ * Free the memory of the specified DrmData item <code>d</code>.
+ *
+ * \param d - a pointer to DrmData
+ */
+static void freeItem(DrmData *d)
+{
+ assert(d != NULL);
+
+ free(d);
+}
+
+/**
+ * Insert a DrmData item with given <code>name</code> into the head of
+ * the DrmData list.
+ *
+ * @param d - the pointer of the JNI interface
+ * @param pInData - the pointer of the DRM content InputStream object.
+ *
+ * @return <code>JNI_DRM_SUCCESS</code> if insert successfully, otherwise
+ * return <code>JNI_DRM_FAILURE</code>
+ */
+static int32_t addItem(DrmData* d)
+{
+ if (NULL == d)
+ return JNI_DRM_FAILURE;
+
+ if (NULL == drmTable) {
+ drmTable = d;
+ return JNI_DRM_SUCCESS;
+ }
+
+ d->next = drmTable;
+ drmTable = d;
+
+ return JNI_DRM_SUCCESS;
+}
+
+/**
+ * Get the item from the DrmData list by the specified <code>
+ * id</code>.
+ *
+ * @param p - the pointer of the DRM content InputStream object.
+ *
+ * @return a pointer to the DrmData item if find it successfuly,
+ * otherwise return NULL
+ */
+static DrmData * getItem(int32_t id)
+{
+ DrmData *d;
+
+ if (NULL == drmTable)
+ return NULL;
+
+ for (d = drmTable; d != NULL; d = d->next) {
+ if (id == d->id)
+ return d;
+ }
+
+ return NULL;
+}
+
+/**
+ * Remove the specified DrmData item <code>d</code>.
+ *
+ * @param p - the pointer of the DRM content InputStream object.
+ *
+ * @return <code>JNI_DRM_SUCCESS</code> if remove successfuly,
+ * otherwise return <code>JNI_DRM_FAILURE</code>
+ */
+static int32_t removeItem(int32_t id)
+{
+ DrmData *curItem, *preItem, *dstItem;
+
+ if (NULL == drmTable)
+ return JNI_DRM_FAILURE;
+
+ preItem = NULL;
+ for (curItem = drmTable; curItem != NULL; curItem = curItem->next) {
+ if (id == curItem->id) {
+ if (curItem == drmTable)
+ drmTable = curItem->next;
+ else
+ preItem->next = curItem->next;
+
+ freeItem(curItem);
+
+ return JNI_DRM_SUCCESS;
+ }
+
+ preItem = curItem;
+ }
+
+ return JNI_DRM_FAILURE;
+}
+
+
+static int32_t getInputStreamDataLength(int32_t handle)
+{
+ JNIEnv* env;
+ jobject* pInputStream;
+ int32_t len;
+ DrmData* p;
+ jclass cls;
+ jmethodID mid;
+
+ p = (DrmData *)handle;
+
+ if (NULL == p)
+ return 0;
+
+ env = p->env;
+ pInputStream = p->pInData;
+ len = p->len;
+
+ if (NULL == env || p->len <= 0 || NULL == pInputStream)
+ return 0;
+
+ /* check the original InputStream is available or not */
+ cls = (*env)->GetObjectClass(env, *pInputStream);
+ mid = (*env)->GetMethodID(env, cls, "available", "()I");
+ (*env)->DeleteLocalRef(env, cls);
+
+ if (NULL == mid)
+ return 0;
+
+ if (0 > (*env)->CallIntMethod(env, *pInputStream, mid))
+ return 0;
+
+ return len;
+}
+
+static int32_t readInputStreamData(int32_t handle, uint8_t* buf, int32_t bufLen)
+{
+ JNIEnv* env;
+ jobject* pInputStream;
+ int32_t len;
+ DrmData* p;
+ jclass cls;
+ jmethodID mid;
+ jbyteArray tmp;
+ int tmpLen;
+ jbyte* pNativeBuf;
+
+ p = (DrmData *)handle;
+
+ if (NULL == p || NULL == buf || bufLen <- 0)
+ return 0;
+
+ env = p->env;
+ pInputStream = p->pInData;
+ len = p->len;
+
+ if (NULL == env || p->len <= 0 || NULL == pInputStream)
+ return 0;
+
+ cls = (*env)->GetObjectClass(env, *pInputStream);
+ mid = (*env)->GetMethodID(env, cls, "read", "([BII)I");
+ tmp = (*env)->NewByteArray(env, bufLen);
+ bufLen = (*env)->CallIntMethod(env, *pInputStream, mid, tmp, 0, bufLen);
+
+ (*env)->DeleteLocalRef(env, cls);
+
+ if (-1 == bufLen)
+ return -1;
+
+ pNativeBuf = (*env)->GetByteArrayElements(env, tmp, NULL);
+ memcpy(buf, pNativeBuf, bufLen);
+ (*env)->ReleaseByteArrayElements(env, tmp, pNativeBuf, 0);
+ (*env)->DeleteLocalRef(env, tmp);
+
+ return bufLen;
+}
+
+static const T_DRM_Rights_Info_Node *searchRightsObject(const jbyte* roId, const T_DRM_Rights_Info_Node* pRightsList)
+{
+ const T_DRM_Rights_Info_Node *pTmp;
+
+ if (NULL == roId || NULL == pRightsList)
+ return NULL;
+
+ pTmp = pRightsList;
+
+ while (NULL != pTmp) {
+ if(0 == strcmp((char *)roId, (char *)pTmp->roInfo.roId))
+ break;
+ pTmp = pTmp->next;
+ }
+
+ return pTmp;
+}
+
+/**
+ * Returns the difference in seconds between the given GMT time
+ * and 1970-01-01 00:00:00 GMT.
+ *
+ * \param year the year (since 1970)
+ * \param month the month (1 - 12)
+ * \param day the day (1 - 31)
+ * \param hour the hour (0 - 23)
+ * \param minute the minute (0 - 59)
+ * \param second the second (0 - 59)
+ *
+ * \return the difference in seconds between the given GMT time
+ * and 1970-01-01 00:00:00 GMT.
+ */
+static int64_t mkgmtime(
+ uint32_t year, uint32_t month, uint32_t day,
+ uint32_t hour, uint32_t minute, uint32_t second)
+{
+ int64_t result;
+
+ /*
+ * FIXME: It does not check whether the specified days
+ * is valid based on the specified months.
+ */
+ assert(year >= 1970
+ && month > 0 && month <= 12
+ && day > 0 && day <= 31
+ && hour < 24 && minute < 60
+ && second < 60);
+
+ /* Set 'day' to the number of days into the year. */
+ day += ydays[month - 1] + (month > 2 && leap (year)) - 1;
+
+ /* Now calculate 'day' to the number of days since Jan 1, 1970. */
+ day = day + 365 * (year - 1970) + nleap(year);
+
+ int64_mul(result, int64_const(day), int64_const(SECONDS_PER_DAY));
+ int64_add(result, result, int64_const(
+ SECONDS_PER_HOUR * hour + SECONDS_PER_MINUTE * minute + second));
+
+ return result;
+}
+
+/**
+ * Compute the milliseconds by the specified <code>date</code>
+ * and <code>time</code>.
+ *
+ * @param date - the specified date,
+ * <code>date = year * 10000 + month * 100 + day</code>
+ * @param time - the specified time,
+ * <code>time = hour * 10000 + minute * 100 + second</code>
+ *
+ * @return the related milliseconds
+ */
+static int64_t computeTime(int32_t date, int32_t time)
+{
+ int32_t year, month, day, hour, minute, second;
+
+ year = date / 10000;
+ month = (date / 100) % 100;
+ day = date % 100;
+ hour = time / 10000;
+ minute = (time / 100) % 100;
+ second = time % 100;
+
+ /* Adjust the invalid parameters. */
+ if (year < 1970) year = 1970;
+ if (month < 1) month = 1;
+ if (month > 12) month = 12;
+ if (day < 1) day = 1;
+ if (day > 31) day = 31;
+ if (hour < 0) hour = 0;
+ if (hour > 23) hour = 23;
+ if (minute < 0) minute = 0;
+ if (minute > 59) minute = 59;
+ if (second < 0) second = 0;
+ if (second > 59) second = 59;
+
+ return mkgmtime(year, month, day, hour, minute, second) * 1000;
+}
+
+/**
+ * Compute the milliseconds by the specified <code>date</code>
+ * and <code>time</code>.
+ * Note that here we always treat 1 year as 365 days and 1 month as 30 days
+ * that is not precise. But it should not be a problem since OMA DRM 2.0
+ * already restricts the interval representation to be day-based,
+ * i.e. there will not be an interval with year or month any more in the
+ * future.
+ *
+ * @param date - the specified date,
+ * <code>date = year * 10000 + month * 100 + day</code>
+ * @param time - the specified time,
+ * <code>time = hour * 10000 + minute * 100 + second</code>
+ *
+ * @return the related milliseconds
+ */
+static int64_t computeInterval(int32_t date, int32_t time)
+{
+ int32_t year, month, day, hour, minute, second;
+ int64_t milliseconds;
+
+ year = date / 10000;
+ month = (date / 100) % 100;
+ day = date % 100;
+ hour = time / 10000;
+ minute = (time / 100) % 100;
+ second = time % 100;
+
+ /* milliseconds = ((((year * 365 + month * 30 + day) * 24
+ * + hour) * 60 + minute) * 60 + second) * 1000;
+ */
+ int64_mul(milliseconds,
+ int64_const(year * DAY_PER_YEAR + month * DAY_PER_MONTH + day),
+ int64_const(MS_PER_DAY));
+ int64_add(milliseconds, milliseconds,
+ int64_const(hour * MS_PER_HOUR + minute * MS_PER_MINUTE +
+ second * MS_PER_SECOND));
+
+ return milliseconds;
+}
+
+static jint getObjectIntField(JNIEnv * env, jobject obj, const char *name, jint * value)
+{
+ jclass clazz;
+ jfieldID field;
+
+ clazz = (*env)->GetObjectClass(env, obj);
+ if (NULL == clazz)
+ return JNI_DRM_FAILURE;
+
+ field = (*env)->GetFieldID(env, clazz, name, "I");
+ (*env)->DeleteLocalRef(env, clazz);
+
+ if (NULL == field)
+ return JNI_DRM_FAILURE;
+
+ *value = (*env)->GetIntField(env, obj, field);
+
+ return JNI_DRM_SUCCESS;
+}
+
+static jint setObjectIntField(JNIEnv * env, jobject obj, const char *name, jint value)
+{
+ jclass clazz;
+ jfieldID field;
+
+ clazz = (*env)->GetObjectClass(env, obj);
+ if (NULL == clazz)
+ return JNI_DRM_FAILURE;
+
+ field = (*env)->GetFieldID(env, clazz, name, "I");
+ (*env)->DeleteLocalRef(env, clazz);
+
+ if (NULL == field)
+ return JNI_DRM_FAILURE;
+
+ (*env)->SetIntField(env, obj, field, value);
+
+ return JNI_DRM_SUCCESS;
+}
+
+static jint setObjectLongField(JNIEnv * env, jobject obj, const char *name, jlong value)
+{
+ jclass clazz;
+ jfieldID field;
+
+ clazz = (*env)->GetObjectClass(env, obj);
+ if (NULL == clazz)
+ return JNI_DRM_FAILURE;
+
+ field = (*env)->GetFieldID(env, clazz, name, "J");
+ (*env)->DeleteLocalRef(env, clazz);
+
+ if (NULL == field)
+ return JNI_DRM_FAILURE;
+
+ (*env)->SetLongField(env, obj, field, value);
+
+ return JNI_DRM_SUCCESS;
+}
+
+static jint setConstraintFields(JNIEnv * env, jobject constraint, T_DRM_Constraint_Info * pConstraint)
+{
+ /* if no this permission */
+ if (pConstraint->indicator == (uint8_t)DRM_NO_RIGHTS) {
+ if (JNI_DRM_FAILURE == setObjectIntField(env, constraint, "count", 0))
+ return JNI_DRM_FAILURE;
+
+ return JNI_DRM_SUCCESS;
+ }
+
+ /* set count field */
+ if (pConstraint->indicator & DRM_COUNT_CONSTRAINT) {
+ if (JNI_DRM_FAILURE == setObjectIntField(env, constraint, "count", pConstraint->count))
+ return JNI_DRM_FAILURE;
+ }
+
+ /* set start time field */
+ if (pConstraint->indicator & DRM_START_TIME_CONSTRAINT) {
+ int64_t startTime;
+
+ startTime = computeTime(pConstraint->startDate, pConstraint->startTime);
+
+ if (JNI_DRM_FAILURE == setObjectLongField(env, constraint, "startDate", startTime))
+ return JNI_DRM_FAILURE;
+ }
+
+ /* set end time field */
+ if (pConstraint->indicator & DRM_END_TIME_CONSTRAINT) {
+ int64_t endTime;
+
+ endTime = computeTime(pConstraint->endDate, pConstraint->endTime);
+
+ if (JNI_DRM_FAILURE == setObjectLongField(env, constraint, "endDate", endTime))
+ return JNI_DRM_FAILURE;
+ }
+
+ /* set interval field */
+ if (pConstraint->indicator & DRM_INTERVAL_CONSTRAINT) {
+ int64_t interval;
+
+ interval = computeInterval(pConstraint->intervalDate, pConstraint->intervalTime);
+
+ if (JNI_DRM_FAILURE == setObjectLongField(env, constraint, "interval", interval))
+ return JNI_DRM_FAILURE;
+ }
+
+ return JNI_DRM_SUCCESS;
+}
+
+static jint setRightsFields(JNIEnv * env, jobject rights, T_DRM_Rights_Info* pRoInfo)
+{
+ jclass clazz;
+ jfieldID field;
+ jstring str;
+ jint index;
+
+ clazz = (*env)->GetObjectClass(env, rights);
+ if (NULL == clazz)
+ return JNI_DRM_FAILURE;
+
+ /* set roId field */
+ field = (*env)->GetFieldID(env, clazz, "roId", "Ljava/lang/String;");
+ (*env)->DeleteLocalRef(env, clazz);
+
+ if (NULL == field)
+ return JNI_DRM_FAILURE;
+
+ str = (*env)->NewStringUTF(env, (char *)pRoInfo->roId);
+ if (NULL == str)
+ return JNI_DRM_FAILURE;
+
+ (*env)->SetObjectField(env, rights, field, str);
+ (*env)->DeleteLocalRef(env, str);
+
+ return JNI_DRM_SUCCESS;
+}
+
+/* native interface */
+JNIEXPORT jint JNICALL
+Java_android_drm_mobile1_DrmRawContent_nativeConstructDrmContent
+ (JNIEnv * env, jobject rawContent, jobject data, jint len, jint mimeType)
+{
+ int32_t id;
+ T_DRM_Input_Data inData;
+ DrmData* drmInData;
+
+ switch (mimeType) {
+ case JNI_DRM_MIMETYPE_MESSAGE:
+ mimeType = TYPE_DRM_MESSAGE;
+ break;
+ case JNI_DRM_MIMETYPE_CONTENT:
+ mimeType = TYPE_DRM_CONTENT;
+ break;
+ default:
+ return JNI_DRM_FAILURE;
+ }
+
+ drmInData = newItem();
+ if (NULL == drmInData)
+ return JNI_DRM_FAILURE;
+
+ drmInData->env = env;
+ drmInData->pInData = &data;
+ drmInData->len = len;
+
+ if (JNI_DRM_FAILURE == addItem(drmInData))
+ return JNI_DRM_FAILURE;
+
+ inData.inputHandle = (int32_t)drmInData;
+ inData.mimeType = mimeType;
+ inData.getInputDataLength = getInputStreamDataLength;
+ inData.readInputData = readInputStreamData;
+
+ id = SVC_drm_openSession(inData);
+ if (id < 0)
+ return JNI_DRM_FAILURE;
+
+ drmInData->id = id;
+
+ return id;
+}
+
+/* native interface */
+JNIEXPORT jstring JNICALL
+Java_android_drm_mobile1_DrmRawContent_nativeGetRightsAddress
+ (JNIEnv * env, jobject rawContent)
+{
+ jint id;
+ uint8_t rightsIssuer[256] = {0};
+ jstring str = NULL;
+
+ if (JNI_DRM_FAILURE == getObjectIntField(env, rawContent, "id", &id))
+ return NULL;
+
+ if (DRM_SUCCESS == SVC_drm_getRightsIssuer(id, rightsIssuer))
+ str = (*env)->NewStringUTF(env, (char *)rightsIssuer);
+
+ return str;
+}
+
+/* native interface */
+JNIEXPORT jint JNICALL
+Java_android_drm_mobile1_DrmRawContent_nativeGetDeliveryMethod
+ (JNIEnv * env, jobject rawContent)
+{
+ jint id;
+ int32_t res;
+
+ if (JNI_DRM_FAILURE == getObjectIntField(env, rawContent, "id", &id))
+ return JNI_DRM_FAILURE;
+
+ res = SVC_drm_getDeliveryMethod(id);
+
+ switch (res) {
+ case FORWARD_LOCK:
+ return JNI_DRM_FORWARD_LOCK;
+ case COMBINED_DELIVERY:
+ return JNI_DRM_COMBINED_DELIVERY;
+ case SEPARATE_DELIVERY:
+ return JNI_DRM_SEPARATE_DELIVERY;
+ case SEPARATE_DELIVERY_FL:
+ return JNI_DRM_SEPARATE_DELIVERY_DM;
+ default:
+ return JNI_DRM_FAILURE;
+ }
+}
+
+/* native interface */
+JNIEXPORT jint JNICALL
+Java_android_drm_mobile1_DrmRawContent_nativeReadContent
+ (JNIEnv * env, jobject rawContent, jbyteArray buf, jint bufOff, jint len, jint mediaOff)
+{
+ jint id;
+ jbyte *nativeBuf;
+ jclass cls;
+ jmethodID mid;
+ DrmData* p;
+ jobject inputStream;
+ jfieldID field;
+
+ if (NULL == buf) {
+ jclass newExcCls = (*env)->FindClass(env, "java.lang.NullPointerException");
+
+ if (newExcCls == NULL)
+ /* Unable to find the exception class, give up. */
+ return JNI_DRM_FAILURE;
+
+ (*env)->ThrowNew(env, newExcCls, "b is null");
+ }
+
+ if (len < 0 || bufOff < 0 || len + bufOff > (*env)->GetArrayLength(env, buf)) {
+ jclass newExcCls = (*env)->FindClass(env, "java/lang/IndexOutOfBoundsException");
+
+ if (newExcCls == NULL)
+ /* Unable to find the exception class, give up. */
+ return JNI_DRM_FAILURE;
+
+ (*env)->ThrowNew(env, newExcCls, NULL);
+ }
+
+ if (mediaOff < 0 || len == 0)
+ return JNI_DRM_FAILURE;
+
+ if (JNI_DRM_FAILURE == getObjectIntField(env, rawContent, "id", &id))
+ return JNI_DRM_FAILURE;
+
+ p = getItem(id);
+ if (NULL == p)
+ return JNI_DRM_FAILURE;
+
+ cls = (*env)->GetObjectClass(env, rawContent);
+ if (NULL == cls)
+ return JNI_DRM_FAILURE;
+
+ field = (*env)->GetFieldID(env, cls, "inData", "Ljava/io/BufferedInputStream;");
+ (*env)->DeleteLocalRef(env, cls);
+
+ if (NULL == field)
+ return JNI_DRM_FAILURE;
+
+ inputStream = (*env)->GetObjectField(env, rawContent, field);
+
+ p->env = env;
+ p->pInData = &inputStream;
+
+ nativeBuf = (*env)->GetByteArrayElements(env, buf, NULL);
+
+ len = SVC_drm_getContent(id, mediaOff, (uint8_t *)nativeBuf + bufOff, len);
+
+ (*env)->ReleaseByteArrayElements(env, buf, nativeBuf, 0);
+
+ if (DRM_MEDIA_EOF == len)
+ return JNI_DRM_EOF;
+ if (len <= 0)
+ return JNI_DRM_FAILURE;
+
+ return len;
+}
+
+/* native interface */
+JNIEXPORT jstring JNICALL
+Java_android_drm_mobile1_DrmRawContent_nativeGetContentType
+ (JNIEnv * env, jobject rawContent)
+{
+ jint id;
+ uint8_t contentType[64] = {0};
+ jstring str = NULL;
+
+ if (JNI_DRM_FAILURE == getObjectIntField(env, rawContent, "id", &id))
+ return NULL;
+
+ if (DRM_SUCCESS == SVC_drm_getContentType(id, contentType))
+ str = (*env)->NewStringUTF(env, (char *)contentType);
+
+ return str;
+}
+
+/* native interface */
+JNIEXPORT jint JNICALL
+Java_android_drm_mobile1_DrmRawContent_nativeGetContentLength
+ (JNIEnv * env, jobject rawContent)
+{
+ jint id;
+ int32_t len;
+
+ if (JNI_DRM_FAILURE == getObjectIntField(env, rawContent, "id", &id))
+ return JNI_DRM_FAILURE;
+
+ len = SVC_drm_getContentLength(id);
+
+ if (DRM_UNKNOWN_DATA_LEN == len)
+ return JNI_DRM_UNKNOWN_DATA_LEN;
+
+ if (0 > len)
+ return JNI_DRM_FAILURE;
+
+ return len;
+}
+
+/* native interface */
+JNIEXPORT void JNICALL
+Java_android_drm_mobile1_DrmRawContent_finalize
+ (JNIEnv * env, jobject rawContent)
+{
+ jint id;
+
+ if (JNI_DRM_FAILURE == getObjectIntField(env, rawContent, "id", &id))
+ return;
+
+ removeItem(id);
+
+ SVC_drm_closeSession(id);
+}
+
+/* native interface */
+JNIEXPORT jint JNICALL
+Java_android_drm_mobile1_DrmRights_nativeGetConstraintInfo
+ (JNIEnv * env, jobject rights, jint permission, jobject constraint)
+{
+ jclass clazz;
+ jfieldID field;
+ jstring str;
+ uint8_t *nativeStr;
+ T_DRM_Rights_Info_Node *pRightsList;
+ T_DRM_Rights_Info_Node *pCurNode;
+ T_DRM_Constraint_Info *pConstraint;
+
+ clazz = (*env)->GetObjectClass(env, rights);
+ if (NULL == clazz)
+ return JNI_DRM_FAILURE;
+
+ field = (*env)->GetFieldID(env, clazz, "roId", "Ljava/lang/String;");
+ (*env)->DeleteLocalRef(env, clazz);
+
+ if (NULL == field)
+ return JNI_DRM_FAILURE;
+
+ str = (*env)->GetObjectField(env, rights, field);
+
+ nativeStr = (uint8_t *)(*env)->GetStringUTFChars(env, str, NULL);
+ if (NULL == nativeStr)
+ return JNI_DRM_FAILURE;
+
+ /* this means forward-lock rights */
+ if (0 == strcmp((char *)nativeStr, "ForwardLock")) {
+ (*env)->ReleaseStringUTFChars(env, str, (char *)nativeStr);
+ return JNI_DRM_SUCCESS;
+ }
+
+ if (DRM_FAILURE == SVC_drm_viewAllRights(&pRightsList)) {
+ (*env)->ReleaseStringUTFChars(env, str, (char *)nativeStr);
+ return JNI_DRM_FAILURE;
+ }
+
+ pCurNode = searchRightsObject((jbyte *)nativeStr, pRightsList);
+ if (NULL == pCurNode) {
+ (*env)->ReleaseStringUTFChars(env, str, (char *)nativeStr);
+ SVC_drm_freeRightsInfoList(pRightsList);
+ return JNI_DRM_FAILURE;
+ }
+ (*env)->ReleaseStringUTFChars(env, str, (char *)nativeStr);
+
+ switch (permission) {
+ case JNI_DRM_PERMISSION_PLAY:
+ pConstraint = &(pCurNode->roInfo.playRights);
+ break;
+ case JNI_DRM_PERMISSION_DISPLAY:
+ pConstraint = &(pCurNode->roInfo.displayRights);
+ break;
+ case JNI_DRM_PERMISSION_EXECUTE:
+ pConstraint = &(pCurNode->roInfo.executeRights);
+ break;
+ case JNI_DRM_PERMISSION_PRINT:
+ pConstraint = &(pCurNode->roInfo.printRights);
+ break;
+ default:
+ SVC_drm_freeRightsInfoList(pRightsList);
+ return JNI_DRM_FAILURE;
+ }
+
+ /* set constraint field */
+ if (JNI_DRM_FAILURE == setConstraintFields(env, constraint, pConstraint)) {
+ SVC_drm_freeRightsInfoList(pRightsList);
+ return JNI_DRM_FAILURE;
+ }
+
+ SVC_drm_freeRightsInfoList(pRightsList);
+
+ return JNI_DRM_SUCCESS;
+}
+
+/* native interface */
+JNIEXPORT jint JNICALL
+Java_android_drm_mobile1_DrmRights_nativeConsumeRights
+ (JNIEnv * env, jobject rights, jint permission)
+{
+ jclass clazz;
+ jfieldID field;
+ jstring str;
+ uint8_t *nativeStr;
+ int32_t id;
+
+ switch (permission) {
+ case JNI_DRM_PERMISSION_PLAY:
+ permission = DRM_PERMISSION_PLAY;
+ break;
+ case JNI_DRM_PERMISSION_DISPLAY:
+ permission = DRM_PERMISSION_DISPLAY;
+ break;
+ case JNI_DRM_PERMISSION_EXECUTE:
+ permission = DRM_PERMISSION_EXECUTE;
+ break;
+ case JNI_DRM_PERMISSION_PRINT:
+ permission = DRM_PERMISSION_PRINT;
+ break;
+ default:
+ return JNI_DRM_FAILURE;
+ }
+
+ clazz = (*env)->GetObjectClass(env, rights);
+ if (NULL == clazz)
+ return JNI_DRM_FAILURE;
+
+ field = (*env)->GetFieldID(env, clazz, "roId", "Ljava/lang/String;");
+ (*env)->DeleteLocalRef(env, clazz);
+
+ if (NULL == field)
+ return JNI_DRM_FAILURE;
+
+ str = (*env)->GetObjectField(env, rights, field);
+
+ nativeStr = (uint8_t *)(*env)->GetStringUTFChars(env, str, NULL);
+ if (NULL == nativeStr)
+ return JNI_DRM_FAILURE;
+
+ if (0 == strcmp("ForwardLock", (char *)nativeStr)) {
+ (*env)->ReleaseStringUTFChars(env, str, (char *)nativeStr);
+ return JNI_DRM_SUCCESS;
+ }
+
+ if (DRM_SUCCESS != SVC_drm_updateRights(nativeStr, permission)) {
+ (*env)->ReleaseStringUTFChars(env, str, (char *)nativeStr);
+ return JNI_DRM_FAILURE;
+ }
+
+ (*env)->ReleaseStringUTFChars(env, str, (char *)nativeStr);
+
+ return JNI_DRM_SUCCESS;
+}
+
+/* native interface */
+JNIEXPORT jint JNICALL
+Java_android_drm_mobile1_DrmRightsManager_nativeInstallDrmRights
+ (JNIEnv * env, jobject rightsManager, jobject data, jint len, jint mimeType, jobject rights)
+{
+ int32_t id;
+ T_DRM_Input_Data inData;
+ DrmData* drmInData;
+ jclass cls;
+ jmethodID mid;
+ T_DRM_Rights_Info rightsInfo;
+
+ switch (mimeType) {
+ case JNI_DRM_MIMETYPE_RIGHTS_XML:
+ mimeType = TYPE_DRM_RIGHTS_XML;
+ break;
+ case JNI_DRM_MIMETYPE_RIGHTS_WBXML:
+ mimeType = TYPE_DRM_RIGHTS_WBXML;
+ break;
+ case JNI_DRM_MIMETYPE_MESSAGE:
+ mimeType = TYPE_DRM_MESSAGE;
+ break;
+ default:
+ return JNI_DRM_FAILURE;
+ }
+
+ drmInData = newItem();
+ if (NULL == drmInData)
+ return JNI_DRM_FAILURE;
+
+ drmInData->env = env;
+ drmInData->pInData = &data;
+ drmInData->len = len;
+
+ inData.inputHandle = (int32_t)drmInData;
+ inData.mimeType = mimeType;
+ inData.getInputDataLength = getInputStreamDataLength;
+ inData.readInputData = readInputStreamData;
+
+ memset(&rightsInfo, 0, sizeof(T_DRM_Rights_Info));
+ if (DRM_FAILURE == SVC_drm_installRights(inData, &rightsInfo))
+ return JNI_DRM_FAILURE;
+
+ freeItem(drmInData);
+
+ return setRightsFields(env, rights, &rightsInfo);
+}
+
+/* native interface */
+JNIEXPORT jint JNICALL
+Java_android_drm_mobile1_DrmRightsManager_nativeQueryRights
+ (JNIEnv * env, jobject rightsManager, jobject rawContent, jobject rights)
+{
+ jint id;
+ T_DRM_Rights_Info rightsInfo;
+
+ if (JNI_DRM_FAILURE == getObjectIntField(env, rawContent, "id", &id))
+ return JNI_DRM_FAILURE;
+
+ memset(&rightsInfo, 0, sizeof(T_DRM_Rights_Info));
+ if (DRM_SUCCESS != SVC_drm_getRightsInfo(id, &rightsInfo))
+ return JNI_DRM_FAILURE;
+
+ return setRightsFields(env, rights, &rightsInfo);
+}
+
+/* native interface */
+JNIEXPORT jint JNICALL
+Java_android_drm_mobile1_DrmRightsManager_nativeGetNumOfRights
+ (JNIEnv * env, jobject rightsManager)
+{
+ T_DRM_Rights_Info_Node *pRightsList;
+ T_DRM_Rights_Info_Node *pCurNode;
+ int32_t num = 0;
+
+ if (DRM_FAILURE == SVC_drm_viewAllRights(&pRightsList))
+ return JNI_DRM_FAILURE;
+
+ pCurNode = pRightsList;
+ while (pCurNode != NULL) {
+ num++;
+ pCurNode = pCurNode->next;
+ }
+
+ SVC_drm_freeRightsInfoList(pRightsList);
+
+ return num;
+}
+
+/* native interface */
+JNIEXPORT jint JNICALL
+Java_android_drm_mobile1_DrmRightsManager_nativeGetRightsList
+ (JNIEnv * env, jobject rightsManager, jobjectArray rightsArray, jint num)
+{
+ T_DRM_Rights_Info_Node *pRightsList;
+ T_DRM_Rights_Info_Node *pCurNode;
+ int32_t index;
+
+ if (DRM_FAILURE == SVC_drm_viewAllRights(&pRightsList))
+ return JNI_DRM_FAILURE;
+
+ pCurNode = pRightsList;
+ for (index = 0; NULL != pCurNode; index++) {
+ jobject rights = (*env)->GetObjectArrayElement(env, rightsArray, index);
+ if (NULL == rights)
+ break;
+
+ if (JNI_DRM_FAILURE == setRightsFields(env, rights, &(pCurNode->roInfo)))
+ break;
+
+ (*env)->SetObjectArrayElement(env, rightsArray, index, rights);
+
+ pCurNode = pCurNode->next;
+ }
+
+ SVC_drm_freeRightsInfoList(pRightsList);
+
+ return index;
+}
+
+/* native interface */
+JNIEXPORT jint JNICALL
+Java_android_drm_mobile1_DrmRightsManager_nativeDeleteRights
+ (JNIEnv * env, jobject rightsManager, jobject rights)
+{
+ jclass clazz;
+ jfieldID field;
+ jstring str;
+ uint8_t *nativeStr;
+
+ clazz = (*env)->GetObjectClass(env, rights);
+ if (NULL == clazz)
+ return JNI_DRM_FAILURE;
+
+ field = (*env)->GetFieldID(env, clazz, "roId", "Ljava/lang/String;");
+ if (NULL == field)
+ return JNI_DRM_FAILURE;
+
+ str = (*env)->GetObjectField(env, rights, field);
+
+ nativeStr = (uint8_t *)(*env)->GetStringUTFChars(env, str, NULL);
+ if (NULL == nativeStr)
+ return JNI_DRM_FAILURE;
+
+ if (0 == strcmp("ForwardLock", (char *)nativeStr))
+ return JNI_DRM_SUCCESS;
+
+ if (DRM_SUCCESS != SVC_drm_deleteRights(nativeStr)) {
+ (*env)->ReleaseStringUTFChars(env, str, (char *)nativeStr);
+ return JNI_DRM_FAILURE;
+ }
+
+ (*env)->ReleaseStringUTFChars(env, str, (char *)nativeStr);
+ return JNI_DRM_SUCCESS;
+}
+
+/*
+ * Table of methods associated with the DrmRawContent class.
+ */
+static JNINativeMethod gDrmRawContentMethods[] = {
+ /* name, signature, funcPtr */
+ {"nativeConstructDrmContent", "(Ljava/io/InputStream;II)I",
+ (void*)Java_android_drm_mobile1_DrmRawContent_nativeConstructDrmContent},
+ {"nativeGetRightsAddress", "()Ljava/lang/String;",
+ (void*)Java_android_drm_mobile1_DrmRawContent_nativeGetRightsAddress},
+ {"nativeGetDeliveryMethod", "()I",
+ (void*)Java_android_drm_mobile1_DrmRawContent_nativeGetDeliveryMethod},
+ {"nativeReadContent", "([BIII)I",
+ (void*)Java_android_drm_mobile1_DrmRawContent_nativeReadContent},
+ {"nativeGetContentType", "()Ljava/lang/String;",
+ (void*)Java_android_drm_mobile1_DrmRawContent_nativeGetContentType},
+ {"nativeGetContentLength", "()I",
+ (void*)Java_android_drm_mobile1_DrmRawContent_nativeGetContentLength},
+ {"finalize", "()V",
+ (void*)Java_android_drm_mobile1_DrmRawContent_finalize},
+};
+
+/*
+ * Table of methods associated with the DrmRights class.
+ */
+static JNINativeMethod gDrmRightsMethods[] = {
+ /* name, signature, funcPtr */
+ {"nativeGetConstraintInfo", "(ILandroid/drm/mobile1/DrmConstraintInfo;)I",
+ (void*)Java_android_drm_mobile1_DrmRights_nativeGetConstraintInfo},
+ {"nativeConsumeRights", "(I)I",
+ (void*)Java_android_drm_mobile1_DrmRights_nativeConsumeRights},
+};
+
+/*
+ * Table of methods associated with the DrmRightsManager class.
+ */
+static JNINativeMethod gDrmRightsManagerMethods[] = {
+ /* name, signature, funcPtr */
+ {"nativeInstallDrmRights", "(Ljava/io/InputStream;IILandroid/drm/mobile1/DrmRights;)I",
+ (void*)Java_android_drm_mobile1_DrmRightsManager_nativeInstallDrmRights},
+ {"nativeQueryRights", "(Landroid/drm/mobile1/DrmRawContent;Landroid/drm/mobile1/DrmRights;)I",
+ (void*)Java_android_drm_mobile1_DrmRightsManager_nativeQueryRights},
+ {"nativeGetNumOfRights", "()I",
+ (void*)Java_android_drm_mobile1_DrmRightsManager_nativeGetNumOfRights},
+ {"nativeGetRightsList", "([Landroid/drm/mobile1/DrmRights;I)I",
+ (void*)Java_android_drm_mobile1_DrmRightsManager_nativeGetRightsList},
+ {"nativeDeleteRights", "(Landroid/drm/mobile1/DrmRights;)I",
+ (void*)Java_android_drm_mobile1_DrmRightsManager_nativeDeleteRights},
+};
+
+/*
+ * Register several native methods for one class.
+ */
+static int registerNativeMethods(JNIEnv* env, const char* className,
+ JNINativeMethod* gMethods, int numMethods)
+{
+ jclass clazz;
+
+ clazz = (*env)->FindClass(env, className);
+ if (clazz == NULL)
+ return JNI_FALSE;
+
+ if ((*env)->RegisterNatives(env, clazz, gMethods, numMethods) < 0)
+ return JNI_FALSE;
+
+ return JNI_TRUE;
+}
+
+/*
+ * Register native methods for all classes we know about.
+ */
+static int registerNatives(JNIEnv* env)
+{
+ if (!registerNativeMethods(env, "android/drm/mobile1/DrmRawContent",
+ gDrmRawContentMethods, sizeof(gDrmRawContentMethods) / sizeof(gDrmRawContentMethods[0])))
+ return JNI_FALSE;
+
+ if (!registerNativeMethods(env, "android/drm/mobile1/DrmRights",
+ gDrmRightsMethods, sizeof(gDrmRightsMethods) / sizeof(gDrmRightsMethods[0])))
+ return JNI_FALSE;
+
+ if (!registerNativeMethods(env, "android/drm/mobile1/DrmRightsManager",
+ gDrmRightsManagerMethods, sizeof(gDrmRightsManagerMethods) / sizeof(gDrmRightsManagerMethods[0])))
+ return JNI_FALSE;
+
+ return JNI_TRUE;
+}
+
+jint JNI_OnLoad(JavaVM* vm, void* reserved)
+{
+ JNIEnv* env = NULL;
+ jint result = -1;
+
+ printf("Entering JNI_OnLoad\n");
+
+ if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_4) != JNI_OK)
+ goto bail;
+
+ assert(env != NULL);
+
+ if (!registerNatives(env))
+ goto bail;
+
+ /* success -- return valid version number */
+ result = JNI_VERSION_1_4;
+
+bail:
+ printf("Leaving JNI_OnLoad (result=0x%x)\n", result);
+ return result;
+}
diff --git a/media/libdrm/mobile1/src/objmng/drm_api.c b/media/libdrm/mobile1/src/objmng/drm_api.c
new file mode 100644
index 0000000..0e453de
--- /dev/null
+++ b/media/libdrm/mobile1/src/objmng/drm_api.c
@@ -0,0 +1,1944 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <svc_drm.h>
+#include <drm_inner.h>
+#include <parser_dm.h>
+#include <parser_dcf.h>
+#include <parser_rel.h>
+#include <drm_rights_manager.h>
+#include <drm_time.h>
+#include <drm_decoder.h>
+#include <aes.h>
+#include "log.h"
+
+/**
+ * Current id.
+ */
+static int32_t curID = 0;
+
+/**
+ * The header pointer for the session list.
+ */
+static T_DRM_Session_Node* sessionTable = NULL;
+
+/**
+ * New a session.
+ */
+static T_DRM_Session_Node* newSession(T_DRM_Input_Data data)
+{
+ T_DRM_Session_Node* s = (T_DRM_Session_Node *)malloc(sizeof(T_DRM_Session_Node));
+
+ if (NULL != s) {
+ memset(s, 0, sizeof(T_DRM_Session_Node));
+
+ s->sessionId = curID++;
+ s->inputHandle = data.inputHandle;
+ s->mimeType = data.mimeType;
+ s->getInputDataLengthFunc = data.getInputDataLength;
+ s->readInputDataFunc = data.readInputData;
+ s->seekInputDataFunc = data.seekInputData;
+ }
+
+ return s;
+}
+
+/**
+ * Free a session.
+ */
+static void freeSession(T_DRM_Session_Node* s)
+{
+ if (NULL == s)
+ return;
+
+ if (NULL != s->rawContent)
+ free(s->rawContent);
+
+ if (NULL != s->readBuf)
+ free(s->readBuf);
+
+ if (NULL != s->infoStruct)
+ free(s->infoStruct);
+
+ free(s);
+}
+
+/**
+ * Add a session to list.
+ */
+static int32_t addSession(T_DRM_Session_Node* s)
+{
+ if (NULL == s)
+ return -1;
+
+ s->next = sessionTable;
+ sessionTable = s;
+
+ return s->sessionId;
+}
+
+/**
+ * Get a session from the list.
+ */
+static T_DRM_Session_Node* getSession(int32_t sessionId)
+{
+ T_DRM_Session_Node* s;
+
+ if (sessionId < 0 || NULL == sessionTable)
+ return NULL;
+
+ for (s = sessionTable; s != NULL; s = s->next) {
+ if (sessionId == s->sessionId)
+ return s;
+ }
+
+ return NULL;
+}
+
+/**
+ * Remove a session from the list.
+ */
+static void removeSession(int32_t sessionId)
+{
+ T_DRM_Session_Node *curS, *preS;
+
+ if (sessionId < 0 || NULL == sessionTable)
+ return;
+
+ if (sessionId == sessionTable->sessionId) {
+ curS = sessionTable;
+ sessionTable = curS->next;
+ freeSession(curS);
+ return;
+ }
+
+ for (preS = sessionTable; preS->next != NULL; preS = preS->next) {
+ if (preS->next->sessionId == sessionId)
+ curS = preS->next;
+ }
+
+ if (NULL == preS->next)
+ return;
+
+ preS->next = curS->next;
+ freeSession(curS);
+}
+
+/**
+ * Try to identify the mimetype according the input DRM data.
+ */
+static int32_t getMimeType(const uint8_t *buf, int32_t bufLen)
+{
+ const uint8_t *p;
+
+ if (NULL == buf || bufLen <= 0)
+ return TYPE_DRM_UNKNOWN;
+
+ p = buf;
+
+ /* check if it is DRM Content Format, only check the first field of Version, it must be "0x01" */
+ if (0x01 == *p)
+ return TYPE_DRM_CONTENT;
+
+ /* check if it is DRM Message, only check the first two bytes, it must be the start flag of boundary: "--" */
+ if (bufLen >= 2 && '-' == *p && '-' == *(p + 1))
+ return TYPE_DRM_MESSAGE;
+
+ /* check if it is DRM Rights XML format, only check the first several bytes, it must be: "<o-ex:rights" */
+ if (bufLen >= 12 && 0 == strncmp("<o-ex:rights", (char *)p, 12))
+ return TYPE_DRM_RIGHTS_XML;
+
+ /* check if it is DRM Rights WBXML format, only check the first two bytes, it must be: 0x03, 0x0e */
+ if (bufLen >= 2 && 0x03 == *p && 0x0e == *(p + 1))
+ return TYPE_DRM_RIGHTS_WBXML;
+
+ return TYPE_DRM_UNKNOWN;
+}
+
+static int32_t drm_skipCRLFinB64(const uint8_t* b64Data, int32_t len)
+{
+ const uint8_t* p;
+ int32_t skipLen = 0;
+
+ if (NULL == b64Data || len <= 0)
+ return -1;
+
+ p = b64Data;
+ while (p - b64Data < len) {
+ if ('\r' == *p || '\n'== *p)
+ skipLen++;
+ p++;
+ }
+
+ return skipLen;
+}
+
+static int32_t drm_scanEndBoundary(const uint8_t* pBuf, int32_t len, uint8_t* const boundary)
+{
+ const uint8_t* p;
+ int32_t leftLen;
+ int32_t boundaryLen;
+
+ if (NULL == pBuf || len <=0 || NULL == boundary)
+ return -1;
+
+ p = pBuf;
+ boundaryLen = strlen((char *)boundary) + 2; /* 2 means: '\r' and '\n' */
+ leftLen = len - (p - pBuf);
+ while (leftLen > 0) {
+ if (NULL == (p = memchr(p, '\r', leftLen)))
+ break;
+
+ leftLen = len - (p - pBuf);
+ if (leftLen < boundaryLen)
+ return -2; /* here means may be the boundary has been split */
+
+ if (('\n' == *(p + 1)) && (0 == memcmp(p + 2, boundary, strlen((char *)boundary))))
+ return p - pBuf; /* find the boundary here */
+
+ p++;
+ leftLen--;
+ }
+
+ return len; /* no boundary found */
+}
+
+static int32_t drm_getLicenseInfo(T_DRM_Rights* pRights, T_DRM_Rights_Info* licenseInfo)
+{
+ if (NULL != licenseInfo && NULL != pRights) {
+ strcpy((char *)licenseInfo->roId, (char *)pRights->uid);
+
+ if (1 == pRights->bIsDisplayable) {
+ licenseInfo->displayRights.indicator = pRights->DisplayConstraint.Indicator;
+ licenseInfo->displayRights.count =
+ pRights->DisplayConstraint.Count;
+ licenseInfo->displayRights.startDate =
+ pRights->DisplayConstraint.StartTime.date;
+ licenseInfo->displayRights.startTime =
+ pRights->DisplayConstraint.StartTime.time;
+ licenseInfo->displayRights.endDate =
+ pRights->DisplayConstraint.EndTime.date;
+ licenseInfo->displayRights.endTime =
+ pRights->DisplayConstraint.EndTime.time;
+ licenseInfo->displayRights.intervalDate =
+ pRights->DisplayConstraint.Interval.date;
+ licenseInfo->displayRights.intervalTime =
+ pRights->DisplayConstraint.Interval.time;
+ }
+ if (1 == pRights->bIsPlayable) {
+ licenseInfo->playRights.indicator = pRights->PlayConstraint.Indicator;
+ licenseInfo->playRights.count = pRights->PlayConstraint.Count;
+ licenseInfo->playRights.startDate =
+ pRights->PlayConstraint.StartTime.date;
+ licenseInfo->playRights.startTime =
+ pRights->PlayConstraint.StartTime.time;
+ licenseInfo->playRights.endDate =
+ pRights->PlayConstraint.EndTime.date;
+ licenseInfo->playRights.endTime =
+ pRights->PlayConstraint.EndTime.time;
+ licenseInfo->playRights.intervalDate =
+ pRights->PlayConstraint.Interval.date;
+ licenseInfo->playRights.intervalTime =
+ pRights->PlayConstraint.Interval.time;
+ }
+ if (1 == pRights->bIsExecuteable) {
+ licenseInfo->executeRights.indicator = pRights->ExecuteConstraint.Indicator;
+ licenseInfo->executeRights.count =
+ pRights->ExecuteConstraint.Count;
+ licenseInfo->executeRights.startDate =
+ pRights->ExecuteConstraint.StartTime.date;
+ licenseInfo->executeRights.startTime =
+ pRights->ExecuteConstraint.StartTime.time;
+ licenseInfo->executeRights.endDate =
+ pRights->ExecuteConstraint.EndTime.date;
+ licenseInfo->executeRights.endTime =
+ pRights->ExecuteConstraint.EndTime.time;
+ licenseInfo->executeRights.intervalDate =
+ pRights->ExecuteConstraint.Interval.date;
+ licenseInfo->executeRights.intervalTime =
+ pRights->ExecuteConstraint.Interval.time;
+ }
+ if (1 == pRights->bIsPrintable) {
+ licenseInfo->printRights.indicator = pRights->PrintConstraint.Indicator;
+ licenseInfo->printRights.count =
+ pRights->PrintConstraint.Count;
+ licenseInfo->printRights.startDate =
+ pRights->PrintConstraint.StartTime.date;
+ licenseInfo->printRights.startTime =
+ pRights->PrintConstraint.StartTime.time;
+ licenseInfo->printRights.endDate =
+ pRights->PrintConstraint.EndTime.date;
+ licenseInfo->printRights.endTime =
+ pRights->PrintConstraint.EndTime.time;
+ licenseInfo->printRights.intervalDate =
+ pRights->PrintConstraint.Interval.date;
+ licenseInfo->printRights.intervalTime =
+ pRights->PrintConstraint.Interval.time;
+ }
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static int32_t drm_addRightsNodeToList(T_DRM_Rights_Info_Node **ppRightsHeader,
+ T_DRM_Rights_Info_Node *pInputRightsNode)
+{
+ T_DRM_Rights_Info_Node *pRightsNode;
+
+ if (NULL == ppRightsHeader || NULL == pInputRightsNode)
+ return FALSE;
+
+ pRightsNode = (T_DRM_Rights_Info_Node *)malloc(sizeof(T_DRM_Rights_Info_Node));
+ if (NULL == pRightsNode)
+ return FALSE;
+
+ memcpy(pRightsNode, pInputRightsNode, sizeof(T_DRM_Rights_Info_Node));
+ pRightsNode->next = NULL;
+
+ /* this means it is the first node */
+ if (NULL == *ppRightsHeader)
+ *ppRightsHeader = pRightsNode;
+ else {
+ T_DRM_Rights_Info_Node *pTmp;
+
+ pTmp = *ppRightsHeader;
+ while (NULL != pTmp->next)
+ pTmp = pTmp->next;
+
+ pTmp->next = pRightsNode;
+ }
+ return TRUE;
+}
+
+static int32_t drm_startConsumeRights(int32_t * bIsXXable,
+ T_DRM_Rights_Constraint * XXConstraint,
+ int32_t * writeFlag)
+{
+ T_DB_TIME_SysTime curDateTime;
+ T_DRM_DATETIME CurrentTime;
+ uint8_t countFlag = 0;
+
+ memset(&CurrentTime, 0, sizeof(T_DRM_DATETIME));
+
+ if (NULL == bIsXXable || 0 == *bIsXXable || NULL == XXConstraint || NULL == writeFlag)
+ return DRM_FAILURE;
+
+ if (0 != (uint8_t)(XXConstraint->Indicator & DRM_NO_CONSTRAINT)) /* Have utter right? */
+ return DRM_SUCCESS;
+
+ *bIsXXable = 0; /* Assume have invalid rights at first */
+ *writeFlag = 0;
+
+ if (0 != (XXConstraint->Indicator & (DRM_START_TIME_CONSTRAINT | DRM_END_TIME_CONSTRAINT | DRM_INTERVAL_CONSTRAINT))) {
+ DRM_time_getSysTime(&curDateTime);
+
+ if (-1 == drm_checkDate(curDateTime.year, curDateTime.month, curDateTime.day,
+ curDateTime.hour, curDateTime.min, curDateTime.sec))
+ return DRM_FAILURE;
+
+ YMD_HMS_2_INT(curDateTime.year, curDateTime.month, curDateTime.day,
+ CurrentTime.date, curDateTime.hour, curDateTime.min,
+ curDateTime.sec, CurrentTime.time);
+ }
+
+ if (0 != (uint8_t)(XXConstraint->Indicator & DRM_COUNT_CONSTRAINT)) { /* Have count restrict? */
+ *writeFlag = 1;
+ /* If it has only one time for use, after use this function, we will delete this rights */
+ if (XXConstraint->Count <= 0) {
+ XXConstraint->Indicator &= ~DRM_COUNT_CONSTRAINT;
+ return DRM_RIGHTS_EXPIRED;
+ }
+
+ if (XXConstraint->Count-- <= 1) {
+ XXConstraint->Indicator &= ~DRM_COUNT_CONSTRAINT;
+ countFlag = 1;
+ }
+ }
+
+ if (0 != (uint8_t)(XXConstraint->Indicator & DRM_START_TIME_CONSTRAINT)) {
+ if (XXConstraint->StartTime.date > CurrentTime.date ||
+ (XXConstraint->StartTime.date == CurrentTime.date &&
+ XXConstraint->StartTime.time >= CurrentTime.time)) {
+ *bIsXXable = 1;
+ return DRM_RIGHTS_PENDING;
+ }
+ }
+
+ if (0 != (uint8_t)(XXConstraint->Indicator & DRM_END_TIME_CONSTRAINT)) { /* Have end time restrict? */
+ if (XXConstraint->EndTime.date < CurrentTime.date ||
+ (XXConstraint->EndTime.date == CurrentTime.date &&
+ XXConstraint->EndTime.time <= CurrentTime.time)) {
+ *writeFlag = 1;
+ XXConstraint->Indicator &= ~DRM_END_TIME_CONSTRAINT;
+ return DRM_RIGHTS_EXPIRED;
+ }
+ }
+
+ if (0 != (uint8_t)(XXConstraint->Indicator & DRM_INTERVAL_CONSTRAINT)) { /* Have interval time restrict? */
+ int32_t year, mon, day, hour, min, sec, date, time;
+ int32_t ret;
+
+ XXConstraint->Indicator |= DRM_END_TIME_CONSTRAINT;
+ XXConstraint->Indicator &= ~DRM_INTERVAL_CONSTRAINT; /* Write off interval right */
+ *writeFlag = 1;
+
+ if (XXConstraint->Interval.date == 0
+ && XXConstraint->Interval.time == 0) {
+ return DRM_RIGHTS_EXPIRED;
+ }
+ date = CurrentTime.date + XXConstraint->Interval.date;
+ time = CurrentTime.time + XXConstraint->Interval.time;
+ INT_2_YMD_HMS(year, mon, day, date, hour, min, sec, time);
+
+ if (sec > 59) {
+ min += sec / 60;
+ sec %= 60;
+ }
+ if (min > 59) {
+ hour += min / 60;
+ min %= 60;
+ }
+ if (hour > 23) {
+ day += hour / 24;
+ hour %= 24;
+ }
+ if (day > 31) {
+ mon += day / 31;
+ day %= 31;
+ }
+ if (mon > 12) {
+ year += mon / 12;
+ mon %= 12;
+ }
+ if (day > (ret = drm_monthDays(year, mon))) {
+ day -= ret;
+ mon++;
+ if (mon > 12) {
+ mon -= 12;
+ year++;
+ }
+ }
+ YMD_HMS_2_INT(year, mon, day, XXConstraint->EndTime.date, hour,
+ min, sec, XXConstraint->EndTime.time);
+ }
+
+ if (1 != countFlag)
+ *bIsXXable = 1; /* Can go here ,so right must be valid */
+ return DRM_SUCCESS;
+}
+
+static int32_t drm_startCheckRights(int32_t * bIsXXable,
+ T_DRM_Rights_Constraint * XXConstraint)
+{
+ T_DB_TIME_SysTime curDateTime;
+ T_DRM_DATETIME CurrentTime;
+
+ memset(&CurrentTime, 0, sizeof(T_DRM_DATETIME));
+
+ if (NULL == bIsXXable || 0 == *bIsXXable || NULL == XXConstraint)
+ return DRM_FAILURE;
+
+ if (0 != (uint8_t)(XXConstraint->Indicator & DRM_NO_CONSTRAINT)) /* Have utter right? */
+ return DRM_SUCCESS;
+
+ *bIsXXable = 0; /* Assume have invalid rights at first */
+
+ if (0 != (XXConstraint->Indicator & (DRM_START_TIME_CONSTRAINT | DRM_END_TIME_CONSTRAINT))) {
+ DRM_time_getSysTime(&curDateTime);
+
+ if (-1 == drm_checkDate(curDateTime.year, curDateTime.month, curDateTime.day,
+ curDateTime.hour, curDateTime.min, curDateTime.sec))
+ return DRM_FAILURE;
+
+ YMD_HMS_2_INT(curDateTime.year, curDateTime.month, curDateTime.day,
+ CurrentTime.date, curDateTime.hour, curDateTime.min,
+ curDateTime.sec, CurrentTime.time);
+ }
+
+ if (0 != (uint8_t)(XXConstraint->Indicator & DRM_COUNT_CONSTRAINT)) { /* Have count restrict? */
+ if (XXConstraint->Count <= 0) {
+ XXConstraint->Indicator &= ~DRM_COUNT_CONSTRAINT;
+ return DRM_RIGHTS_EXPIRED;
+ }
+ }
+
+ if (0 != (uint8_t)(XXConstraint->Indicator & DRM_START_TIME_CONSTRAINT)) {
+ if (XXConstraint->StartTime.date > CurrentTime.date ||
+ (XXConstraint->StartTime.date == CurrentTime.date &&
+ XXConstraint->StartTime.time >= CurrentTime.time)) {
+ *bIsXXable = 1;
+ return DRM_RIGHTS_PENDING;
+ }
+ }
+
+ if (0 != (uint8_t)(XXConstraint->Indicator & DRM_END_TIME_CONSTRAINT)) { /* Have end time restrict? */
+ if (XXConstraint->EndTime.date < CurrentTime.date ||
+ (XXConstraint->EndTime.date == CurrentTime.date &&
+ XXConstraint->EndTime.time <= CurrentTime.time)) {
+ XXConstraint->Indicator &= ~DRM_END_TIME_CONSTRAINT;
+ return DRM_RIGHTS_EXPIRED;
+ }
+ }
+
+ if (0 != (uint8_t)(XXConstraint->Indicator & DRM_INTERVAL_CONSTRAINT)) { /* Have interval time restrict? */
+ if (XXConstraint->Interval.date == 0 && XXConstraint->Interval.time == 0) {
+ XXConstraint->Indicator &= ~DRM_INTERVAL_CONSTRAINT;
+ return DRM_RIGHTS_EXPIRED;
+ }
+ }
+
+ *bIsXXable = 1;
+ return DRM_SUCCESS;
+}
+
+int32_t drm_checkRoAndUpdate(int32_t id, int32_t permission)
+{
+ int32_t writeFlag = 0;
+ int32_t roAmount;
+ int32_t validRoAmount = 0;
+ int32_t flag = DRM_FAILURE;
+ int32_t i, j;
+ T_DRM_Rights *pRo;
+ T_DRM_Rights *pCurRo;
+ int32_t * pNumOfPriority;
+ int32_t iNum;
+ T_DRM_Rights_Constraint * pCurConstraint;
+ T_DRM_Rights_Constraint * pCompareConstraint;
+ int priority[8] = {1, 2, 4, 3, 8, 6, 7, 5};
+
+ if (FALSE == drm_writeOrReadInfo(id, NULL, &roAmount, GET_ROAMOUNT))
+ return DRM_FAILURE;
+
+ validRoAmount = roAmount;
+ if (roAmount < 1)
+ return DRM_NO_RIGHTS;
+
+ pRo = malloc(roAmount * sizeof(T_DRM_Rights));
+ pCurRo = pRo;
+ if (NULL == pRo)
+ return DRM_FAILURE;
+
+ if (FALSE == drm_writeOrReadInfo(id, pRo, &roAmount, GET_ALL_RO)) {
+ free(pRo);
+ return DRM_FAILURE;
+ }
+
+ /** check the right priority */
+ pNumOfPriority = malloc(sizeof(int32_t) * roAmount);
+ for(i = 0; i < roAmount; i++) {
+ iNum = roAmount - 1;
+ for(j = 0; j < roAmount; j++) {
+ if(i == j)
+ continue;
+ switch(permission) {
+ case DRM_PERMISSION_PLAY:
+ pCurConstraint = &pRo[i].PlayConstraint;
+ pCompareConstraint = &pRo[j].PlayConstraint;
+ break;
+ case DRM_PERMISSION_DISPLAY:
+ pCurConstraint = &pRo[i].DisplayConstraint;
+ pCompareConstraint = &pRo[j].DisplayConstraint;
+ break;
+ case DRM_PERMISSION_EXECUTE:
+ pCurConstraint = &pRo[i].ExecuteConstraint;
+ pCompareConstraint = &pRo[j].ExecuteConstraint;
+ break;
+ case DRM_PERMISSION_PRINT:
+ pCurConstraint = &pRo[i].PrintConstraint;
+ pCompareConstraint = &pRo[j].PrintConstraint;
+ break;
+ default:
+ free(pRo);
+ free(pNumOfPriority);
+ return DRM_FAILURE;
+ }
+
+ /**get priority by Indicator*/
+ if(0 == (pCurConstraint->Indicator & DRM_NO_CONSTRAINT) &&
+ 0 == (pCompareConstraint->Indicator & DRM_NO_CONSTRAINT)) {
+ int num1, num2;
+ num1 = (pCurConstraint->Indicator & 0x0e) >> 1;
+ num2 = (pCompareConstraint->Indicator & 0x0e) >> 1;
+ if(priority[num1] > priority[num2]) {
+ iNum--;
+ continue;
+ } else if(priority[pCurConstraint->Indicator] < priority[pCompareConstraint->Indicator])
+ continue;
+ } else if(pCurConstraint->Indicator > pCompareConstraint->Indicator) {
+ iNum--;
+ continue;
+ } else if(pCurConstraint->Indicator < pCompareConstraint->Indicator)
+ continue;
+
+ if(0 != (pCurConstraint->Indicator & DRM_END_TIME_CONSTRAINT)) {
+ if(pCurConstraint->EndTime.date < pCompareConstraint->EndTime.date) {
+ iNum--;
+ continue;
+ } else if(pCurConstraint->EndTime.date > pCompareConstraint->EndTime.date)
+ continue;
+
+ if(pCurConstraint->EndTime.time < pCompareConstraint->EndTime.time) {
+ iNum--;
+ continue;
+ } else if(pCurConstraint->EndTime.date > pCompareConstraint->EndTime.date)
+ continue;
+ }
+
+ if(0 != (pCurConstraint->Indicator & DRM_INTERVAL_CONSTRAINT)) {
+ if(pCurConstraint->Interval.date < pCompareConstraint->Interval.date) {
+ iNum--;
+ continue;
+ } else if(pCurConstraint->Interval.date > pCompareConstraint->Interval.date)
+ continue;
+
+ if(pCurConstraint->Interval.time < pCompareConstraint->Interval.time) {
+ iNum--;
+ continue;
+ } else if(pCurConstraint->Interval.time > pCompareConstraint->Interval.time)
+ continue;
+ }
+
+ if(0 != (pCurConstraint->Indicator & DRM_COUNT_CONSTRAINT)) {
+ if(pCurConstraint->Count < pCompareConstraint->Count) {
+ iNum--;
+ continue;
+ } else if(pCurConstraint->Count > pCompareConstraint->Count)
+ continue;
+ }
+
+ if(i < j)
+ iNum--;
+ }
+ pNumOfPriority[iNum] = i;
+ }
+
+ for (i = 0; i < validRoAmount; i++) {
+ /** check the right priority */
+ if (pNumOfPriority[i] >= validRoAmount)
+ break;
+
+ pCurRo = pRo + pNumOfPriority[i];
+
+ switch (permission) {
+ case DRM_PERMISSION_PLAY:
+ flag =
+ drm_startConsumeRights(&pCurRo->bIsPlayable,
+ &pCurRo->PlayConstraint, &writeFlag);
+ break;
+ case DRM_PERMISSION_DISPLAY:
+ flag =
+ drm_startConsumeRights(&pCurRo->bIsDisplayable,
+ &pCurRo->DisplayConstraint,
+ &writeFlag);
+ break;
+ case DRM_PERMISSION_EXECUTE:
+ flag =
+ drm_startConsumeRights(&pCurRo->bIsExecuteable,
+ &pCurRo->ExecuteConstraint,
+ &writeFlag);
+ break;
+ case DRM_PERMISSION_PRINT:
+ flag =
+ drm_startConsumeRights(&pCurRo->bIsPrintable,
+ &pCurRo->PrintConstraint, &writeFlag);
+ break;
+ default:
+ free(pNumOfPriority);
+ free(pRo);
+ return DRM_FAILURE;
+ }
+
+ /* Here confirm the valid RO amount and set the writeFlag */
+ if (0 == pCurRo->bIsPlayable && 0 == pCurRo->bIsDisplayable &&
+ 0 == pCurRo->bIsExecuteable && 0 == pCurRo->bIsPrintable) {
+ int32_t iCurPri;
+
+ /** refresh the right priority */
+ iCurPri = pNumOfPriority[i];
+ for(j = i; j < validRoAmount - 1; j++)
+ pNumOfPriority[j] = pNumOfPriority[j + 1];
+
+ if(iCurPri != validRoAmount - 1) {
+ memcpy(pCurRo, pRo + validRoAmount - 1,
+ sizeof(T_DRM_Rights));
+ for(j = 0; j < validRoAmount -1; j++) {
+ if(validRoAmount - 1 == pNumOfPriority[j])
+ pNumOfPriority[j] = iCurPri;
+ }
+ }
+
+ /* Here means it is not the last one RO, so the invalid RO should be deleted */
+ writeFlag = 1;
+ validRoAmount--; /* If current right is invalid */
+ i--;
+ }
+
+ /* If the flag is TRUE, this means: we have found a valid RO, so break, no need to check other RO */
+ if (DRM_SUCCESS == flag)
+ break;
+ }
+
+ if (1 == writeFlag) {
+ /* Delete the *.info first */
+ //drm_removeIdInfoFile(id);
+
+ if (FALSE == drm_writeOrReadInfo(id, pRo, &validRoAmount, SAVE_ALL_RO))
+ flag = DRM_FAILURE;
+ }
+
+ free(pNumOfPriority);
+ free(pRo);
+ return flag;
+}
+
+
+/* see svc_drm.h */
+int32_t SVC_drm_installRights(T_DRM_Input_Data data, T_DRM_Rights_Info* pRightsInfo)
+{
+ uint8_t *buf;
+ int32_t dataLen, bufLen;
+ T_DRM_Rights rights;
+
+ if (0 == data.inputHandle)
+ return DRM_RIGHTS_DATA_INVALID;
+
+ /* Get input rights data length */
+ dataLen = data.getInputDataLength(data.inputHandle);
+ if (dataLen <= 0)
+ return DRM_RIGHTS_DATA_INVALID;
+
+ /* Check if the length is larger than DRM max malloc length */
+ if (dataLen > DRM_MAX_MALLOC_LEN)
+ bufLen = DRM_MAX_MALLOC_LEN;
+ else
+ bufLen = dataLen;
+
+ buf = (uint8_t *)malloc(bufLen);
+ if (NULL == buf)
+ return DRM_FAILURE;
+
+ /* Read input data to buffer */
+ if (0 >= data.readInputData(data.inputHandle, buf, bufLen)) {
+ free(buf);
+ return DRM_RIGHTS_DATA_INVALID;
+ }
+
+ /* if the input mime type is unknown, DRM engine will try to recognize it. */
+ if (TYPE_DRM_UNKNOWN == data.mimeType)
+ data.mimeType = getMimeType(buf, bufLen);
+
+ switch(data.mimeType) {
+ case TYPE_DRM_MESSAGE: /* in case of Combined Delivery, extract the rights part to install */
+ {
+ T_DRM_DM_Info dmInfo;
+
+ memset(&dmInfo, 0, sizeof(T_DRM_DM_Info));
+ if (FALSE == drm_parseDM(buf, bufLen, &dmInfo)) {
+ free(buf);
+ return DRM_RIGHTS_DATA_INVALID;
+ }
+
+ /* if it is not Combined Delivery, it can not use to "SVC_drm_installRights" */
+ if (COMBINED_DELIVERY != dmInfo.deliveryType || dmInfo.rightsOffset <= 0 || dmInfo.rightsLen <= 0) {
+ free(buf);
+ return DRM_RIGHTS_DATA_INVALID;
+ }
+
+ memset(&rights, 0, sizeof(T_DRM_Rights));
+ if (FALSE == drm_relParser(buf + dmInfo.rightsOffset, dmInfo.rightsLen, TYPE_DRM_RIGHTS_XML, &rights)) {
+ free(buf);
+ return DRM_RIGHTS_DATA_INVALID;
+ }
+ }
+ break;
+ case TYPE_DRM_RIGHTS_XML:
+ case TYPE_DRM_RIGHTS_WBXML:
+ memset(&rights, 0, sizeof(T_DRM_Rights));
+ if (FALSE == drm_relParser(buf, bufLen, data.mimeType, &rights)) {
+ free(buf);
+ return DRM_RIGHTS_DATA_INVALID;
+ }
+ break;
+ case TYPE_DRM_CONTENT: /* DCF should not using "SVC_drm_installRights", it should be used to open a session. */
+ case TYPE_DRM_UNKNOWN:
+ default:
+ free(buf);
+ return DRM_MEDIA_DATA_INVALID;
+ }
+
+ free(buf);
+
+ /* append the rights information to DRM engine storage */
+ if (FALSE == drm_appendRightsInfo(&rights))
+ return DRM_FAILURE;
+
+ memset(pRightsInfo, 0, sizeof(T_DRM_Rights_Info));
+ drm_getLicenseInfo(&rights, pRightsInfo);
+
+ return DRM_SUCCESS;
+}
+
+/* see svc_drm.h */
+int32_t SVC_drm_openSession(T_DRM_Input_Data data)
+{
+ int32_t session;
+ int32_t dataLen;
+ T_DRM_Session_Node* s;
+
+ if (0 == data.inputHandle)
+ return DRM_MEDIA_DATA_INVALID;
+
+ /* Get input data length */
+ dataLen = data.getInputDataLength(data.inputHandle);
+ if (dataLen <= 0)
+ return DRM_MEDIA_DATA_INVALID;
+
+ s = newSession(data);
+ if (NULL == s)
+ return DRM_FAILURE;
+
+ /* Check if the length is larger than DRM max malloc length */
+ if (dataLen > DRM_MAX_MALLOC_LEN)
+ s->rawContentLen = DRM_MAX_MALLOC_LEN;
+ else
+ s->rawContentLen = dataLen;
+
+ s->rawContent = (uint8_t *)malloc(s->rawContentLen);
+ if (NULL == s->rawContent)
+ return DRM_FAILURE;
+
+ /* Read input data to buffer */
+ if (0 >= data.readInputData(data.inputHandle, s->rawContent, s->rawContentLen)) {
+ freeSession(s);
+ return DRM_MEDIA_DATA_INVALID;
+ }
+
+ /* if the input mime type is unknown, DRM engine will try to recognize it. */
+ if (TYPE_DRM_UNKNOWN == data.mimeType)
+ data.mimeType = getMimeType(s->rawContent, s->rawContentLen);
+
+ switch(data.mimeType) {
+ case TYPE_DRM_MESSAGE:
+ {
+ T_DRM_DM_Info dmInfo;
+
+ memset(&dmInfo, 0, sizeof(T_DRM_DM_Info));
+ if (FALSE == drm_parseDM(s->rawContent, s->rawContentLen, &dmInfo)) {
+ freeSession(s);
+ return DRM_MEDIA_DATA_INVALID;
+ }
+
+ s->deliveryMethod = dmInfo.deliveryType;
+
+ if (SEPARATE_DELIVERY_FL == s->deliveryMethod)
+ s->contentLength = DRM_UNKNOWN_DATA_LEN;
+ else
+ s->contentLength = dmInfo.contentLen;
+
+ s->transferEncoding = dmInfo.transferEncoding;
+ s->contentOffset = dmInfo.contentOffset;
+ s->bEndData = FALSE;
+ strcpy((char *)s->contentType, (char *)dmInfo.contentType);
+ strcpy((char *)s->contentID, (char *)dmInfo.contentID);
+
+ if (SEPARATE_DELIVERY_FL == s->deliveryMethod) {
+ s->infoStruct = (T_DRM_Dcf_Node *)malloc(sizeof(T_DRM_Dcf_Node));
+ if (NULL == s->infoStruct)
+ return DRM_FAILURE;
+ memset(s->infoStruct, 0, sizeof(T_DRM_Dcf_Node));
+
+ ((T_DRM_Dcf_Node *)(s->infoStruct))->encContentLength = dmInfo.contentLen;
+ strcpy((char *)((T_DRM_Dcf_Node *)(s->infoStruct))->rightsIssuer, (char *)dmInfo.rightsIssuer);
+ break;
+ }
+
+ if (DRM_MESSAGE_CODING_BASE64 == s->transferEncoding) {
+ s->infoStruct = (T_DRM_DM_Base64_Node *)malloc(sizeof(T_DRM_DM_Base64_Node));
+ if (NULL == s->infoStruct)
+ return DRM_FAILURE;
+ memset(s->infoStruct, 0, sizeof(T_DRM_DM_Base64_Node));
+
+ strcpy((char *)((T_DRM_DM_Base64_Node *)(s->infoStruct))->boundary, (char *)dmInfo.boundary);
+ } else {
+ s->infoStruct = (T_DRM_DM_Binary_Node *)malloc(sizeof(T_DRM_DM_Binary_Node));
+ if (NULL == s->infoStruct)
+ return DRM_FAILURE;
+ memset(s->infoStruct, 0, sizeof(T_DRM_DM_Binary_Node));
+
+ strcpy((char *)((T_DRM_DM_Binary_Node *)(s->infoStruct))->boundary, (char *)dmInfo.boundary);
+ }
+
+
+ if (DRM_MESSAGE_CODING_BASE64 == s->transferEncoding) {
+ if (s->contentLength > 0) {
+ int32_t encLen, decLen;
+
+ encLen = s->contentLength;
+ decLen = encLen / DRM_B64_ENC_BLOCK * DRM_B64_DEC_BLOCK;
+
+ decLen = drm_decodeBase64(s->rawContent, decLen, s->rawContent + s->contentOffset, &encLen);
+ s->contentLength = decLen;
+ } else {
+ int32_t encLen = DRM_MAX_MALLOC_LEN - s->contentOffset, decLen;
+ int32_t skipLen, needBytes, i;
+ uint8_t *pStart;
+ int32_t res, bFoundBoundary = FALSE;
+
+ pStart = s->rawContent + s->contentOffset;
+ if (-1 == (skipLen = drm_skipCRLFinB64(pStart, encLen))) {
+ freeSession(s);
+ return DRM_FAILURE;
+ }
+
+ needBytes = DRM_B64_ENC_BLOCK - ((encLen - skipLen) % DRM_B64_ENC_BLOCK);
+ if (needBytes < DRM_B64_ENC_BLOCK) {
+ s->rawContent = (uint8_t *)realloc(s->rawContent, DRM_MAX_MALLOC_LEN + needBytes);
+ if (NULL == s->rawContent) {
+ freeSession(s);
+ return DRM_FAILURE;
+ }
+
+ i = 0;
+ while (i < needBytes) {
+ if (-1 != data.readInputData(data.inputHandle, s->rawContent + DRM_MAX_MALLOC_LEN + i, 1)) {
+ if ('\r' == *(s->rawContent + DRM_MAX_MALLOC_LEN + i) || '\n' == *(s->rawContent + DRM_MAX_MALLOC_LEN + i))
+ continue;
+ i++;
+ } else
+ break;
+ }
+ encLen += i;
+ }
+
+ res = drm_scanEndBoundary(pStart, encLen, ((T_DRM_DM_Base64_Node *)(s->infoStruct))->boundary);
+ if (-1 == res) {
+ freeSession(s);
+ return DRM_FAILURE;
+ }
+ if (-2 == res) { /* may be there is a boundary */
+ int32_t boundaryLen, leftLen, readBytes;
+ char* pTmp = memrchr(pStart, '\r', encLen);
+
+ if (NULL == pTmp) {
+ freeSession(s);
+ return DRM_FAILURE; /* conflict */
+ }
+ boundaryLen = strlen((char *)((T_DRM_DM_Base64_Node *)(s->infoStruct))->boundary) + 2; /* 2 means: '\r''\n' */
+ s->readBuf = (uint8_t *)malloc(boundaryLen);
+ if (NULL == s->readBuf) {
+ freeSession(s);
+ return DRM_FAILURE;
+ }
+ s->readBufOff = encLen - ((uint8_t *)pTmp - pStart);
+ s->readBufLen = boundaryLen - s->readBufOff;
+ memcpy(s->readBuf, pTmp, s->readBufOff);
+ readBytes = data.readInputData(data.inputHandle, s->readBuf + s->readBufOff, s->readBufLen);
+ if (-1 == readBytes || readBytes < s->readBufLen) {
+ freeSession(s);
+ return DRM_MEDIA_DATA_INVALID;
+ }
+
+ if (0 == drm_scanEndBoundary(s->readBuf, boundaryLen, ((T_DRM_DM_Base64_Node *)(s->infoStruct))->boundary)) {
+ encLen = (uint8_t *)pTmp - pStart; /* yes, it is the end boundary */
+ bFoundBoundary = TRUE;
+ }
+ } else {
+ if (res >= 0 && res < encLen) {
+ encLen = res;
+ bFoundBoundary = TRUE;
+ }
+ }
+
+ decLen = encLen / DRM_B64_ENC_BLOCK * DRM_B64_DEC_BLOCK;
+ decLen = drm_decodeBase64(s->rawContent, decLen, s->rawContent + s->contentOffset, &encLen);
+ ((T_DRM_DM_Base64_Node *)(s->infoStruct))->b64DecodeDataLen = decLen;
+ if (bFoundBoundary)
+ s->contentLength = decLen;
+ }
+ } else {
+ /* binary data */
+ if (DRM_UNKNOWN_DATA_LEN == s->contentLength) {
+ /* try to check whether there is boundary may be split */
+ int32_t res, binContentLen;
+ uint8_t* pStart;
+ int32_t bFoundBoundary = FALSE;
+
+ pStart = s->rawContent + s->contentOffset;
+ binContentLen = s->rawContentLen - s->contentOffset;
+ res = drm_scanEndBoundary(pStart, binContentLen, ((T_DRM_DM_Binary_Node *)(s->infoStruct))->boundary);
+
+ if (-1 == res) {
+ freeSession(s);
+ return DRM_FAILURE;
+ }
+
+ if (-2 == res) { /* may be the boundary is split */
+ int32_t boundaryLen, leftLen, readBytes;
+ char* pTmp = memrchr(pStart, '\r', binContentLen);
+
+ if (NULL == pTmp) {
+ freeSession(s);
+ return DRM_FAILURE; /* conflict */
+ }
+
+ boundaryLen = strlen((char *)((T_DRM_DM_Binary_Node *)(s->infoStruct))->boundary) + 2; /* 2 means: '\r''\n' */
+ s->readBuf = (uint8_t *)malloc(boundaryLen);
+ if (NULL == s->readBuf) {
+ freeSession(s);
+ return DRM_FAILURE;
+ }
+ s->readBufOff = binContentLen - ((uint8_t *)pTmp - pStart);
+ s->readBufLen = boundaryLen - s->readBufOff;
+ memcpy(s->readBuf, pTmp, s->readBufOff);
+ readBytes = data.readInputData(data.inputHandle, s->readBuf + s->readBufOff, s->readBufLen);
+ if (-1 == readBytes || readBytes < s->readBufLen) {
+ freeSession(s);
+ return DRM_MEDIA_DATA_INVALID;
+ }
+
+ if (0 == drm_scanEndBoundary(s->readBuf, boundaryLen, ((T_DRM_DM_Binary_Node *)(s->infoStruct))->boundary)) {
+ binContentLen = (uint8_t *)pTmp - pStart; /* yes, it is the end boundary */
+ bFoundBoundary = TRUE;
+ }
+ } else {
+ if (res >= 0 && res < binContentLen) {
+ binContentLen = res;
+ bFoundBoundary = TRUE;
+ }
+ }
+
+ if (bFoundBoundary)
+ s->contentLength = binContentLen;
+ }
+ }
+ }
+ break;
+ case TYPE_DRM_CONTENT:
+ {
+ T_DRM_DCF_Info dcfInfo;
+ uint8_t* pEncData = NULL;
+
+ memset(&dcfInfo, 0, sizeof(T_DRM_DCF_Info));
+ if (FALSE == drm_dcfParser(s->rawContent, s->rawContentLen, &dcfInfo, &pEncData)) {
+ freeSession(s);
+ return DRM_MEDIA_DATA_INVALID;
+ }
+
+ s->infoStruct = (T_DRM_Dcf_Node *)malloc(sizeof(T_DRM_Dcf_Node));
+ if (NULL == s->infoStruct)
+ return DRM_FAILURE;
+ memset(s->infoStruct, 0, sizeof(T_DRM_Dcf_Node));
+
+ s->deliveryMethod = SEPARATE_DELIVERY;
+ s->contentLength = dcfInfo.DecryptedDataLen;
+ ((T_DRM_Dcf_Node *)(s->infoStruct))->encContentLength = dcfInfo.EncryptedDataLen;
+ s->contentOffset = pEncData - s->rawContent;
+ strcpy((char *)s->contentType, (char *)dcfInfo.ContentType);
+ strcpy((char *)s->contentID, (char *)dcfInfo.ContentURI);
+ strcpy((char *)((T_DRM_Dcf_Node *)(s->infoStruct))->rightsIssuer, (char *)dcfInfo.Rights_Issuer);
+ }
+ break;
+ case TYPE_DRM_RIGHTS_XML: /* rights object should using "SVC_drm_installRights", it can not open a session */
+ case TYPE_DRM_RIGHTS_WBXML: /* rights object should using "SVC_drm_installRights", it can not open a session */
+ case TYPE_DRM_UNKNOWN:
+ default:
+ freeSession(s);
+ return DRM_MEDIA_DATA_INVALID;
+ }
+
+ if ((SEPARATE_DELIVERY_FL == s->deliveryMethod || SEPARATE_DELIVERY == s->deliveryMethod) &&
+ s->contentOffset + ((T_DRM_Dcf_Node *)(s->infoStruct))->encContentLength <= DRM_MAX_MALLOC_LEN) {
+ uint8_t keyValue[DRM_KEY_LEN];
+ uint8_t lastDcfBuf[DRM_TWO_AES_BLOCK_LEN];
+ int32_t seekPos, moreBytes;
+
+ if (TRUE == drm_getKey(s->contentID, keyValue)) {
+ seekPos = s->contentOffset + ((T_DRM_Dcf_Node *)(s->infoStruct))->encContentLength - DRM_TWO_AES_BLOCK_LEN;
+ memcpy(lastDcfBuf, s->rawContent + seekPos, DRM_TWO_AES_BLOCK_LEN);
+
+ if (TRUE == drm_updateDcfDataLen(lastDcfBuf, keyValue, &moreBytes)) {
+ s->contentLength = ((T_DRM_Dcf_Node *)(s->infoStruct))->encContentLength;
+ s->contentLength -= moreBytes;
+ }
+ }
+ }
+
+ session = addSession(s);
+ if (-1 == session)
+ return DRM_FAILURE;
+
+ return session;
+}
+
+/* see svc_drm.h */
+int32_t SVC_drm_getDeliveryMethod(int32_t session)
+{
+ T_DRM_Session_Node* s;
+
+ if (session < 0)
+ return DRM_FAILURE;
+
+ s = getSession(session);
+ if (NULL == s)
+ return DRM_SESSION_NOT_OPENED;
+
+ return s->deliveryMethod;
+}
+
+/* see svc_drm.h */
+int32_t SVC_drm_getContentType(int32_t session, uint8_t* mediaType)
+{
+ T_DRM_Session_Node* s;
+
+ if (session < 0 || NULL == mediaType)
+ return DRM_FAILURE;
+
+ s = getSession(session);
+ if (NULL == s)
+ return DRM_SESSION_NOT_OPENED;
+
+ strcpy((char *)mediaType, (char *)s->contentType);
+
+ return DRM_SUCCESS;
+}
+
+/* see svc_drm.h */
+int32_t SVC_drm_checkRights(int32_t session, int32_t permission)
+{
+ T_DRM_Session_Node* s;
+ int32_t id;
+ T_DRM_Rights *pRo, *pCurRo;
+ int32_t roAmount;
+ int32_t i;
+ int32_t res = DRM_FAILURE;
+
+ if (session < 0)
+ return DRM_FAILURE;
+
+ s = getSession(session);
+ if (NULL == s)
+ return DRM_SESSION_NOT_OPENED;
+
+ /* if it is Forward-Lock cases, check it and return directly */
+ if (FORWARD_LOCK == s->deliveryMethod) {
+ if (DRM_PERMISSION_PLAY == permission ||
+ DRM_PERMISSION_DISPLAY == permission ||
+ DRM_PERMISSION_EXECUTE == permission ||
+ DRM_PERMISSION_PRINT == permission)
+ return DRM_SUCCESS;
+
+ return DRM_FAILURE;
+ }
+
+ /* if try to forward, only DCF can be forwarded */
+ if (DRM_PERMISSION_FORWARD == permission) {
+ if (SEPARATE_DELIVERY == s->deliveryMethod)
+ return DRM_SUCCESS;
+
+ return DRM_FAILURE;
+ }
+
+ /* The following will check CD or SD other permissions */
+ if (FALSE == drm_readFromUidTxt(s->contentID, &id, GET_ID))
+ return DRM_FAILURE;
+
+ drm_writeOrReadInfo(id, NULL, &roAmount, GET_ROAMOUNT);
+ if (roAmount <= 0)
+ return DRM_FAILURE;
+
+ pRo = malloc(roAmount * sizeof(T_DRM_Rights));
+ if (NULL == pRo)
+ return DRM_FAILURE;
+
+ drm_writeOrReadInfo(id, pRo, &roAmount, GET_ALL_RO);
+
+ pCurRo = pRo;
+ for (i = 0; i < roAmount; i++) {
+ switch (permission) {
+ case DRM_PERMISSION_PLAY:
+ res = drm_startCheckRights(&(pCurRo->bIsPlayable), &(pCurRo->PlayConstraint));
+ break;
+ case DRM_PERMISSION_DISPLAY:
+ res = drm_startCheckRights(&(pCurRo->bIsDisplayable), &(pCurRo->DisplayConstraint));
+ break;
+ case DRM_PERMISSION_EXECUTE:
+ res = drm_startCheckRights(&(pCurRo->bIsExecuteable), &(pCurRo->ExecuteConstraint));
+ break;
+ case DRM_PERMISSION_PRINT:
+ res = drm_startCheckRights(&(pCurRo->bIsPrintable), &(pCurRo->PrintConstraint));
+ break;
+ default:
+ free(pRo);
+ return DRM_FAILURE;
+ }
+
+ if (DRM_SUCCESS == res) {
+ free(pRo);
+ return DRM_SUCCESS;
+ }
+ pCurRo++;
+ }
+
+ free(pRo);
+ return res;
+}
+
+/* see svc_drm.h */
+int32_t SVC_drm_consumeRights(int32_t session, int32_t permission)
+{
+ T_DRM_Session_Node* s;
+ int32_t id;
+
+ if (session < 0)
+ return DRM_FAILURE;
+
+ s = getSession(session);
+ if (NULL == s)
+ return DRM_SESSION_NOT_OPENED;
+
+ if (DRM_PERMISSION_FORWARD == permission) {
+ if (SEPARATE_DELIVERY == s->deliveryMethod)
+ return DRM_SUCCESS;
+
+ return DRM_FAILURE;
+ }
+
+ if (FORWARD_LOCK == s->deliveryMethod) /* Forwardlock type have utter rights */
+ return DRM_SUCCESS;
+
+ if (FALSE == drm_readFromUidTxt(s->contentID, &id, GET_ID))
+ return DRM_FAILURE;
+
+ return drm_checkRoAndUpdate(id, permission);
+}
+
+/* see svc_drm.h */
+int32_t SVC_drm_getContentLength(int32_t session)
+{
+ T_DRM_Session_Node* s;
+
+ if (session < 0)
+ return DRM_FAILURE;
+
+ s = getSession(session);
+ if (NULL == s)
+ return DRM_SESSION_NOT_OPENED;
+
+ if (DRM_UNKNOWN_DATA_LEN == s->contentLength && s->contentOffset + ((T_DRM_Dcf_Node *)(s->infoStruct))->encContentLength <= DRM_MAX_MALLOC_LEN &&
+ (SEPARATE_DELIVERY == s->deliveryMethod || SEPARATE_DELIVERY_FL == s->deliveryMethod)) {
+ uint8_t keyValue[DRM_KEY_LEN];
+ uint8_t lastDcfBuf[DRM_TWO_AES_BLOCK_LEN];
+ int32_t seekPos, moreBytes;
+
+ if (TRUE == drm_getKey(s->contentID, keyValue)) {
+ seekPos = s->contentOffset + ((T_DRM_Dcf_Node *)(s->infoStruct))->encContentLength - DRM_TWO_AES_BLOCK_LEN;
+ memcpy(lastDcfBuf, s->rawContent + seekPos, DRM_TWO_AES_BLOCK_LEN);
+
+ if (TRUE == drm_updateDcfDataLen(lastDcfBuf, keyValue, &moreBytes)) {
+ s->contentLength = ((T_DRM_Dcf_Node *)(s->infoStruct))->encContentLength;
+ s->contentLength -= moreBytes;
+ }
+ }
+ }
+
+ return s->contentLength;
+}
+
+static int32_t drm_readAesData(uint8_t* buf, T_DRM_Session_Node* s, int32_t aesStart, int32_t bufLen)
+{
+ if (NULL == buf || NULL == s || aesStart < 0 || bufLen < 0)
+ return -1;
+
+ if (aesStart - s->contentOffset + bufLen > ((T_DRM_Dcf_Node *)(s->infoStruct))->encContentLength)
+ return -2;
+
+ if (aesStart < DRM_MAX_MALLOC_LEN) {
+ if (aesStart + bufLen <= DRM_MAX_MALLOC_LEN) { /* read from buffer */
+ memcpy(buf, s->rawContent + aesStart, bufLen);
+ return bufLen;
+ } else { /* first read from buffer and then from InputStream */
+ int32_t point = DRM_MAX_MALLOC_LEN - aesStart;
+ int32_t res;
+
+ if (((T_DRM_Dcf_Node *)(s->infoStruct))->bAesBackupBuf) {
+ memcpy(buf, ((T_DRM_Dcf_Node *)(s->infoStruct))->aesBackupBuf, DRM_ONE_AES_BLOCK_LEN);
+ res = s->readInputDataFunc(s->inputHandle, buf + DRM_ONE_AES_BLOCK_LEN, DRM_ONE_AES_BLOCK_LEN);
+ if (0 == res || -1 == res)
+ return -1;
+
+ res += DRM_ONE_AES_BLOCK_LEN;
+ } else {
+ memcpy(buf, s->rawContent + aesStart, point);
+ res = s->readInputDataFunc(s->inputHandle, buf + point, bufLen - point);
+ if (0 == res || -1 == res)
+ return -1;
+
+ res += point;
+ }
+
+ memcpy(((T_DRM_Dcf_Node *)(s->infoStruct))->aesBackupBuf, buf + DRM_ONE_AES_BLOCK_LEN, DRM_ONE_AES_BLOCK_LEN);
+ ((T_DRM_Dcf_Node *)(s->infoStruct))->bAesBackupBuf = TRUE;
+
+ return res;
+ }
+ } else { /* read from InputStream */
+ int32_t res;
+
+ memcpy(buf, ((T_DRM_Dcf_Node *)(s->infoStruct))->aesBackupBuf, DRM_ONE_AES_BLOCK_LEN);
+ res = s->readInputDataFunc(s->inputHandle, buf + DRM_ONE_AES_BLOCK_LEN, DRM_ONE_AES_BLOCK_LEN);
+
+ if (0 == res || -1 == res)
+ return -1;
+
+ memcpy(((T_DRM_Dcf_Node *)(s->infoStruct))->aesBackupBuf, buf + DRM_ONE_AES_BLOCK_LEN, DRM_ONE_AES_BLOCK_LEN);
+
+ return DRM_ONE_AES_BLOCK_LEN + res;
+ }
+}
+
+static int32_t drm_readContentFromBuf(T_DRM_Session_Node* s, int32_t offset, uint8_t* mediaBuf, int32_t mediaBufLen)
+{
+ int32_t readBytes;
+
+ if (offset > s->contentLength)
+ return DRM_FAILURE;
+
+ if (offset == s->contentLength)
+ return DRM_MEDIA_EOF;
+
+ if (offset + mediaBufLen > s->contentLength)
+ readBytes = s->contentLength - offset;
+ else
+ readBytes = mediaBufLen;
+
+ if (DRM_MESSAGE_CODING_BASE64 == s->transferEncoding)
+ memcpy(mediaBuf, s->rawContent + offset, readBytes);
+ else
+ memcpy(mediaBuf, s->rawContent + s->contentOffset + offset, readBytes);
+
+ return readBytes;
+}
+
+static int32_t drm_readB64ContentFromInputStream(T_DRM_Session_Node* s, int32_t offset, uint8_t* mediaBuf, int32_t mediaBufLen)
+{
+ uint8_t encBuf[DRM_B64_ENC_BLOCK], decBuf[DRM_B64_DEC_BLOCK];
+ int32_t encLen, decLen;
+ int32_t i, j, piece, leftLen, firstBytes;
+ int32_t readBytes = 0;
+
+ if (offset < ((T_DRM_DM_Base64_Node *)(s->infoStruct))->b64DecodeDataLen) {
+ readBytes = ((T_DRM_DM_Base64_Node *)(s->infoStruct))->b64DecodeDataLen - offset;
+ memcpy(mediaBuf, s->rawContent + offset, readBytes);
+ } else {
+ if (s->bEndData)
+ return DRM_MEDIA_EOF;
+
+ firstBytes = offset % DRM_B64_DEC_BLOCK;
+ if (firstBytes > 0) {
+ if (DRM_B64_DEC_BLOCK - firstBytes >= mediaBufLen) {
+ readBytes = mediaBufLen;
+ memcpy(mediaBuf, ((T_DRM_DM_Base64_Node *)(s->infoStruct))->b64DecodeData + firstBytes, readBytes);
+ return readBytes;
+ }
+
+ readBytes = DRM_B64_DEC_BLOCK - firstBytes;
+ memcpy(mediaBuf, ((T_DRM_DM_Base64_Node *)(s->infoStruct))->b64DecodeData + firstBytes, readBytes);
+ }
+ }
+
+ leftLen = mediaBufLen - readBytes;
+ encLen = (leftLen - 1) / DRM_B64_DEC_BLOCK * DRM_B64_ENC_BLOCK + DRM_B64_ENC_BLOCK;
+ piece = encLen / DRM_B64_ENC_BLOCK;
+
+ for (i = 0; i < piece; i++) {
+ j = 0;
+ while (j < DRM_B64_ENC_BLOCK) {
+ if (NULL != s->readBuf && s->readBufLen > 0) { /* read from backup buffer */
+ *(encBuf + j) = s->readBuf[s->readBufOff];
+ s->readBufOff++;
+ s->readBufLen--;
+ } else { /* read from InputStream */
+ if (0 == s->readInputDataFunc(s->inputHandle, encBuf + j, 1))
+ return DRM_MEDIA_DATA_INVALID;
+ }
+
+ if ('\r' == *(encBuf + j) || '\n' == *(encBuf + j))
+ continue; /* skip CRLF */
+
+ if ('-' == *(encBuf + j)) {
+ int32_t k, len;
+
+ /* invalid base64 data, it comes to end boundary */
+ if (0 != j)
+ return DRM_MEDIA_DATA_INVALID;
+
+ /* check whether it is really the boundary */
+ len = strlen((char *)((T_DRM_DM_Base64_Node *)(s->infoStruct))->boundary);
+ if (NULL == s->readBuf) {
+ s->readBuf = (uint8_t *)malloc(len);
+ if (NULL == s->readBuf)
+ return DRM_FAILURE;
+ }
+
+ s->readBuf[0] = '-';
+ for (k = 0; k < len - 1; k++) {
+ if (NULL != s->readBuf && s->readBufLen > 0) { /* read from backup buffer */
+ *(s->readBuf + k + 1) = s->readBuf[s->readBufOff];
+ s->readBufOff++;
+ s->readBufLen--;
+ } else { /* read from InputStream */
+ if (-1 == s->readInputDataFunc(s->inputHandle, s->readBuf + k + 1, 1))
+ return DRM_MEDIA_DATA_INVALID;
+ }
+ }
+ if (0 == memcmp(s->readBuf, ((T_DRM_DM_Base64_Node *)(s->infoStruct))->boundary, len))
+ s->bEndData = TRUE;
+ else
+ return DRM_MEDIA_DATA_INVALID;
+
+ break;
+ }
+ j++;
+ }
+
+ if (TRUE == s->bEndData) { /* it means come to the end of base64 data */
+ if (0 == readBytes)
+ return DRM_MEDIA_EOF;
+
+ break;
+ }
+
+ encLen = DRM_B64_ENC_BLOCK;
+ decLen = DRM_B64_DEC_BLOCK;
+ if (-1 == (decLen = drm_decodeBase64(decBuf, decLen, encBuf, &encLen)))
+ return DRM_MEDIA_DATA_INVALID;
+
+ if (leftLen >= decLen) {
+ memcpy(mediaBuf + readBytes, decBuf, decLen);
+ readBytes += decLen;
+ leftLen -= decLen;
+ } else {
+ if (leftLen > 0) {
+ memcpy(mediaBuf + readBytes, decBuf, leftLen);
+ readBytes += leftLen;
+ }
+ break;
+ }
+ }
+ memcpy(((T_DRM_DM_Base64_Node *)(s->infoStruct))->b64DecodeData, decBuf, DRM_B64_DEC_BLOCK);
+
+ return readBytes;
+}
+
+static int32_t drm_readBase64Content(T_DRM_Session_Node* s, int32_t offset, uint8_t* mediaBuf, int32_t mediaBufLen)
+{
+ int32_t readBytes;
+
+ /* when the content length has been well-known */
+ if (s->contentLength >= 0)
+ readBytes = drm_readContentFromBuf(s, offset, mediaBuf, mediaBufLen);
+ else /* else when the content length has not been well-known yet */
+ if (offset < ((T_DRM_DM_Base64_Node *)(s->infoStruct))->b64DecodeDataLen)
+ if (offset + mediaBufLen <= ((T_DRM_DM_Base64_Node *)(s->infoStruct))->b64DecodeDataLen) {
+ readBytes = mediaBufLen;
+ memcpy(mediaBuf, s->rawContent + offset, readBytes);
+ } else
+ readBytes = drm_readB64ContentFromInputStream(s, offset, mediaBuf, mediaBufLen);
+ else
+ readBytes = drm_readB64ContentFromInputStream(s, offset, mediaBuf, mediaBufLen);
+
+ return readBytes;
+}
+
+static int32_t drm_readBinaryContentFromInputStream(T_DRM_Session_Node* s, int32_t offset, uint8_t* mediaBuf, int32_t mediaBufLen)
+{
+ int32_t res = 0, readBytes = 0;
+ int32_t leftLen;
+
+ if (s->contentOffset + offset < DRM_MAX_MALLOC_LEN) {
+ readBytes = DRM_MAX_MALLOC_LEN - s->contentOffset - offset;
+ memcpy(mediaBuf, s->rawContent + s->contentOffset + offset, readBytes);
+ } else
+ if (s->bEndData)
+ return DRM_MEDIA_EOF;
+
+ leftLen = mediaBufLen - readBytes;
+
+ if (NULL != s->readBuf && s->readBufLen > 0) { /* read from backup buffer */
+ if (leftLen <= s->readBufLen) {
+ memcpy(mediaBuf, s->readBuf + s->readBufOff, leftLen);
+ s->readBufOff += leftLen;
+ s->readBufLen -= leftLen;
+ readBytes += leftLen;
+ leftLen = 0;
+ } else {
+ memcpy(mediaBuf, s->readBuf + s->readBufOff, s->readBufLen);
+ s->readBufOff += s->readBufLen;
+ leftLen -= s->readBufLen;
+ readBytes += s->readBufLen;
+ s->readBufLen = 0;
+ }
+ }
+
+ if (leftLen > 0) {
+ res = s->readInputDataFunc(s->inputHandle, mediaBuf + readBytes, mediaBufLen - readBytes);
+ if (-1 == res)
+ return DRM_MEDIA_DATA_INVALID;
+ }
+
+ readBytes += res;
+ res = drm_scanEndBoundary(mediaBuf, readBytes, ((T_DRM_DM_Binary_Node *)(s->infoStruct))->boundary);
+ if (-1 == res)
+ return DRM_MEDIA_DATA_INVALID;
+ if (-2 == res) { /* may be the boundary is split */
+ int32_t boundaryLen, len, off, k;
+ char* pTmp = memrchr(mediaBuf, '\r', readBytes);
+
+ if (NULL == pTmp)
+ return DRM_FAILURE; /* conflict */
+
+ boundaryLen = strlen((char *)((T_DRM_DM_Binary_Node *)(s->infoStruct))->boundary) + 2; /* 2 means: '\r''\n' */
+ if (NULL == s->readBuf) {
+ s->readBuf = (uint8_t *)malloc(boundaryLen);
+ if (NULL == s->readBuf)
+ return DRM_FAILURE;
+ }
+
+ off = readBytes - ((uint8_t *)pTmp - mediaBuf);
+ len = boundaryLen - off;
+ memcpy(s->readBuf, pTmp, off);
+ for (k = 0; k < boundaryLen - off; k++) {
+ if (NULL != s->readBuf && s->readBufLen > 0) { /* read from backup buffer */
+ *(s->readBuf + k + off) = s->readBuf[s->readBufOff];
+ s->readBufOff++;
+ s->readBufLen--;
+ } else { /* read from InputStream */
+ if (-1 == s->readInputDataFunc(s->inputHandle, s->readBuf + k + off, 1))
+ return DRM_MEDIA_DATA_INVALID;
+ }
+ }
+ s->readBufOff = off;
+ s->readBufLen = len;
+
+ if (0 == drm_scanEndBoundary(s->readBuf, boundaryLen, ((T_DRM_DM_Binary_Node *)(s->infoStruct))->boundary)) {
+ readBytes = (uint8_t *)pTmp - mediaBuf; /* yes, it is the end boundary */
+ s->bEndData = TRUE;
+ }
+ } else {
+ if (res >= 0 && res < readBytes) {
+ readBytes = res;
+ s->bEndData = TRUE;
+ }
+ }
+
+ if (s->bEndData) {
+ if (0 == readBytes)
+ return DRM_MEDIA_EOF;
+ }
+
+ return readBytes;
+}
+
+static int32_t drm_readBinaryContent(T_DRM_Session_Node* s, int32_t offset, uint8_t* mediaBuf, int32_t mediaBufLen)
+{
+ int32_t readBytes;
+
+ if (s->contentLength >= 0)
+ readBytes = drm_readContentFromBuf(s, offset, mediaBuf, mediaBufLen);
+ else /* else when the content length has not been well-known yet */
+ if (s->contentOffset + offset < DRM_MAX_MALLOC_LEN)
+ if (s->contentOffset + offset + mediaBufLen <= DRM_MAX_MALLOC_LEN) {
+ readBytes = mediaBufLen;
+ memcpy(mediaBuf, s->rawContent + s->contentOffset + offset, readBytes);
+ } else
+ readBytes = drm_readBinaryContentFromInputStream(s, offset, mediaBuf, mediaBufLen);
+ else
+ readBytes = drm_readBinaryContentFromInputStream(s, offset, mediaBuf, mediaBufLen);
+
+ return readBytes;
+}
+
+static int32_t drm_readAesContent(T_DRM_Session_Node* s, int32_t offset, uint8_t* mediaBuf, int32_t mediaBufLen)
+{
+ uint8_t keyValue[DRM_KEY_LEN];
+ uint8_t buf[DRM_TWO_AES_BLOCK_LEN];
+ int32_t readBytes = 0;
+ int32_t bufLen, piece, i, copyBytes, leftBytes;
+ int32_t aesStart, mediaStart, mediaBufOff;
+ aes_decrypt_ctx ctx[1];
+
+ if (FALSE == drm_getKey(s->contentID, keyValue))
+ return DRM_NO_RIGHTS;
+
+ /* when the content length has been well-known */
+ if (s->contentLength > 0) {
+ if (offset > s->contentLength)
+ return DRM_FAILURE;
+
+ if (offset == s->contentLength)
+ return DRM_MEDIA_EOF;
+
+ if (offset + mediaBufLen > s->contentLength)
+ readBytes = s->contentLength - offset;
+ else
+ readBytes = mediaBufLen;
+
+ aesStart = s->contentOffset + (offset / DRM_ONE_AES_BLOCK_LEN * DRM_ONE_AES_BLOCK_LEN);
+ piece = (offset + readBytes - 1) / DRM_ONE_AES_BLOCK_LEN - offset / DRM_ONE_AES_BLOCK_LEN + 2;
+ mediaStart = offset % DRM_ONE_AES_BLOCK_LEN;
+
+ aes_decrypt_key128(keyValue, ctx);
+ mediaBufOff = 0;
+ leftBytes = readBytes;
+
+ for (i = 0; i < piece - 1; i++) {
+ memcpy(buf, s->rawContent + aesStart + i * DRM_ONE_AES_BLOCK_LEN, DRM_TWO_AES_BLOCK_LEN);
+ bufLen = DRM_TWO_AES_BLOCK_LEN;
+
+ if (drm_aesDecBuffer(buf, &bufLen, ctx) < 0)
+ return DRM_MEDIA_DATA_INVALID;
+
+ if (0 != i)
+ mediaStart = 0;
+
+ if (bufLen - mediaStart <= leftBytes)
+ copyBytes = bufLen - mediaStart;
+ else
+ copyBytes = leftBytes;
+
+ memcpy(mediaBuf + mediaBufOff, buf + mediaStart, copyBytes);
+ leftBytes -= copyBytes;
+ mediaBufOff += copyBytes;
+ }
+ } else {
+ int32_t res;
+
+ if (s->bEndData)
+ return DRM_MEDIA_EOF;
+
+ if (((T_DRM_Dcf_Node *)(s->infoStruct))->aesDecDataLen > ((T_DRM_Dcf_Node *)(s->infoStruct))->aesDecDataOff) {
+ if (mediaBufLen < ((T_DRM_Dcf_Node *)(s->infoStruct))->aesDecDataLen - ((T_DRM_Dcf_Node *)(s->infoStruct))->aesDecDataOff)
+ copyBytes = mediaBufLen;
+ else
+ copyBytes = ((T_DRM_Dcf_Node *)(s->infoStruct))->aesDecDataLen - ((T_DRM_Dcf_Node *)(s->infoStruct))->aesDecDataOff;
+
+ memcpy(mediaBuf, ((T_DRM_Dcf_Node *)(s->infoStruct))->aesDecData + ((T_DRM_Dcf_Node *)(s->infoStruct))->aesDecDataOff, copyBytes);
+ ((T_DRM_Dcf_Node *)(s->infoStruct))->aesDecDataOff += copyBytes;
+ readBytes += copyBytes;
+ }
+
+ leftBytes = mediaBufLen - readBytes;
+ if (0 == leftBytes)
+ return readBytes;
+ if (leftBytes < 0)
+ return DRM_FAILURE;
+
+ offset += readBytes;
+ aesStart = s->contentOffset + (offset / DRM_ONE_AES_BLOCK_LEN * DRM_ONE_AES_BLOCK_LEN);
+ piece = (offset + leftBytes - 1) / DRM_ONE_AES_BLOCK_LEN - offset / DRM_ONE_AES_BLOCK_LEN + 2;
+ mediaBufOff = readBytes;
+
+ aes_decrypt_key128(keyValue, ctx);
+
+ for (i = 0; i < piece - 1; i++) {
+ if (-1 == (res = drm_readAesData(buf, s, aesStart, DRM_TWO_AES_BLOCK_LEN)))
+ return DRM_MEDIA_DATA_INVALID;
+
+ if (-2 == res)
+ break;
+
+ bufLen = DRM_TWO_AES_BLOCK_LEN;
+ aesStart += DRM_ONE_AES_BLOCK_LEN;
+
+ if (drm_aesDecBuffer(buf, &bufLen, ctx) < 0)
+ return DRM_MEDIA_DATA_INVALID;
+
+ drm_discardPaddingByte(buf, &bufLen);
+
+ if (bufLen <= leftBytes)
+ copyBytes = bufLen;
+ else
+ copyBytes = leftBytes;
+
+ memcpy(mediaBuf + mediaBufOff, buf, copyBytes);
+ leftBytes -= copyBytes;
+ mediaBufOff += copyBytes;
+ readBytes += copyBytes;
+ }
+
+ memcpy(((T_DRM_Dcf_Node *)(s->infoStruct))->aesDecData, buf, DRM_ONE_AES_BLOCK_LEN);
+ ((T_DRM_Dcf_Node *)(s->infoStruct))->aesDecDataLen = bufLen;
+ ((T_DRM_Dcf_Node *)(s->infoStruct))->aesDecDataOff = copyBytes;
+
+ if (aesStart - s->contentOffset > ((T_DRM_Dcf_Node *)(s->infoStruct))->encContentLength - DRM_TWO_AES_BLOCK_LEN && ((T_DRM_Dcf_Node *)(s->infoStruct))->aesDecDataOff == ((T_DRM_Dcf_Node *)(s->infoStruct))->aesDecDataLen) {
+ s->bEndData = TRUE;
+ if (0 == readBytes)
+ return DRM_MEDIA_EOF;
+ }
+ }
+
+ return readBytes;
+}
+
+/* see svc_drm.h */
+int32_t SVC_drm_getContent(int32_t session, int32_t offset, uint8_t* mediaBuf, int32_t mediaBufLen)
+{
+ T_DRM_Session_Node* s;
+ int32_t readBytes;
+
+ if (session < 0 || offset < 0 || NULL == mediaBuf || mediaBufLen <= 0)
+ return DRM_FAILURE;
+
+ s = getSession(session);
+ if (NULL == s)
+ return DRM_SESSION_NOT_OPENED;
+
+ if (0 >= s->getInputDataLengthFunc(s->inputHandle))
+ return DRM_MEDIA_DATA_INVALID;
+
+ switch(s->deliveryMethod) {
+ case FORWARD_LOCK:
+ case COMBINED_DELIVERY:
+ if (DRM_MESSAGE_CODING_BASE64 == s->transferEncoding)
+ readBytes = drm_readBase64Content(s, offset, mediaBuf, mediaBufLen);
+ else /* binary */
+ readBytes = drm_readBinaryContent(s, offset, mediaBuf, mediaBufLen);
+ break;
+ case SEPARATE_DELIVERY:
+ case SEPARATE_DELIVERY_FL:
+ readBytes = drm_readAesContent(s, offset, mediaBuf, mediaBufLen);
+ break;
+ default:
+ return DRM_FAILURE;
+ }
+
+ return readBytes;
+}
+
+/* see svc_drm.h */
+int32_t SVC_drm_getRightsIssuer(int32_t session, uint8_t* rightsIssuer)
+{
+ T_DRM_Session_Node* s;
+
+ if (session < 0 || NULL == rightsIssuer)
+ return DRM_FAILURE;
+
+ s = getSession(session);
+ if (NULL == s)
+ return DRM_SESSION_NOT_OPENED;
+
+ if (SEPARATE_DELIVERY == s->deliveryMethod || SEPARATE_DELIVERY_FL == s->deliveryMethod) {
+ strcpy((char *)rightsIssuer, (char *)((T_DRM_Dcf_Node *)(s->infoStruct))->rightsIssuer);
+ return DRM_SUCCESS;
+ }
+
+ return DRM_NOT_SD_METHOD;
+}
+
+/* see svc_drm.h */
+int32_t SVC_drm_getRightsInfo(int32_t session, T_DRM_Rights_Info* rights)
+{
+ T_DRM_Session_Node* s;
+ T_DRM_Rights rightsInfo;
+ int32_t roAmount, id;
+
+ if (session < 0 || NULL == rights)
+ return DRM_FAILURE;
+
+ s = getSession(session);
+ if (NULL == s)
+ return DRM_SESSION_NOT_OPENED;
+
+ if (FORWARD_LOCK == s->deliveryMethod) {
+ strcpy((char *)rights->roId, "ForwardLock");
+ rights->displayRights.indicator = DRM_NO_CONSTRAINT;
+ rights->playRights.indicator = DRM_NO_CONSTRAINT;
+ rights->executeRights.indicator = DRM_NO_CONSTRAINT;
+ rights->printRights.indicator = DRM_NO_CONSTRAINT;
+ return DRM_SUCCESS;
+ }
+
+ if (FALSE == drm_readFromUidTxt(s->contentID, &id, GET_ID))
+ return DRM_NO_RIGHTS;
+
+ if (FALSE == drm_writeOrReadInfo(id, NULL, &roAmount, GET_ROAMOUNT))
+ return DRM_FAILURE;
+
+ if (roAmount < 0)
+ return DRM_NO_RIGHTS;
+
+ /* some rights has been installed, but now there is no valid rights */
+ if (0 == roAmount) {
+ strcpy((char *)rights->roId, s->contentID);
+ rights->displayRights.indicator = DRM_NO_PERMISSION;
+ rights->playRights.indicator = DRM_NO_PERMISSION;
+ rights->executeRights.indicator = DRM_NO_PERMISSION;
+ rights->printRights.indicator = DRM_NO_PERMISSION;
+ return DRM_SUCCESS;
+ }
+
+ roAmount = 1;
+ memset(&rightsInfo, 0, sizeof(T_DRM_Rights));
+ if (FALSE == drm_writeOrReadInfo(id, &rightsInfo, &roAmount, GET_A_RO))
+ return DRM_FAILURE;
+
+ memset(rights, 0, sizeof(T_DRM_Rights_Info));
+ drm_getLicenseInfo(&rightsInfo, rights);
+ return DRM_SUCCESS;
+}
+
+/* see svc_drm.h */
+int32_t SVC_drm_closeSession(int32_t session)
+{
+ if (session < 0)
+ return DRM_FAILURE;
+
+ if (NULL == getSession(session))
+ return DRM_SESSION_NOT_OPENED;
+
+ removeSession(session);
+
+ return DRM_SUCCESS;
+}
+
+/* see svc_drm.h */
+int32_t SVC_drm_updateRights(uint8_t* contentID, int32_t permission)
+{
+ int32_t id;
+
+ if (NULL == contentID)
+ return DRM_FAILURE;
+
+ if (FALSE == drm_readFromUidTxt(contentID, &id, GET_ID))
+ return DRM_FAILURE;
+
+ return drm_checkRoAndUpdate(id, permission);
+}
+
+/* see svc_drm.h */
+int32_t SVC_drm_viewAllRights(T_DRM_Rights_Info_Node **ppRightsInfo)
+{
+ T_DRM_Rights_Info_Node rightsNode;
+ int32_t maxId, id, roAmount, j;
+ T_DRM_Rights rights;
+
+ memset(&rights, 0, sizeof(T_DRM_Rights));
+
+ if (NULL == ppRightsInfo)
+ return DRM_FAILURE;
+
+ *ppRightsInfo = NULL;
+
+ maxId = drm_getMaxIdFromUidTxt();
+ if (-1 == maxId)
+ return DRM_FAILURE;
+
+ for (id = 1; id <= maxId; id++) {
+ drm_writeOrReadInfo(id, NULL, &roAmount, GET_ROAMOUNT);
+ if (roAmount <= 0) /* this means there is not any rights */
+ continue;
+
+ for (j = 1; j <= roAmount; j++) {
+ if (FALSE == drm_writeOrReadInfo(id, &rights, &j, GET_A_RO))
+ continue;
+
+ memset(&rightsNode, 0, sizeof(T_DRM_Rights_Info_Node));
+
+ drm_getLicenseInfo(&rights, &(rightsNode.roInfo));
+
+ if (FALSE == drm_addRightsNodeToList(ppRightsInfo, &rightsNode))
+ continue;
+ }
+ }
+ return DRM_SUCCESS;
+}
+
+/* see svc_drm.h */
+int32_t SVC_drm_freeRightsInfoList(T_DRM_Rights_Info_Node *pRightsHeader)
+{
+ T_DRM_Rights_Info_Node *pNode, *pTmp;
+
+ if (NULL == pRightsHeader)
+ return DRM_FAILURE;
+
+ pNode = pRightsHeader;
+
+ while (NULL != pNode) {
+ pTmp = pNode;
+ pNode = pNode->next;
+ free(pTmp);
+ }
+ return DRM_SUCCESS;
+}
+
+/* see svc_drm.h */
+int32_t SVC_drm_deleteRights(uint8_t* roId)
+{
+ int32_t maxId, id, roAmount, j;
+ T_DRM_Rights rights;
+
+ memset(&rights, 0, sizeof(T_DRM_Rights));
+
+ if (NULL == roId)
+ return DRM_FAILURE;
+
+ maxId = drm_getMaxIdFromUidTxt();
+ if (-1 == maxId)
+ return DRM_NO_RIGHTS;
+
+ for (id = 1; id <= maxId; id++) {
+ drm_writeOrReadInfo(id, NULL, &roAmount, GET_ROAMOUNT);
+ if (roAmount <= 0) /* this means there is not any rights */
+ continue;
+
+ for (j = 1; j <= roAmount; j++) {
+ if (FALSE == drm_writeOrReadInfo(id, &rights, &j, GET_A_RO))
+ continue;
+
+ /* here find the RO which will be deleted */
+ if (0 == strcmp((char *)rights.uid, (char *)roId)) {
+ T_DRM_Rights *pAllRights;
+
+ pAllRights = (T_DRM_Rights *)malloc(roAmount * sizeof(T_DRM_Rights));
+ if (NULL == pAllRights)
+ return DRM_FAILURE;
+
+ drm_writeOrReadInfo(id, pAllRights, &roAmount, GET_ALL_RO);
+ roAmount--;
+ if (0 == roAmount) { /* this means it is the last one rights */
+ drm_removeIdInfoFile(id); /* delete the id.info file first */
+ drm_updateUidTxtWhenDelete(id); /* update uid.txt file */
+ free(pAllRights);
+ return DRM_SUCCESS;
+ } else /* using the last one rights instead of the deleted one */
+ memcpy(pAllRights + (j - 1), pAllRights + roAmount, sizeof(T_DRM_Rights));
+
+ /* delete the id.info file first */
+// drm_removeIdInfoFile(id);
+
+ if (FALSE == drm_writeOrReadInfo(id, pAllRights, &roAmount, SAVE_ALL_RO)) {
+ free(pAllRights);
+ return DRM_FAILURE;
+ }
+
+ free(pAllRights);
+ return DRM_SUCCESS;
+ }
+ }
+ }
+
+ return DRM_FAILURE;
+}
diff --git a/media/libdrm/mobile1/src/objmng/drm_decoder.c b/media/libdrm/mobile1/src/objmng/drm_decoder.c
new file mode 100644
index 0000000..82c7efb
--- /dev/null
+++ b/media/libdrm/mobile1/src/objmng/drm_decoder.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <objmng/drm_decoder.h>
+
+/* global variables */
+static const uint8_t * base64_alphabet = (const uint8_t *)"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+#define SKIP_CRLF(p) while('\r' == *(p) || '\n' == *(p)) \
+ p++
+
+static int8_t get_alphabet_index(int8_t ch)
+{
+ uint8_t * tmp;
+
+ if ('=' == ch)
+ return 64;
+
+ tmp = (uint8_t *)strchr((const char *)base64_alphabet, ch);
+ if (NULL == tmp)
+ return -1;
+
+ return (int8_t)(tmp - base64_alphabet);
+}
+
+/* See drm_decoder.h */
+int32_t drm_decodeBase64(uint8_t * dest, int32_t destLen, uint8_t * src, int32_t * srcLen)
+{
+ int32_t maxDestSize, i, maxGroup;
+ uint8_t *pDest, *pSrc;
+ int8_t tpChar;
+
+ if (NULL == src || NULL == srcLen || *srcLen <= 0 || destLen < 0)
+ return -1;
+
+ maxDestSize = (*srcLen) * 3/4;
+ if (NULL == dest || 0 == destLen)
+ return maxDestSize;
+
+ if (destLen < maxDestSize)
+ maxDestSize = destLen;
+ maxGroup = maxDestSize/3;
+
+ pDest = dest; /* start to decode src to dest */
+ pSrc = src;
+ for (i = 0; i < maxGroup && *srcLen - (pSrc - src) >= 4; i++) {
+ SKIP_CRLF(pSrc);
+ if (pSrc - src >= *srcLen)
+ break;
+ tpChar = get_alphabet_index(*pSrc); /* to first byte */
+ if (-1 == tpChar || 64 == tpChar)
+ return -1;
+ pDest[0] = tpChar << 2;
+ pSrc++;
+ SKIP_CRLF(pSrc);
+ tpChar = get_alphabet_index(*pSrc);
+ if (-1 == tpChar || 64 == tpChar)
+ return -1;
+ pDest[0] |= (tpChar >> 4);
+ pDest[1] = tpChar << 4; /* to second byte */
+ pSrc++;
+ SKIP_CRLF(pSrc);
+ tpChar = get_alphabet_index(*pSrc);
+ if (-1 == tpChar)
+ return -1;
+ if (64 == tpChar) /* end */
+ return pDest - dest + 1;
+ pDest[1] |= (tpChar >> 2);
+ pDest[2] = tpChar << 6; /* to third byte */
+ pSrc++;
+ SKIP_CRLF(pSrc);
+ tpChar = get_alphabet_index(*pSrc);
+ if (-1 == tpChar)
+ return -1;
+ if (64 == tpChar) /* end */
+ return pDest - dest + 2;
+ pDest[2] |= tpChar;
+ pDest += 3;
+ pSrc++;
+ }
+ *srcLen = pSrc - src;
+ return pDest - dest;
+}
diff --git a/media/libdrm/mobile1/src/objmng/drm_file.c b/media/libdrm/mobile1/src/objmng/drm_file.c
new file mode 100644
index 0000000..e6c303e
--- /dev/null
+++ b/media/libdrm/mobile1/src/objmng/drm_file.c
@@ -0,0 +1,694 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <objmng/drm_file.h>
+
+#include <unistd.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <errno.h>
+#include <string.h>
+
+/**
+ * Fails on zaurus?
+ #define DEVICE_FILESYSTEM
+*/
+#define DEFAULT_TOTAL_SPACE (4L * 1024L * 1024L) /* 4 Meg. */
+
+#ifndef DEVICE_FILESYSTEM
+/* Store the total space on FS VM can use. */
+static int32_t totalSpace;
+/* how many remain space can VM use. */
+static int32_t availableSize;
+#endif
+
+extern char* getStorageRoot(void);
+
+static char tmpPathBuf1[MAX_FILENAME_LEN];
+static char tmpPathBuf2[MAX_FILENAME_LEN];
+
+static int32_t
+convertFilename(const uint16_t *strData, int32_t strLength, char *buffer);
+
+static int calcDirSize(char *path, int len, uint8_t includeSubdirs);
+
+#ifndef DEVICE_FILESYSTEM
+static void initFsVariables(void);
+#endif
+
+/**
+ * Convert a Java string into a nul terminated ascii string to pass to posix
+ * @param strData first character of name
+ * @param strLength number of characters in name
+ * @param buffer Buffer to store terminated string in (at least MAXPATHLEN)
+ * @return Length of filename in characters (excl. nul), or -1 on failure.
+ */
+static int32_t
+convertFilename(const uint16_t *strData, int32_t strLength, char *buffer)
+{
+ int idx;
+
+ if (strLength >= (MAXPATHLEN-1))
+ {
+ Trace("convertFilename '%.*S' too long", strLength, strData);
+ return -1;
+ }
+
+ for (idx = 0; idx < strLength; ++idx)
+ *buffer++ = (char)*strData++;
+
+ *buffer = 0;
+ return strLength;
+}
+
+
+/**
+ * Perform a stat() call on the given filename.
+ * Helper for getFileLength and exists
+ * @param name unicode name
+ * @param nameLen number of unicode characters in name
+ * @param sbuf stat buffer
+ * @return TRUE on success, FALSE on failure
+ */
+static int32_t
+getFileStat(const uint16_t *name, int32_t nameLen, struct stat *sbuf)
+{
+ Trace("getFileStat: %.*S", nameLen, name);
+
+ if (convertFilename(name, nameLen, tmpPathBuf1) <= 0)
+ {
+ Trace("getFileStat: bad filename");
+ }
+ else if (stat(tmpPathBuf1, sbuf) != 0)
+ {
+ Trace("getFileStat %s: stat() errno=%d", tmpPathBuf1, errno);
+ }
+ else /* Successful */
+ {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+#ifndef DEVICE_FILESYSTEM
+/**
+ * initial the variables like totalSpace, availableSize...
+ */
+static void initFsVariables(void)
+{
+ totalSpace = DEFAULT_TOTAL_SPACE;
+
+ availableSize = totalSpace;
+}
+#endif /* DEVICE_FILESYSTEM */
+
+/**
+ * calculate the size of everything inside path pointed directory
+ * this function will use path pointed buffer to store some extra info
+ * so param len is needed.
+ * @param path the directory path need to calculate
+ * @param len length of the path buffer, not the path string length
+ * @param includeSubdirs also calculate all the subdirs in path holds?
+ * @return the calculated size, DRM_FILE_FAILURE on failure.
+ */
+static int calcDirSize(char *path, int len, uint8_t includeSubdirs)
+{
+ struct dirent *ent;
+ struct stat stat_buf;
+
+ DIR *dir = NULL;
+ int size = 0;
+ int exists = -1;
+ int dirPathLen = strlen(path);
+
+ /* Ensure space for wildcard */
+ if((dirPathLen + 2) >= MAXPATHLEN || (dirPathLen + 2) >= len)
+ {
+ return DRM_FILE_FAILURE;
+ }
+
+ if(path[dirPathLen - 1] != '/')
+ {
+ path[dirPathLen++] = '/';
+ path[dirPathLen] = '\0';
+ }
+
+ dir = opendir(path);
+ if (dir == NULL)
+ {
+ return DRM_FILE_FAILURE;
+ }
+
+ while ((ent = readdir(dir)) != NULL )
+ {
+ if (strcmp(ent->d_name, ".") == 0 ||
+ strcmp(ent->d_name, "..") == 0)
+ {
+ continue;
+ }
+
+ path[dirPathLen] = '\0';
+ if ((int)(strlen(ent->d_name) + dirPathLen + 1) < len)
+ {
+ strcat(path, ent->d_name);
+ }
+ else
+ {
+ continue;
+ }
+
+ exists = stat(path, &stat_buf);
+ if (exists != -1)
+ {
+ /* exclude the storage occupied by directory itself */
+ if (stat_buf.st_mode & S_IFDIR)
+ {
+ if(includeSubdirs)
+ {
+ /* calculate the size recursively */
+ int ret;
+ ret = calcDirSize(path, len, includeSubdirs);
+ /* ignore failure in subdirs */
+ if( DRM_FILE_FAILURE != ret )
+ {
+ size += ret;
+ }
+ }
+ }
+ else
+ {
+ size += stat_buf.st_size;
+ }
+ }
+ }
+
+ closedir(dir);
+ return size;
+}
+
+/* see drm_file.h */
+int32_t DRM_file_startup(void)
+{
+ Trace("DRM_file_startup");
+
+#ifndef DEVICE_FILESYSTEM
+ availableSize = -1;
+
+ initFsVariables();
+#endif
+
+ return DRM_FILE_SUCCESS; /* Nothing to do */
+}
+
+/* see drm_file.h */
+int32_t
+DRM_file_listOpen(const uint16_t *prefix,
+ int32_t prefixLen,
+ int32_t* session,
+ int32_t* iteration)
+{
+ Trace("DRM_file_listOpen: %.*S", prefixLen, prefix);
+
+ if (convertFilename(prefix, prefixLen, tmpPathBuf1) <= 0)
+ {
+ Trace("DRM_file_listOpen: bad filename");
+ }
+ else
+ {
+ DIR *dir;
+
+ /* find the last /, and store the offset to the leaf prefix in
+ * *iteration
+ */
+
+ char *sep = strrchr(tmpPathBuf1, '/');
+ /* Root "/" is a leaf */
+ if (sep == NULL || ((sep != NULL) && (sep == tmpPathBuf1)))
+ {
+ *iteration = prefixLen;
+
+#ifdef TRACE_ON
+ sep = " <empty>"; /* trace will show sep+1 */
+#endif
+ }
+ else
+ {
+ *iteration = sep - tmpPathBuf1 + 1;
+ *sep = 0;
+ }
+
+ dir = opendir(tmpPathBuf1);
+
+ if (dir == NULL)
+ {
+ Trace("DRM_file_listOpen: opendir %s: errno=%d", tmpPathBuf1, errno);
+ }
+ else
+ {
+ Trace("DRM_file_listOpen: dir %s, filter %s", tmpPathBuf1, sep+1);
+ *session = (int32_t)dir;
+ return DRM_FILE_SUCCESS;
+ }
+ }
+
+ return DRM_FILE_FAILURE;
+}
+
+/* see drm_file.h */
+int32_t
+DRM_file_listNextEntry(const uint16_t *prefix, int32_t prefixLen,
+ uint16_t* entry, int32_t entrySize,
+ int32_t *session, int32_t* iteration)
+{
+ struct dirent *ent;
+
+ /* We stored the offset of the leaf part of the prefix (if any)
+ * in *iteration
+ */
+ const uint16_t* strData = prefix + *iteration;
+ int32_t strLength = prefixLen - *iteration;
+
+ /* entrySize is bytes for some reason. Convert to ucs chars */
+ entrySize /= 2;
+
+ /* Now we want to filter for files which start with the (possibly empty)
+ * sequence at strData. We have to return fully-qualified filenames,
+ * which means *iteration characters from prefix, plus the
+ * leaf name.
+ */
+
+ while ( (ent = readdir((DIR *)*session)) != NULL)
+ {
+ int len = strlen(ent->d_name);
+
+ if ( (len + *iteration) > entrySize)
+ {
+ Trace("DRM_file_listNextEntry: %s too long", ent->d_name);
+ }
+ else if (strcmp(ent->d_name, ".") != 0 &&
+ strcmp(ent->d_name, "..") != 0)
+ {
+ int idx;
+ struct stat sinfo;
+
+ /* check against the filter */
+
+ for (idx = 0; idx < strLength; ++idx)
+ {
+ if (ent->d_name[idx] != strData[idx])
+ goto next_name;
+ }
+
+ Trace("DRM_file_listNextEntry: matched %s", ent->d_name);
+
+ /* Now generate the fully-qualified name */
+
+ for (idx = 0; idx < *iteration; ++idx)
+ entry[idx] = prefix[idx];
+
+ for (idx = 0; idx < len; ++idx)
+ entry[*iteration + idx] = (unsigned char)ent->d_name[idx];
+
+ /*add "/" at the end of a DIR file entry*/
+ if (getFileStat(entry, idx + *iteration, &sinfo)){
+ if (S_ISDIR(sinfo.st_mode) &&
+ (idx + 1 + *iteration) < entrySize) {
+ entry[*iteration + idx] = '/';
+ ++idx;
+ }
+ }
+ else
+ {
+ Trace("DRM_file_listNextEntry: stat FAILURE on %.*S",
+ idx + *iteration, entry);
+ }
+ Trace("DRM_file_listNextEntry: got %.*S", idx + *iteration, entry);
+
+ return idx + *iteration;
+ }
+
+ next_name:
+ Trace("DRM_file_listNextEntry: rejected %s", ent->d_name);
+ }
+
+ Trace("DRM_file_listNextEntry: end of list");
+ return 0;
+}
+
+/* see drm_file.h */
+int32_t
+DRM_file_listClose(int32_t session, int32_t iteration)
+{
+ closedir( (DIR *)session);
+ return DRM_FILE_SUCCESS;
+}
+
+/* see drm_file.h */
+int32_t
+DRM_file_getFileLength(const uint16_t *name, int32_t nameLen)
+{
+ struct stat sbuf;
+
+ if (getFileStat(name, nameLen, &sbuf))
+ {
+ if (sbuf.st_size >= INT32_MAX)
+ {
+ Trace("DRM_file_getFileLength: file too big");
+ }
+ else /* Successful */
+ {
+ Trace("DRM_file_getFileLength: %.*S -> %d",
+ nameLen, name, (int32_t)sbuf.st_size);
+ return (int32_t)sbuf.st_size;
+ }
+ }
+
+ return DRM_FILE_FAILURE;
+}
+
+/* see drm_file.h */
+int32_t
+DRM_file_delete(const uint16_t *name, int32_t nameLen)
+{
+ Trace("DRM_file_delete: %.*S", nameLen, name);
+
+ if (convertFilename(name, nameLen, tmpPathBuf1) <= 0)
+ {
+ Trace("DRM_file_delete: bad filename");
+ return DRM_FILE_FAILURE;
+ }
+ else
+ {
+ struct stat sinfo;
+ if (stat(tmpPathBuf1, &sinfo) != 0){
+ Trace("DRM_file_delete: stat failed, errno=%d", errno);
+ return DRM_FILE_FAILURE;
+ }
+#ifndef DEVICE_FILESYSTEM
+ if (S_ISDIR(sinfo.st_mode)){
+ /* it's a dir */
+ if (rmdir(tmpPathBuf1) != 0){
+ Trace("DRM_file_delete: dir remove failed, errno=%d", errno);
+ return DRM_FILE_FAILURE;
+ }
+ else
+ {
+ return DRM_FILE_SUCCESS;
+ }
+ }
+#endif
+ /* it's a file */
+ if (unlink(tmpPathBuf1) != 0)
+ {
+ Trace("DRM_file_delete: file remove failed, errno=%d", errno);
+ return DRM_FILE_FAILURE;
+ }
+ else
+ {
+#ifndef DEVICE_FILESYSTEM
+ availableSize += sinfo.st_size;
+#endif
+ return DRM_FILE_SUCCESS;
+ }
+ }
+ return DRM_FILE_FAILURE;
+}
+
+/* see drm_file.h */
+int32_t
+DRM_file_rename(const uint16_t *oldName, int32_t oldNameLen,
+ const uint16_t *newName, int32_t newNameLen)
+{
+ Trace("DRM_file_rename %.*S -> %.*S",
+ oldNameLen, oldName, newNameLen, newName);
+ if (DRM_file_exists(newName, newNameLen) != DRM_FILE_FAILURE)
+ {
+ Trace("DRM_file_rename: filename:%s exist",newName);
+ return DRM_FILE_FAILURE;
+ }
+
+ if (convertFilename(oldName, oldNameLen, tmpPathBuf1) <= 0 ||
+ convertFilename(newName, newNameLen, tmpPathBuf2) <= 0)
+ {
+ Trace("DRM_file_rename: bad filename");
+ }
+ else if (rename(tmpPathBuf1, tmpPathBuf2) != 0)
+ {
+ Trace("DRM_file_rename: failed errno=%d", errno);
+ }
+ else /* Success */
+ {
+ return DRM_FILE_SUCCESS;
+ }
+
+ return DRM_FILE_FAILURE;
+}
+
+/* see drm_file.h */
+int32_t
+DRM_file_exists(const uint16_t *name, int32_t nameLen)
+{
+ struct stat sbuf;
+
+ Trace("DRM_file_exists: %.*S", nameLen, name);
+
+ /*remove trailing "/" separators, except the first "/" standing for root*/
+ while ((nameLen > 1) && (name[nameLen -1] == '/'))
+ --nameLen;
+
+ if (getFileStat(name, nameLen, &sbuf))
+ {
+ Trace("DRM_file_exists: stat returns mode 0x%x", sbuf.st_mode);
+
+ if (S_ISDIR(sbuf.st_mode))
+ return DRM_FILE_ISDIR;
+ if (S_ISREG(sbuf.st_mode))
+ return DRM_FILE_ISREG;
+ }
+
+ return DRM_FILE_FAILURE;
+}
+
+/* see drm_file.h */
+int32_t
+DRM_file_open(const uint16_t *name, int32_t nameLen, int32_t mode,
+ int32_t* handle)
+{
+ int res;
+
+#if DRM_FILE_MODE_READ != 1 || DRM_FILE_MODE_WRITE != 2
+#error constants changed
+#endif
+
+ /* Convert DRM file modes to posix modes */
+ static const int modes[4] =
+ { 0,
+ O_RDONLY,
+ O_WRONLY | O_CREAT,
+ O_RDWR | O_CREAT
+ };
+
+ Trace("DRM_file_open %.*S mode 0x%x", nameLen, name, mode);
+
+ assert((mode & ~(DRM_FILE_MODE_READ|DRM_FILE_MODE_WRITE)) == 0);
+
+ if (convertFilename(name, nameLen, tmpPathBuf1) <= 0)
+ {
+ Trace("DRM_file_open: bad filename");
+ return DRM_FILE_FAILURE;
+ }
+
+ if ((res = open(tmpPathBuf1, modes[mode], 0777)) == -1)
+ {
+ Trace("DRM_file_open: open failed errno=%d", errno);
+ return DRM_FILE_FAILURE;
+ }
+
+ Trace("DRM_file_open: open '%s; returned %d", tmpPathBuf1, res);
+ *handle = res;
+
+ return DRM_FILE_SUCCESS;
+}
+
+/* see drm_file.h */
+int32_t
+DRM_file_read(int32_t handle, uint8_t* dst, int32_t length)
+{
+ int n;
+
+ assert(length > 0);
+
+ /* TODO: Make dst a void *? */
+
+ n = read((int)handle, dst, (size_t)length);
+ if (n > 0)
+ {
+ Trace("DRM_file_read handle=%d read %d bytes", handle, n);
+ return n;
+ }
+ else if (n == 0)
+ {
+ Trace("DRM_file_read read EOF: handle=%d", handle);
+ return DRM_FILE_EOF;
+ }
+ else
+ {
+ Trace("DRM_file_read failed handle=%d, errno=%d", handle, errno);
+ return DRM_FILE_FAILURE;
+ }
+}
+
+/* see drm_file.h */
+int32_t
+DRM_file_write(int32_t handle, const uint8_t* src, int32_t length)
+{
+ /* TODO: Make dst a void *? */
+ int n;
+#ifndef DEVICE_FILESYSTEM
+ int delta;
+ off_t prevPos;
+ struct stat sbuf;
+ int prevFileSize;
+#endif
+
+ assert(length >= 0);
+
+#ifndef DEVICE_FILESYSTEM
+ if ( -1 == fstat((int)handle, &sbuf) )
+ {
+ Trace("DRM_file_write: fstat error %d", errno);
+ return DRM_FILE_FAILURE;
+ }
+ prevFileSize = (int)(sbuf.st_size);
+ prevPos = lseek( (int)handle, 0, SEEK_CUR);
+ if ( (off_t)-1 == prevPos )
+ {
+ Trace("DRM_file_write: get current pos error %d", errno);
+ return DRM_FILE_FAILURE;
+ }
+ delta = (int)prevPos + length - prevFileSize;
+ if (delta > availableSize)
+ {
+ Trace("DRM_file_write: not enough size!");
+ return DRM_FILE_FAILURE;
+ }
+#endif
+ n = write((int)handle, src, (size_t)length);
+ if (n < 0)
+ {
+ Trace("DRM_file_write failed errno=%d", errno);
+ return DRM_FILE_FAILURE;
+ }
+#ifndef DEVICE_FILESYSTEM
+ delta = prevPos + n - prevFileSize;
+
+ if ( delta > 0 )
+ {
+ availableSize -= delta;
+ }
+#endif
+ Trace("DRM_file_write handle=%d wrote %d/%d bytes", handle, n, length);
+
+ return n;
+}
+
+/* see drm_file.h */
+int32_t DRM_file_close(int32_t handle)
+{
+ if (close((int)handle) == 0)
+ {
+ Trace("DRM_file_close handle=%d success", handle);
+ return DRM_FILE_SUCCESS;
+ }
+
+ Trace("DRM_file_close handle=%d failed", handle);
+ return DRM_FILE_FAILURE;
+}
+
+/* see drm_file.h */
+int32_t
+DRM_file_setPosition(int32_t handle, int32_t value)
+{
+#ifndef DEVICE_FILESYSTEM
+ struct stat sbuf;
+#endif
+ off_t newPos;
+
+ if (value < 0)
+ {
+ Trace("DRM_file_setPosition: handle=%d negative value (%d)",
+ handle, value);
+ return DRM_FILE_FAILURE;
+ }
+
+#ifndef DEVICE_FILESYSTEM
+ if ( fstat((int)handle, &sbuf) == -1 )
+ {
+ Trace("DRM_file_setPosition: fstat fail errno=%d", errno);
+ return DRM_FILE_FAILURE;
+ }
+
+ if ( ((off_t)value > sbuf.st_size) &&
+ (availableSize < (value - (int)(sbuf.st_size))) )
+ {
+ Trace("DRM_file_setPosition: not enough space");
+ return DRM_FILE_FAILURE;
+ }
+#endif
+
+ newPos = lseek( (int)handle, (off_t)value, SEEK_SET);
+ if ( newPos == (off_t)-1 )
+ {
+ Trace("DRM_file_setPosition: seek failed: errno=%d", errno);
+ }
+ else
+ {
+#ifndef DEVICE_FILESYSTEM
+ if ( newPos > sbuf.st_size )
+ {
+ availableSize -= (int)(newPos - sbuf.st_size);
+ }
+#endif
+ return DRM_FILE_SUCCESS;
+ }
+
+ return DRM_FILE_FAILURE;
+}
+
+/* see drm_file.h */
+int32_t
+DRM_file_mkdir(const uint16_t* name, int32_t nameChars)
+{
+ Trace("DRM_file_mkdir started!..");
+
+ if (convertFilename(name, nameChars, tmpPathBuf1) <= 0)
+ {
+ Trace("DRM_file_mkdir: bad filename");
+ return DRM_FILE_FAILURE;
+ }
+
+ if (mkdir(tmpPathBuf1,0777) != 0)
+ {
+ Trace("DRM_file_mkdir failed!errno=%d",errno);
+ return DRM_FILE_FAILURE;
+ }
+
+ return DRM_FILE_SUCCESS;
+}
diff --git a/media/libdrm/mobile1/src/objmng/drm_i18n.c b/media/libdrm/mobile1/src/objmng/drm_i18n.c
new file mode 100644
index 0000000..b1118a9
--- /dev/null
+++ b/media/libdrm/mobile1/src/objmng/drm_i18n.c
@@ -0,0 +1,444 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <objmng/drm_i18n.h>
+
+#define IS_GB2312_HIGH_BYTE(c) ((c) >= 0xA1 && (c) <= 0xF7)
+#define IS_GB2312_LOW_BYTE(c) ((c) >= 0xA1 && (c) <= 0xFE)
+#define IS_GBK_HIGH_BYTE(c) ((c) >= 0x81 && (c) <= 0xFE)
+#define IS_GBK_LOW_BYTE(c) ((c) >= 0x40 && (c) <= 0xFE && (c) != 0x7F)
+#define IS_BIG5_HIGH_BYTE(c) ((c) >= 0xA1 && (c) <= 0xF9)
+#define IS_BIG5_LOW_BYTE(c) (((c) >= 0x40 && (c) <= 0x7E) \
+ || ((c) >= 0xA1 && (c) <= 0xFE))
+#define IS_ASCII(c) ((c) <= 127)
+
+#define INVALID_UNICODE 0xFFFD
+
+#define I18N_LATIN1_SUPPORT
+#define I18N_UTF8_UTF16_SUPPORT
+
+
+/**
+ * Simply convert ISO 8859-1 (latin1) to unicode
+ */
+static int32_t latin1ToWcs(const uint8_t *mbs, int32_t mbsLen,
+ uint16_t *wcsBuf, int32_t bufSizeInWideChar,
+ int32_t *bytesConsumed);
+
+/**
+ * Convert one unicode char to ISO 8859-1 (latin1) byte
+ */
+static int32_t wcToLatin1(uint16_t wc, uint8_t * mbs, int32_t bufSize);
+
+/**
+ * Convert UTF-8 to unicode
+ */
+static int32_t utf8ToWcs(const uint8_t *mbs, int32_t mbsLen,
+ uint16_t *wcsBuf, int32_t bufSizeInWideChar,
+ int32_t *bytesConsumed);
+
+/**
+ * Convert one unicode char to UTF-8 bytes
+ */
+static int32_t wcToUtf8(uint16_t wc, uint8_t * mbs, int32_t bufSize);
+
+/**
+ * Convert UTF-16 BE to unicode
+ */
+static int32_t utf16beToWcs(const uint8_t *mbs, int32_t mbsLen,
+ uint16_t *wcsBuf, int32_t bufSizeInWideChar,
+ int32_t *bytesConsumed);
+
+/**
+ * Convert one unicode char to UTF-16 BE bytes
+ */
+static int32_t wcToUtf16be(uint16_t wc, uint8_t * mbs, int32_t bufSize);
+
+/**
+ * Convert UTF-16 LE to unicode
+ */
+static int32_t utf16leToWcs(const uint8_t *mbs, int32_t mbsLen,
+ uint16_t *wcsBuf, int32_t bufSizeInWideChar,
+ int32_t *bytesConsumed);
+
+/**
+ * Convert one unicode char to UTF-16 LE bytes
+ */
+static int32_t wcToUtf16le(uint16_t wc, uint8_t * mbs, int32_t bufSize);
+
+/*
+ * see drm_i18n.h
+ */
+int32_t DRM_i18n_mbsToWcs(DRM_Charset_t charset,
+ const uint8_t *mbs, int32_t mbsLen,
+ uint16_t *wcsBuf, int32_t bufSizeInWideChar,
+ int32_t *bytesConsumed)
+{
+ switch (charset)
+ {
+#ifdef I18N_GB2312_SUPPORT
+ case DRM_CHARSET_GB2312:
+ return gb2312ToWcs(mbs, mbsLen, wcsBuf, bufSizeInWideChar, bytesConsumed);
+#endif
+#ifdef I18N_GBK_SUPPORT
+ case DRM_CHARSET_GBK:
+ return gbkToWcs(mbs, mbsLen, wcsBuf, bufSizeInWideChar, bytesConsumed);
+#endif
+#ifdef I18N_BIG5_SUPPORT
+ case DRM_CHARSET_BIG5:
+ return big5ToWcs(mbs, mbsLen, wcsBuf, bufSizeInWideChar, bytesConsumed);
+#endif
+#ifdef I18N_LATIN1_SUPPORT
+ case DRM_CHARSET_LATIN1:
+ return latin1ToWcs(mbs, mbsLen, wcsBuf, bufSizeInWideChar, bytesConsumed);
+#endif
+#ifdef I18N_ISO8859X_SUPPORT
+ case DRM_CHARSET_LATIN2:
+ case DRM_CHARSET_LATIN3:
+ case DRM_CHARSET_LATIN4:
+ case DRM_CHARSET_CYRILLIC:
+ case DRM_CHARSET_ARABIC:
+ case DRM_CHARSET_GREEK:
+ case DRM_CHARSET_HEBREW:
+ case DRM_CHARSET_LATIN5:
+ case DRM_CHARSET_LATIN6:
+ case DRM_CHARSET_THAI:
+ case DRM_CHARSET_LATIN7:
+ case DRM_CHARSET_LATIN8:
+ case DRM_CHARSET_LATIN9:
+ case DRM_CHARSET_LATIN10:
+ return iso8859xToWcs(charset, mbs, mbsLen, wcsBuf, bufSizeInWideChar, bytesConsumed);
+#endif
+#ifdef I18N_UTF8_UTF16_SUPPORT
+ case DRM_CHARSET_UTF8:
+ return utf8ToWcs(mbs, mbsLen, wcsBuf, bufSizeInWideChar, bytesConsumed);
+ case DRM_CHARSET_UTF16BE:
+ return utf16beToWcs(mbs, mbsLen, wcsBuf, bufSizeInWideChar, bytesConsumed);
+ case DRM_CHARSET_UTF16LE:
+ return utf16leToWcs(mbs, mbsLen, wcsBuf, bufSizeInWideChar, bytesConsumed);
+#endif
+ default:
+ return -1;
+ }
+}
+
+/*
+ * see drm_i18n.h
+ */
+int32_t DRM_i18n_wcsToMbs(DRM_Charset_t charset,
+ const uint16_t *wcs, int32_t wcsLen,
+ uint8_t *mbsBuf, int32_t bufSizeInByte)
+{
+ int32_t (* wcToMbFunc)(uint16_t, uint8_t *, int32_t);
+ int32_t charIndex = 0;
+ int32_t numMultiBytes = 0;
+
+ switch (charset)
+ {
+#ifdef I18N_LATIN1_SUPPORT
+ case DRM_CHARSET_LATIN1:
+ wcToMbFunc = wcToLatin1;
+ break;
+#endif
+#ifdef I18N_UTF8_UTF16_SUPPORT
+ case DRM_CHARSET_UTF8:
+ wcToMbFunc = wcToUtf8;
+ break;
+ case DRM_CHARSET_UTF16BE:
+ wcToMbFunc = wcToUtf16be;
+ break;
+ case DRM_CHARSET_UTF16LE:
+ wcToMbFunc = wcToUtf16le;
+ break;
+#endif
+#ifdef I18N_ISO8859X_SUPPORT
+ case DRM_CHARSET_LATIN2:
+ case DRM_CHARSET_LATIN3:
+ case DRM_CHARSET_LATIN4:
+ case DRM_CHARSET_CYRILLIC:
+ case DRM_CHARSET_ARABIC:
+ case DRM_CHARSET_GREEK:
+ case DRM_CHARSET_HEBREW:
+ case DRM_CHARSET_LATIN5:
+ case DRM_CHARSET_LATIN6:
+ case DRM_CHARSET_THAI:
+ case DRM_CHARSET_LATIN7:
+ case DRM_CHARSET_LATIN8:
+ case DRM_CHARSET_LATIN9:
+ case DRM_CHARSET_LATIN10:
+ return wcsToIso8859x(charset, wcs, wcsLen, mbsBuf, bufSizeInByte);
+#endif
+ default:
+ return -1;
+ }
+
+ if (mbsBuf) {
+ while (numMultiBytes < bufSizeInByte && charIndex < wcsLen) {
+ /* TODO: handle surrogate pair values here */
+ int32_t mbLen = wcToMbFunc(wcs[charIndex],
+ &mbsBuf[numMultiBytes], bufSizeInByte - numMultiBytes);
+
+ if (numMultiBytes + mbLen > bufSizeInByte) {
+ /* Insufficient buffer. Don't update numMultiBytes */
+ break;
+ }
+ charIndex++;
+ numMultiBytes += mbLen;
+ }
+ } else {
+ while (charIndex < wcsLen) {
+ /* TODO: handle surrogate pair values here */
+ numMultiBytes += wcToMbFunc(wcs[charIndex], NULL, 0);
+ charIndex++;
+ }
+ }
+
+ return numMultiBytes;
+}
+
+
+#ifdef I18N_LATIN1_SUPPORT
+
+int32_t latin1ToWcs(const uint8_t *mbs, int32_t mbsLen,
+ uint16_t *wcsBuf, int32_t bufSizeInWideChar,
+ int32_t *bytesConsumed)
+{
+ int32_t charsToConvert;
+ int32_t len;
+
+ if (wcsBuf == NULL) {
+ return mbsLen;
+ }
+
+ len = charsToConvert = mbsLen > bufSizeInWideChar ? bufSizeInWideChar : mbsLen;
+ if (len < 0)
+ return 0;
+ while (len--) {
+ *wcsBuf++ = *mbs++;
+ }
+
+ if (bytesConsumed)
+ *bytesConsumed = charsToConvert;
+
+ return charsToConvert;
+}
+
+int32_t wcToLatin1(uint16_t wc, uint8_t * mbs, int32_t bufSize)
+{
+ uint8_t ch;
+
+ if (wc < 0x100) {
+ ch = (uint8_t)(wc & 0xff);
+ } else {
+ ch = '?';
+ }
+ if (mbs && bufSize > 0)
+ *mbs = ch;
+ return 1;
+}
+
+#endif /* I18N_LATIN1_SUPPORT */
+
+#ifdef I18N_UTF8_UTF16_SUPPORT
+
+int32_t utf8ToWcs(const uint8_t *mbs, int32_t mbsLen,
+ uint16_t *wcsBuf, int32_t bufSizeInWideChar,
+ int32_t *bytesConsumed)
+{
+ int32_t charsConverted = 0;
+ int32_t i = 0;
+ int32_t wideChar;
+
+ if (wcsBuf == NULL) {
+ /* No conversion but we're still going to calculate bytesConsumed */
+ bufSizeInWideChar = mbsLen * 2;
+ }
+
+ while((i < mbsLen) && (charsConverted < bufSizeInWideChar)) {
+ uint8_t ch = mbs[i];
+ uint8_t ch2, ch3, ch4;
+
+ wideChar = -1;
+
+ if(IS_ASCII(ch)) {
+ wideChar = ch;
+ i++;
+ } else if ((ch & 0xc0) == 0xc0) {
+ int utfStart = i;
+ if ((ch & 0xe0) == 0xc0) {
+ /* 2 byte sequence */
+ if (i + 1 < mbsLen && ((ch2 = mbs[i + 1]) & 0xc0) == 0x80) {
+ wideChar = (uint16_t)(((ch & 0x1F) << 6) | (ch2 & 0x3F));
+ i += 2;
+ } else {
+ /* skip incomplete sequence */
+ i++;
+ }
+ } else if ((ch & 0xf0) == 0xe0) {
+ /* 3 byte sequence */
+ if (i + 2 < mbsLen
+ && ((ch2 = mbs[i + 1]) & 0xc0) == 0x80
+ && ((ch3 = mbs[i + 2]) & 0xc0) == 0x80) {
+ wideChar = (uint16_t)(((ch & 0x0F) << 12) | ((ch2 & 0x3F) << 6) | (ch3 & 0x3F));
+ i += 3;
+ } else {
+ /* skip incomplete sequence (up to 2 bytes) */
+ i++;
+ if (i < mbsLen && (mbs[i] & 0xc0) == 0x80)
+ i++;
+ }
+ } else if ((ch & 0xf8) == 0xf0) {
+ /* 4 byte sequence */
+ if (i + 3 < mbsLen
+ && ((ch2 = mbs[i + 1]) & 0xc0) == 0x80
+ && ((ch3 = mbs[i + 2]) & 0xc0) == 0x80
+ && ((ch4 = mbs[i + 3]) & 0xc0) == 0x80) {
+ /* FIXME: we do NOT support U+10000 - U+10FFFF for now.
+ * leave it as 0xFFFD. */
+ wideChar = INVALID_UNICODE;
+ i += 4;
+ } else {
+ /* skip incomplete sequence (up to 3 bytes) */
+ i++;
+ if (i < mbsLen && (mbs[i] & 0xc0) == 0x80) {
+ i++;
+ if (i < mbsLen && (mbs[i] & 0xc0) == 0x80) {
+ i++;
+ }
+ }
+ }
+ } else {
+ /* invalid */
+ i++;
+ }
+ if (i >= mbsLen && wideChar == -1) {
+ /* Possible incomplete UTF-8 sequence at the end of mbs.
+ * Leave it to the caller.
+ */
+ i = utfStart;
+ break;
+ }
+ } else {
+ /* invalid */
+ i++;
+ }
+ if(wcsBuf) {
+ if (wideChar == -1)
+ wideChar = INVALID_UNICODE;
+ wcsBuf[charsConverted] = (uint16_t)wideChar;
+ }
+ charsConverted++;
+ }
+
+ if (bytesConsumed)
+ *bytesConsumed = i;
+
+ return charsConverted;
+}
+
+int32_t wcToUtf8(uint16_t wc, uint8_t * mbs, int32_t bufSize)
+{
+ if (wc <= 0x7f) {
+ if (mbs && (bufSize >= 1)) {
+ *mbs = (uint8_t)wc;
+ }
+ return 1;
+ } else if (wc <= 0x7ff) {
+ if (mbs && (bufSize >= 2)) {
+ *mbs++ = (uint8_t)((wc >> 6) | 0xc0);
+ *mbs = (uint8_t)((wc & 0x3f) | 0x80);
+ }
+ return 2;
+ } else {
+ if (mbs && (bufSize >= 3)) {
+ *mbs++ = (uint8_t)((wc >> 12) | 0xe0);
+ *mbs++ = (uint8_t)(((wc >> 6) & 0x3f)| 0x80);
+ *mbs = (uint8_t)((wc & 0x3f) | 0x80);
+ }
+ return 3;
+ }
+}
+
+int32_t utf16beToWcs(const uint8_t *mbs, int32_t mbsLen,
+ uint16_t *wcsBuf, int32_t bufSizeInWideChar,
+ int32_t *bytesConsumed)
+{
+ int32_t charsToConvert;
+ int32_t len;
+
+ if (wcsBuf == NULL) {
+ return mbsLen / 2;
+ }
+
+ len = charsToConvert = (mbsLen / 2) > bufSizeInWideChar ? bufSizeInWideChar : (mbsLen / 2);
+ while (len--) {
+ /* TODO: handle surrogate pair values */
+ *wcsBuf++ = (uint16_t)((*mbs << 8) | *(mbs + 1));
+ mbs += 2;
+ }
+
+ if (bytesConsumed)
+ *bytesConsumed = charsToConvert * 2;
+
+ return charsToConvert;
+}
+
+int32_t wcToUtf16be(uint16_t wc, uint8_t * mbs, int32_t bufSize)
+{
+ if (mbs && bufSize >= 2) {
+ /* TODO: handle surrogate pair values */
+ *mbs = (uint8_t)(wc >> 8);
+ *(mbs + 1) = (uint8_t)(wc & 0xff);
+ }
+ return 2;
+}
+
+int32_t utf16leToWcs(const uint8_t *mbs, int32_t mbsLen,
+ uint16_t *wcsBuf, int32_t bufSizeInWideChar,
+ int32_t *bytesConsumed)
+{
+ int32_t charsToConvert;
+ int32_t len;
+
+ if (wcsBuf == NULL) {
+ return mbsLen / 2;
+ }
+
+ len = charsToConvert = (mbsLen / 2) > bufSizeInWideChar ? bufSizeInWideChar : (mbsLen / 2);
+ while (len--) {
+ /* TODO: handle surrogate pair values */
+ *wcsBuf++ = (uint16_t)(*mbs | (*(mbs + 1) << 8));
+ mbs += 2;
+ }
+
+ if (bytesConsumed)
+ *bytesConsumed = charsToConvert * 2;
+
+ return charsToConvert;
+}
+
+int32_t wcToUtf16le(uint16_t wc, uint8_t * mbs, int32_t bufSize)
+{
+ if (mbs && bufSize >= 2) {
+ /* TODO: handle surrogate pair values */
+ *mbs = (uint8_t)(wc & 0xff);
+ *(mbs + 1) = (uint8_t)(wc >> 8);
+ }
+ return 2;
+}
+
+#endif /* I18N_UTF8_UTF16_SUPPORT */
+
diff --git a/media/libdrm/mobile1/src/objmng/drm_rights_manager.c b/media/libdrm/mobile1/src/objmng/drm_rights_manager.c
new file mode 100644
index 0000000..80901f5
--- /dev/null
+++ b/media/libdrm/mobile1/src/objmng/drm_rights_manager.c
@@ -0,0 +1,688 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <drm_rights_manager.h>
+#include <drm_inner.h>
+#include <drm_file.h>
+#include <drm_i18n.h>
+
+static int32_t drm_getString(uint8_t* string, int32_t len, int32_t handle)
+{
+ int32_t i;
+
+ for (i = 0; i < len; i++) {
+ if (DRM_FILE_FAILURE == DRM_file_read(handle, &string[i], 1))
+ return FALSE;
+ if (string[i] == '\n') {
+ string[i + 1] = '\0';
+ break;
+ }
+ }
+ return TRUE;
+}
+
+static int32_t drm_putString(uint8_t* string, int32_t handle)
+{
+ int32_t i = 0;
+
+ for (i = 0;; i++) {
+ if (string[i] == '\0')
+ break;
+ if (DRM_FILE_FAILURE == DRM_file_write(handle, &string[i], 1))
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static int32_t drm_writeToUidTxt(uint8_t* Uid, int32_t* id)
+{
+ int32_t length;
+ int32_t i;
+ uint8_t idStr[8];
+ int32_t idMax;
+ uint8_t(*uidStr)[256];
+ uint16_t nameUcs2[MAX_FILENAME_LEN];
+ int32_t nameLen;
+ int32_t bytesConsumed;
+ int32_t handle;
+ int32_t fileRes;
+
+ if (*id < 1)
+ return FALSE;
+
+ /* convert in ucs2 */
+ nameLen = strlen(DRM_UID_FILE_PATH);
+ nameLen = DRM_i18n_mbsToWcs(DRM_CHARSET_UTF8,
+ (uint8_t *)DRM_UID_FILE_PATH,
+ nameLen,
+ nameUcs2,
+ MAX_FILENAME_LEN,
+ &bytesConsumed);
+ fileRes = DRM_file_open(nameUcs2,
+ nameLen,
+ DRM_FILE_MODE_READ,
+ &handle);
+ if (DRM_FILE_SUCCESS != fileRes) {
+ DRM_file_open(nameUcs2,
+ nameLen,
+ DRM_FILE_MODE_WRITE,
+ &handle);
+ DRM_file_write(handle, (uint8_t *)"0\n", 2);
+ DRM_file_close(handle);
+ DRM_file_open(nameUcs2,
+ nameLen,
+ DRM_FILE_MODE_READ,
+ &handle);
+ }
+
+ if (!drm_getString(idStr, 8, handle)) {
+ DRM_file_close(handle);
+ return FALSE;
+ }
+ idMax = atoi((char *)idStr);
+
+ if (idMax < *id)
+ uidStr = malloc((idMax + 1) * 256);
+ else
+ uidStr = malloc(idMax * 256);
+
+ for (i = 0; i < idMax; i++) {
+ if (!drm_getString(uidStr[i], 256, handle)) {
+ DRM_file_close(handle);
+ free(uidStr);
+ return FALSE;
+ }
+ }
+ length = strlen((char *)Uid);
+ strcpy((char *)uidStr[*id - 1], (char *)Uid);
+ uidStr[*id - 1][length] = '\n';
+ uidStr[*id - 1][length + 1] = '\0';
+ if (idMax < (*id))
+ idMax++;
+ DRM_file_close(handle);
+
+ DRM_file_open(nameUcs2,
+ nameLen,
+ DRM_FILE_MODE_WRITE,
+ &handle);
+ sprintf((char *)idStr, "%d", idMax);
+
+ if (!drm_putString(idStr, handle)) {
+ DRM_file_close(handle);
+ free(uidStr);
+ return FALSE;
+ }
+ if (DRM_FILE_FAILURE == DRM_file_write(handle, (uint8_t *)"\n", 1)) {
+ DRM_file_close(handle);
+ free(uidStr);
+ return FALSE;
+ }
+ for (i = 0; i < idMax; i++) {
+ if (!drm_putString(uidStr[i], handle)) {
+ DRM_file_close(handle);
+ free(uidStr);
+ return FALSE;
+ }
+ }
+ if (DRM_FILE_FAILURE == DRM_file_write(handle, (uint8_t *)"\n", 1)) {
+ DRM_file_close(handle);
+ free(uidStr);
+ return FALSE;
+ }
+ DRM_file_close(handle);
+ free(uidStr);
+ return TRUE;
+}
+
+/* See objmng_files.h */
+int32_t drm_readFromUidTxt(uint8_t* Uid, int32_t* id, int32_t option)
+{
+ int32_t i;
+ uint8_t p[256] = { 0 };
+ uint8_t idStr[8];
+ int32_t idMax = 0;
+ uint16_t nameUcs2[MAX_FILENAME_LEN];
+ int32_t nameLen = 0;
+ int32_t bytesConsumed;
+ int32_t handle;
+ int32_t fileRes;
+
+ if (NULL == id || NULL == Uid)
+ return FALSE;
+
+ DRM_file_startup();
+
+ /* convert in ucs2 */
+ nameLen = strlen(DRM_UID_FILE_PATH);
+ nameLen = DRM_i18n_mbsToWcs(DRM_CHARSET_UTF8,
+ (uint8_t *)DRM_UID_FILE_PATH,
+ nameLen,
+ nameUcs2,
+ MAX_FILENAME_LEN,
+ &bytesConsumed);
+ fileRes = DRM_file_open(nameUcs2,
+ nameLen,
+ DRM_FILE_MODE_READ,
+ &handle);
+ if (DRM_FILE_SUCCESS != fileRes) {
+ DRM_file_open(nameUcs2,
+ nameLen,
+ DRM_FILE_MODE_WRITE,
+ &handle);
+ DRM_file_write(handle, (uint8_t *)"0\n", 2);
+ DRM_file_close(handle);
+ DRM_file_open(nameUcs2,
+ nameLen,
+ DRM_FILE_MODE_READ,
+ &handle);
+ }
+
+ if (!drm_getString(idStr, 8, handle)) {
+ DRM_file_close(handle);
+ return FALSE;
+ }
+ idMax = atoi((char *)idStr);
+
+ if (option == GET_UID) {
+ if (*id < 1 || *id > idMax) {
+ DRM_file_close(handle);
+ return FALSE;
+ }
+ for (i = 1; i <= *id; i++) {
+ if (!drm_getString(Uid, 256, handle)) {
+ DRM_file_close(handle);
+ return FALSE;
+ }
+ }
+ DRM_file_close(handle);
+ return TRUE;
+ }
+ if (option == GET_ID) {
+ *id = -1;
+ for (i = 1; i <= idMax; i++) {
+ if (!drm_getString(p, 256, handle)) {
+ DRM_file_close(handle);
+ return FALSE;
+ }
+ if (strstr((char *)p, (char *)Uid) != NULL
+ && strlen((char *)p) == strlen((char *)Uid) + 1) {
+ *id = i;
+ DRM_file_close(handle);
+ return TRUE;
+ }
+ if ((*id == -1) && (strlen((char *)p) < 3))
+ *id = i;
+ }
+ if (*id != -1) {
+ DRM_file_close(handle);
+ return FALSE;
+ }
+ *id = idMax + 1;
+ DRM_file_close(handle);
+ return FALSE;
+ }
+ DRM_file_close(handle);
+ return FALSE;
+}
+
+static int32_t drm_acquireId(uint8_t* uid, int32_t* id)
+{
+ if (TRUE == drm_readFromUidTxt(uid, id, GET_ID))
+ return TRUE;
+
+ drm_writeToUidTxt(uid, id);
+
+ return FALSE; /* The Uid is not exit, then return FALSE indicate it */
+}
+
+int32_t drm_writeOrReadInfo(int32_t id, T_DRM_Rights* Ro, int32_t* RoAmount, int32_t option)
+{
+ uint8_t fullname[MAX_FILENAME_LEN] = {0};
+ int32_t tmpRoAmount;
+ uint16_t nameUcs2[MAX_FILENAME_LEN];
+ int32_t nameLen = 0;
+ int32_t bytesConsumed;
+ int32_t handle;
+ int32_t fileRes;
+
+ sprintf((char *)fullname, ANDROID_DRM_CORE_PATH"%d"EXTENSION_NAME_INFO, id);
+
+ /* convert in ucs2 */
+ nameLen = strlen((char *)fullname);
+ nameLen = DRM_i18n_mbsToWcs(DRM_CHARSET_UTF8,
+ fullname,
+ nameLen,
+ nameUcs2,
+ MAX_FILENAME_LEN,
+ &bytesConsumed);
+ fileRes = DRM_file_open(nameUcs2,
+ nameLen,
+ DRM_FILE_MODE_READ,
+ &handle);
+ if (DRM_FILE_SUCCESS != fileRes) {
+ if (GET_ALL_RO == option || GET_A_RO == option)
+ return FALSE;
+
+ if (GET_ROAMOUNT == option) {
+ *RoAmount = -1;
+ return TRUE;
+ }
+ }
+
+ DRM_file_close(handle);
+ DRM_file_open(nameUcs2,
+ nameLen,
+ DRM_FILE_MODE_READ | DRM_FILE_MODE_WRITE,
+ &handle);
+
+ switch(option) {
+ case GET_ROAMOUNT:
+ if (DRM_FILE_FAILURE == DRM_file_read(handle, (uint8_t*)RoAmount, sizeof(int32_t))) {
+ DRM_file_close(handle);
+ return FALSE;
+ }
+ break;
+ case GET_ALL_RO:
+ DRM_file_setPosition(handle, sizeof(int32_t));
+
+ if (DRM_FILE_FAILURE == DRM_file_read(handle, (uint8_t*)Ro, (*RoAmount) * sizeof(T_DRM_Rights))) {
+ DRM_file_close(handle);
+ return FALSE;
+ }
+ break;
+ case SAVE_ALL_RO:
+ if (DRM_FILE_FAILURE == DRM_file_write(handle, (uint8_t*)RoAmount, sizeof(int32_t))) {
+ DRM_file_close(handle);
+ return FALSE;
+ }
+
+ if (NULL != Ro && *RoAmount >= 1) {
+ if (DRM_FILE_FAILURE == DRM_file_write(handle, (uint8_t*) Ro, (*RoAmount) * sizeof(T_DRM_Rights))) {
+ DRM_file_close(handle);
+ return FALSE;
+ }
+ }
+ break;
+ case GET_A_RO:
+ DRM_file_setPosition(handle, sizeof(int32_t) + (*RoAmount - 1) * sizeof(T_DRM_Rights));
+
+ if (DRM_FILE_FAILURE == DRM_file_read(handle, (uint8_t*)Ro, sizeof(T_DRM_Rights))) {
+ DRM_file_close(handle);
+ return FALSE;
+ }
+ break;
+ case SAVE_A_RO:
+ DRM_file_setPosition(handle, sizeof(int32_t) + (*RoAmount - 1) * sizeof(T_DRM_Rights));
+
+ if (DRM_FILE_FAILURE == DRM_file_write(handle, (uint8_t*)Ro, sizeof(T_DRM_Rights))) {
+ DRM_file_close(handle);
+ return FALSE;
+ }
+
+ DRM_file_setPosition(handle, 0);
+ if (DRM_FILE_FAILURE == DRM_file_read(handle, (uint8_t*)&tmpRoAmount, sizeof(int32_t))) {
+ DRM_file_close(handle);
+ return FALSE;
+ }
+ if (tmpRoAmount < *RoAmount) {
+ DRM_file_setPosition(handle, 0);
+ DRM_file_write(handle, (uint8_t*)RoAmount, sizeof(int32_t));
+ }
+ break;
+ default:
+ DRM_file_close(handle);
+ return FALSE;
+ }
+
+ DRM_file_close(handle);
+ return TRUE;
+}
+
+int32_t drm_appendRightsInfo(T_DRM_Rights* rights)
+{
+ int32_t id;
+ int32_t roAmount;
+
+ if (NULL == rights)
+ return FALSE;
+
+ drm_acquireId(rights->uid, &id);
+
+ if (FALSE == drm_writeOrReadInfo(id, NULL, &roAmount, GET_ROAMOUNT))
+ return FALSE;
+
+ if (-1 == roAmount)
+ roAmount = 0;
+
+ /* The RO amount increase */
+ roAmount++;
+
+ /* Save the rights information */
+ if (FALSE == drm_writeOrReadInfo(id, rights, &roAmount, SAVE_A_RO))
+ return FALSE;
+
+ return TRUE;
+}
+
+int32_t drm_getMaxIdFromUidTxt()
+{
+ uint8_t idStr[8];
+ int32_t idMax = 0;
+ uint16_t nameUcs2[MAX_FILENAME_LEN] = {0};
+ int32_t nameLen = 0;
+ int32_t bytesConsumed;
+ int32_t handle;
+ int32_t fileRes;
+
+ /* convert in ucs2 */
+ nameLen = strlen(DRM_UID_FILE_PATH);
+ nameLen = DRM_i18n_mbsToWcs(DRM_CHARSET_UTF8,
+ (uint8_t *)DRM_UID_FILE_PATH,
+ nameLen,
+ nameUcs2,
+ MAX_FILENAME_LEN,
+ &bytesConsumed);
+ fileRes = DRM_file_open(nameUcs2,
+ nameLen,
+ DRM_FILE_MODE_READ,
+ &handle);
+
+ /* this means the uid.txt file is not exist, so there is not any DRM object */
+ if (DRM_FILE_SUCCESS != fileRes)
+ return 0;
+
+ if (!drm_getString(idStr, 8, handle)) {
+ DRM_file_close(handle);
+ return -1;
+ }
+ DRM_file_close(handle);
+
+ idMax = atoi((char *)idStr);
+ return idMax;
+}
+
+int32_t drm_removeIdInfoFile(int32_t id)
+{
+ uint8_t filename[MAX_FILENAME_LEN] = {0};
+ uint16_t nameUcs2[MAX_FILENAME_LEN];
+ int32_t nameLen = 0;
+ int32_t bytesConsumed;
+
+ if (id <= 0)
+ return FALSE;
+
+ sprintf((char *)filename, ANDROID_DRM_CORE_PATH"%d"EXTENSION_NAME_INFO, id);
+
+ /* convert in ucs2 */
+ nameLen = strlen((char *)filename);
+ nameLen = DRM_i18n_mbsToWcs(DRM_CHARSET_UTF8,
+ filename,
+ nameLen,
+ nameUcs2,
+ MAX_FILENAME_LEN,
+ &bytesConsumed);
+ if (DRM_FILE_SUCCESS != DRM_file_delete(nameUcs2, nameLen))
+ return FALSE;
+
+ return TRUE;
+}
+
+int32_t drm_updateUidTxtWhenDelete(int32_t id)
+{
+ uint16_t nameUcs2[MAX_FILENAME_LEN];
+ int32_t nameLen = 0;
+ int32_t bytesConsumed;
+ int32_t handle;
+ int32_t fileRes;
+ int32_t bufferLen;
+ uint8_t *buffer;
+ uint8_t idStr[8];
+ int32_t idMax;
+
+ if (id <= 0)
+ return FALSE;
+
+ nameLen = strlen(DRM_UID_FILE_PATH);
+ nameLen = DRM_i18n_mbsToWcs(DRM_CHARSET_UTF8,
+ (uint8_t *)DRM_UID_FILE_PATH,
+ nameLen,
+ nameUcs2,
+ MAX_FILENAME_LEN,
+ &bytesConsumed);
+ bufferLen = DRM_file_getFileLength(nameUcs2, nameLen);
+ if (bufferLen <= 0)
+ return FALSE;
+
+ buffer = (uint8_t *)malloc(bufferLen);
+ if (NULL == buffer)
+ return FALSE;
+
+ fileRes = DRM_file_open(nameUcs2,
+ nameLen,
+ DRM_FILE_MODE_READ,
+ &handle);
+ if (DRM_FILE_SUCCESS != fileRes) {
+ free(buffer);
+ return FALSE;
+ }
+
+ drm_getString(idStr, 8, handle);
+ idMax = atoi((char *)idStr);
+
+ bufferLen -= strlen((char *)idStr);
+ fileRes = DRM_file_read(handle, buffer, bufferLen);
+ buffer[bufferLen] = '\0';
+ DRM_file_close(handle);
+
+ /* handle this buffer */
+ {
+ uint8_t *pStart, *pEnd;
+ int32_t i, movLen;
+
+ pStart = buffer;
+ pEnd = pStart;
+ for (i = 0; i < id; i++) {
+ if (pEnd != pStart)
+ pStart = ++pEnd;
+ while ('\n' != *pEnd)
+ pEnd++;
+ if (pStart == pEnd)
+ pStart--;
+ }
+ movLen = bufferLen - (pEnd - buffer);
+ memmove(pStart, pEnd, movLen);
+ bufferLen -= (pEnd - pStart);
+ }
+
+ if (DRM_FILE_SUCCESS != DRM_file_delete(nameUcs2, nameLen)) {
+ free(buffer);
+ return FALSE;
+ }
+
+ fileRes = DRM_file_open(nameUcs2,
+ nameLen,
+ DRM_FILE_MODE_WRITE,
+ &handle);
+ if (DRM_FILE_SUCCESS != fileRes) {
+ free(buffer);
+ return FALSE;
+ }
+ sprintf((char *)idStr, "%d", idMax);
+ drm_putString(idStr, handle);
+ DRM_file_write(handle, (uint8_t*)"\n", 1);
+ DRM_file_write(handle, buffer, bufferLen);
+ free(buffer);
+ DRM_file_close(handle);
+ return TRUE;
+}
+
+int32_t drm_getKey(uint8_t* uid, uint8_t* KeyValue)
+{
+ T_DRM_Rights ro;
+ int32_t id, roAmount;
+
+ if (NULL == uid || NULL == KeyValue)
+ return FALSE;
+
+ if (FALSE == drm_readFromUidTxt(uid, &id, GET_ID))
+ return FALSE;
+
+ if (FALSE == drm_writeOrReadInfo(id, NULL, &roAmount, GET_ROAMOUNT))
+ return FALSE;
+
+ if (roAmount <= 0)
+ return FALSE;
+
+ memset(&ro, 0, sizeof(T_DRM_Rights));
+ roAmount = 1;
+ if (FALSE == drm_writeOrReadInfo(id, &ro, &roAmount, GET_A_RO))
+ return FALSE;
+
+ memcpy(KeyValue, ro.KeyValue, DRM_KEY_LEN);
+ return TRUE;
+}
+
+void drm_discardPaddingByte(uint8_t *decryptedBuf, int32_t *decryptedBufLen)
+{
+ int32_t tmpLen = *decryptedBufLen;
+ int32_t i;
+
+ if (NULL == decryptedBuf || *decryptedBufLen < 0)
+ return;
+
+ /* Check whether the last several bytes are padding or not */
+ for (i = 1; i < decryptedBuf[tmpLen - 1]; i++) {
+ if (decryptedBuf[tmpLen - 1 - i] != decryptedBuf[tmpLen - 1])
+ break; /* Not the padding bytes */
+ }
+ if (i == decryptedBuf[tmpLen - 1]) /* They are padding bytes */
+ *decryptedBufLen = tmpLen - i;
+ return;
+}
+
+int32_t drm_aesDecBuffer(uint8_t * Buffer, int32_t * BufferLen, aes_decrypt_ctx ctx[1])
+{
+ uint8_t dbuf[3 * DRM_ONE_AES_BLOCK_LEN], buf[DRM_ONE_AES_BLOCK_LEN];
+ uint64_t i, len, wlen = DRM_ONE_AES_BLOCK_LEN, curLen, restLen;
+ uint8_t *pTarget, *pTargetHead;
+
+ pTargetHead = Buffer;
+ pTarget = Buffer;
+ curLen = 0;
+ restLen = *BufferLen;
+
+ if (restLen > 2 * DRM_ONE_AES_BLOCK_LEN) {
+ len = 2 * DRM_ONE_AES_BLOCK_LEN;
+ } else {
+ len = restLen;
+ }
+ memcpy(dbuf, Buffer, (size_t)len);
+ restLen -= len;
+ Buffer += len;
+
+ if (len < 2 * DRM_ONE_AES_BLOCK_LEN) { /* The original file is less than one block in length */
+ len -= DRM_ONE_AES_BLOCK_LEN;
+ /* Decrypt from position len to position len + DRM_ONE_AES_BLOCK_LEN */
+ aes_decrypt((dbuf + len), (dbuf + len), ctx);
+
+ /* Undo the CBC chaining */
+ for (i = 0; i < len; ++i)
+ dbuf[i] ^= dbuf[i + DRM_ONE_AES_BLOCK_LEN];
+
+ /* Output the decrypted bytes */
+ memcpy(pTarget, dbuf, (size_t)len);
+ pTarget += len;
+ } else {
+ uint8_t *b1 = dbuf, *b2 = b1 + DRM_ONE_AES_BLOCK_LEN, *b3 = b2 + DRM_ONE_AES_BLOCK_LEN, *bt;
+
+ for (;;) { /* While some ciphertext remains, prepare to decrypt block b2 */
+ /* Read in the next block to see if ciphertext stealing is needed */
+ b3 = Buffer;
+ if (restLen > DRM_ONE_AES_BLOCK_LEN) {
+ len = DRM_ONE_AES_BLOCK_LEN;
+ } else {
+ len = restLen;
+ }
+ restLen -= len;
+ Buffer += len;
+
+ /* Decrypt the b2 block */
+ aes_decrypt((uint8_t *)b2, buf, ctx);
+
+ if (len == 0 || len == DRM_ONE_AES_BLOCK_LEN) { /* No ciphertext stealing */
+ /* Unchain CBC using the previous ciphertext block in b1 */
+ for (i = 0; i < DRM_ONE_AES_BLOCK_LEN; ++i)
+ buf[i] ^= b1[i];
+ } else { /* Partial last block - use ciphertext stealing */
+ wlen = len;
+ /* Produce last 'len' bytes of plaintext by xoring with */
+ /* The lowest 'len' bytes of next block b3 - C[N-1] */
+ for (i = 0; i < len; ++i)
+ buf[i] ^= b3[i];
+
+ /* Reconstruct the C[N-1] block in b3 by adding in the */
+ /* Last (DRM_ONE_AES_BLOCK_LEN - len) bytes of C[N-2] in b2 */
+ for (i = len; i < DRM_ONE_AES_BLOCK_LEN; ++i)
+ b3[i] = buf[i];
+
+ /* Decrypt the C[N-1] block in b3 */
+ aes_decrypt((uint8_t *)b3, (uint8_t *)b3, ctx);
+
+ /* Produce the last but one plaintext block by xoring with */
+ /* The last but two ciphertext block */
+ for (i = 0; i < DRM_ONE_AES_BLOCK_LEN; ++i)
+ b3[i] ^= b1[i];
+
+ /* Write decrypted plaintext blocks */
+ memcpy(pTarget, b3, DRM_ONE_AES_BLOCK_LEN);
+ pTarget += DRM_ONE_AES_BLOCK_LEN;
+ }
+
+ /* Write the decrypted plaintext block */
+ memcpy(pTarget, buf, (size_t)wlen);
+ pTarget += wlen;
+
+ if (len != DRM_ONE_AES_BLOCK_LEN) {
+ *BufferLen = pTarget - pTargetHead;
+ return 0;
+ }
+
+ /* Advance the buffer pointers */
+ bt = b1, b1 = b2, b2 = b3, b3 = bt;
+ }
+ }
+ return 0;
+}
+
+int32_t drm_updateDcfDataLen(uint8_t* pDcfLastData, uint8_t* keyValue, int32_t* moreBytes)
+{
+ aes_decrypt_ctx ctx[1];
+ int32_t len = DRM_TWO_AES_BLOCK_LEN;
+
+ if (NULL == pDcfLastData || NULL == keyValue)
+ return FALSE;
+
+ aes_decrypt_key128(keyValue, ctx);
+
+ if (drm_aesDecBuffer(pDcfLastData, &len, ctx) < 0)
+ return FALSE;
+
+ drm_discardPaddingByte(pDcfLastData, &len);
+
+ *moreBytes = DRM_TWO_AES_BLOCK_LEN - len;
+
+ return TRUE;
+}
diff --git a/media/libdrm/mobile1/src/objmng/drm_time.c b/media/libdrm/mobile1/src/objmng/drm_time.c
new file mode 100644
index 0000000..fceb4952
--- /dev/null
+++ b/media/libdrm/mobile1/src/objmng/drm_time.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file
+ * DRM 1.0 Reference Port: linux implementation of drm_time.c.
+ */
+
+#include <objmng/drm_time.h>
+#include <unistd.h>
+
+/* See drm_time.h */
+uint32_t DRM_time_getElapsedSecondsFrom1970(void)
+{
+ return time(NULL);
+}
+
+/* See drm_time.h */
+void DRM_time_sleep(uint32_t ms)
+{
+ usleep(ms * 1000);
+}
+
+/* See drm_time.h */
+void DRM_time_getSysTime(T_DB_TIME_SysTime *time_ptr)
+{
+ time_t t;
+ struct tm *tm_t;
+
+ time(&t);
+ tm_t = gmtime(&t);
+
+ time_ptr->year = tm_t->tm_year + 1900;
+ time_ptr->month = tm_t->tm_mon + 1;
+ time_ptr->day = tm_t->tm_mday;
+ time_ptr->hour = tm_t->tm_hour;
+ time_ptr->min = tm_t->tm_min;
+ time_ptr->sec = tm_t->tm_sec;
+}
diff --git a/media/libdrm/mobile1/src/parser/parser_dcf.c b/media/libdrm/mobile1/src/parser/parser_dcf.c
new file mode 100644
index 0000000..06aa830
--- /dev/null
+++ b/media/libdrm/mobile1/src/parser/parser_dcf.c
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <parser_dcf.h>
+#include <svc_drm.h>
+
+static int32_t drm_parseUintVar(uint8_t * buffer, uint8_t * len)
+{
+ int32_t i;
+ int32_t byteLen;
+ int32_t sum;
+
+ if (NULL == buffer)
+ return DRM_UINT_VAR_ERR;
+
+ byteLen = 0;
+ while ((buffer[byteLen] & UINT_VAR_FLAG) > 0 && byteLen < MAX_UINT_VAR_BYTE) /* UINT_VAR_FLAG == 0x80 */
+ byteLen++;
+
+ if (byteLen >= MAX_UINT_VAR_BYTE) /* MAX_UINT_VAR_BYTE == 5 */
+ return DRM_UINT_VAR_ERR; /* The var int is too large, and that is impossible */
+
+ *len = (uint8_t)(byteLen + 1);
+ sum = buffer[byteLen];
+ for (i = byteLen - 1; i >= 0; i--)
+ sum += ((buffer[i] & UINT_VAR_DATA) << 7 * (byteLen - i)); /* UINT_VAR_DATA == 0x7F */
+
+ return sum;
+}
+
+/* See parser_dcf.h */
+int32_t drm_dcfParser(uint8_t *buffer, int32_t bufferLen, T_DRM_DCF_Info *pDcfInfo,
+ uint8_t **ppEncryptedData)
+{
+ uint8_t *tmpBuf;
+ uint8_t *pStart, *pEnd;
+ uint8_t *pHeader, *pData;
+ uint8_t varLen;
+
+ if (NULL == buffer || bufferLen <= 0 || NULL == pDcfInfo)
+ return FALSE;
+
+ tmpBuf = buffer;
+ /* 1. Parse the version, content-type and content-url */
+ pDcfInfo->Version = *(tmpBuf++);
+ if (0x01 != pDcfInfo->Version) /* Because it is OMA DRM v1.0, the vension must be 1 */
+ return FALSE;
+ pDcfInfo->ContentTypeLen = *(tmpBuf++);
+ pDcfInfo->ContentURILen = *(tmpBuf++);
+ strncpy((char *)pDcfInfo->ContentType, (char *)tmpBuf, pDcfInfo->ContentTypeLen);
+ tmpBuf += pDcfInfo->ContentTypeLen;
+ strncpy((char *)pDcfInfo->ContentURI, (char *)tmpBuf, pDcfInfo->ContentURILen);
+ tmpBuf += pDcfInfo->ContentURILen;
+
+ /* 2. Get the headers length and data length */
+ pDcfInfo->HeadersLen = drm_parseUintVar(tmpBuf, &varLen);
+ if (DRM_UINT_VAR_ERR == pDcfInfo->HeadersLen)
+ return FALSE;
+ tmpBuf += varLen;
+ pDcfInfo->DecryptedDataLen = DRM_UNKNOWN_DATA_LEN;
+ pDcfInfo->EncryptedDataLen = drm_parseUintVar(tmpBuf, &varLen);
+ if (DRM_UINT_VAR_ERR == pDcfInfo->EncryptedDataLen)
+ return FALSE;
+ tmpBuf += varLen;
+ pHeader = tmpBuf;
+ tmpBuf += pDcfInfo->HeadersLen;
+ pData = tmpBuf;
+
+ /* 3. Parse the headers */
+ pStart = pHeader;
+ while (pStart < pData) {
+ pEnd = pStart;
+ while ('\r' != *pEnd && pEnd < pData)
+ pEnd++;
+
+ if (0 == strncmp((char *)pStart, HEADER_ENCRYPTION_METHOD, HEADER_ENCRYPTION_METHOD_LEN))
+ strncpy((char *)pDcfInfo->Encryption_Method,
+ (char *)(pStart + HEADER_ENCRYPTION_METHOD_LEN),
+ pEnd - pStart - HEADER_ENCRYPTION_METHOD_LEN);
+ else if (0 == strncmp((char *)pStart, HEADER_RIGHTS_ISSUER, HEADER_RIGHTS_ISSUER_LEN))
+ strncpy((char *)pDcfInfo->Rights_Issuer,
+ (char *)(pStart + HEADER_RIGHTS_ISSUER_LEN),
+ pEnd - pStart - HEADER_RIGHTS_ISSUER_LEN);
+ else if (0 == strncmp((char *)pStart, HEADER_CONTENT_NAME, HEADER_CONTENT_NAME_LEN))
+ strncpy((char *)pDcfInfo->Content_Name,
+ (char *)(pStart + HEADER_CONTENT_NAME_LEN),
+ pEnd - pStart - HEADER_CONTENT_NAME_LEN);
+ else if (0 == strncmp((char *)pStart, HEADER_CONTENT_DESCRIPTION, HEADER_CONTENT_DESCRIPTION_LEN))
+ strncpy((char *)pDcfInfo->ContentDescription,
+ (char *)(pStart + HEADER_CONTENT_DESCRIPTION_LEN),
+ pEnd - pStart - HEADER_CONTENT_DESCRIPTION_LEN);
+ else if (0 == strncmp((char *)pStart, HEADER_CONTENT_VENDOR, HEADER_CONTENT_VENDOR_LEN))
+ strncpy((char *)pDcfInfo->ContentVendor,
+ (char *)(pStart + HEADER_CONTENT_VENDOR_LEN),
+ pEnd - pStart - HEADER_CONTENT_VENDOR_LEN);
+ else if (0 == strncmp((char *)pStart, HEADER_ICON_URI, HEADER_ICON_URI_LEN))
+ strncpy((char *)pDcfInfo->Icon_URI,
+ (char *)(pStart + HEADER_ICON_URI_LEN),
+ pEnd - pStart - HEADER_ICON_URI_LEN);
+
+ if ('\n' == *(pEnd + 1))
+ pStart = pEnd + 2; /* Two bytes: a '\r' and a '\n' */
+ else
+ pStart = pEnd + 1;
+ }
+
+ /* 4. Give out the location of encrypted data */
+ if (NULL != ppEncryptedData)
+ *ppEncryptedData = pData;
+
+ return TRUE;
+}
diff --git a/media/libdrm/mobile1/src/parser/parser_dm.c b/media/libdrm/mobile1/src/parser/parser_dm.c
new file mode 100644
index 0000000..567e650
--- /dev/null
+++ b/media/libdrm/mobile1/src/parser/parser_dm.c
@@ -0,0 +1,271 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <parser_dm.h>
+#include <parser_dcf.h>
+#include <svc_drm.h>
+#include "log.h"
+
+#define DRM_SKIP_SPACE_TAB(p) while( (*(p) == ' ') || (*(p) == '\t') ) \
+ p++
+
+typedef enum _DM_PARSE_STATUS {
+ DM_PARSE_START,
+ DM_PARSING_RIGHTS,
+ DM_PARSING_CONTENT,
+ DM_PARSE_END
+} DM_PARSE_STATUS;
+
+static int drm_strnicmp(const uint8_t* s1, const uint8_t* s2, int32_t n)
+{
+ if (n < 0 || NULL == s1 || NULL == s2)
+ return -1;
+
+ if (n == 0)
+ return 0;
+
+ while (n-- != 0 && tolower(*s1) == tolower(*s2))
+ {
+ if (n == 0 || *s1 == '\0' || *s2 == '\0')
+ break;
+ s1++;
+ s2++;
+ }
+
+ return tolower(*s1) - tolower(*s2);
+}
+
+const uint8_t * drm_strnstr(const uint8_t * str, const uint8_t * strSearch, int32_t len)
+{
+ int32_t i, stringLen;
+
+ if (NULL == str || NULL == strSearch || len <= 0)
+ return NULL;
+
+ stringLen = strlen((char *)strSearch);
+ for (i = 0; i < len - stringLen + 1; i++) {
+ if (str[i] == *strSearch && 0 == memcmp(str + i, strSearch, stringLen))
+ return str + i;
+ }
+ return NULL;
+}
+
+/* See parser_dm.h */
+int32_t drm_parseDM(const uint8_t *buffer, int32_t bufferLen, T_DRM_DM_Info *pDmInfo)
+{
+ const uint8_t *pStart = NULL, *pEnd = NULL;
+ const uint8_t *pBufferEnd;
+ int32_t contentLen, leftLen;
+ DM_PARSE_STATUS status = DM_PARSE_START;
+ int32_t boundaryLen;
+
+ if (NULL == buffer || bufferLen <= 0 || NULL == pDmInfo)
+ return FALSE;
+
+ /* Find the end of the input buffer */
+ pBufferEnd = buffer + bufferLen;
+ leftLen = bufferLen;
+
+ /* Find out the boundary */
+ pStart = drm_strnstr(buffer, (uint8_t *)"--", bufferLen);
+ if (NULL == pStart)
+ return FALSE; /* No boundary error */
+ pEnd = pStart;
+
+ /* Record the boundary */
+ pEnd = drm_strnstr(pStart, (uint8_t *)DRM_NEW_LINE_CRLF, leftLen);
+ /* if can not find the CRLF, return FALSE */
+ if (NULL == pEnd)
+ return FALSE;
+ strncpy((char *)pDmInfo->boundary, (char *)pStart, pEnd - pStart);
+ boundaryLen = strlen((char *)pDmInfo->boundary) + 2; /* 2 means: '\r' and '\n' */
+
+ pEnd += 2; /* skip the '\r' and '\n' */
+ pStart = pEnd;
+ leftLen = pBufferEnd - pStart;
+ do {
+ pDmInfo->transferEncoding = DRM_MESSAGE_CODING_7BIT; /* According RFC2045 chapter 6.1, the default value should be 7bit.*/
+ strcpy((char *)pDmInfo->contentType, "text/plain"); /* According RFC2045 chapter 5.2, the default value should be "text/plain". */
+
+ /* Deal the header information */
+ while ((('\r' != *pStart) || ('\n' != *(pStart + 1))) && pStart < pBufferEnd) {
+ pEnd = drm_strnstr(pStart, (uint8_t *)DRM_NEW_LINE_CRLF, leftLen);
+ if (NULL == pEnd)
+ return FALSE;
+
+ if (0 != pDmInfo->deliveryType) { /* This means the delivery type has been confirmed */
+ if (0 == strncmp((char *)pStart, HEADERS_TRANSFER_CODING, HEADERS_TRANSFER_CODING_LEN)) {
+ pStart += HEADERS_TRANSFER_CODING_LEN;
+ DRM_SKIP_SPACE_TAB(pStart);
+
+ if (0 == strncmp((char *)pStart, TRANSFER_CODING_TYPE_7BIT, pEnd - pStart))
+ pDmInfo->transferEncoding = DRM_MESSAGE_CODING_7BIT;
+ else if (0 == strncmp((char *)pStart, TRANSFER_CODING_TYPE_8BIT, pEnd - pStart))
+ pDmInfo->transferEncoding = DRM_MESSAGE_CODING_8BIT;
+ else if (0 == strncmp((char *)pStart, TRANSFER_CODING_TYPE_BINARY, pEnd - pStart))
+ pDmInfo->transferEncoding = DRM_MESSAGE_CODING_BINARY;
+ else if (0 == strncmp((char *)pStart, TRANSFER_CODING_TYPE_BASE64, pEnd - pStart))
+ pDmInfo->transferEncoding = DRM_MESSAGE_CODING_BASE64;
+ else
+ return FALSE; /* Unknown transferCoding error */
+ } else if (0 == drm_strnicmp(pStart, (uint8_t *)HEADERS_CONTENT_TYPE, HEADERS_CONTENT_TYPE_LEN)) {
+ pStart += HEADERS_CONTENT_TYPE_LEN;
+ DRM_SKIP_SPACE_TAB(pStart);
+
+ if (pEnd - pStart > 0) {
+ strncpy((char *)pDmInfo->contentType, (char *)pStart, pEnd - pStart);
+ pDmInfo->contentType[pEnd - pStart] = '\0';
+ }
+ } else if (0 == drm_strnicmp(pStart, (uint8_t *)HEADERS_CONTENT_ID, HEADERS_CONTENT_ID_LEN)) {
+ uint8_t tmpBuf[MAX_CONTENT_ID] = {0};
+ uint8_t *pTmp;
+
+ pStart += HEADERS_CONTENT_ID_LEN;
+ DRM_SKIP_SPACE_TAB(pStart);
+
+ /* error: more than one content id */
+ if(drm_strnstr(pStart, (uint8_t*)HEADERS_CONTENT_ID, pBufferEnd - pStart)){
+ LOGD("drm_dmParser: error: more than one content id\r\n");
+ return FALSE;
+ }
+
+ status = DM_PARSING_CONTENT; /* can go here means that the rights object has been parsed. */
+
+ /* Change the format from <...> to cid:... */
+ if (NULL != (pTmp = (uint8_t *)memchr((char *)pStart, '<', pEnd - pStart))) {
+ strncpy((char *)tmpBuf, (char *)(pTmp + 1), pEnd - pTmp - 1);
+
+ if (NULL != (pTmp = (uint8_t *)memchr((char *)tmpBuf, '>', pEnd - pTmp - 1))) {
+ *pTmp = '\0';
+
+ memset(pDmInfo->contentID, 0, MAX_CONTENT_ID);
+ sprintf((char *)pDmInfo->contentID, "%s%s", "cid:", (int8_t *)tmpBuf);
+ }
+ }
+ }
+ } else { /* First confirm delivery type, Forward_Lock, Combined Delivery or Separate Delivery */
+ if (0 == drm_strnicmp(pStart, (uint8_t *)HEADERS_CONTENT_TYPE, HEADERS_CONTENT_TYPE_LEN)) {
+ pStart += HEADERS_CONTENT_TYPE_LEN;
+ DRM_SKIP_SPACE_TAB(pStart);
+
+ if (pEnd - pStart > 0) {
+ strncpy((char *)pDmInfo->contentType, (char *)pStart, pEnd - pStart);
+ pDmInfo->contentType[pEnd - pStart] = '\0';
+ }
+
+ if (0 == strcmp((char *)pDmInfo->contentType, DRM_MIME_TYPE_RIGHTS_XML)) {
+ pDmInfo->deliveryType = COMBINED_DELIVERY;
+ status = DM_PARSING_RIGHTS;
+ }
+ else if (0 == strcmp((char *)pDmInfo->contentType, DRM_MIME_TYPE_CONTENT)) {
+ pDmInfo->deliveryType = SEPARATE_DELIVERY_FL;
+ status = DM_PARSING_CONTENT;
+ }
+ else if (0 == pDmInfo->deliveryType) {
+ pDmInfo->deliveryType = FORWARD_LOCK;
+ status = DM_PARSING_CONTENT;
+ }
+ }
+ }
+ pEnd += 2; /* skip the '\r' and '\n' */
+ pStart = pEnd;
+ leftLen = pBufferEnd - pStart;
+ }
+ pStart += 2; /* skip the second CRLF: "\r\n" */
+ pEnd = pStart;
+
+ /* Deal the content part, including rel or real content */
+ while (leftLen > 0) {
+ if (NULL == (pEnd = memchr(pEnd, '\r', leftLen))) {
+ pEnd = pBufferEnd;
+ break; /* no boundary found */
+ }
+
+ leftLen = pBufferEnd - pEnd;
+ if (leftLen < boundaryLen) {
+ pEnd = pBufferEnd;
+ break; /* here means may be the boundary has been split */
+ }
+
+ if (('\n' == *(pEnd + 1)) && (0 == memcmp(pEnd + 2, pDmInfo->boundary, strlen((char *)pDmInfo->boundary))))
+ break; /* find the boundary here */
+
+ pEnd++;
+ leftLen--;
+ }
+
+ if (pEnd >= pBufferEnd)
+ contentLen = DRM_UNKNOWN_DATA_LEN;
+ else
+ contentLen = pEnd - pStart;
+
+ switch(pDmInfo->deliveryType) {
+ case FORWARD_LOCK:
+ pDmInfo->contentLen = contentLen;
+ pDmInfo->contentOffset = pStart - buffer;
+ status = DM_PARSE_END;
+ break;
+ case COMBINED_DELIVERY:
+ if (DM_PARSING_RIGHTS == status) {
+ pDmInfo->rightsLen = contentLen;
+ pDmInfo->rightsOffset = pStart - buffer;
+ } else {
+ pDmInfo->contentLen = contentLen;
+ pDmInfo->contentOffset = pStart - buffer;
+ status = DM_PARSE_END;
+ }
+ break;
+ case SEPARATE_DELIVERY_FL:
+ {
+ T_DRM_DCF_Info dcfInfo;
+ uint8_t* pEncData = NULL;
+
+ memset(&dcfInfo, 0, sizeof(T_DRM_DCF_Info));
+ if (DRM_UNKNOWN_DATA_LEN == contentLen)
+ contentLen = pEnd - pStart;
+ if (FALSE == drm_dcfParser(pStart, contentLen, &dcfInfo, &pEncData))
+ return FALSE;
+
+ pDmInfo->contentLen = dcfInfo.EncryptedDataLen;
+ pDmInfo->contentOffset = pEncData - buffer;
+ strcpy((char *)pDmInfo->contentType, (char *)dcfInfo.ContentType);
+ strcpy((char *)pDmInfo->contentID, (char *)dcfInfo.ContentURI);
+ strcpy((char *)pDmInfo->rightsIssuer, (char *)dcfInfo.Rights_Issuer);
+ status = DM_PARSE_END;
+ }
+ break;
+ default:
+ return FALSE;
+ }
+
+ if (DM_PARSING_RIGHTS == status) {
+ /* Here means the rights object data has been completed, boundary must exist */
+ leftLen = pBufferEnd - pEnd;
+ pStart = drm_strnstr(pEnd, pDmInfo->boundary, leftLen);
+ if (NULL == pStart)
+ return FALSE;
+ leftLen = pBufferEnd - pStart;
+ pEnd = drm_strnstr(pStart, (uint8_t *)DRM_NEW_LINE_CRLF, leftLen);
+ if (NULL == pEnd)
+ return FALSE; /* only rights object, no media object, error */
+
+ pEnd += 2; /* skip the "\r\n" */
+ pStart = pEnd;
+ }
+ } while (DM_PARSE_END != status);
+
+ return TRUE;
+}
diff --git a/media/libdrm/mobile1/src/parser/parser_rel.c b/media/libdrm/mobile1/src/parser/parser_rel.c
new file mode 100644
index 0000000..537fa9c
--- /dev/null
+++ b/media/libdrm/mobile1/src/parser/parser_rel.c
@@ -0,0 +1,663 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <parser_rel.h>
+#include <parser_dm.h>
+#include <xml_tinyParser.h>
+#include <wbxml_tinyparser.h>
+#include <drm_decoder.h>
+#include <svc_drm.h>
+
+/* See parser_rel.h */
+int32_t drm_monthDays(int32_t year, int32_t month)
+{
+ switch (month) {
+ case 1:
+ case 3:
+ case 5:
+ case 7:
+ case 8:
+ case 10:
+ case 12:
+ return 31;
+ case 4:
+ case 6:
+ case 9:
+ case 11:
+ return 30;
+ case 2:
+ if (((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0))
+ return 29;
+ else
+ return 28;
+ default:
+ return -1;
+ }
+}
+
+int32_t drm_checkDate(int32_t year, int32_t month, int32_t day,
+ int32_t hour, int32_t min, int32_t sec)
+{
+ if (month >= 1 && month <= 12 &&
+ day >= 1 && day <= drm_monthDays(year, month) &&
+ hour >= 0 && hour <= 23 &&
+ min >= 0 && min <= 59 && sec >= 0 && sec <= 59)
+ return 0;
+ else
+ return -1;
+}
+
+static int32_t drm_getStartEndTime(uint8_t * pValue, int32_t valueLen,
+ T_DRM_DATETIME * dateTime)
+{
+ int32_t year, mon, day, hour, min, sec;
+ uint8_t pTmp[64] = {0};
+
+ strncpy((char *)pTmp, (char *)pValue, valueLen);
+ {
+ uint8_t * pHead = pTmp;
+ uint8_t * pEnd = NULL;
+ uint8_t tmpByte;
+
+ /** get year */
+ pEnd = (uint8_t *)strstr((char *)pHead, "-");
+ if(NULL == pEnd)
+ return FALSE;
+ tmpByte = *pEnd;
+ *pEnd = '\0';
+ year = atoi((char *)pHead);
+ pHead = pEnd + 1;
+ *pEnd = tmpByte;
+
+ /** get month */
+ pEnd = (uint8_t *)strstr((char *)pHead, "-");
+ if(NULL == pEnd)
+ return FALSE;
+ tmpByte = *pEnd;
+ *pEnd = '\0';
+ mon = atoi((char *)pHead);
+ pHead = pEnd + 1;
+ *pEnd = tmpByte;
+
+ /** get day */
+ pEnd = (uint8_t *)strstr((char *)pHead, "T");
+ if(NULL == pEnd)
+ return FALSE;
+ tmpByte = *pEnd;
+ *pEnd = '\0';
+ day = atoi((char *)pHead);
+ pHead = pEnd + 1;
+ *pEnd = tmpByte;
+
+ /** get hour */
+ pEnd = (uint8_t *)strstr((char *)pHead, ":");
+ if(NULL == pEnd)
+ return FALSE;
+ tmpByte = *pEnd;
+ *pEnd = '\0';
+ hour = atoi((char *)pHead);
+ pHead = pEnd + 1;
+ *pEnd = tmpByte;
+
+ /** get minute */
+ pEnd = (uint8_t *)strstr((char *)pHead, ":");
+ if(NULL == pEnd)
+ return FALSE;
+ tmpByte = *pEnd;
+ *pEnd = '\0';
+ min = atoi((char *)pHead);
+ pHead = pEnd + 1;
+ *pEnd = tmpByte;
+
+ /** get second */
+ sec = atoi((char *)pHead);
+ }
+ if (0 != drm_checkDate(year, mon, day, hour, min, sec))
+ return FALSE;
+
+ YMD_HMS_2_INT(year, mon, day, dateTime->date, hour, min, sec,
+ dateTime->time);
+ return TRUE;
+}
+
+static int32_t drm_checkWhetherHasUnknowConstraint(uint8_t* drm_constrain)
+{
+ char* begin_constrain = "<o-ex:constraint>";
+ char* end_constrain = "</o-ex:constraint>";
+ char* constrain_begin = strstr((char*)drm_constrain,begin_constrain);
+ char* constrain_end = strstr((char*)drm_constrain,end_constrain);
+ uint32_t constrain_len = 0;
+
+ if(NULL == constrain_begin)
+ return FALSE;
+
+ if(NULL == constrain_end)
+ return TRUE;
+
+ /* compute valid characters length */
+ {
+ uint32_t constrain_begin_len = strlen(begin_constrain);
+ char* cur_pos = constrain_begin + constrain_begin_len;
+
+ constrain_len = (constrain_end - constrain_begin) - constrain_begin_len;
+
+ while(cur_pos < constrain_end){
+ if(isspace(*cur_pos))
+ constrain_len--;
+
+ cur_pos++;
+ }
+ }
+
+ /* check all constraints */
+ {
+ #define DRM_ALL_CONSTRAINT_COUNT 5
+
+ int32_t i = 0;
+ int32_t has_datetime = FALSE;
+ int32_t has_start_or_end = FALSE;
+
+ char* all_vaild_constraints[DRM_ALL_CONSTRAINT_COUNT][2] = {
+ {"<o-dd:count>","</o-dd:count>"},
+ {"<o-dd:interval>","</o-dd:interval>"},
+ {"<o-dd:datetime>","</o-dd:datetime>"},
+ {"<o-dd:start>","</o-dd:start>"},
+ {"<o-dd:end>","</o-dd:end>"}
+ };
+
+ for(i = 0; i < DRM_ALL_CONSTRAINT_COUNT; i++){
+ char*start = strstr((char*)drm_constrain,all_vaild_constraints[i][0]);
+
+ if(start && (start < constrain_end)){
+ char* end = strstr((char*)drm_constrain,all_vaild_constraints[i][1]);
+
+ if(end && (end < constrain_end)){
+ if(0 == strncmp(all_vaild_constraints[i][0],"<o-dd:datetime>",strlen("<o-dd:datetime>"))){
+ constrain_len -= strlen(all_vaild_constraints[i][0]);
+ constrain_len -= strlen(all_vaild_constraints[i][1]);
+
+ if(0 == constrain_len)
+ return TRUE;
+
+ has_datetime = TRUE;
+ continue;
+ }
+
+ if((0 == strncmp(all_vaild_constraints[i][0],"<o-dd:start>",strlen("<o-dd:start>")))
+ || (0 == strncmp(all_vaild_constraints[i][0],"<o-dd:end>",strlen("<o-dd:end>")))){
+ if(FALSE == has_datetime)
+ return TRUE;
+ else
+ has_start_or_end = TRUE;
+ }
+
+ constrain_len -= (end - start);
+ constrain_len -= strlen(all_vaild_constraints[i][1]);
+
+ if(0 == constrain_len)
+ if(has_datetime != has_start_or_end)
+ return TRUE;
+ else
+ return FALSE;
+ }
+ else
+ return TRUE;
+ }
+ }
+
+ if(has_datetime != has_start_or_end)
+ return TRUE;
+
+ if(constrain_len)
+ return TRUE;
+ else
+ return FALSE;
+ }
+}
+
+static int32_t drm_getRightValue(uint8_t * buffer, int32_t bufferLen,
+ T_DRM_Rights * ro, uint8_t * operation,
+ uint8_t oper_char)
+{
+ uint8_t *pBuf, *pValue;
+ uint8_t sProperty[256];
+ int32_t valueLen;
+ int32_t year, mon, day, hour, min, sec;
+ T_DRM_Rights_Constraint *pConstraint;
+ int32_t *bIsAble;
+ uint8_t *ret = NULL;
+ int32_t flag = 0;
+
+ if (operation == NULL) {
+ switch (oper_char) {
+ case REL_TAG_PLAY:
+ pConstraint = &(ro->PlayConstraint);
+ bIsAble = &(ro->bIsPlayable);
+ break;
+ case REL_TAG_DISPLAY:
+ pConstraint = &(ro->DisplayConstraint);
+ bIsAble = &(ro->bIsDisplayable);
+ break;
+ case REL_TAG_EXECUTE:
+ pConstraint = &(ro->ExecuteConstraint);
+ bIsAble = &(ro->bIsExecuteable);
+ break;
+ case REL_TAG_PRINT:
+ pConstraint = &(ro->PrintConstraint);
+ bIsAble = &(ro->bIsPrintable);
+ break;
+ default:
+ return FALSE; /* The input parm is err */
+ }
+ } else {
+ if (strcmp((char *)operation, "play") == 0) {
+ pConstraint = &(ro->PlayConstraint);
+ bIsAble = &(ro->bIsPlayable);
+ } else if (strcmp((char *)operation, "display") == 0) {
+ pConstraint = &(ro->DisplayConstraint);
+ bIsAble = &(ro->bIsDisplayable);
+ } else if (strcmp((char *)operation, "execute") == 0) {
+ pConstraint = &(ro->ExecuteConstraint);
+ bIsAble = &(ro->bIsExecuteable);
+ } else if (strcmp((char *)operation, "print") == 0) {
+ pConstraint = &(ro->PrintConstraint);
+ bIsAble = &(ro->bIsPrintable);
+ } else
+ return FALSE; /* The input parm is err */
+ }
+
+ if (operation == NULL) {
+ sprintf((char *)sProperty, "%c%c%c%c", REL_TAG_RIGHTS,
+ REL_TAG_AGREEMENT, REL_TAG_PERMISSION, oper_char);
+ ret = WBXML_DOM_getNode(buffer, bufferLen, sProperty);
+ } else {
+ sprintf((char *)sProperty,
+ "o-ex:rights\\o-ex:agreement\\o-ex:permission\\o-dd:%s",
+ operation);
+ ret = XML_DOM_getNode(buffer, sProperty);
+ }
+ CHECK_VALIDITY(ret);
+ if (NULL == ret)
+ return TRUE;
+ WRITE_RO_FLAG(*bIsAble, 1, pConstraint->Indicator, DRM_NO_CONSTRAINT); /* If exit first assume have utter rights */
+ flag = 1;
+
+ if (operation == NULL) { /* If father element node is not exit then return */
+ sprintf((char *)sProperty, "%c%c%c%c%c", REL_TAG_RIGHTS,
+ REL_TAG_AGREEMENT, REL_TAG_PERMISSION, oper_char,
+ REL_TAG_CONSTRAINT);
+ ret = WBXML_DOM_getNode(buffer, bufferLen, sProperty);
+ } else {
+ sprintf((char *)sProperty,
+ "o-ex:rights\\o-ex:agreement\\o-ex:permission\\o-dd:%s\\o-ex:constraint",
+ operation);
+ ret = XML_DOM_getNode(buffer, sProperty);
+ }
+
+ CHECK_VALIDITY(ret);
+ if (ret == NULL)
+ return TRUE;
+
+ if(TRUE == drm_checkWhetherHasUnknowConstraint(ret))
+ return FALSE;
+
+ *bIsAble = 0;
+ pConstraint->Indicator = DRM_NO_PERMISSION; /* If exit constraint assume have no rights */
+ flag = 2;
+
+ if (operation == NULL) {
+ sprintf((char *)sProperty, "%c%c%c%c%c%c", REL_TAG_RIGHTS,
+ REL_TAG_AGREEMENT, REL_TAG_PERMISSION, oper_char,
+ REL_TAG_CONSTRAINT, REL_TAG_INTERVAL);
+ pBuf =
+ WBXML_DOM_getNodeValue(buffer, bufferLen, sProperty, (uint8_t **)&pValue,
+ &valueLen);
+ } else {
+ sprintf((char *)sProperty,
+ "o-ex:rights\\o-ex:agreement\\o-ex:permission\\o-dd:%s\\o-ex:constraint\\o-dd:interval",
+ operation);
+ pBuf = XML_DOM_getNodeValue(buffer, sProperty, &pValue, &valueLen);
+ }
+ CHECK_VALIDITY(pBuf);
+ if (pBuf) { /* If interval element exit then get the value */
+ uint8_t pTmp[64] = {0};
+
+ strncpy((char *)pTmp, (char *)pValue, valueLen);
+ {
+ uint8_t * pHead = pTmp + 1;
+ uint8_t * pEnd = NULL;
+ uint8_t tmpChar;
+
+ /** get year */
+ pEnd = (uint8_t *)strstr((char *)pHead, "Y");
+ if(NULL == pEnd)
+ return FALSE;
+ tmpChar = *pEnd;
+ *pEnd = '\0';
+ year = atoi((char *)pHead);
+ pHead = pEnd + 1;
+ *pEnd = tmpChar;
+
+ /** get month */
+ pEnd = (uint8_t *)strstr((char *)pHead, "M");
+ if(NULL == pEnd)
+ return FALSE;
+ tmpChar = *pEnd;
+ *pEnd = '\0';
+ mon = atoi((char *)pHead);
+ pHead = pEnd + 1;
+ *pEnd = tmpChar;
+
+ /** get day */
+ pEnd = (uint8_t *)strstr((char *)pHead, "D");
+ if(NULL == pEnd)
+ return FALSE;
+ tmpChar = *pEnd;
+ *pEnd = '\0';
+ day = atoi((char *)pHead);
+ pHead = pEnd + 2;
+ *pEnd = tmpChar;
+
+ /** get hour */
+ pEnd = (uint8_t *)strstr((char *)pHead, "H");
+ if(NULL == pEnd)
+ return FALSE;
+ tmpChar = *pEnd;
+ *pEnd = '\0';
+ hour = atoi((char *)pHead);
+ pHead = pEnd + 1;
+ *pEnd = tmpChar;
+
+ /** get minute */
+ pEnd = (uint8_t *)strstr((char *)pHead, "M");
+ if(NULL == pEnd)
+ return FALSE;
+ tmpChar = *pEnd;
+ *pEnd = '\0';
+ min = atoi((char *)pHead);
+ pHead = pEnd + 1;
+ *pEnd = tmpChar;
+
+ /** get second */
+ pEnd = (uint8_t *)strstr((char *)pHead, "S");
+ if(NULL == pEnd)
+ return FALSE;
+ tmpChar = *pEnd;
+ *pEnd = '\0';
+ sec = atoi((char *)pHead);
+ pHead = pEnd + 1;
+ *pEnd = tmpChar;
+ }
+
+ if (year < 0 || mon < 0 || day < 0 || hour < 0
+ || min < 0 || sec < 0)
+ return FALSE;
+ YMD_HMS_2_INT(year, mon, day, pConstraint->Interval.date, hour,
+ min, sec, pConstraint->Interval.time);
+ WRITE_RO_FLAG(*bIsAble, 1, pConstraint->Indicator,
+ DRM_INTERVAL_CONSTRAINT);
+ flag = 3;
+ }
+
+ if (operation == NULL) {
+ sprintf((char *)sProperty, "%c%c%c%c%c%c", REL_TAG_RIGHTS,
+ REL_TAG_AGREEMENT, REL_TAG_PERMISSION, oper_char,
+ REL_TAG_CONSTRAINT, REL_TAG_COUNT);
+ pBuf =
+ WBXML_DOM_getNodeValue(buffer, bufferLen, sProperty, (uint8_t **)&pValue,
+ &valueLen);
+ } else {
+ sprintf((char *)sProperty,
+ "o-ex:rights\\o-ex:agreement\\o-ex:permission\\o-dd:%s\\o-ex:constraint\\o-dd:count",
+ operation);
+ pBuf = XML_DOM_getNodeValue(buffer, sProperty, &pValue, &valueLen);
+ }
+ CHECK_VALIDITY(pBuf);
+ if (pBuf) { /* If count element exit the get the value */
+ uint8_t pTmp[16] = {0};
+ int32_t i;
+
+ for (i = 0; i < valueLen; i++) { /* Check the count format */
+ if (0 == isdigit(*(pValue + i)))
+ return FALSE;
+ }
+
+ strncpy((char *)pTmp, (char *)pValue, valueLen);
+ pConstraint->Count = atoi((char *)pTmp);
+
+ if(0 == pConstraint->Count)
+ {
+ WRITE_RO_FLAG(*bIsAble, 0, pConstraint->Indicator, DRM_NO_PERMISSION);
+ }
+ else if( pConstraint->Count > 0)
+ {
+ WRITE_RO_FLAG(*bIsAble, 1, pConstraint->Indicator, DRM_COUNT_CONSTRAINT);
+ }
+ else /* < 0 */
+ {
+ return FALSE;
+ }
+
+ flag = 3;
+ }
+
+ if (operation == NULL) {
+ sprintf((char *)sProperty, "%c%c%c%c%c%c%c", REL_TAG_RIGHTS,
+ REL_TAG_AGREEMENT, REL_TAG_PERMISSION, oper_char,
+ REL_TAG_CONSTRAINT, REL_TAG_DATETIME, REL_TAG_START);
+ pBuf =
+ WBXML_DOM_getNodeValue(buffer, bufferLen, sProperty, (uint8_t **)&pValue,
+ &valueLen);
+ } else {
+ sprintf((char *)sProperty,
+ "o-ex:rights\\o-ex:agreement\\o-ex:permission\\o-dd:%s\\o-ex:constraint\\o-dd:datetime\\o-dd:start",
+ operation);
+ pBuf = XML_DOM_getNodeValue(buffer, sProperty, &pValue, &valueLen);
+ }
+ CHECK_VALIDITY(pBuf);
+ if (pBuf) { /* If start element exit then get the value */
+ if (FALSE ==
+ drm_getStartEndTime(pValue, valueLen, &pConstraint->StartTime))
+ return FALSE;
+ WRITE_RO_FLAG(*bIsAble, 1, pConstraint->Indicator, DRM_START_TIME_CONSTRAINT);
+ flag = 3;
+ }
+
+ if (operation == NULL) {
+ sprintf((char *)sProperty, "%c%c%c%c%c%c%c", REL_TAG_RIGHTS,
+ REL_TAG_AGREEMENT, REL_TAG_PERMISSION, oper_char,
+ REL_TAG_CONSTRAINT, REL_TAG_DATETIME, REL_TAG_END);
+ pBuf =
+ WBXML_DOM_getNodeValue(buffer, bufferLen, sProperty, (uint8_t **)&pValue,
+ &valueLen);
+ } else {
+ sprintf((char *)sProperty,
+ "o-ex:rights\\o-ex:agreement\\o-ex:permission\\o-dd:%s\\o-ex:constraint\\o-dd:datetime\\o-dd:end",
+ operation);
+ pBuf = XML_DOM_getNodeValue(buffer, sProperty, &pValue, &valueLen);
+ }
+ CHECK_VALIDITY(pBuf);
+ if (pBuf) {
+ if (FALSE ==
+ drm_getStartEndTime(pValue, valueLen, &pConstraint->EndTime))
+ return FALSE;
+ WRITE_RO_FLAG(*bIsAble, 1, pConstraint->Indicator, DRM_END_TIME_CONSTRAINT);
+ flag = 3;
+ }
+
+ if (2 == flag)
+ WRITE_RO_FLAG(*bIsAble, 1, pConstraint->Indicator, DRM_NO_CONSTRAINT); /* If exit first assume have utter rights */
+ return TRUE;
+}
+
+/* See parser_rel.h */
+int32_t drm_relParser(uint8_t* buffer, int32_t bufferLen, int32_t Format, T_DRM_Rights* pRights)
+{
+ uint8_t *pBuf, *pValue;
+ uint8_t sProperty[256];
+ int32_t valueLen;
+
+ if (TYPE_DRM_RIGHTS_WBXML != Format && TYPE_DRM_RIGHTS_XML != Format) /* It is not the support parse format */
+ return FALSE;
+
+ if (TYPE_DRM_RIGHTS_XML == Format) {
+ /* Check whether it is a CD, and parse it using TYPE_DRM_RIGHTS_XML */
+ if (NULL != drm_strnstr(buffer, (uint8_t *)HEADERS_CONTENT_ID, bufferLen))
+ return FALSE;
+
+ pBuf =
+ XML_DOM_getNodeValue(buffer,
+ (uint8_t *)"o-ex:rights\\o-ex:context\\o-dd:version",
+ &pValue, &valueLen);
+ CHECK_VALIDITY(pBuf);
+
+ if (pBuf) {
+ if (valueLen > 8) /* Check version lenth */
+ return FALSE;
+
+ /* error version */
+ if(strncmp(pValue,"1.0",valueLen))
+ return FALSE;
+
+ strncpy((char *)pRights->Version, (char *)pValue, valueLen);
+ } else
+ return FALSE;
+
+ /* this means there is more than one version label in rights */
+ if(strstr((char*)pBuf, "<o-dd:version>"))
+ return FALSE;
+
+ pBuf =
+ XML_DOM_getNodeValue(buffer,
+ (uint8_t *)"o-ex:rights\\o-ex:agreement\\o-ex:asset\\ds:KeyInfo\\ds:KeyValue",
+ &pValue, &valueLen);
+ CHECK_VALIDITY(pBuf);
+ if (pBuf) { /* Get keyvalue */
+ int32_t keyLen;
+
+ if (24 != valueLen)
+ return FALSE;
+
+ keyLen = drm_decodeBase64(NULL, 0, pValue, &valueLen);
+ if (keyLen < 0)
+ return FALSE;
+
+ if (DRM_KEY_LEN != drm_decodeBase64(pRights->KeyValue, keyLen, pValue, &valueLen))
+ return FALSE;
+ }
+
+ pBuf =
+ XML_DOM_getNodeValue(buffer,
+ (uint8_t *)"o-ex:rights\\o-ex:agreement\\o-ex:asset\\o-ex:context\\o-dd:uid",
+ &pValue, &valueLen);
+ CHECK_VALIDITY(pBuf);
+ if (pBuf) {
+ if (valueLen > DRM_UID_LEN)
+ return FALSE;
+ strncpy((char *)pRights->uid, (char *)pValue, valueLen);
+ pRights->uid[valueLen] = '\0';
+ } else
+ return FALSE;
+
+ /* this means there is more than one uid label in rights */
+ if(strstr((char*)pBuf, "<o-dd:uid>"))
+ return FALSE;
+
+ if (FALSE ==
+ drm_getRightValue(buffer, bufferLen, pRights, (uint8_t *)"play", 0))
+ return FALSE;
+
+ if (FALSE ==
+ drm_getRightValue(buffer, bufferLen, pRights, (uint8_t *)"display", 0))
+ return FALSE;
+
+ if (FALSE ==
+ drm_getRightValue(buffer, bufferLen, pRights, (uint8_t *)"execute", 0))
+ return FALSE;
+
+ if (FALSE ==
+ drm_getRightValue(buffer, bufferLen, pRights, (uint8_t *)"print", 0))
+ return FALSE;
+ } else if (TYPE_DRM_RIGHTS_WBXML == Format) {
+ if (!REL_CHECK_WBXML_HEADER(buffer))
+ return FALSE;
+
+ sprintf((char *)sProperty, "%c%c%c", REL_TAG_RIGHTS, REL_TAG_CONTEXT,
+ REL_TAG_VERSION);
+ pBuf =
+ WBXML_DOM_getNodeValue(buffer, bufferLen, sProperty, (uint8_t **)&pValue,
+ &valueLen);
+ CHECK_VALIDITY(pBuf);
+
+ if (pBuf) {
+ if (valueLen > 8) /* Check version lenth */
+ return FALSE;
+ strncpy((char *)pRights->Version, (char *)pValue, valueLen);
+ } else
+ return FALSE;
+
+ sprintf((char *)sProperty, "%c%c%c%c%c",
+ REL_TAG_RIGHTS, REL_TAG_AGREEMENT, REL_TAG_ASSET,
+ REL_TAG_KEYINFO, REL_TAG_KEYVALUE);
+ pBuf =
+ WBXML_DOM_getNodeValue(buffer, bufferLen, sProperty, (uint8_t **)&pValue,
+ &valueLen);
+ CHECK_VALIDITY(pBuf);
+ if (pBuf) {
+ if (DRM_KEY_LEN != valueLen)
+ return FALSE;
+ memcpy(pRights->KeyValue, pValue, DRM_KEY_LEN);
+ memset(pValue, 0, DRM_KEY_LEN); /* Clean the KeyValue */
+ }
+
+ sprintf((char *)sProperty, "%c%c%c%c%c",
+ REL_TAG_RIGHTS, REL_TAG_AGREEMENT, REL_TAG_ASSET,
+ REL_TAG_CONTEXT, REL_TAG_UID);
+ pBuf =
+ WBXML_DOM_getNodeValue(buffer, bufferLen, sProperty, (uint8_t **)&pValue,
+ &valueLen);
+ CHECK_VALIDITY(pBuf);
+ if (pBuf) {
+ if (valueLen > DRM_UID_LEN)
+ return FALSE;
+ strncpy((char *)pRights->uid, (char *)pValue, valueLen);
+ pRights->uid[valueLen] = '\0';
+ } else
+ return FALSE;
+
+ if (FALSE ==
+ drm_getRightValue(buffer, bufferLen, pRights, NULL,
+ REL_TAG_PLAY))
+ return FALSE;
+
+ if (FALSE ==
+ drm_getRightValue(buffer, bufferLen, pRights, NULL,
+ REL_TAG_DISPLAY))
+ return FALSE;
+
+ if (FALSE ==
+ drm_getRightValue(buffer, bufferLen, pRights, NULL,
+ REL_TAG_EXECUTE))
+ return FALSE;
+
+ if (FALSE ==
+ drm_getRightValue(buffer, bufferLen, pRights, NULL,
+ REL_TAG_PRINT))
+ return FALSE;
+ }
+
+ return TRUE;
+}
diff --git a/media/libdrm/mobile1/src/xml/xml_tinyparser.c b/media/libdrm/mobile1/src/xml/xml_tinyparser.c
new file mode 100644
index 0000000..7580312
--- /dev/null
+++ b/media/libdrm/mobile1/src/xml/xml_tinyparser.c
@@ -0,0 +1,834 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <xml/xml_tinyParser.h>
+
+int32_t xml_errno;
+
+#ifdef XML_DOM_PARSER
+
+#define XML_IS_WHITESPACE(x) ((x) == '\t' || (x) == '\n' || (x) == ' ' || (x) == '\r')
+#define XML_IS_NAMECHAR(ch) (isalpha(ch) || isdigit(ch) || ch ==':' || \
+ ch == '_' || ch == '-' || ch =='.')
+
+static uint8_t *xml_ignore_blank(uint8_t *buffer)
+{
+ if (NULL == buffer)
+ return NULL;
+
+ while (XML_IS_WHITESPACE(*buffer))
+ buffer++;
+
+ return buffer;
+}
+
+static uint8_t *xml_goto_tagend(uint8_t *buffer)
+{
+ int32_t nameLen, valueLen;
+ uint8_t *name, *value;
+
+ if (NULL == buffer)
+ return NULL;
+
+ /* Ignore the start-tag */
+ if (*buffer == '<') {
+ buffer++;
+ while (buffer != NULL && XML_IS_NAMECHAR(*buffer))
+ buffer++;
+ if (NULL == buffer)
+ return NULL;
+ }
+
+ do {
+ if (NULL == (buffer = xml_ignore_blank(buffer)))
+ return NULL;
+
+ if (*buffer == '>' || (*buffer == '/' && *(buffer + 1) == '>'))
+ return buffer;
+
+ if (NULL ==
+ XML_DOM_getAttr(buffer, &name, &nameLen, &value, &valueLen))
+ return NULL;
+
+ buffer = value + valueLen + 1;
+ } while (*buffer != '\0');
+
+ return NULL;
+}
+
+static uint8_t *xml_match_tag(uint8_t *buffer)
+{
+ int32_t tagLen, tagType, bal;
+
+ if (NULL == buffer)
+ return NULL;
+
+ bal = 0;
+ do {
+ if (NULL == (buffer = XML_DOM_getTag(buffer, &tagLen, &tagType)))
+ return NULL;
+
+ switch (tagType) {
+ case XML_TAG_SELF:
+ case XML_TAG_START:
+ if (NULL == (buffer = xml_goto_tagend(buffer + tagLen + 1)))
+ return NULL;
+ if (strncmp((char *)buffer, "/>", 2) == 0) {
+ buffer += 2;
+ } else {
+ bal++;
+ }
+ break;
+
+ case XML_TAG_END:
+ if (bal <= 0)
+ return NULL;
+ buffer = buffer + tagLen + 2;
+ bal--;
+ break;
+ }
+ } while (bal != 0);
+
+ return buffer;
+}
+
+uint8_t *XML_DOM_getAttr(uint8_t *buffer, uint8_t **pName, int32_t *nameLen,
+ uint8_t **pValue, int32_t *valueLen)
+{
+ uint8_t charQuoted;
+
+ if (NULL == buffer) {
+ XML_ERROR(XML_ERROR_BUFFER_NULL);
+ return NULL;
+ }
+
+ /* Ignore the tag */
+ if (*buffer == '<') {
+ buffer++;
+ /* Ignore the STag */
+ while (buffer != NULL && XML_IS_NAMECHAR(*buffer))
+ buffer++;
+ if (NULL == buffer)
+ return NULL;
+ }
+
+ if (NULL == (buffer = xml_ignore_blank(buffer))) {
+ XML_ERROR(XML_ERROR_BUFFER_NULL);
+ return NULL;
+ }
+
+ /* Name */
+ *pName = buffer;
+ while (buffer != NULL && XML_IS_NAMECHAR(*buffer))
+ buffer++;
+ if (NULL == buffer) {
+ XML_ERROR(XML_ERROR_ATTR_NAME);
+ return NULL;
+ }
+ *nameLen = buffer - *pName;
+ if (*nameLen <= 0) {
+ XML_ERROR(XML_ERROR_ATTR_NAME);
+ return NULL;
+ }
+
+ /* '=' */
+ buffer = xml_ignore_blank(buffer);
+ if (NULL == buffer || *buffer != '=') {
+ XML_ERROR(XML_ERROR_ATTR_MISSED_EQUAL);
+ return NULL;
+ }
+
+ /* Value */
+ buffer++;
+ buffer = xml_ignore_blank(buffer);
+ if (NULL == buffer || (*buffer != '"' && *buffer != '\'')) {
+ XML_ERROR(XML_ERROR_ATTR_VALUE);
+ return NULL;
+ }
+ charQuoted = *buffer++;
+ *pValue = buffer;
+ while (*buffer != '\0' && *buffer != charQuoted)
+ buffer++;
+ if (*buffer != charQuoted) {
+ XML_ERROR(XML_ERROR_ATTR_VALUE);
+ return NULL;
+ }
+ *valueLen = buffer - *pValue;
+
+ XML_ERROR(XML_ERROR_OK);
+
+ return buffer + 1;
+}
+
+uint8_t *XML_DOM_getValue(uint8_t *buffer, uint8_t **pValue, int32_t *valueLen)
+{
+ uint8_t *pEnd;
+
+ if (NULL == buffer) {
+ XML_ERROR(XML_ERROR_BUFFER_NULL);
+ return NULL;
+ }
+
+ /* Ignore the STag */
+ if (*buffer == '<') {
+ buffer++;
+ /* If it's an end_tag, no value should be returned */
+ if (*buffer == '/') {
+ *valueLen = 0;
+ XML_ERROR(XML_ERROR_NOVALUE);
+ return NULL;
+ }
+
+ while (buffer != NULL && XML_IS_NAMECHAR(*buffer))
+ buffer++;
+ if (NULL == buffer) {
+ XML_ERROR(XML_ERROR_BUFFER_NULL);
+ return NULL;
+ }
+
+ if (NULL == (buffer = xml_goto_tagend(buffer))) {
+ XML_ERROR(XML_ERROR_PROPERTY_END);
+ return NULL;
+ }
+ }
+
+ /* <test/> node found */
+ if (*buffer == '/') {
+ if (*(buffer + 1) != '>') {
+ XML_ERROR(XML_ERROR_PROPERTY_END);
+ return NULL;
+ }
+ XML_ERROR(XML_ERROR_OK);
+ *valueLen = 0;
+ return buffer;
+ }
+
+ if (*buffer == '>')
+ buffer++;
+
+ if (NULL == (buffer = xml_ignore_blank(buffer))) {
+ XML_ERROR(XML_ERROR_BUFFER_NULL);
+ return NULL;
+ }
+
+ /* the following is a tag instead of the value */
+ if (*buffer == '<') { /* nono value, such as <test></test> */
+ buffer++;
+ if (*buffer != '/') {
+ XML_ERROR(XML_ERROR_ENDTAG);
+ return NULL;
+ }
+ *valueLen = 0;
+ XML_ERROR(XML_ERROR_OK);
+ return NULL;
+ }
+
+ *pValue = buffer;
+ pEnd = NULL;
+ while (*buffer != '\0' && *buffer != '<') {
+ if (!XML_IS_WHITESPACE(*buffer))
+ pEnd = buffer;
+ buffer++;
+ }
+ if (*buffer != '<' || pEnd == NULL) {
+ XML_ERROR(XML_ERROR_VALUE);
+ return NULL;
+ }
+
+ *valueLen = pEnd - *pValue + 1;
+
+ buffer++;
+ if (*buffer != '/') {
+ XML_ERROR(XML_ERROR_ENDTAG);
+ return NULL;
+ }
+
+ XML_ERROR(XML_ERROR_OK);
+
+ return buffer - 1;
+}
+
+uint8_t *XML_DOM_getTag(uint8_t *buffer, int32_t *tagLen, int32_t *tagType)
+{
+ uint8_t *pStart;
+
+ /* WARNING: <!-- --> comment is not supported in this verison */
+ if (NULL == buffer) {
+ XML_ERROR(XML_ERROR_BUFFER_NULL);
+ return NULL;
+ }
+
+ do {
+ while (*buffer != '<') {
+ if (*buffer == '\0') {
+ XML_ERROR(XML_ERROR_BUFFER_NULL);
+ return NULL;
+ }
+
+ if (*buffer == '\"' || *buffer == '\'') {
+ uint8_t charQuoted = *buffer;
+ buffer++;
+ while (*buffer != '\0' && *buffer != charQuoted)
+ buffer++;
+ if (*buffer == '\0') {
+ XML_ERROR(XML_ERROR_BUFFER_NULL);
+ return NULL;
+ }
+ }
+ buffer++;
+ }
+ buffer++;
+ } while (*buffer == '!' || *buffer == '?');
+
+ pStart = buffer - 1;
+
+ if (*buffer == '/') {
+ buffer++;
+ *tagType = XML_TAG_END;
+ } else {
+ /* check here if it is self-end-tag */
+ uint8_t *pCheck = xml_goto_tagend(pStart);
+ if (pCheck == NULL) {
+ XML_ERROR(XML_ERROR_PROPERTY_END);
+ return NULL;
+ }
+
+ if (*pCheck == '>')
+ *tagType = XML_TAG_START;
+ else if (strncmp((char *)pCheck, "/>", 2) == 0)
+ *tagType = XML_TAG_SELF;
+ else {
+ XML_ERROR(XML_ERROR_PROPERTY_END);
+ return NULL;
+ }
+ }
+
+ while (buffer != NULL && XML_IS_NAMECHAR(*buffer))
+ buffer++;
+ if (NULL == buffer) {
+ XML_ERROR(XML_ERROR_BUFFER_NULL);
+ return NULL;
+ }
+
+ if (*tagType == XML_TAG_END)
+ *tagLen = buffer - pStart - 2;
+ else
+ *tagLen = buffer - pStart - 1;
+
+ XML_ERROR(XML_ERROR_OK);
+
+ return pStart;
+}
+
+uint8_t *XML_DOM_getNode(uint8_t *buffer, const uint8_t *const node)
+{
+ uint8_t *pStart;
+ uint8_t buf[XML_MAX_PROPERTY_LEN + 2];
+ uint8_t *nodeStr = buf;
+ uint8_t *retPtr = NULL;
+ int32_t tagLen, tagType;
+ uint8_t *lastNode = (uint8_t *)"";
+
+ if (NULL == buffer) {
+ XML_ERROR(XML_ERROR_BUFFER_NULL);
+ return NULL;
+ }
+
+ strncpy((char *)nodeStr, (char *)node, XML_MAX_PROPERTY_LEN);
+ strcat((char *)nodeStr, "\\");
+ pStart = (uint8_t *)strchr((char *)nodeStr, '\\');
+
+ while (pStart != NULL) {
+ *pStart = '\0';
+
+ /* get the first start_tag from buffer */
+ if (NULL == (buffer = XML_DOM_getTag(buffer, &tagLen, &tagType))) {
+ XML_ERROR(XML_ERROR_NO_SUCH_NODE);
+ return NULL;
+ }
+
+ if (tagType == XML_TAG_END) {
+ if (0 ==
+ strncmp((char *)lastNode, (char *)(buffer + 2), strlen((char *)lastNode)))
+ XML_ERROR(XML_ERROR_NO_SUCH_NODE);
+ else
+ XML_ERROR(XML_ERROR_NO_START_TAG);
+ return NULL;
+ }
+
+ /* wrong node, contiue to fetch the next node */
+ if ((int32_t) strlen((char *)nodeStr) != tagLen
+ || strncmp((char *)nodeStr, (char *)(buffer + 1), tagLen) != 0) {
+ /* we should ignore all the middle code */
+ buffer = xml_match_tag(buffer);
+ continue;
+ }
+
+ retPtr = buffer; /* retPtr starts with '<xxx>' */
+ buffer += (tagLen + 1);
+
+ if (tagType == XML_TAG_SELF) {
+ nodeStr = pStart + 1;
+ break;
+ }
+
+ lastNode = nodeStr;
+ nodeStr = pStart + 1;
+ pStart = (uint8_t *)strchr((char *)nodeStr, '\\');
+ }
+
+ /* Check 5: nodeStr should be empty here */
+ if (*nodeStr != '\0') {
+ XML_ERROR(XML_ERROR_NO_SUCH_NODE);
+ return NULL;
+ }
+
+ XML_ERROR(XML_ERROR_OK);
+
+ return retPtr;
+}
+
+uint8_t *XML_DOM_getNodeValue(uint8_t *buffer, uint8_t *node,
+ uint8_t **value, int32_t *valueLen)
+{
+ uint8_t *pStart;
+ uint8_t *lastTag;
+
+ if (NULL == node || NULL == buffer) {
+ XML_ERROR(XML_ERROR_BUFFER_NULL);
+ return NULL;
+ }
+
+ lastTag = node + strlen((char *)node) - 1;
+ while (lastTag >= node && *lastTag != '\\')
+ lastTag--;
+ lastTag++;
+
+ if (NULL == (pStart = XML_DOM_getNode(buffer, node)))
+ return NULL;
+
+ pStart += (strlen((char *)lastTag) + 1);
+
+ if (NULL == (pStart = xml_goto_tagend(pStart))) {
+ XML_ERROR(XML_ERROR_PROPERTY_END);
+ return NULL;
+ }
+
+ if (NULL == (pStart = XML_DOM_getValue(pStart, value, valueLen)))
+ return NULL;
+
+ /* Check the end tag */
+#ifdef XML_DOM_CHECK_ENDTAG
+ if (strncmp((char *)pStart, "/>", 2) == 0) {
+
+ } else if (strncmp((char *)lastTag, (char *)(pStart + 2), strlen((char *)lastTag)) !=
+ 0) {
+ XML_ERROR(XML_ERROR_ENDTAG);
+ return NULL;
+ }
+#endif
+
+ XML_ERROR(XML_ERROR_OK);
+
+ return *value;
+}
+
+uint8_t *XML_DOM_getNextNode(uint8_t *buffer, uint8_t **pNodeName, int32_t *nodenameLen)
+{
+ int32_t tagType;
+
+ if (NULL == buffer)
+ return NULL;
+
+ do {
+ if (NULL ==
+ (buffer = XML_DOM_getTag(buffer + 1, nodenameLen, &tagType))) {
+ XML_ERROR(XML_ERROR_NO_SUCH_NODE);
+ return NULL;
+ }
+ } while (tagType == XML_TAG_END);
+
+ *pNodeName = buffer + 1;
+
+ XML_ERROR(XML_ERROR_OK);
+
+ return buffer;
+}
+
+#endif /* XML_DOM_PARSER */
+
+#ifdef WBXML_DOM_PARSER
+
+#ifdef WBXML_OLD_VERSION
+uint8_t *WBXML_DOM_getNode(uint8_t *buffer, int32_t bufferLen,
+ uint8_t *node)
+{
+ int32_t i = 0, j = 0;
+
+ if (NULL == buffer || node == NULL) {
+ XML_ERROR(XML_ERROR_BUFFER_NULL);
+ return NULL;
+ }
+
+ while (i < bufferLen) {
+ if (WBXML_GET_TAG(buffer[i]) == WBXML_GET_TAG(node[j])) {
+ j++;
+ if (node[j] == '\0')
+ break;
+
+ /* Check if there is the content(it should have content) */
+ if (!WBXML_HAS_CONTENT(buffer[i])) {
+ /*XML_ERROR(WBXML_ERROR_MISSED_CONTENT); */
+ XML_ERROR(XML_ERROR_NO_SUCH_NODE);
+ return NULL;
+ }
+
+ /* Ignore the attrib filed */
+ if (WBXML_HAS_ATTR(buffer[i])) {
+ while (i < bufferLen && buffer[i] != WBXML_ATTR_END)
+ i++;
+ if (i >= bufferLen)
+ break;
+ }
+ }
+ i++;
+
+ /* Ignore the content filed */
+ if (buffer[i] == WBXML_STR_I) {
+ while (i < bufferLen && buffer[i] != WBXML_END)
+ i++;
+ if (i >= bufferLen)
+ break;
+ i++;
+ }
+ }
+
+ if (i >= bufferLen) {
+ XML_ERROR(XML_ERROR_NO_SUCH_NODE);
+ return NULL;
+ }
+
+ XML_ERROR(XML_ERROR_OK);
+
+ return buffer + i + 1;
+}
+
+uint8_t *WBXML_DOM_getNodeValue(uint8_t *buffer, int32_t bufferLen,
+ uint8_t *node,
+ uint8_t **value, int32_t *valueLen)
+{
+ int32_t i;
+ uint8_t *pEnd;
+
+ *value = NULL;
+ *valueLen = 0;
+
+ pEnd = buffer + bufferLen;
+ buffer = WBXML_DOM_getNode(buffer, bufferLen, node);
+ if (NULL == buffer) {
+ XML_ERROR(XML_ERROR_NO_SUCH_NODE);
+ return NULL;
+ }
+
+ if (*buffer == WBXML_OPAUE) {
+ buffer++;
+ *valueLen = WBXML_GetUintVar(buffer, &i);
+ if (*valueLen < 0) {
+ XML_ERROR(WBXML_ERROR_MBUINT32);
+ return NULL;
+ }
+ buffer += i;
+ *value = buffer;
+ return *value;
+ }
+
+ if (*buffer != WBXML_STR_I) {
+ XML_ERROR(WBXML_ERROR_MISSED_STARTTAG);
+ return NULL;
+ }
+
+ buffer++;
+
+ i = 0;
+ while ((buffer + i) < pEnd && buffer[i] != WBXML_END)
+ i++;
+
+ if (buffer[i] != WBXML_END) {
+ XML_ERROR(WBXML_ERROR_MISSED_ENDTAG);
+ return NULL;
+ }
+
+ *value = buffer;
+ *valueLen = i;
+ XML_ERROR(XML_ERROR_OK);
+
+ return *value;
+}
+#endif /* WBXML_OLD_VERSION */
+
+#define MAX_UINT_VAR_BYTE 4
+#define UINTVAR_INVALID -1
+int32_t WBXML_GetUintVar(const uint8_t *const buffer, int32_t *len)
+{
+ int32_t i, byteLen;
+ int32_t sum;
+
+ byteLen = 0;
+ while ((buffer[byteLen] & 0x80) > 0 && byteLen < MAX_UINT_VAR_BYTE)
+ byteLen++;
+
+ if (byteLen > MAX_UINT_VAR_BYTE)
+ return UINTVAR_INVALID;
+
+ *len = byteLen + 1;
+ sum = buffer[byteLen];
+ for (i = byteLen - 1; i >= 0; i--)
+ sum += ((buffer[i] & 0x7F) << 7 * (byteLen - i));
+
+ return sum;
+}
+
+XML_BOOL WBXML_DOM_Init(WBXML * pWbxml, uint8_t *buffer,
+ int32_t bufferLen)
+{
+ int32_t num, len;
+
+ pWbxml->End = buffer + bufferLen;
+ pWbxml->version = *buffer++;
+ if (UINTVAR_INVALID == (num = WBXML_GetUintVar(buffer, &len)))
+ return XML_FALSE;
+ buffer += len;
+ pWbxml->publicid = num;
+ if (UINTVAR_INVALID == (num = WBXML_GetUintVar(buffer, &len)))
+ return XML_FALSE;
+ buffer += len;
+ pWbxml->charset = num;
+ if (UINTVAR_INVALID == (num = WBXML_GetUintVar(buffer, &len)))
+ return XML_FALSE;
+ buffer += len;
+ pWbxml->strTable = buffer;
+ pWbxml->strTableLen = num;
+ buffer += num;
+ pWbxml->curPtr = pWbxml->Content = buffer;
+ pWbxml->depth = 0;
+
+ return XML_TRUE;
+}
+
+void WBXML_DOM_Rewind(WBXML * pWbxml)
+{
+ pWbxml->curPtr = pWbxml->Content;
+}
+
+XML_BOOL WBXML_DOM_Eof(WBXML * pWbxml)
+{
+ if (pWbxml->curPtr > pWbxml->End)
+ return XML_TRUE;
+
+ return XML_FALSE;
+}
+
+uint8_t WBXML_DOM_GetTag(WBXML * pWbxml)
+{
+ uint8_t tagChar;
+
+ if (pWbxml->curPtr > pWbxml->End)
+ return XML_EOF;
+
+ tagChar = *pWbxml->curPtr;
+ pWbxml->curPtr++;
+
+ if (WBXML_GET_TAG(tagChar) == WBXML_CONTENT_END)
+ pWbxml->depth--;
+ else
+ pWbxml->depth++;
+
+ return tagChar;
+}
+
+uint8_t WBXML_DOM_GetChar(WBXML * pWbxml)
+{
+ return *pWbxml->curPtr++;
+}
+
+void WBXML_DOM_Seek(WBXML * pWbxml, int32_t offset)
+{
+ pWbxml->curPtr += offset;
+}
+
+uint8_t WBXML_DOM_GetUIntVar(WBXML * pWbxml)
+{
+ int32_t num, len;
+
+ num = WBXML_GetUintVar(pWbxml->curPtr, &len);
+ pWbxml->curPtr += len;
+
+ return (uint8_t)num;
+}
+
+#ifdef XML_TREE_STRUCTURE
+
+#ifdef DEBUG_MODE
+static int32_t malloc_times = 0;
+static int32_t free_times = 0;
+void XML_PrintMallocInfo()
+{
+ printf("====XML_PrintMallocInfo====\n");
+ printf(" Total malloc times:%d\n", malloc_times);
+ printf(" Total free times:%d\n", free_times);
+ printf("===========================\n");
+}
+#endif
+
+void *xml_malloc(int32_t size)
+{
+#ifdef DEBUG_MODE
+ malloc_times++;
+#endif
+ return malloc(size);
+}
+
+void xml_free(void *buffer)
+{
+#ifdef DEBUG_MODE
+ free_times++;
+#endif
+ free(buffer);
+}
+
+XML_TREE *xml_tree_fillnode(uint8_t **buf, int32_t tagLen)
+{
+ XML_TREE *Tree;
+ uint8_t *pAttr, *pName, *pValue;
+ int32_t nameLen, valueLen;
+ uint8_t *buffer = *buf;
+
+ if (NULL == (Tree = (XML_TREE *) xml_malloc(sizeof(XML_TREE))))
+ return NULL;
+ memset(Tree, 0, sizeof(XML_TREE));
+
+ strncpy((char *)Tree->tag, (char *)++buffer, tagLen);
+ buffer += tagLen;
+ pAttr = buffer;
+
+ /* attribute */
+ while (NULL !=
+ (pAttr =
+ XML_DOM_getAttr(pAttr, &pName, &nameLen, &pValue,
+ &valueLen))) {
+ XML_TREE_ATTR *attr;
+ if (NULL ==
+ (attr = (XML_TREE_ATTR *) xml_malloc(sizeof(XML_TREE_ATTR))))
+ return NULL;
+ memset(attr, 0, sizeof(XML_TREE_ATTR));
+ strncpy((char *)attr->name, (char *)pName, nameLen);
+ strncpy((char *)attr->value, (char *)pValue, valueLen);
+ buffer = pValue + valueLen + 1;
+
+ if (NULL != Tree->attr) // no attribute now
+ Tree->last_attr->next = attr;
+ else
+ Tree->attr = attr;
+ Tree->last_attr = attr;
+ }
+
+ /* value */
+ pAttr = XML_DOM_getValue(buffer, &pValue, &valueLen);
+ if (pAttr != NULL && valueLen > 0) {
+ strncpy((char *)Tree->value, (char *)pValue, valueLen);
+ buffer = pValue + valueLen;
+ }
+
+ *buf = buffer;
+ return Tree;
+}
+
+XML_TREE *XML_makeTree(uint8_t **buf)
+{
+ uint8_t *pBuf;
+ int32_t valueLen, tagType;
+ uint8_t *buffer = *buf;
+ XML_TREE *TreeHead = NULL;
+
+ if (NULL == (buffer = XML_DOM_getTag(buffer, &valueLen, &tagType)))
+ return NULL;
+ if (XML_TAG_END == tagType)
+ return NULL;
+ if (NULL == (TreeHead = xml_tree_fillnode(&buffer, valueLen)))
+ return NULL;
+ if (XML_TAG_SELF == tagType) {
+ *buf = buffer;
+ return TreeHead;
+ }
+
+ do {
+ if (NULL == (pBuf = XML_DOM_getTag(buffer, &valueLen, &tagType)))
+ return NULL;
+
+ switch (tagType) {
+ case XML_TAG_SELF:
+ case XML_TAG_START:
+ if (NULL == TreeHead->child)
+ TreeHead->child = XML_makeTree(&buffer);
+ else if (NULL == TreeHead->child->last_brother) {
+ TreeHead->child->brother = XML_makeTree(&buffer);
+ TreeHead->child->last_brother = TreeHead->child->brother;
+ } else {
+ TreeHead->child->last_brother->brother =
+ XML_makeTree(&buffer);
+ TreeHead->child->last_brother =
+ TreeHead->child->last_brother->brother;
+ }
+ break;
+ case XML_TAG_END:
+ *buf = pBuf;
+ return TreeHead;
+ }
+ buffer++;
+ } while (1);
+}
+
+void XML_freeTree(XML_TREE * pTree)
+{
+ XML_TREE *p, *pNext;
+ XML_TREE_ATTR *pa, *lastpa;
+
+ if (NULL == pTree)
+ return;
+
+ p = pTree->brother;
+ while (NULL != p) {
+ pNext = p->brother;
+ p->brother = NULL;
+ XML_freeTree(p);
+ p = pNext;
+ }
+
+ if (NULL != pTree->child)
+ XML_freeTree(pTree->child);
+
+ pa = pTree->attr;
+ while (NULL != pa) {
+ lastpa = pa;
+ pa = pa->next;
+ xml_free(lastpa);
+ }
+ xml_free(pTree);
+}
+
+#endif /* XML_TREE_STRUCTURE */
+
+#endif /* WBXML_DOM_PARSER */