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
+1
View File
@@ -0,0 +1 @@
include $(call all-subdir-makefiles)
+190
View File
@@ -0,0 +1,190 @@
Copyright (c) 2005-2008, 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.
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.
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
+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 */