diff --git a/bin/jrasp-packages.sh b/bin/jrasp-packages.sh
index 48c7ebb8..37447d53 100755
--- a/bin/jrasp-packages.sh
+++ b/bin/jrasp-packages.sh
@@ -26,7 +26,6 @@ mkdir -p ${JRASP_TARGET_DIR}/temp
mkdir -p ${JRASP_TARGET_DIR}/provider
mkdir -p ${JRASP_TARGET_DIR}/required-module # 用户必装模块路径(仓库,全部复制到run/pid)
mkdir -p ${JRASP_TARGET_DIR}/optional-module # 用户可选的模块路径(仓库,部分复制到run/pid)
-mkdir -p ${JRASP_TARGET_DIR}/algorithm-module # 检测算法模块(仓库,全部复制到run/pid)
mkdir -p ${JRASP_TARGET_DIR}/run # java进程相关数据:token、module
mkdir -p ${JRASP_TARGET_DIR}/logs # jrasp日志:系统日志、检测日志、心跳日志等
diff --git a/jrasp-api/pom.xml b/jrasp-api/pom.xml
index 61991878..e80762b6 100644
--- a/jrasp-api/pom.xml
+++ b/jrasp-api/pom.xml
@@ -5,7 +5,7 @@
jrasp-agent
com.jrasp
- 1.0.3
+ 1.0.4
4.0.0
diff --git a/jrasp-api/src/main/java/com/jrasp/api/algorithm/Algorithm.java b/jrasp-api/src/main/java/com/jrasp/api/algorithm/Algorithm.java
index 067ca348..f4d018f0 100644
--- a/jrasp-api/src/main/java/com/jrasp/api/algorithm/Algorithm.java
+++ b/jrasp-api/src/main/java/com/jrasp/api/algorithm/Algorithm.java
@@ -1,6 +1,5 @@
package com.jrasp.api.algorithm;
-import java.util.ArrayList;
import java.util.HashMap;
public interface Algorithm {
@@ -17,12 +16,12 @@ public interface Algorithm {
/**
* 安全检测算法
+ *
+ * @param httpInfo http信息
* @param parameters 参数
- * @param stack 调用栈
- * @param httpInfo http信息
* @return 检测结果
*/
- boolean check(String[] parameters, ArrayList stack, HashMap httpInfo);
+ boolean check(HashMap httpInfo, Object... parameters) throws Exception;
/**
* @return 算法描述
diff --git a/jrasp-api/src/main/java/com/jrasp/api/algorithm/AlgorithmManager.java b/jrasp-api/src/main/java/com/jrasp/api/algorithm/AlgorithmManager.java
index 49a110e3..584dc998 100644
--- a/jrasp-api/src/main/java/com/jrasp/api/algorithm/AlgorithmManager.java
+++ b/jrasp-api/src/main/java/com/jrasp/api/algorithm/AlgorithmManager.java
@@ -1,18 +1,15 @@
package com.jrasp.api.algorithm;
-import java.util.ArrayList;
import java.util.HashMap;
public interface AlgorithmManager {
/**
- *
* @param algorithm 算法对象
* @return 注册是否成功
*/
boolean register(Algorithm algorithm);
/**
- *
* @param algorithm 算法对象
* @return 销毁是否成功
*/
@@ -20,12 +17,12 @@ public interface AlgorithmManager {
/**
* 安全检测算法
- * @param type 攻击类型
+ *
+ * @param type 攻击类型
+ * @param httpInfo http信息
* @param parameters 参数
- * @param stack 调用栈
- * @param httpInfo http信息
* @return 检测结果
*/
- boolean check(String type, String[] parameters, ArrayList stack, HashMap httpInfo);
+ boolean doCheck(String type, HashMap httpInfo, Object... parameters) throws Exception;
}
diff --git a/jrasp-common-api/pom.xml b/jrasp-common-api/pom.xml
index de0dc5d9..478f61e2 100644
--- a/jrasp-common-api/pom.xml
+++ b/jrasp-common-api/pom.xml
@@ -5,11 +5,11 @@
jrasp-agent
com.jrasp
- 1.0.3
+ 1.0.4
4.0.0
jrasp-common-api
jrasp-common-api ${jrasp.version}
-
\ No newline at end of file
+
diff --git a/jrasp-core/dependency-reduced-pom.xml b/jrasp-core/dependency-reduced-pom.xml
index 91a7c0e9..ab02ee09 100644
--- a/jrasp-core/dependency-reduced-pom.xml
+++ b/jrasp-core/dependency-reduced-pom.xml
@@ -3,7 +3,7 @@
jrasp-agent
com.jrasp
- 1.0.3
+ 1.0.4
4.0.0
jrasp-core
@@ -78,7 +78,7 @@
com.jrasp
jrasp-spy
- 1.0.3
+ 1.0.4
provided
diff --git a/jrasp-core/pom.xml b/jrasp-core/pom.xml
index e54629f6..a44f5672 100644
--- a/jrasp-core/pom.xml
+++ b/jrasp-core/pom.xml
@@ -5,7 +5,7 @@
jrasp-agent
com.jrasp
- 1.0.3
+ 1.0.4
4.0.0
diff --git a/jrasp-core/src/main/java/com/jrasp/core/CoreConfigure.java b/jrasp-core/src/main/java/com/jrasp/core/CoreConfigure.java
index d7a3caea..3a63c6ff 100644
--- a/jrasp-core/src/main/java/com/jrasp/core/CoreConfigure.java
+++ b/jrasp-core/src/main/java/com/jrasp/core/CoreConfigure.java
@@ -109,11 +109,6 @@ public String getSystemModuleLibPath() {
return getRaspHome() + File.separatorChar + SYSTEM_MODULE_FILE_NAME;
}
- // 获取用户模块(必装)模块路径(文件变化的监控路径)
- public String getAlgorithmModuleLibPath() {
- return getRaspHome() + File.separatorChar + ALGORITHM_MODULE_FILE_NAME;
- }
-
// 获取用户模块(必装)模块路径(文件变化的监控路径)
public String getUserModuleLibPath() {
return getRaspHome() + File.separatorChar + REQUIRED_MODULE_FILE_NAME;
@@ -244,11 +239,6 @@ public String getRuntimeRequiredModulePath() {
return getProcessPidPath() + File.separator + REQUIRED_MODULE_FILE_NAME;
}
- // 获取进程运行时pid/algorithm-module
- public String getRuntimeAlgorithmModulePath() {
- return getProcessPidPath() + File.separator + ALGORITHM_MODULE_FILE_NAME;
- }
-
// 获取进程运行时pid/optional-nodule
public String getRuntimeOptionalModulePath() {
return getProcessPidPath() + File.separator + OPTIONAL_MODULE_FILE_NAME;
diff --git a/jrasp-core/src/main/java/com/jrasp/core/JvmRasp.java b/jrasp-core/src/main/java/com/jrasp/core/JvmRasp.java
index d6030b45..46114acb 100644
--- a/jrasp-core/src/main/java/com/jrasp/core/JvmRasp.java
+++ b/jrasp-core/src/main/java/com/jrasp/core/JvmRasp.java
@@ -67,7 +67,6 @@ private void initPidRunDir() {
mkdirs(cfg.getProcessPidPath());
mkdirs(cfg.getRuntimeSystemModulePath());
mkdirs(cfg.getRuntimeRequiredModulePath());
- mkdirs(cfg.getRuntimeAlgorithmModulePath());
mkdirs(cfg.getRuntimeOptionalModulePath());
// JVM 退出时删除目录
try {
diff --git a/jrasp-core/src/main/java/com/jrasp/core/algorithm/DefaultAlgorithmManager.java b/jrasp-core/src/main/java/com/jrasp/core/algorithm/DefaultAlgorithmManager.java
index 9d6e5769..c81162af 100644
--- a/jrasp-core/src/main/java/com/jrasp/core/algorithm/DefaultAlgorithmManager.java
+++ b/jrasp-core/src/main/java/com/jrasp/core/algorithm/DefaultAlgorithmManager.java
@@ -6,7 +6,7 @@
import com.jrasp.core.log.LogFactory;
import java.util.*;
-import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.ConcurrentHashMap;
import static com.jrasp.core.log.AgentLogIdConstant.AGENT_COMMON_LOG_ID;
@@ -16,56 +16,27 @@ public class DefaultAlgorithmManager implements AlgorithmManager {
public static final DefaultAlgorithmManager instance = new DefaultAlgorithmManager();
- /**
- * 读多写少
- */
- private static Map> algorithmMaps = new HashMap>(16);
+ private static Map algorithmMaps = new ConcurrentHashMap(16);
@Override
public boolean register(Algorithm algorithm) {
String type = algorithm.getType();
- if (algorithmMaps.containsKey(type)) {
- CopyOnWriteArrayList algorithms = algorithmMaps.get(type);
- algorithms.add(algorithm);
- logger.info(AGENT_COMMON_LOG_ID, "add new algorithm", algorithm.getName());
- } else {
- CopyOnWriteArrayList algorithms = new CopyOnWriteArrayList();
- // todo 相同的id,保证只有一个
- algorithms.add(algorithm);
- algorithmMaps.put(type, algorithms);
- }
+ algorithmMaps.put(type, algorithm);
+ logger.info(AGENT_COMMON_LOG_ID, "register algorithm module {}", type);
return true;
}
@Override
public boolean destroy(Algorithm algorithm) {
String type = algorithm.getType();
- String name = algorithm.getName();
- CopyOnWriteArrayList algorithms = algorithmMaps.get(type);
- int index = -1;
- for (int i = 0; i < algorithms.size() ; i++) {
- if (name.equals(algorithms.get(i).getName())) {
- index = i;
- break;
- }
- }
- if (index >= 0) {
- logger.info(AGENT_COMMON_LOG_ID, "remove algorithm", algorithm.getName());
- algorithms.remove(index);
- }
+ algorithmMaps.remove(type);
+ logger.info(AGENT_COMMON_LOG_ID, "destroy algorithm module {}", type);
return true;
}
@Override
- public boolean check(String type, String[] parameters, ArrayList stack, HashMap httpInfo) {
- CopyOnWriteArrayList algorithms = algorithmMaps.get(type);
- for (int i = 0; i < algorithms.size(); i++) {
- Algorithm algorithm = algorithms.get(i);
- boolean check = algorithm.check(parameters, stack, httpInfo);
- if (check) {
- return true;
- }
- }
- return false;
+ public boolean doCheck(String type, HashMap httpInfo, Object... parameters) throws Exception {
+ Algorithm algorithm = algorithmMaps.get(type);
+ return algorithm.check(httpInfo, parameters);
}
}
diff --git a/jrasp-core/src/main/java/com/jrasp/core/log/LogFactory.java b/jrasp-core/src/main/java/com/jrasp/core/log/LogFactory.java
index cda3fec4..e0952938 100644
--- a/jrasp-core/src/main/java/com/jrasp/core/log/LogFactory.java
+++ b/jrasp-core/src/main/java/com/jrasp/core/log/LogFactory.java
@@ -54,7 +54,6 @@ private static void setImplementation(Class extends Log> implClass) {
try {
Constructor extends Log> candidate = implClass.getConstructor(String.class);
Log log = candidate.newInstance(LogFactory.class.getName());
- log.info(SLF4_LOG_INIT_LOG_ID, "Logging initialized using '" + implClass + "' adapter.");
logConstructor = candidate;
} catch (Throwable t) {
throw new LogException("Error setting Log implementation. Cause: " + t, t);
diff --git a/jrasp-core/src/main/java/com/jrasp/core/manager/impl/DefaultCoreLoadedClassDataSource.java b/jrasp-core/src/main/java/com/jrasp/core/manager/impl/DefaultCoreLoadedClassDataSource.java
index 2b82636f..a23c292a 100644
--- a/jrasp-core/src/main/java/com/jrasp/core/manager/impl/DefaultCoreLoadedClassDataSource.java
+++ b/jrasp-core/src/main/java/com/jrasp/core/manager/impl/DefaultCoreLoadedClassDataSource.java
@@ -115,7 +115,7 @@ private List> find(final Matcher matcher,
// 所以当尝试获取这个类更多详细信息的时候会引起关联类的ClassNotFoundException等未知的错误(取决于底层ClassLoader的实现)
// 这里没有办法穷举出所有的异常情况,所以catch Throwable来完成异常容灾处理
// 当解析类出现异常的时候,直接简单粗暴的认为根本没有这个类就好了
- logger.info(DEFAULT_CORE_LOADED_CLASS_DATA_SOURCE_LOG_ID,"remove from findForReTransform, because loading class:{} occur an exception", clazz.getName(), cause);
+ logger.debug(DEFAULT_CORE_LOADED_CLASS_DATA_SOURCE_LOG_ID,"remove from findForReTransform, because loading class:{} occur an exception", clazz.getName(), cause);
}
}
return classes;
diff --git a/jrasp-core/src/main/java/com/jrasp/core/manager/impl/DefaultCoreModuleManager.java b/jrasp-core/src/main/java/com/jrasp/core/manager/impl/DefaultCoreModuleManager.java
index f131c1ab..26eea696 100755
--- a/jrasp-core/src/main/java/com/jrasp/core/manager/impl/DefaultCoreModuleManager.java
+++ b/jrasp-core/src/main/java/com/jrasp/core/manager/impl/DefaultCoreModuleManager.java
@@ -61,10 +61,6 @@ public class DefaultCoreModuleManager implements CoreModuleManager {
private final File requiredModuleLibDir; // 必装模块目录
private final File requiredModuleLibCopyDir; // 必装模块Copy目录
- // 必装算法模块目录
- private final File algorithmModuleLibDir; // 必装算法模块目录
- private final File algorithmModuleLibCopyDir; // 必装算法模块Copy目录
-
// 可选模块目录
private final File optionalModuleLibDir; // 可选模块目录
private final File optionalModuleLibCopyDir; // 可选模块Copy目录
@@ -108,9 +104,6 @@ public DefaultCoreModuleManager(final CoreConfigure cfg,
// 必装模块
this.requiredModuleLibDir = new File(cfg.getUserModuleLibPath());
this.requiredModuleLibCopyDir = new File(cfg.getRuntimeRequiredModulePath());
- // 必装算法模块
- this.algorithmModuleLibDir = new File(cfg.getAlgorithmModuleLibPath());
- this.algorithmModuleLibCopyDir = new File(cfg.getRuntimeAlgorithmModulePath());
// 非必装模块
// 非必装模块较为特殊:由jrasp-daemon复制到运行时目录,这里仅需要监听文件变化
this.optionalModuleLibDir = new File(cfg.getRuntimeOptionalModulePath());
@@ -704,11 +697,10 @@ public synchronized CoreModuleManager reset() throws ModuleException {
// 1. 强制卸载所有模块
unloadAll();
- // 2.加载系统模块、必装模块、非必须模块、算法模块
+ // 2.加载系统模块、必装模块、非必须模块
loadModule(systemModuleLibDir, systemModuleLibCopyDir, cfg.getLaunchMode());
loadModule(requiredModuleLibDir, requiredModuleLibCopyDir, cfg.getLaunchMode());
loadModule(optionalModuleLibDir, optionalModuleLibCopyDir, cfg.getLaunchMode());
- loadModule(algorithmModuleLibDir, algorithmModuleLibCopyDir, cfg.getLaunchMode());
return this;
}
@@ -772,9 +764,10 @@ private void softFlush() {
final ArrayList checksumCRC32s = new ArrayList();
final ArrayList removeCoreModules = new ArrayList();
// 1. 找出所有有变动的文件(add/remove)
- final ArrayList appendJarFiles1 = getAllChangeModuleJar(getUserModuleLibFiles1(), checksumCRC32s); // 系统必装
- final ArrayList appendJarFiles2 = getAllChangeModuleJar(getUserModuleLibFiles2(), checksumCRC32s); // 系统可选
- final ArrayList appendAlgorithmJarFiles = getAllChangeModuleJar(getAlgorithmModuleLibFiles(), checksumCRC32s); // 算法模块
+ // 系统必装
+ final ArrayList appendJarFiles1 = getAllChangeModuleJar(getUserModuleLibFiles1(), checksumCRC32s);
+ // 系统可选
+ final ArrayList appendJarFiles2 = getAllChangeModuleJar(getUserModuleLibFiles2(), checksumCRC32s);
// 2. 找出所有待卸载的已加载用户模块
for (final CoreModule coreModule : loadedModuleBOMap.values()) {
@@ -787,8 +780,8 @@ private void softFlush() {
// 如果CRC32已经在这次待加载的集合中,则说明这个文件没有变动,忽略
if (checksumCRC32s.contains(moduleJarClassLoader.getChecksumCRC32())) {
- logger.info(AGENT_COMMON_LOG_ID, "soft-flushing module: module-jar already loaded, ignored. module-jar={};CRC32={};",
- coreModule.getJarFile(),
+ logger.info(AGENT_COMMON_LOG_ID, "soft-flushing module: {} already loaded, ignored.CRC32={};",
+ coreModule.getJarFile().getName(),
moduleJarClassLoader.getChecksumCRC32()
);
continue;
@@ -816,12 +809,6 @@ private void softFlush() {
new ModuleLibLoader(jarFile, null, cfg.getLaunchMode()) // todo 重构:可选模块不需要复制,这里代码比较难以理解
.load(new InnerModuleJarLoadCallback(), new InnerModuleLoadCallback());
}
-
- // 6. 加载算法模块
- for (final File jarFile : appendAlgorithmJarFiles) {
- new ModuleLibLoader(jarFile, new File(cfg.getRuntimeAlgorithmModulePath()), cfg.getLaunchMode())
- .load(new InnerModuleJarLoadCallback(), new InnerModuleLoadCallback());
- }
} catch (Throwable cause) {
logger.warn(AGENT_COMMON_LOG_ID, "soft-flushing modules: occur error.", cause);
}
@@ -869,10 +856,6 @@ private void forceFlush() throws ModuleException {
// 3. 加载非必装模块
loadModule(optionalModuleLibDir, optionalModuleLibCopyDir, cfg.getLaunchMode());
-
- // 4.加载算法模块
- loadModule(algorithmModuleLibDir, algorithmModuleLibCopyDir, cfg.getLaunchMode());
-
}
// 找出所以变动的模块
@@ -904,16 +887,11 @@ public File[] getUserModuleLibFiles1() {
return getUserModuleLibFiles(cfg.getUserModuleLibPath());
}
- // 获取用户可选模块加载文件
+ // 获取用户可选模块加载文件 todo 需要修复
public File[] getUserModuleLibFiles2() {
return getUserModuleLibFiles(cfg.getRuntimeOptionalModulePath());
}
- // 算法模块
- public File[] getAlgorithmModuleLibFiles() {
- return getUserModuleLibFiles(cfg.getRuntimeAlgorithmModulePath());
- }
-
private synchronized File[] getUserModuleLibFiles(String libPath) {
final Collection foundModuleJarFiles = new LinkedHashSet();
final File path = new File(libPath);
diff --git a/jrasp-core/src/main/java/com/jrasp/core/manager/impl/JwtTokenServiceImpl.java b/jrasp-core/src/main/java/com/jrasp/core/manager/impl/JwtTokenServiceImpl.java
index 9d0b2910..8daeb98a 100644
--- a/jrasp-core/src/main/java/com/jrasp/core/manager/impl/JwtTokenServiceImpl.java
+++ b/jrasp-core/src/main/java/com/jrasp/core/manager/impl/JwtTokenServiceImpl.java
@@ -11,6 +11,8 @@
import org.jose4j.keys.PbkdfKey;
import org.jose4j.lang.JoseException;
+import java.sql.Driver;
+
import static com.jrasp.core.log.AgentLogIdConstant.AGENT_COMMON_LOG_ID;
public class JwtTokenServiceImpl implements JwtTokenService {
diff --git a/jrasp-core/src/main/java/com/jrasp/core/manager/impl/RaspClassFileTransformer.java b/jrasp-core/src/main/java/com/jrasp/core/manager/impl/RaspClassFileTransformer.java
index 3bbe4a41..ab6e3bbb 100755
--- a/jrasp-core/src/main/java/com/jrasp/core/manager/impl/RaspClassFileTransformer.java
+++ b/jrasp-core/src/main/java/com/jrasp/core/manager/impl/RaspClassFileTransformer.java
@@ -98,13 +98,7 @@ public byte[] transform(final ClassLoader loader,
} catch (Throwable cause) {
- logger.warn(AGENT_COMMON_LOG_ID,"jrasp transform {} in loader={}; failed, module={} at watch={}, will ignore this transform.",
- internalClassName,
- loader,
- uniqueId,
- watchId,
- cause
- );
+ // ignore
return null;
} finally {
RaspProtector.instance.exitProtecting();
diff --git a/jrasp-jose4j/pom.xml b/jrasp-jose4j/pom.xml
index ae7abd05..970584ff 100644
--- a/jrasp-jose4j/pom.xml
+++ b/jrasp-jose4j/pom.xml
@@ -4,13 +4,13 @@
jrasp-agent
com.jrasp
- 1.0.3
+ 1.0.4
org.bitbucket.b_c
jose4j
jar
- jose4j ${jrasp.version}
+ jrasp-jose4j ${jrasp.version}
UTF-8
diff --git a/jrasp-launcher/pom.xml b/jrasp-launcher/pom.xml
index 6c6b9e4e..2e2fc3be 100644
--- a/jrasp-launcher/pom.xml
+++ b/jrasp-launcher/pom.xml
@@ -5,7 +5,7 @@
jrasp-agent
com.jrasp
- 1.0.3
+ 1.0.4
4.0.0
@@ -51,4 +51,4 @@
-
\ No newline at end of file
+
diff --git a/jrasp-module-admin/pom.xml b/jrasp-module-admin/pom.xml
index 7a4adc5c..b39549f2 100644
--- a/jrasp-module-admin/pom.xml
+++ b/jrasp-module-admin/pom.xml
@@ -5,7 +5,7 @@
com.jrasp
jrasp-module-starter
- 1.0.3
+ 1.0.4
../jrasp-module-starter/pom.xml
4.0.0
@@ -50,4 +50,4 @@
-
\ No newline at end of file
+
diff --git a/jrasp-module-admin/src/main/java/com/jrasp/module/admin/InfoModule.java b/jrasp-module-admin/src/main/java/com/jrasp/module/admin/InfoModule.java
index 5e1e2985..a99d46e0 100755
--- a/jrasp-module-admin/src/main/java/com/jrasp/module/admin/InfoModule.java
+++ b/jrasp-module-admin/src/main/java/com/jrasp/module/admin/InfoModule.java
@@ -15,7 +15,6 @@
@Information(id = "info", version = "0.0.1", author = "jrasp")
public class InfoModule implements Module {
-
@Resource
private ConfigInfo configInfo;
diff --git a/jrasp-module-starter/pom.xml b/jrasp-module-starter/pom.xml
index d308c61b..b9b4507f 100644
--- a/jrasp-module-starter/pom.xml
+++ b/jrasp-module-starter/pom.xml
@@ -5,7 +5,7 @@
jrasp-agent
com.jrasp
- 1.0.3
+ 1.0.4
4.0.0
@@ -49,4 +49,4 @@
-
\ No newline at end of file
+
diff --git a/jrasp-provider-api/pom.xml b/jrasp-provider-api/pom.xml
index 3ba63e3e..38b63b4e 100644
--- a/jrasp-provider-api/pom.xml
+++ b/jrasp-provider-api/pom.xml
@@ -5,7 +5,7 @@
jrasp-agent
com.jrasp
- 1.0.3
+ 1.0.4
4.0.0
@@ -19,4 +19,4 @@
-
\ No newline at end of file
+
diff --git a/jrasp-spy/pom.xml b/jrasp-spy/pom.xml
index 683af9d2..d160755a 100644
--- a/jrasp-spy/pom.xml
+++ b/jrasp-spy/pom.xml
@@ -5,7 +5,7 @@
jrasp-agent
com.jrasp
- 1.0.3
+ 1.0.4
4.0.0
@@ -42,4 +42,4 @@
-
\ No newline at end of file
+
diff --git a/jrasp-system-provider/pom.xml b/jrasp-system-provider/pom.xml
index 8ba9f53f..1b7e65bc 100644
--- a/jrasp-system-provider/pom.xml
+++ b/jrasp-system-provider/pom.xml
@@ -5,7 +5,7 @@
jrasp-agent
com.jrasp
- 1.0.3
+ 1.0.4
4.0.0
@@ -48,4 +48,4 @@
-
\ No newline at end of file
+
diff --git a/pom.xml b/pom.xml
index af98d07b..1e6b7de6 100644
--- a/pom.xml
+++ b/pom.xml
@@ -7,7 +7,7 @@
com.jrasp
jrasp-agent
pom
- 1.0.3
+ 1.0.4
jrasp-agent ${jrasp.version}
@@ -26,7 +26,7 @@
UTF-8
- 1.0.3
+ 1.0.4
jrasp
8.1.2.v20120308
1.0.2