M7350v1_en_gpl

This commit is contained in:
T
2024-09-09 08:52:07 +00:00
commit f9cc65cfda
65988 changed files with 26357421 additions and 0 deletions
+80
View File
@@ -0,0 +1,80 @@
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/openssl/include \
$(call include-path-for, system-core)/cutils
LOCAL_CFLAGS := $(LOCAL_DRM_CFLAG)
LOCAL_SHARED_LIBRARIES := \
libutils \
libcutils \
libcrypto
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
LOCAL_SHARED_LIBRARIES := libdrm1 \
libutils \
libcutils
LOCAL_MODULE := libdrm1_jni
include $(BUILD_SHARED_LIBRARY)
@@ -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__ */
@@ -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__ */
@@ -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__ */
@@ -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__ */
@@ -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
@@ -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__ */
@@ -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 <openssl/aes.h>
#include <drm_common_types.h>
#include <parser_rel.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 key The structure of the CEK.
*
* \return
* -0
*/
int32_t drm_aesDecBuffer(uint8_t * Buffer, int32_t * BufferLen, AES_KEY *key);
/**
* 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__ */
@@ -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__ */
@@ -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__ */
@@ -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__ */
@@ -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__ */
@@ -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__ */
@@ -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__ */
@@ -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__ */
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -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;
}
@@ -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;
}
@@ -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 */
@@ -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_KEY *key)
{
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), key);
/* 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, key);
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, key);
/* 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_KEY key;
int32_t len = DRM_TWO_AES_BLOCK_LEN;
if (NULL == pDcfLastData || NULL == keyValue)
return FALSE;
AES_set_decrypt_key(keyValue, DRM_KEY_LEN * 8, &key);
if (drm_aesDecBuffer(pDcfLastData, &len, &key) < 0)
return FALSE;
drm_discardPaddingByte(pDcfLastData, &len);
*moreBytes = DRM_TWO_AES_BLOCK_LEN - len;
return TRUE;
}
@@ -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;
}
@@ -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;
}
@@ -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;
}
@@ -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;
}
@@ -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 */