From 959770b23b5c9bfab6e75fe5e22541595a09b9ca Mon Sep 17 00:00:00 2001 From: y-chan Date: Fri, 16 Jun 2023 20:59:52 +0900 Subject: [PATCH] add vvlib manifest validation --- run.py | 4 ++- voicevox_engine/downloadable_library.py | 36 +++++++++++++++++++++++-- voicevox_engine/model.py | 14 ++++++++++ 3 files changed, 51 insertions(+), 3 deletions(-) diff --git a/run.py b/run.py index f15731def..7aed8c8bc 100644 --- a/run.py +++ b/run.py @@ -181,7 +181,9 @@ async def block_origin_middleware(request: Request, call_next): engine_manifest_loader = EngineManifestLoader( root_dir / "engine_manifest.json", root_dir ) - library_manager = LibraryManager(get_save_dir() / "installed_libraries") + library_manager = LibraryManager( + get_save_dir() / "installed_libraries", engine_manifest_loader.load_manifest() + ) metas_store = MetasStore(root_dir / "speaker_info") diff --git a/voicevox_engine/downloadable_library.py b/voicevox_engine/downloadable_library.py index 74c255f69..ef4a3283e 100644 --- a/voicevox_engine/downloadable_library.py +++ b/voicevox_engine/downloadable_library.py @@ -6,8 +6,11 @@ from typing import Dict from fastapi import HTTPException +from pydantic import ValidationError +from semver.version import Version -from voicevox_engine.model import DownloadableLibrary, InstalledLibrary +from voicevox_engine.engine_manifest import EngineManifest +from voicevox_engine.model import DownloadableLibrary, InstalledLibrary, VvlibManifest __all__ = ["LibraryManager"] @@ -15,9 +18,10 @@ class LibraryManager: - def __init__(self, library_root_dir: Path): + def __init__(self, library_root_dir: Path, engine_manifest: EngineManifest): self.library_root_dir = library_root_dir self.library_root_dir.mkdir(exist_ok=True) + self.supported_vvlib_version = engine_manifest.supported_vvlib_manifest_version def downloadable_libraries(self): # == ダウンロード情報をネットワーク上から取得する場合 @@ -84,5 +88,33 @@ def install_library(self, library_id: str, file: BytesIO): if zf.testzip() is not None: raise HTTPException(status_code=422, detail="不正なZIPファイルです。") + # validate manifest version + vvlib_manifest = None + try: + vvlib_manifest = json.loads( + zf.read("vvlib_manifest.json").decode("utf-8") + ) + except KeyError: + raise HTTPException( + status_code=422, detail="指定された音声ライブラリにvvlib_manifest.jsonが存在しません。" + ) + except: + raise HTTPException( + status_code=422, detail="指定された音声ライブラリのvvlib_manifest.jsonは不正です。" + ) + + try: + VvlibManifest.validate(vvlib_manifest) + except ValidationError: + raise HTTPException( + status_code=422, + detail="指定された音声ライブラリのvvlib_manifest.jsonに不正なデータが含まれています。", + ) + + if Version.parse(vvlib_manifest["manifest_version"]) > Version.parse( + self.supported_vvlib_version + ): + raise HTTPException(status_code=422, detail="指定された音声ライブラリは未対応です。") + zf.extractall(library_dir) return library_dir diff --git a/voicevox_engine/model.py b/voicevox_engine/model.py index 9799b2ee6..2dfb245af 100644 --- a/voicevox_engine/model.py +++ b/voicevox_engine/model.py @@ -287,3 +287,17 @@ class SupportedFeaturesInfo(BaseModel): support_adjusting_silence_scale: bool = Field(title="前後の無音時間が調節可能かどうか") support_interrogative_upspeak: bool = Field(title="疑似疑問文に対応しているかどうか") support_switching_device: bool = Field(title="CPU/GPUの切り替えが可能かどうか") + + +class VvlibManifest(BaseModel): + """ + vvlib(VOICEVOX Library)に関する情報 + """ + + manifest_version: str = Field(title="マニフェストバージョン") + name: str = Field(title="音声ライブラリ名") + version: str = Field(title="音声ライブラリバージョン") + uuid: str = Field(title="音声ライブラリのUUID") + brand_name: str = Field(title="エンジンのブランド名") + engine_name: str = Field(title="エンジン名") + engine_uuid: str = Field(title="エンジンのUUID")