diff --git a/src/main/java/net/geedge/asw/common/util/Constants.java b/src/main/java/net/geedge/asw/common/util/Constants.java index f81bab1..2fe4f98 100644 --- a/src/main/java/net/geedge/asw/common/util/Constants.java +++ b/src/main/java/net/geedge/asw/common/util/Constants.java @@ -104,7 +104,10 @@ public class Constants { public static final Map ENV_TERMINAL_WEBSOCKET_SESSION = T.MapUtil.newHashMap(); - + /** + * Android package type + */ + public static final List ANDROID_PACKAGE_TYPE_LIST = T.ListUtil.of("xapk", "apk"); public static final String EMPTY_FILE_MD5 = "d41d8cd98f00b204e9800998ecf8427e"; } diff --git a/src/main/java/net/geedge/asw/common/util/RCode.java b/src/main/java/net/geedge/asw/common/util/RCode.java index a93bcac..6b717f2 100644 --- a/src/main/java/net/geedge/asw/common/util/RCode.java +++ b/src/main/java/net/geedge/asw/common/util/RCode.java @@ -55,6 +55,7 @@ public enum RCode { // Package PACKAGE_ID_CANNOT_EMPTY(202001, "package id cannot be empty"), PACKAGE_DESCRIPTION_CANNOT_EMPTY(202002, "package description cannot be empty"), + PACKAGE_FILE_TYPE_ERROR(202003, "package invalid file"), // Runner diff --git a/src/main/java/net/geedge/asw/module/app/service/impl/PackageServiceImpl.java b/src/main/java/net/geedge/asw/module/app/service/impl/PackageServiceImpl.java index d4a0ea5..3f4f2a2 100644 --- a/src/main/java/net/geedge/asw/module/app/service/impl/PackageServiceImpl.java +++ b/src/main/java/net/geedge/asw/module/app/service/impl/PackageServiceImpl.java @@ -1,9 +1,12 @@ package net.geedge.asw.module.app.service.impl; import cn.dev33.satoken.stp.StpUtil; +import cn.hutool.core.io.FileUtil; import cn.hutool.log.Log; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import net.geedge.asw.common.util.ASWException; +import net.geedge.asw.common.util.Constants; import net.geedge.asw.common.util.RCode; import net.geedge.asw.common.util.T; import net.geedge.asw.module.app.dao.PackageDao; @@ -22,10 +25,14 @@ import org.springframework.core.io.Resource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.io.BufferedReader; import java.io.File; -import java.nio.file.Path; +import java.io.InputStream; +import java.io.InputStreamReader; import java.util.List; import java.util.Map; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; @Service public class PackageServiceImpl extends ServiceImpl implements IPackageService { @@ -64,48 +71,72 @@ public class PackageServiceImpl extends ServiceImpl i } @Override + @Transactional(rollbackFor = Exception.class) public PackageEntity savePackage(String workspaceId, String description, Resource fileResource) { + + String pkgId = T.StrUtil.uuid(); + String filename = fileResource.getFilename(); + String suffix = T.FileUtil.extName(filename); + suffix = T.StrUtil.emptyToDefault(suffix, "apk"); + if (!Constants.ANDROID_PACKAGE_TYPE_LIST.contains(suffix)) { + throw new ASWException(RCode.PACKAGE_FILE_TYPE_ERROR); + } + String saveFileName = pkgId + "." + suffix; + File destination = T.FileUtil.file(PkgConstant.APK_FILES_DIR, saveFileName); PackageEntity entity = new PackageEntity(); + ApkUtil apkUtil = new ApkUtil(); + //apkUtil.setAaptToolPath(Path.of(T.WebPathUtil.getRootPath(), "lib", "aapt").toString()); + apkUtil.setAaptToolPath("D:\\Desktop\\asw\\aapt.exe"); try { - String pkgId = T.StrUtil.uuid(); - entity.setId(pkgId); - entity.setName(fileResource.getFilename()); - entity.setDescription(T.StrUtil.emptyToDefault(description, "")); - - // 默认安卓 - entity.setPlatform(PkgConstant.Platform.ANDROID.getValue()); - - entity.setWorkspaceId(workspaceId); - entity.setCreateUserId(StpUtil.getLoginIdAsString()); - entity.setUpdateUserId(StpUtil.getLoginIdAsString()); - entity.setCreateTimestamp(System.currentTimeMillis()); - entity.setUpdateTimestamp(System.currentTimeMillis()); - - byte[] bytes = fileResource.getInputStream().readAllBytes(); - entity.setSize((long) bytes.length); - - // path - String fileExtName = T.StrUtil.emptyToDefault(T.FileUtil.extName(fileResource.getFilename()), "pcap"); - String saveFileName = pkgId + "." + fileExtName; - File destination = T.FileUtil.file(PkgConstant.APK_FILES_DIR, saveFileName); FileUtils.copyInputStreamToFile(fileResource.getInputStream(), destination); - entity.setPath(destination.getPath()); - - // parse - try { - ApkUtil apkUtil = new ApkUtil(); - apkUtil.setAaptToolPath(Path.of(T.WebPathUtil.getRootPath(), "lib", "aapt").toString()); - ApkInfo apkInfo = apkUtil.parseApk(entity.getPath()); + if (suffix.equals("apk")) { + // parse + ApkInfo apkInfo = apkUtil.parseApk(destination.getPath()); + if (T.ObjectUtil.isNull(apkInfo)) { + throw new ASWException(RCode.PACKAGE_FILE_TYPE_ERROR); + } entity.setVersion(apkInfo.getVersionName()); entity.setIdentifier(apkInfo.getPackageName()); - } catch (Exception e) { - log.error(e, "[savePackage] [parse error] [file: {}]", fileResource.getFilename()); + } else { + ZipFile zipFile = new ZipFile(destination); + ZipEntry entry = zipFile.getEntry("manifest.json"); + InputStream inputStream = zipFile.getInputStream(entry); + StringBuilder manifestJson = new StringBuilder(); + BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); + String line; + while ((line = reader.readLine()) != null) { + manifestJson.append(line).append("\n"); + } + Map manifest = T.JSONUtil.toBean(manifestJson.toString(), Map.class); + ZipEntry packageFile = zipFile.getEntry(T.StrUtil.concat(true,T.MapUtil.getStr(manifest, "package_name"),".apk")); + File temp = T.FileUtil.file(Constants.TEMP_PATH, packageFile.getName()); + FileUtil.writeBytes(zipFile.getInputStream(packageFile).readAllBytes(), temp); + ApkInfo apkInfo = apkUtil.parseApk(temp.getPath()); + String versionName = apkInfo.getVersionName(); + String packageName = apkInfo.getPackageName(); + if (!T.BooleanUtil.and(versionName.equals(T.MapUtil.getStr(manifest, "version_name")), packageName.equals(T.MapUtil.getStr(manifest, "package_name")))){ + throw new ASWException(RCode.PACKAGE_FILE_TYPE_ERROR); + } + entity.setVersion(versionName); + entity.setIdentifier(packageName); } - - this.save(entity); } catch (Exception e) { - log.error(e, "[savePackage] [error] [file: {}]", fileResource.getFilename()); + log.error(e, "[savePackage] [save package error] [file: {}]", fileResource.getFilename()); + FileUtil.del(destination); + throw new ASWException(RCode.PACKAGE_FILE_TYPE_ERROR); } + entity.setId(pkgId); + entity.setName(fileResource.getFilename()); + entity.setDescription(T.StrUtil.emptyToDefault(description, "")); + entity.setPlatform(PkgConstant.Platform.ANDROID.getValue()); + entity.setWorkspaceId(workspaceId); + entity.setCreateUserId(StpUtil.getLoginIdAsString()); + entity.setUpdateUserId(StpUtil.getLoginIdAsString()); + entity.setCreateTimestamp(System.currentTimeMillis()); + entity.setUpdateTimestamp(System.currentTimeMillis()); + entity.setSize(destination.length()); + entity.setPath(destination.getPath()); + this.save(entity); return entity; } diff --git a/src/main/resources/db/migration/R__AZ_sys_i18n.sql b/src/main/resources/db/migration/R__AZ_sys_i18n.sql index 886415b..28ca0ee 100644 --- a/src/main/resources/db/migration/R__AZ_sys_i18n.sql +++ b/src/main/resources/db/migration/R__AZ_sys_i18n.sql @@ -139,5 +139,8 @@ INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_ INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (231, '302002', 'PLAYBOOK_NAME_DUPLICATE', '剧本名称重复', 'zh', '', 'admin', 1724030366000); INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (232, '601005', 'ENVIRONMENT_ID_CANNOT_EMPTY', 'environment id cannot be empty', 'en', '', 'admin', 1724030366000); INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (233, '601005', 'ENVIRONMENT_ID_CANNOT_EMPTY', '环境 id 不能为空', 'zh', '', 'admin', 1724030366000); +INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (234, '202003', 'PACKAGE_FILE_TYPE_ERROR', 'package invalid file', 'en', '', 'admin', 1724030366000); +INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (235, '202003', 'PACKAGE_FILE_TYPE_ERROR', '无效安装包文件', 'zh', '', 'admin', 1724030366000); + SET FOREIGN_KEY_CHECKS = 1;