/* Copyright 2012-2013, Polyvi Inc. (http://polyvi.github.io/openxface) This program is distributed under the terms of the GNU General Public License. This file is part of xFace. xFace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. xFace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with xFace. If not, see <http://www.gnu.org/licenses/>. */ package com.polyvi.xface.app.transferpolicy; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.util.ArrayList; import android.content.Context; import android.content.SharedPreferences; import com.polyvi.xface.XSecurityPolicy; import com.polyvi.xface.app.XApplication; import com.polyvi.xface.core.XAppCheckListener; import com.polyvi.xface.core.XISystemContext; import com.polyvi.xface.event.XEvent; import com.polyvi.xface.event.XEventType; import com.polyvi.xface.event.XSystemEventCenter; import com.polyvi.xface.util.XConstant; import com.polyvi.xface.util.XCryptor; import com.polyvi.xface.util.XFileUtils; import com.polyvi.xface.util.XFileVisitor; import com.polyvi.xface.util.XLog; /** * app转移的安全策略 */ public class XTransferSecurityPolicy implements XSecurityPolicy, XFileVisitor { private static final String CLASS_NAME = XTransferSecurityPolicy.class .getSimpleName(); private XISystemContext mSysCtx; private ArrayList<String> mMd5Array; private boolean mIsContinueTraverse; private XCryptor mCryptor; public XTransferSecurityPolicy(XISystemContext sysCtx) { mIsContinueTraverse = true; mSysCtx = sysCtx; mMd5Array = new ArrayList<String>(); mCryptor = new XCryptor(); } @Override public boolean checkAppStart(XApplication app, XAppCheckListener listener) { String transferedAppMd5 = calTransferedAppMd5(app.getAppInfo() .getSrcRoot()); if (null != transferedAppMd5) { String prefMd5 = readPrefMd5(app.getAppId()); if (transferedAppMd5.equals(prefMd5)) { listener.onCheckSuccess(app, mSysCtx); return true; } } sendMd5InvalidEvt(app); listener.onCheckSuccess(app, mSysCtx); return true; } @Override public boolean checkAppClose(XApplication app) { return true; } /** * 从apps.pref中读取对应app的md5值 * * @param appId * @return */ private String readPrefMd5(String appId) { SharedPreferences preference = mSysCtx.getContext() .getSharedPreferences( XPreInstallAppsTransferPolicy.APPS_MD5_FILE_NAME, Context.MODE_WORLD_READABLE | Context.MODE_WORLD_WRITEABLE); String md5 = preference.getString(appId, null); if (null == md5) { XLog.d(CLASS_NAME, "App id: " + appId + " not found in " + XPreInstallAppsTransferPolicy.APPS_MD5_FILE_NAME); return null; } return md5; } /** * 计算转移后的app的md5值 * * @param appSrcRoot * @return */ private String calTransferedAppMd5(String appSrcRoot) { if (null == appSrcRoot) { XLog.w(CLASS_NAME, "calTransferedAppMd5 app src_Root is null!"); return null; } // src前面有file协议会无法找到相应路径,所以需要去掉file协议头 appSrcRoot = appSrcRoot.split(XConstant.FILE_SCHEME)[1]; XFileUtils.walkDirectory(appSrcRoot, this); String md5 = XTransferPolicyUtils.calAppMd5(mMd5Array, mCryptor); mMd5Array.clear(); return md5; } /** * 同步发送md5值未匹配的事件 * * @param app */ private void sendMd5InvalidEvt(XApplication app) { XEvent evt = new XEvent(XEventType.MD5_INVALID, app.getAppId()); mSysCtx.getEventCenter().sendEventSync(evt); } @Override public void visit(String filePath) { // 计算md5值 try { if (filePath.endsWith(".html") || filePath.endsWith(".js") || filePath.endsWith(".htm")) { FileInputStream is = new FileInputStream(new File(filePath)); String md5 = mCryptor.calMD5Value(is); mMd5Array.add(md5); } } catch (FileNotFoundException e) { XLog.e(CLASS_NAME, filePath + " Not Found!"); mMd5Array = null; mIsContinueTraverse = false; } } @Override public boolean isContinueTraverse() { return mIsContinueTraverse; } }