Compare commits
30 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
67cba29a8f
|
|||
| 2e5fc75fee | |||
|
|
f58c6c3880 | ||
|
|
2b52a367f2 | ||
| 36e6801f29 | |||
| 2cd7d69aa5 | |||
| 1aaaab10dc | |||
| e04415db9b | |||
| 911beb25bc | |||
| 0a6ac353ff | |||
| f89ea7eab6 | |||
|
6eb3649753
|
|||
|
8a13d0fe07
|
|||
|
321e5f342e
|
|||
|
dbdb73c120
|
|||
|
7ad6f27b75
|
|||
|
dd8b2d6fec
|
|||
|
981913d729
|
|||
| 5fbfc2db81 | |||
| e5cd9bddde | |||
| 068b1a6512 | |||
| 265fe6765d | |||
| 5c970f4a09 | |||
|
53b0d99431
|
|||
|
37acbf07a7
|
|||
|
d47d29426e
|
|||
|
602c6ed43a
|
|||
|
d8a0944810
|
|||
|
aa7ae6128d
|
|||
|
|
ae08d4475c |
44
.github/ISSUE_TEMPLATE/bug_report.md
vendored
44
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -1,31 +1,35 @@
|
|||||||
---
|
---
|
||||||
name: Bug report
|
name: "[请按照此模板填写] 报告 Bug"
|
||||||
about: Create a bug report to help us improve
|
about: "创建一个 Bug 报告,不按照模板的 Issue 会被关闭。"
|
||||||
title: "[Bug] Summarize the bug here"
|
title: "[Bug] 总结你的 Bug 报告"
|
||||||
labels: bug
|
labels: bug
|
||||||
assignees: taurusxin
|
assignees: taurusxin
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**Describe the bug**
|
**Bug 描述**
|
||||||
A clear and concise description of what the bug is.
|
清晰地描述一下 Bug 的大致问题。
|
||||||
|
|
||||||
**To Reproduce**
|
**复现方法**
|
||||||
Steps to reproduce the behavior:
|
|
||||||
1. Go to '...'
|
|
||||||
2. Click on '....'
|
|
||||||
3. Scroll down to '....'
|
|
||||||
4. See error
|
|
||||||
|
|
||||||
**Expected behavior**
|
复现此 Bug 的方法
|
||||||
A clear and concise description of what you expected to happen.
|
|
||||||
|
|
||||||
**Screenshots**
|
1. 打开 '...'
|
||||||
If applicable, add screenshots to help explain your problem.
|
2. 点击 '....'
|
||||||
|
3. 发生报错
|
||||||
|
|
||||||
**Desktop (please complete the following information):**
|
**预期行为**
|
||||||
- OS: [e.g. Windows 11]
|
|
||||||
|
|
||||||
|
解释一下原本应该出现的结果。
|
||||||
|
|
||||||
**Additional context**
|
**屏幕截图**
|
||||||
Add any other context about the problem here.
|
|
||||||
|
如果可以,屏幕截图可以更好地阐述你的问题。
|
||||||
|
|
||||||
|
**环境**
|
||||||
|
|
||||||
|
- OS: [e.g. Windows 11]
|
||||||
|
- 软件版本: [e.g. 1.3.2]
|
||||||
|
|
||||||
|
**附加内容**
|
||||||
|
|
||||||
|
添加更多其他内容以帮助开发者更好地了解这个 Bug。
|
||||||
|
|||||||
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@@ -1,20 +0,0 @@
|
|||||||
---
|
|
||||||
name: Feature request
|
|
||||||
about: Suggest an idea for this project
|
|
||||||
title: "[Feature] Summarize new feature here"
|
|
||||||
labels: ''
|
|
||||||
assignees: ''
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Is your feature request related to a problem? Please describe.**
|
|
||||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
|
||||||
|
|
||||||
**Describe the solution you'd like**
|
|
||||||
A clear and concise description of what you want to happen.
|
|
||||||
|
|
||||||
**Describe alternatives you've considered**
|
|
||||||
A clear and concise description of any alternative solutions or features you've considered.
|
|
||||||
|
|
||||||
**Additional context**
|
|
||||||
Add any other context or screenshots about the feature request here.
|
|
||||||
8
.github/workflows/autobuild.yml
vendored
8
.github/workflows/autobuild.yml
vendored
@@ -53,11 +53,17 @@ jobs:
|
|||||||
- name: Build
|
- name: Build
|
||||||
run: cmake --build ${{ env.BUILD_PATH }} -j 4 --config ${{ env.BUILD_TYPE }}
|
run: cmake --build ${{ env.BUILD_PATH }} -j 4 --config ${{ env.BUILD_TYPE }}
|
||||||
|
|
||||||
- name: Upload artifact
|
- name: Upload artifact executable
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: Windows amd64 Build - MSVC
|
name: Windows amd64 Build - MSVC
|
||||||
path: ${{ env.BUILD_PATH }}/${{ env.BUILD_TYPE }}/ncmdump.exe
|
path: ${{ env.BUILD_PATH }}/${{ env.BUILD_TYPE }}/ncmdump.exe
|
||||||
|
|
||||||
|
- name: Upload artifact DLL
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: Windows amd64 Build - MSVC DLL
|
||||||
|
path: ${{ env.BUILD_PATH }}/${{ env.BUILD_TYPE }}/libncmdump.dll
|
||||||
|
|
||||||
build_on_linux:
|
build_on_linux:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|||||||
@@ -14,34 +14,73 @@ if(MSVC)
|
|||||||
add_compile_options("$<$<CXX_COMPILER_ID:MSVC>:/execution-charset:utf-8>")
|
add_compile_options("$<$<CXX_COMPILER_ID:MSVC>:/execution-charset:utf-8>")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
FILE(GLOB HEADERS ./*.h)
|
FILE(GLOB COMMON_HEADERS src/include/*.h)
|
||||||
FILE(GLOB COMMON_SOURCES cJSON.cpp aes.cpp main.cpp ncmcrypt.cpp)
|
FILE(GLOB COMMON_SOURCES src/ncmcrypt.cpp src/utils/*.cpp)
|
||||||
FILE(GLOB WIN_SOURCES win32_init.cpp)
|
FILE(GLOB EXECUTABLE_SOURCES src/main.cpp)
|
||||||
|
FILE(GLOB LIBRARY_HEADERS src/lib/libncmdump.h)
|
||||||
|
FILE(GLOB LIBRARY_SOURCES src/lib/*.cpp)
|
||||||
|
FILE(GLOB WIN_SOURCES src/platform/win32_init.cpp)
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
set(SOURCES ${COMMON_SOURCES} ${WIN_SOURCES})
|
add_executable(ncmdump_exec
|
||||||
else()
|
${COMMON_HEADERS}
|
||||||
set(SOURCES ${COMMON_SOURCES})
|
${COMMON_SOURCES}
|
||||||
endif()
|
${EXECUTABLE_SOURCES}
|
||||||
add_executable(ncmdump
|
${WIN_SOURCES}
|
||||||
${HEADERS}
|
)
|
||||||
${SOURCES}
|
add_library(ncmdump_lib SHARED
|
||||||
)
|
${COMMON_HEADERS}
|
||||||
target_link_libraries(ncmdump tag)
|
${COMMON_SOURCES}
|
||||||
target_include_directories(ncmdump PRIVATE taglib)
|
${LIBRARY_HEADERS}
|
||||||
target_include_directories(ncmdump PRIVATE taglib/taglib)
|
${LIBRARY_SOURCES}
|
||||||
target_include_directories(ncmdump PRIVATE taglib/taglib/toolkit)
|
${WIN_SOURCES}
|
||||||
target_include_directories(ncmdump PRIVATE taglib/taglib/mpeg/id3v2)
|
)
|
||||||
|
|
||||||
|
set_target_properties(ncmdump_lib PROPERTIES OUTPUT_NAME "libncmdump")
|
||||||
|
|
||||||
|
target_include_directories(ncmdump_lib PRIVATE src/include)
|
||||||
|
|
||||||
|
target_link_libraries(ncmdump_lib tag)
|
||||||
|
target_include_directories(ncmdump_lib PRIVATE taglib)
|
||||||
|
target_include_directories(ncmdump_lib PRIVATE taglib/taglib)
|
||||||
|
target_include_directories(ncmdump_lib PRIVATE taglib/taglib/toolkit)
|
||||||
|
target_include_directories(ncmdump_lib PRIVATE taglib/taglib/mpeg/id3v2)
|
||||||
|
|
||||||
if(WIN32)
|
|
||||||
if(CMAKE_COMPILER_IS_GNUCXX)
|
if(CMAKE_COMPILER_IS_GNUCXX)
|
||||||
target_link_options(ncmdump PRIVATE -static)
|
# static link when using MinGW
|
||||||
|
target_link_options(ncmdump_exec PRIVATE -static)
|
||||||
|
target_link_options(ncmdump_lib PRIVATE -static)
|
||||||
endif()
|
endif()
|
||||||
|
else()
|
||||||
|
add_executable(ncmdump_exec
|
||||||
|
${COMMON_HEADERS}
|
||||||
|
${COMMON_SOURCES}
|
||||||
|
${EXECUTABLE_SOURCES}
|
||||||
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# all executable target
|
||||||
|
set_target_properties(ncmdump_exec PROPERTIES OUTPUT_NAME "ncmdump")
|
||||||
|
target_include_directories(ncmdump_exec PRIVATE src/include)
|
||||||
|
|
||||||
|
target_link_libraries(ncmdump_exec tag)
|
||||||
|
target_include_directories(ncmdump_exec PRIVATE taglib)
|
||||||
|
target_include_directories(ncmdump_exec PRIVATE taglib/taglib)
|
||||||
|
target_include_directories(ncmdump_exec PRIVATE taglib/taglib/toolkit)
|
||||||
|
target_include_directories(ncmdump_exec PRIVATE taglib/taglib/mpeg/id3v2)
|
||||||
|
|
||||||
include(GNUInstallDirs)
|
include(GNUInstallDirs)
|
||||||
install(TARGETS ncmdump
|
|
||||||
BUNDLE DESTINATION .
|
if(WIN32)
|
||||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
install(TARGETS ncmdump_exec ncmdump_lib
|
||||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
BUNDLE DESTINATION .
|
||||||
)
|
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||||
|
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||||
|
)
|
||||||
|
else()
|
||||||
|
install(TARGETS ncmdump_exec
|
||||||
|
BUNDLE DESTINATION .
|
||||||
|
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||||
|
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|||||||
21
README.md
21
README.md
@@ -6,8 +6,9 @@
|
|||||||
|
|
||||||
该版本为最早的 C++ 版本,也是作者开发的市面上第一个支持 ncm 转换的程序
|
该版本为最早的 C++ 版本,也是作者开发的市面上第一个支持 ncm 转换的程序
|
||||||
|
|
||||||
源码复刻自 anonymous5l/ncmdump,感谢前辈的付出!
|
源码复刻自 anonymous5l/ncmdump,感谢前辈的付出!做了 Windows 下的移植,修复了一些编译问题
|
||||||
做了 Windows 下的移植,修复了一些编译问题
|
|
||||||
|
1.3.0 版本更新说明:因为之前有小伙伴反馈无法解密带有特殊字符的文件名,例如中文、日文、韩文或者是表情符号等,在1.3.0以及之后的版本彻底修复了这个问题,所有的 UTF-8 字符都可以正常解密。并且还自带了 dll 的构建,可以供其他应用程序(C#、Python、Java等)调用。
|
||||||
|
|
||||||
## 传送门
|
## 传送门
|
||||||
|
|
||||||
@@ -15,7 +16,9 @@
|
|||||||
|
|
||||||
## 使用
|
## 使用
|
||||||
|
|
||||||
你可以使用 Homebrew 来安装 ncmdump
|
### 命令行工具
|
||||||
|
|
||||||
|
你可以使用 Homebrew 来安装 ncmdump 的 cli 版本
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
brew install ncmdump
|
brew install ncmdump
|
||||||
@@ -41,6 +44,12 @@ ncmdump file1 file2...
|
|||||||
ncmdump -d folder
|
ncmdump -d folder
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### 动态库
|
||||||
|
|
||||||
|
或者,如果你想利用此项目进行二次开发,例如在你的 C#、Python、Java 等项目中调用,你可以使用 `libncmdump` 动态库,具体使用方法见仓库的 `example` 文件夹
|
||||||
|
|
||||||
|
请注意!如果你在 Windows 下开发,传递到库构造函数的文件名编码**必须为 UTF-8 编码**,否则会抛出运行时错误。
|
||||||
|
|
||||||
## 编译项目
|
## 编译项目
|
||||||
|
|
||||||
克隆本仓库
|
克隆本仓库
|
||||||
@@ -78,3 +87,9 @@ cmake --build build -j 8 --config Release
|
|||||||
# Windows MinGW / Linux / macOS
|
# Windows MinGW / Linux / macOS
|
||||||
cmake --build build -j 8
|
cmake --build build -j 8
|
||||||
```
|
```
|
||||||
|
|
||||||
|
你可以在 `build` 文件夹下找到编译好的二进制文件,以及一个可供其它项目使用的动态库(Windows Only),使用方法见仓库的 `example` 文件夹
|
||||||
|
|
||||||
|
## Star History
|
||||||
|
|
||||||
|
[](https://star-history.com/#taurusxin/ncmdump&Date)
|
||||||
|
|||||||
67
example/csharp/NeteaseCrypt.cs
Normal file
67
example/csharp/NeteaseCrypt.cs
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace libncmdump_demo_cli
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// NeteaseCrypt C# Wrapper
|
||||||
|
/// </summary>
|
||||||
|
class NeteaseCrypt
|
||||||
|
{
|
||||||
|
const string DLL_PATH = "libncmdump.dll";
|
||||||
|
|
||||||
|
[DllImport(DLL_PATH, CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
private static extern IntPtr CreateNeteaseCrypt(IntPtr path);
|
||||||
|
|
||||||
|
[DllImport(DLL_PATH, CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
private static extern int Dump(IntPtr NeteaseCrypt);
|
||||||
|
|
||||||
|
[DllImport(DLL_PATH, CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
private static extern void FixMetadata(IntPtr NeteaseCrypt);
|
||||||
|
|
||||||
|
[DllImport(DLL_PATH, CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
private static extern void DestroyNeteaseCrypt(IntPtr NeteaseCrypt);
|
||||||
|
|
||||||
|
private IntPtr NeteaseCryptClass = IntPtr.Zero;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 创建 NeteaseCrypt 类的实例。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="FileName">网易云音乐 ncm 加密文件路径</param>
|
||||||
|
public NeteaseCrypt(string FileName)
|
||||||
|
{
|
||||||
|
byte[] bytes = Encoding.UTF8.GetBytes(FileName);
|
||||||
|
|
||||||
|
IntPtr inputPtr = Marshal.AllocHGlobal(bytes.Length + 1);
|
||||||
|
Marshal.Copy(bytes, 0, inputPtr, bytes.Length);
|
||||||
|
Marshal.WriteByte(inputPtr, bytes.Length, 0);
|
||||||
|
|
||||||
|
NeteaseCryptClass = CreateNeteaseCrypt(inputPtr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 启动转换过程。
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>返回一个整数,指示转储过程的结果。如果成功,返回0;如果失败,返回1。</returns>
|
||||||
|
public int Dump()
|
||||||
|
{
|
||||||
|
return Dump(NeteaseCryptClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 修复音乐文件元数据。
|
||||||
|
/// </summary>
|
||||||
|
public void FixMetadata()
|
||||||
|
{
|
||||||
|
FixMetadata(NeteaseCryptClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 销毁 NeteaseCrypt 类的实例。
|
||||||
|
/// </summary>
|
||||||
|
public void Destroy()
|
||||||
|
{
|
||||||
|
DestroyNeteaseCrypt(NeteaseCryptClass);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
26
example/csharp/Program.cs
Normal file
26
example/csharp/Program.cs
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace libncmdump_demo_cli
|
||||||
|
{
|
||||||
|
internal class Program
|
||||||
|
{
|
||||||
|
static void Main(string[] args)
|
||||||
|
{
|
||||||
|
// 文件名
|
||||||
|
string filePath = "test.ncm";
|
||||||
|
|
||||||
|
// 创建 NeteaseCrypt 类的实例
|
||||||
|
NeteaseCrypt neteaseCrypt = new NeteaseCrypt(filePath);
|
||||||
|
|
||||||
|
// 启动转换过程
|
||||||
|
int result = neteaseCrypt.Dump();
|
||||||
|
|
||||||
|
// 修复元数据
|
||||||
|
neteaseCrypt.FixMetadata();
|
||||||
|
|
||||||
|
// [务必]销毁 NeteaseCrypt 类的实例
|
||||||
|
neteaseCrypt.Destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
31
src/lib/libncmdump.cpp
Normal file
31
src/lib/libncmdump.cpp
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
#include "libncmdump.h"
|
||||||
|
#include <filesystem>
|
||||||
|
|
||||||
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
API NeteaseCrypt* CreateNeteaseCrypt(const char* path) {
|
||||||
|
fs::path fPath = fs::u8path(path);
|
||||||
|
return new NeteaseCrypt(fPath.u8string());
|
||||||
|
}
|
||||||
|
|
||||||
|
API int Dump(NeteaseCrypt* neteaseCrypt) {
|
||||||
|
try
|
||||||
|
{
|
||||||
|
neteaseCrypt->Dump();
|
||||||
|
}
|
||||||
|
catch (const std::invalid_argument& e)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
API void FixMetadata(NeteaseCrypt* neteaseCrypt) {
|
||||||
|
neteaseCrypt->FixMetadata();
|
||||||
|
}
|
||||||
|
|
||||||
|
API void DestroyNeteaseCrypt(NeteaseCrypt* neteaseCrypt) {
|
||||||
|
delete neteaseCrypt;
|
||||||
|
}
|
||||||
|
}
|
||||||
14
src/lib/libncmdump.h
Normal file
14
src/lib/libncmdump.h
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
#include "ncmcrypt.h"
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#define API __declspec(dllexport)
|
||||||
|
#else
|
||||||
|
#define API
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
API NeteaseCrypt* CreateNeteaseCrypt(const char* path);
|
||||||
|
API int Dump(NeteaseCrypt* neteaseCrypt);
|
||||||
|
API void FixMetadata(NeteaseCrypt* neteaseCrypt);
|
||||||
|
API void DestroyNeteaseCrypt(NeteaseCrypt* neteaseCrypt);
|
||||||
|
}
|
||||||
@@ -35,7 +35,7 @@ void processFile(const fs::path &filePath)
|
|||||||
crypt.Dump();
|
crypt.Dump();
|
||||||
crypt.FixMetadata();
|
crypt.FixMetadata();
|
||||||
|
|
||||||
std::cout << BOLDGREEN << "Done: " << RESET << "'" << crypt.dumpFilepath().u8string() << "'" << std::endl;
|
std::cout << BOLDGREEN << "[Done] " << RESET << "'" << filePath.u8string() << "' -> '" << crypt.dumpFilepath().u8string() << "'" << std::endl;
|
||||||
}
|
}
|
||||||
catch (const std::invalid_argument &e)
|
catch (const std::invalid_argument &e)
|
||||||
{
|
{
|
||||||
@@ -77,7 +77,7 @@ int main(int argc, char **argv)
|
|||||||
#define COMPARE_STR(s1, s2) (strcmp(s1, s2) == 0)
|
#define COMPARE_STR(s1, s2) (strcmp(s1, s2) == 0)
|
||||||
#define HELP_SHORT "-h"
|
#define HELP_SHORT "-h"
|
||||||
#define HELP_LONG "--help"
|
#define HELP_LONG "--help"
|
||||||
#define FOLDER "-d"
|
#define PROCESS_FOLDER "-d"
|
||||||
for (int i = 1; i < argc; ++i)
|
for (int i = 1; i < argc; ++i)
|
||||||
{
|
{
|
||||||
if (COMPARE_STR(argv[i], HELP_SHORT) || COMPARE_STR(argv[i], HELP_LONG))
|
if (COMPARE_STR(argv[i], HELP_SHORT) || COMPARE_STR(argv[i], HELP_LONG))
|
||||||
@@ -85,13 +85,13 @@ int main(int argc, char **argv)
|
|||||||
displayHelp();
|
displayHelp();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else if (COMPARE_STR(argv[i], FOLDER))
|
else if (COMPARE_STR(argv[i], PROCESS_FOLDER))
|
||||||
{
|
{
|
||||||
processFolders = true;
|
processFolders = true;
|
||||||
if (i + 1 < argc && argv[i + 1][0] != '-')
|
if (i + 1 < argc && argv[i + 1][0] != '-')
|
||||||
{
|
{
|
||||||
folderProvided = true;
|
folderProvided = true;
|
||||||
processFilesInFolder(argv[i + 1]);
|
processFilesInFolder(fs::u8path(argv[i + 1]));
|
||||||
// Skip the folder name
|
// Skip the folder name
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
#include "aes.h"
|
#include "aes.h"
|
||||||
#include "base64.h"
|
#include "base64.h"
|
||||||
#include "cJSON.h"
|
#include "cJSON.h"
|
||||||
|
#include "color.h"
|
||||||
|
|
||||||
#define TAGLIB_STATIC
|
#define TAGLIB_STATIC
|
||||||
#include "taglib/toolkit/tfile.h"
|
#include "taglib/toolkit/tfile.h"
|
||||||
@@ -94,12 +95,18 @@ NeteaseMusicMetadata::NeteaseMusicMetadata(cJSON *raw)
|
|||||||
artistLen = cJSON_GetArraySize(swap);
|
artistLen = cJSON_GetArraySize(swap);
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
for (i = 0; i < artistLen - 1; i++)
|
for (i = 0; i < artistLen; i++)
|
||||||
{
|
{
|
||||||
mArtist += std::string(cJSON_GetStringValue(cJSON_GetArrayItem(cJSON_GetArrayItem(swap, i), 0)));
|
auto artist = cJSON_GetArrayItem(swap, i);
|
||||||
mArtist += "/";
|
if (cJSON_GetArraySize(artist) > 0)
|
||||||
|
{
|
||||||
|
if (!mArtist.empty())
|
||||||
|
{
|
||||||
|
mArtist += "/";
|
||||||
|
}
|
||||||
|
mArtist += std::string(cJSON_GetStringValue(cJSON_GetArrayItem(artist, 0)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
mArtist += std::string(cJSON_GetStringValue(cJSON_GetArrayItem(cJSON_GetArrayItem(swap, i), 0)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
swap = cJSON_GetObjectItem(raw, "bitrate");
|
swap = cJSON_GetObjectItem(raw, "bitrate");
|
||||||
@@ -247,9 +254,10 @@ void NeteaseCrypt::FixMetadata()
|
|||||||
tag->setAlbum(TagLib::String(mMetaData->album(), TagLib::String::UTF8));
|
tag->setAlbum(TagLib::String(mMetaData->album(), TagLib::String::UTF8));
|
||||||
}
|
}
|
||||||
|
|
||||||
tag->setComment(TagLib::String("Create by netease copyright protected dump tool. author 5L", TagLib::String::UTF8));
|
tag->setComment(TagLib::String("Create by taurusxin/ncmdump.", TagLib::String::UTF8));
|
||||||
|
|
||||||
audioFile->save();
|
audioFile->save();
|
||||||
|
audioFile->~File();
|
||||||
}
|
}
|
||||||
|
|
||||||
void NeteaseCrypt::Dump()
|
void NeteaseCrypt::Dump()
|
||||||
@@ -351,7 +359,7 @@ NeteaseCrypt::NeteaseCrypt(std::string const &path)
|
|||||||
|
|
||||||
if (n <= 0)
|
if (n <= 0)
|
||||||
{
|
{
|
||||||
std::cout << "[Warn] " << path << " missing metadata infomation can't fix some infomation!" << std::endl;
|
std::cout << BOLDYELLOW << "[Warn] " << RESET << "'" << path << "' missing metadata infomation can't fix some infomation!" << std::endl;
|
||||||
|
|
||||||
mMetaData = NULL;
|
mMetaData = NULL;
|
||||||
}
|
}
|
||||||
@@ -384,23 +392,24 @@ NeteaseCrypt::NeteaseCrypt(std::string const &path)
|
|||||||
mMetaData = new NeteaseMusicMetadata(cJSON_Parse(modifyDecryptData.c_str()));
|
mMetaData = new NeteaseMusicMetadata(cJSON_Parse(modifyDecryptData.c_str()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// skip crc32 & unuse charset
|
// skip crc32 & image version
|
||||||
if (!mFile.seekg(9, mFile.cur))
|
if (!mFile.seekg(5, mFile.cur))
|
||||||
{
|
{
|
||||||
throw std::invalid_argument("can't seek file");
|
throw std::invalid_argument("can't seek file");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t cover_frame_len{0};
|
||||||
|
read(reinterpret_cast<char *>(&cover_frame_len), 4);
|
||||||
read(reinterpret_cast<char *>(&n), sizeof(n));
|
read(reinterpret_cast<char *>(&n), sizeof(n));
|
||||||
|
|
||||||
if (n > 0)
|
if (n > 0)
|
||||||
{
|
{
|
||||||
char *imageData = (char *)malloc(n);
|
mImageData = std::string(n, '\0');
|
||||||
read(imageData, n);
|
read(&mImageData[0], n);
|
||||||
|
|
||||||
mImageData = std::string(imageData, n);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::cout << "[Warn] " << path << " missing album can't fix album image!" << std::endl;
|
std::cout << BOLDYELLOW << "[Warn] " << RESET << "'" << path << "' missing album can't fix album image!" << std::endl;
|
||||||
}
|
}
|
||||||
|
mFile.seekg(cover_frame_len - n, mFile.cur);
|
||||||
}
|
}
|
||||||
BIN
test/expect.bin
BIN
test/expect.bin
Binary file not shown.
Reference in New Issue
Block a user