forked from sim1222-mirror/wrapper
Compare commits
15 Commits
Author | SHA1 | Date | |
---|---|---|---|
4459548fb3 | |||
6ffd3585b6 | |||
3b3a73bb60 | |||
ca1f26a950 | |||
639f50bf4d | |||
57dd342fd7 | |||
1077660bcc | |||
976118d948 | |||
86d1c1a507 | |||
aa1886e487 | |||
b96afbbd3a | |||
c37d47c2ec | |||
4fdc3aabce | |||
5e687bed4f | |||
cfd4ad5fd1 |
49
.github/workflows/build.yml
vendored
Normal file
49
.github/workflows/build.yml
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
name: Build
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "main" ]
|
||||
pull_request:
|
||||
branches: [ "main" ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install aria2
|
||||
run: sudo apt install aria2 -y
|
||||
|
||||
- name: Install LLVM
|
||||
run: sudo bash -c "$(wget -O - https://apt.llvm.org/llvm.sh)"
|
||||
|
||||
- name: Set up Android NDK r23b
|
||||
run: |
|
||||
aria2c -o android-ndk-r23b-linux.zip https://dl.google.com/android/repository/android-ndk-r23b-linux.zip
|
||||
unzip -q -d ~ android-ndk-r23b-linux.zip
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
make
|
||||
|
||||
- name: Set outputs
|
||||
id: vars
|
||||
run: echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: Wrapper.x86_64.${{ steps.vars.outputs.sha_short }}
|
||||
include-hidden-files: true
|
||||
path: |
|
||||
rootfs
|
||||
wrapper
|
||||
Dockerfile
|
||||
|
||||
|
47
.github/workflows/wrapper-qemu.yml
vendored
Normal file
47
.github/workflows/wrapper-qemu.yml
vendored
Normal file
@ -0,0 +1,47 @@
|
||||
name: wrapper-qemu
|
||||
|
||||
on:
|
||||
workflow_run:
|
||||
workflows: ["Build"]
|
||||
types: [completed]
|
||||
|
||||
jobs:
|
||||
on-success:
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.event.workflow_run.conclusion == 'success' }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Download wrapper-qemu basic image
|
||||
run: wget https://github.com/zhaarey/wrapper/releases/download/wrapper-qemu/wrapper.qcow2
|
||||
|
||||
- name: Mount image
|
||||
run: |
|
||||
sudo apt-get install -y qemu-utils
|
||||
sudo modprobe nbd max_part=8
|
||||
sudo qemu-nbd --connect=/dev/nbd0 wrapper.qcow2
|
||||
sudo mkdir /mnt/wrapper
|
||||
sudo mount /dev/nbd0p3 /mnt/wrapper/
|
||||
|
||||
- name: Download latest artifact
|
||||
uses: dawidd6/action-download-artifact@v6
|
||||
with:
|
||||
github_token: ${{secrets.ACTION_TOKEN}}
|
||||
run_id: ${{ github.event.workflow_run.id }}
|
||||
|
||||
- name: Copy wrapper to image
|
||||
run: |
|
||||
mv Wrapper.x86_64.* wrapper
|
||||
sudo mv wrapper /mnt/wrapper/root/wrapper
|
||||
sudo chmod +x /mnt/wrapper/root/wrapper/wrapper
|
||||
|
||||
- name: Unmount image
|
||||
run: |
|
||||
sudo umount /mnt/wrapper/
|
||||
sudo qemu-nbd --disconnect /dev/nbd0
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: wrapper-qemu
|
||||
path: wrapper.qcow2
|
92
.gitignore
vendored
Normal file
92
.gitignore
vendored
Normal file
@ -0,0 +1,92 @@
|
||||
|
||||
# Prerequisites
|
||||
*.d
|
||||
|
||||
# Object files
|
||||
*.o
|
||||
*.ko
|
||||
*.obj
|
||||
*.elf
|
||||
|
||||
# Linker output
|
||||
*.ilk
|
||||
*.map
|
||||
*.exp
|
||||
|
||||
# Precompiled Headers
|
||||
*.gch
|
||||
*.pch
|
||||
|
||||
# Libraries
|
||||
*.lib
|
||||
*.a
|
||||
*.la
|
||||
*.lo
|
||||
|
||||
# Shared objects (inc. Windows DLLs)
|
||||
*.dll
|
||||
*.so
|
||||
*.so.*
|
||||
*.dylib
|
||||
|
||||
# Executables
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
||||
*.i*86
|
||||
*.x86_64
|
||||
*.hex
|
||||
|
||||
# Debug files
|
||||
*.dSYM/
|
||||
*.su
|
||||
*.idb
|
||||
*.pdb
|
||||
|
||||
# Kernel Module Compile Results
|
||||
*.mod*
|
||||
*.cmd
|
||||
.tmp_versions/
|
||||
modules.order
|
||||
Module.symvers
|
||||
Mkfile.old
|
||||
dkms.conf
|
||||
|
||||
# Prerequisites
|
||||
*.d
|
||||
|
||||
# Compiled Object files
|
||||
*.slo
|
||||
*.lo
|
||||
*.o
|
||||
*.obj
|
||||
|
||||
# Precompiled Headers
|
||||
*.gch
|
||||
*.pch
|
||||
|
||||
# Compiled Dynamic libraries
|
||||
*.so
|
||||
*.dylib
|
||||
*.dll
|
||||
|
||||
# Fortran module files
|
||||
*.mod
|
||||
*.smod
|
||||
|
||||
# Compiled Static libraries
|
||||
*.lai
|
||||
*.la
|
||||
*.a
|
||||
*.lib
|
||||
|
||||
# Executables
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
||||
|
||||
rootfs/
|
||||
.vscode/
|
||||
wrapper
|
||||
rootfs/system/bin/linker64
|
||||
build/
|
58
CMakeLists.txt
Normal file
58
CMakeLists.txt
Normal file
@ -0,0 +1,58 @@
|
||||
cmake_minimum_required(VERSION 3.25)
|
||||
|
||||
project(wrapper)
|
||||
include(ExternalProject)
|
||||
|
||||
set(CMAKE_C_STANDARD 99)
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
|
||||
set(ANDROID_NDK_PATH "$ENV{HOME}/android-ndk-r23b")
|
||||
set(TOOLCHAIN "${ANDROID_NDK_PATH}/toolchains/llvm/prebuilt/linux-x86_64")
|
||||
|
||||
set(CMAKE_C_COMPILER "${TOOLCHAIN}/bin/x86_64-linux-android22-clang")
|
||||
set(CMAKE_CXX_COMPILER "${TOOLCHAIN}/bin/x86_64-linux-android22-clang++")
|
||||
set(C_COMPILER "${TOOLCHAIN}/bin/clang")
|
||||
|
||||
set(CMAKE_C_FLAGS "-Wall -Werror -O3")
|
||||
set(CMAKE_CXX_FLAGS "-Wall -Werror -O3")
|
||||
|
||||
set(CMDLINE_SOURCE cmdline.c)
|
||||
set(HANDLE_SOURCE main.cpp)
|
||||
set(MAIN_SOURCE main.c)
|
||||
set(WRAPPER_SOURCE wrapper.c)
|
||||
|
||||
add_library(cmdline_object OBJECT ${CMDLINE_SOURCE})
|
||||
add_library(handle_object OBJECT ${HANDLE_SOURCE})
|
||||
|
||||
add_executable(main ${MAIN_SOURCE} $<TARGET_OBJECTS:cmdline_object> $<TARGET_OBJECTS:handle_object>)
|
||||
|
||||
set_target_properties(main PROPERTIES
|
||||
COMPILE_DEFINITIONS "MyRelease"
|
||||
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/rootfs/system/bin"
|
||||
)
|
||||
|
||||
find_library(ANDROIDAPPMUSIC_LIB androidappmusic PATHS ${CMAKE_SOURCE_DIR}/rootfs/system/lib64)
|
||||
find_library(STORESERVICESCORE_LIB storeservicescore PATHS ${CMAKE_SOURCE_DIR}/rootfs/system/lib64)
|
||||
find_library(MEDIAPLATFORM_LIB mediaplatform PATHS ${CMAKE_SOURCE_DIR}/rootfs/system/lib64)
|
||||
find_library(CXX_SHARED_LIB c++_shared PATHS ${CMAKE_SOURCE_DIR}/rootfs/system/lib64)
|
||||
|
||||
# Link libraries
|
||||
target_link_libraries(main
|
||||
${CXX_SHARED_LIB}
|
||||
${ANDROIDAPPMUSIC_LIB}
|
||||
${STORESERVICESCORE_LIB}
|
||||
${MEDIAPLATFORM_LIB}
|
||||
)
|
||||
|
||||
link_directories(${CMAKE_SOURCE_DIR}/rootfs/system/lib64)
|
||||
|
||||
ExternalProject_Add(
|
||||
wrapper
|
||||
PREFIX ${CMAKE_BINARY_DIR}
|
||||
SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ${C_COMPILER} -O3 -Wall -o wrapper ${WRAPPER_SOURCE}
|
||||
BUILD_IN_SOURCE 1
|
||||
INSTALL_COMMAND ""
|
||||
DEPENDS main
|
||||
)
|
10
Dockerfile
Normal file
10
Dockerfile
Normal file
@ -0,0 +1,10 @@
|
||||
FROM ubuntu:latest
|
||||
|
||||
WORKDIR /app
|
||||
#COPY --from=builder /app /app
|
||||
COPY . /app
|
||||
ENV args ""
|
||||
|
||||
CMD ["bash", "-c", "./wrapper ${args}"]
|
||||
|
||||
EXPOSE 10020 20020
|
13
Makefile
13
Makefile
@ -1,13 +0,0 @@
|
||||
all: handle.o main wrapper
|
||||
|
||||
handle.o: main.cpp
|
||||
~/android-ndk-r23b/standalone/bin/clang++ -Wall -Werror -nostdlib -c -O3 -o handle.o main.cpp
|
||||
|
||||
main: handle.o test.c
|
||||
~/android-ndk-r23b/standalone/bin/clang -DMyRelease -Wall -Werror -L ./rootfs/system/lib64 -landroidappmusic -lstoreservicescore -lmediaplatform -lc++_shared -O3 -Wall -o rootfs/system/bin/main handle.o test.c
|
||||
|
||||
wrapper: wrapper.c
|
||||
clang -O3 -Wall -o wrapper wrapper.c
|
||||
|
||||
clean:
|
||||
rm handle.o wrapper rootfs/system/bin/main
|
73
README.md
73
README.md
@ -1,2 +1,71 @@
|
||||
# wrapper
|
||||
All files from anonymous, No need for an Android emulator to decrypt alac
|
||||
## Wrapper
|
||||
|
||||
No need for an Android emulator to decrypt ALAC files. All files from anonymous.
|
||||
|
||||
### Recommended Environment
|
||||
#### Only support Linux x86_64 and arm64.
|
||||
For best results, it's recommended to use **Windows Subsystem for Linux (WSL)**.
|
||||
|
||||
# Special thanks
|
||||
- Anonymous, for providing the original version of this project and the legacy Frida decryption method.
|
||||
- chocomint, for providing support for arm64 arch.
|
||||
|
||||
---
|
||||
### Version 2 Docker
|
||||
Available for x86_64 and arm64. Need to download prebuilt version from releases or actions.
|
||||
|
||||
Build image: `docker build --tag wrapper .`
|
||||
|
||||
Login: `docker run -v ./rootfs/data:/app/rootfs/data -p 10020:10020 -e args="-L username:password -F -H 0.0.0.0" wrapper`
|
||||
|
||||
Run: `docker run -v ./rootfs/data:/app/rootfs/data -p 10020:10020 -e args="-H 0.0.0.0" wrapper`
|
||||
|
||||
|
||||
|
||||
### Version 2
|
||||
|
||||
#### Usage:
|
||||
```shell
|
||||
./wrapper [OPTION]...
|
||||
-h, --help Print help and exit
|
||||
-V, --version Print version and exit
|
||||
-H, --host=STRING (default: `127.0.0.1`)
|
||||
-D, --decrypt-port=INT (default: `10020`)
|
||||
-M, --m3u8-port=INT (default: `20020`)
|
||||
-P, --proxy=STRING (default: `''`)
|
||||
-L, --login=STRING ([username]:[password])
|
||||
```
|
||||
#### Installation x86_64:
|
||||
```shell
|
||||
sudo -i
|
||||
wget "https://github.com/zhaarey/wrapper/releases/download/linux.V2/wrapper.x86_64.tar.gz"
|
||||
mkdir wrapper
|
||||
tar -xzf wrapper.x86_64.tar.gz -C wrapper
|
||||
cd wrapper
|
||||
./wrapper
|
||||
```
|
||||
#### Installation arm64:
|
||||
```shell
|
||||
sudo -i
|
||||
wget "https://github.com/zhaarey/wrapper/releases/download/arm64/wrapper.arm64.tar.gz"
|
||||
mkdir wrapper
|
||||
tar -xzf wrapper.arm64.tar.gz -C wrapper
|
||||
cd wrapper
|
||||
./wrapper
|
||||
```
|
||||
|
||||
|
||||
|
||||
---
|
||||
### Version 1
|
||||
#### Usage:
|
||||
`./wrapper [port] ([username] [password])`
|
||||
#### Installation only x86_64:
|
||||
```shell
|
||||
sudo -i
|
||||
wget "https://github.com/zhaarey/wrapper/releases/download/linux/wrapper.linux.x86_64.tar.gz"
|
||||
mkdir wrapper
|
||||
tar -xzf wrapper.linux.x86_64.tar.gz -C wrapper
|
||||
cd wrapper
|
||||
./wrapper
|
||||
```
|
||||
|
639
cmdline.c
Normal file
639
cmdline.c
Normal file
@ -0,0 +1,639 @@
|
||||
/*
|
||||
File autogenerated by gengetopt version 2.23
|
||||
generated with the following command:
|
||||
gengetopt
|
||||
|
||||
The developers of gengetopt consider the fixed text that goes in all
|
||||
gengetopt output files to be in the public domain:
|
||||
we make no copyright claims on it.
|
||||
*/
|
||||
|
||||
/* If we use autoconf. */
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef FIX_UNUSED
|
||||
#define FIX_UNUSED(X) (void) (X) /* avoid warnings for unused params */
|
||||
#endif
|
||||
|
||||
#include <getopt.h>
|
||||
|
||||
#include "cmdline.h"
|
||||
|
||||
const char *gengetopt_args_info_purpose = "";
|
||||
|
||||
const char *gengetopt_args_info_usage = "Usage: wrapper [OPTION]...";
|
||||
|
||||
const char *gengetopt_args_info_versiontext = "";
|
||||
|
||||
const char *gengetopt_args_info_description = "";
|
||||
|
||||
const char *gengetopt_args_info_help[] = {
|
||||
" -h, --help Print help and exit",
|
||||
" -V, --version Print version and exit",
|
||||
" -H, --host=STRING (default=`127.0.0.1')",
|
||||
" -D, --decrypt-port=INT (default=`10020')",
|
||||
" -M, --m3u8-port=INT (default=`20020')",
|
||||
" -P, --proxy=STRING (default=`')",
|
||||
" -L, --login=STRING username:password",
|
||||
" -F, --code-from-file (default=off)",
|
||||
0
|
||||
};
|
||||
|
||||
typedef enum {ARG_NO
|
||||
, ARG_FLAG
|
||||
, ARG_STRING
|
||||
, ARG_INT
|
||||
} cmdline_parser_arg_type;
|
||||
|
||||
static
|
||||
void clear_given (struct gengetopt_args_info *args_info);
|
||||
static
|
||||
void clear_args (struct gengetopt_args_info *args_info);
|
||||
|
||||
static int
|
||||
cmdline_parser_internal (int argc, char **argv, struct gengetopt_args_info *args_info,
|
||||
struct cmdline_parser_params *params, const char *additional_error);
|
||||
|
||||
|
||||
static char *
|
||||
gengetopt_strdup (const char *s);
|
||||
|
||||
static
|
||||
void clear_given (struct gengetopt_args_info *args_info)
|
||||
{
|
||||
args_info->help_given = 0 ;
|
||||
args_info->version_given = 0 ;
|
||||
args_info->host_given = 0 ;
|
||||
args_info->decrypt_port_given = 0 ;
|
||||
args_info->m3u8_port_given = 0 ;
|
||||
args_info->proxy_given = 0 ;
|
||||
args_info->login_given = 0 ;
|
||||
args_info->code_from_file_given = 0 ;
|
||||
}
|
||||
|
||||
static
|
||||
void clear_args (struct gengetopt_args_info *args_info)
|
||||
{
|
||||
FIX_UNUSED (args_info);
|
||||
args_info->host_arg = gengetopt_strdup ("127.0.0.1");
|
||||
args_info->host_orig = NULL;
|
||||
args_info->decrypt_port_arg = 10020;
|
||||
args_info->decrypt_port_orig = NULL;
|
||||
args_info->m3u8_port_arg = 20020;
|
||||
args_info->m3u8_port_orig = NULL;
|
||||
args_info->proxy_arg = gengetopt_strdup ("");
|
||||
args_info->proxy_orig = NULL;
|
||||
args_info->login_arg = NULL;
|
||||
args_info->login_orig = NULL;
|
||||
args_info->code_from_file_flag = 0;
|
||||
|
||||
}
|
||||
|
||||
static
|
||||
void init_args_info(struct gengetopt_args_info *args_info)
|
||||
{
|
||||
|
||||
|
||||
args_info->help_help = gengetopt_args_info_help[0] ;
|
||||
args_info->version_help = gengetopt_args_info_help[1] ;
|
||||
args_info->host_help = gengetopt_args_info_help[2] ;
|
||||
args_info->decrypt_port_help = gengetopt_args_info_help[3] ;
|
||||
args_info->m3u8_port_help = gengetopt_args_info_help[4] ;
|
||||
args_info->proxy_help = gengetopt_args_info_help[5] ;
|
||||
args_info->login_help = gengetopt_args_info_help[6] ;
|
||||
args_info->code_from_file_help = gengetopt_args_info_help[7] ;
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
cmdline_parser_print_version (void)
|
||||
{
|
||||
printf ("%s %s\n",
|
||||
(strlen(CMDLINE_PARSER_PACKAGE_NAME) ? CMDLINE_PARSER_PACKAGE_NAME : CMDLINE_PARSER_PACKAGE),
|
||||
CMDLINE_PARSER_VERSION);
|
||||
|
||||
if (strlen(gengetopt_args_info_versiontext) > 0)
|
||||
printf("\n%s\n", gengetopt_args_info_versiontext);
|
||||
}
|
||||
|
||||
static void print_help_common(void)
|
||||
{
|
||||
size_t len_purpose = strlen(gengetopt_args_info_purpose);
|
||||
size_t len_usage = strlen(gengetopt_args_info_usage);
|
||||
|
||||
if (len_usage > 0) {
|
||||
printf("%s\n", gengetopt_args_info_usage);
|
||||
}
|
||||
if (len_purpose > 0) {
|
||||
printf("%s\n", gengetopt_args_info_purpose);
|
||||
}
|
||||
|
||||
if (len_usage || len_purpose) {
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
if (strlen(gengetopt_args_info_description) > 0) {
|
||||
printf("%s\n\n", gengetopt_args_info_description);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
cmdline_parser_print_help (void)
|
||||
{
|
||||
int i = 0;
|
||||
print_help_common();
|
||||
while (gengetopt_args_info_help[i])
|
||||
printf("%s\n", gengetopt_args_info_help[i++]);
|
||||
}
|
||||
|
||||
void
|
||||
cmdline_parser_init (struct gengetopt_args_info *args_info)
|
||||
{
|
||||
clear_given (args_info);
|
||||
clear_args (args_info);
|
||||
init_args_info (args_info);
|
||||
}
|
||||
|
||||
void
|
||||
cmdline_parser_params_init(struct cmdline_parser_params *params)
|
||||
{
|
||||
if (params)
|
||||
{
|
||||
params->override = 0;
|
||||
params->initialize = 1;
|
||||
params->check_required = 1;
|
||||
params->check_ambiguity = 0;
|
||||
params->print_errors = 1;
|
||||
}
|
||||
}
|
||||
|
||||
struct cmdline_parser_params *
|
||||
cmdline_parser_params_create(void)
|
||||
{
|
||||
struct cmdline_parser_params *params =
|
||||
(struct cmdline_parser_params *)malloc(sizeof(struct cmdline_parser_params));
|
||||
cmdline_parser_params_init(params);
|
||||
return params;
|
||||
}
|
||||
|
||||
static void
|
||||
free_string_field (char **s)
|
||||
{
|
||||
if (*s)
|
||||
{
|
||||
free (*s);
|
||||
*s = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
cmdline_parser_release (struct gengetopt_args_info *args_info)
|
||||
{
|
||||
|
||||
free_string_field (&(args_info->host_arg));
|
||||
free_string_field (&(args_info->host_orig));
|
||||
free_string_field (&(args_info->decrypt_port_orig));
|
||||
free_string_field (&(args_info->m3u8_port_orig));
|
||||
free_string_field (&(args_info->proxy_arg));
|
||||
free_string_field (&(args_info->proxy_orig));
|
||||
free_string_field (&(args_info->login_arg));
|
||||
free_string_field (&(args_info->login_orig));
|
||||
|
||||
|
||||
|
||||
clear_given (args_info);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
write_into_file(FILE *outfile, const char *opt, const char *arg, const char *values[])
|
||||
{
|
||||
FIX_UNUSED (values);
|
||||
if (arg) {
|
||||
fprintf(outfile, "%s=\"%s\"\n", opt, arg);
|
||||
} else {
|
||||
fprintf(outfile, "%s\n", opt);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
cmdline_parser_dump(FILE *outfile, struct gengetopt_args_info *args_info)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
if (!outfile)
|
||||
{
|
||||
fprintf (stderr, "%s: cannot dump options to stream\n", CMDLINE_PARSER_PACKAGE);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (args_info->help_given)
|
||||
write_into_file(outfile, "help", 0, 0 );
|
||||
if (args_info->version_given)
|
||||
write_into_file(outfile, "version", 0, 0 );
|
||||
if (args_info->host_given)
|
||||
write_into_file(outfile, "host", args_info->host_orig, 0);
|
||||
if (args_info->decrypt_port_given)
|
||||
write_into_file(outfile, "decrypt-port", args_info->decrypt_port_orig, 0);
|
||||
if (args_info->m3u8_port_given)
|
||||
write_into_file(outfile, "m3u8-port", args_info->m3u8_port_orig, 0);
|
||||
if (args_info->proxy_given)
|
||||
write_into_file(outfile, "proxy", args_info->proxy_orig, 0);
|
||||
if (args_info->login_given)
|
||||
write_into_file(outfile, "login", args_info->login_orig, 0);
|
||||
if (args_info->code_from_file_given)
|
||||
write_into_file(outfile, "code-from-file", 0, 0 );
|
||||
|
||||
|
||||
i = EXIT_SUCCESS;
|
||||
return i;
|
||||
}
|
||||
|
||||
int
|
||||
cmdline_parser_file_save(const char *filename, struct gengetopt_args_info *args_info)
|
||||
{
|
||||
FILE *outfile;
|
||||
int i = 0;
|
||||
|
||||
outfile = fopen(filename, "w");
|
||||
|
||||
if (!outfile)
|
||||
{
|
||||
fprintf (stderr, "%s: cannot open file for writing: %s\n", CMDLINE_PARSER_PACKAGE, filename);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
i = cmdline_parser_dump(outfile, args_info);
|
||||
fclose (outfile);
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
void
|
||||
cmdline_parser_free (struct gengetopt_args_info *args_info)
|
||||
{
|
||||
cmdline_parser_release (args_info);
|
||||
}
|
||||
|
||||
/** @brief replacement of strdup, which is not standard */
|
||||
char *
|
||||
gengetopt_strdup (const char *s)
|
||||
{
|
||||
char *result = 0;
|
||||
if (!s)
|
||||
return result;
|
||||
|
||||
result = (char*)malloc(strlen(s) + 1);
|
||||
if (result == (char*)0)
|
||||
return (char*)0;
|
||||
strcpy(result, s);
|
||||
return result;
|
||||
}
|
||||
|
||||
int
|
||||
cmdline_parser (int argc, char **argv, struct gengetopt_args_info *args_info)
|
||||
{
|
||||
return cmdline_parser2 (argc, argv, args_info, 0, 1, 1);
|
||||
}
|
||||
|
||||
int
|
||||
cmdline_parser_ext (int argc, char **argv, struct gengetopt_args_info *args_info,
|
||||
struct cmdline_parser_params *params)
|
||||
{
|
||||
int result;
|
||||
result = cmdline_parser_internal (argc, argv, args_info, params, 0);
|
||||
|
||||
if (result == EXIT_FAILURE)
|
||||
{
|
||||
cmdline_parser_free (args_info);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int
|
||||
cmdline_parser2 (int argc, char **argv, struct gengetopt_args_info *args_info, int override, int initialize, int check_required)
|
||||
{
|
||||
int result;
|
||||
struct cmdline_parser_params params;
|
||||
|
||||
params.override = override;
|
||||
params.initialize = initialize;
|
||||
params.check_required = check_required;
|
||||
params.check_ambiguity = 0;
|
||||
params.print_errors = 1;
|
||||
|
||||
result = cmdline_parser_internal (argc, argv, args_info, ¶ms, 0);
|
||||
|
||||
if (result == EXIT_FAILURE)
|
||||
{
|
||||
cmdline_parser_free (args_info);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int
|
||||
cmdline_parser_required (struct gengetopt_args_info *args_info, const char *prog_name)
|
||||
{
|
||||
FIX_UNUSED (args_info);
|
||||
FIX_UNUSED (prog_name);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static char *package_name = 0;
|
||||
|
||||
/**
|
||||
* @brief updates an option
|
||||
* @param field the generic pointer to the field to update
|
||||
* @param orig_field the pointer to the orig field
|
||||
* @param field_given the pointer to the number of occurrence of this option
|
||||
* @param prev_given the pointer to the number of occurrence already seen
|
||||
* @param value the argument for this option (if null no arg was specified)
|
||||
* @param possible_values the possible values for this option (if specified)
|
||||
* @param default_value the default value (in case the option only accepts fixed values)
|
||||
* @param arg_type the type of this option
|
||||
* @param check_ambiguity @see cmdline_parser_params.check_ambiguity
|
||||
* @param override @see cmdline_parser_params.override
|
||||
* @param no_free whether to free a possible previous value
|
||||
* @param multiple_option whether this is a multiple option
|
||||
* @param long_opt the corresponding long option
|
||||
* @param short_opt the corresponding short option (or '-' if none)
|
||||
* @param additional_error possible further error specification
|
||||
*/
|
||||
static
|
||||
int update_arg(void *field, char **orig_field,
|
||||
unsigned int *field_given, unsigned int *prev_given,
|
||||
char *value, const char *possible_values[],
|
||||
const char *default_value,
|
||||
cmdline_parser_arg_type arg_type,
|
||||
int check_ambiguity, int override,
|
||||
int no_free, int multiple_option,
|
||||
const char *long_opt, char short_opt,
|
||||
const char *additional_error)
|
||||
{
|
||||
char *stop_char = 0;
|
||||
const char *val = value;
|
||||
int found;
|
||||
char **string_field;
|
||||
FIX_UNUSED (field);
|
||||
|
||||
stop_char = 0;
|
||||
found = 0;
|
||||
|
||||
if (!multiple_option && prev_given && (*prev_given || (check_ambiguity && *field_given)))
|
||||
{
|
||||
if (short_opt != '-')
|
||||
fprintf (stderr, "%s: `--%s' (`-%c') option given more than once%s\n",
|
||||
package_name, long_opt, short_opt,
|
||||
(additional_error ? additional_error : ""));
|
||||
else
|
||||
fprintf (stderr, "%s: `--%s' option given more than once%s\n",
|
||||
package_name, long_opt,
|
||||
(additional_error ? additional_error : ""));
|
||||
return 1; /* failure */
|
||||
}
|
||||
|
||||
FIX_UNUSED (default_value);
|
||||
|
||||
if (field_given && *field_given && ! override)
|
||||
return 0;
|
||||
if (prev_given)
|
||||
(*prev_given)++;
|
||||
if (field_given)
|
||||
(*field_given)++;
|
||||
if (possible_values)
|
||||
val = possible_values[found];
|
||||
|
||||
switch(arg_type) {
|
||||
case ARG_FLAG:
|
||||
*((int *)field) = !*((int *)field);
|
||||
break;
|
||||
case ARG_INT:
|
||||
if (val) *((int *)field) = strtol (val, &stop_char, 0);
|
||||
break;
|
||||
case ARG_STRING:
|
||||
if (val) {
|
||||
string_field = (char **)field;
|
||||
if (!no_free && *string_field)
|
||||
free (*string_field); /* free previous string */
|
||||
*string_field = gengetopt_strdup (val);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
|
||||
/* check numeric conversion */
|
||||
switch(arg_type) {
|
||||
case ARG_INT:
|
||||
if (val && !(stop_char && *stop_char == '\0')) {
|
||||
fprintf(stderr, "%s: invalid numeric value: %s\n", package_name, val);
|
||||
return 1; /* failure */
|
||||
}
|
||||
break;
|
||||
default:
|
||||
;
|
||||
};
|
||||
|
||||
/* store the original value */
|
||||
switch(arg_type) {
|
||||
case ARG_NO:
|
||||
case ARG_FLAG:
|
||||
break;
|
||||
default:
|
||||
if (value && orig_field) {
|
||||
if (no_free) {
|
||||
*orig_field = value;
|
||||
} else {
|
||||
if (*orig_field)
|
||||
free (*orig_field); /* free previous string */
|
||||
*orig_field = gengetopt_strdup (value);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return 0; /* OK */
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
cmdline_parser_internal (
|
||||
int argc, char **argv, struct gengetopt_args_info *args_info,
|
||||
struct cmdline_parser_params *params, const char *additional_error)
|
||||
{
|
||||
int c; /* Character of the parsed option. */
|
||||
|
||||
int error_occurred = 0;
|
||||
struct gengetopt_args_info local_args_info;
|
||||
|
||||
int override;
|
||||
int initialize;
|
||||
int check_required;
|
||||
int check_ambiguity;
|
||||
|
||||
package_name = argv[0];
|
||||
|
||||
/* TODO: Why is this here? It is not used anywhere. */
|
||||
override = params->override;
|
||||
FIX_UNUSED(override);
|
||||
|
||||
initialize = params->initialize;
|
||||
check_required = params->check_required;
|
||||
|
||||
/* TODO: Why is this here? It is not used anywhere. */
|
||||
check_ambiguity = params->check_ambiguity;
|
||||
FIX_UNUSED(check_ambiguity);
|
||||
|
||||
if (initialize)
|
||||
cmdline_parser_init (args_info);
|
||||
|
||||
cmdline_parser_init (&local_args_info);
|
||||
|
||||
optarg = 0;
|
||||
optind = 0;
|
||||
opterr = params->print_errors;
|
||||
optopt = '?';
|
||||
|
||||
while (1)
|
||||
{
|
||||
int option_index = 0;
|
||||
|
||||
static struct option long_options[] = {
|
||||
{ "help", 0, NULL, 'h' },
|
||||
{ "version", 0, NULL, 'V' },
|
||||
{ "host", 1, NULL, 'H' },
|
||||
{ "decrypt-port", 1, NULL, 'D' },
|
||||
{ "m3u8-port", 1, NULL, 'M' },
|
||||
{ "proxy", 1, NULL, 'P' },
|
||||
{ "login", 1, NULL, 'L' },
|
||||
{ "code-from-file", 0, NULL, 'F' },
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
c = getopt_long (argc, argv, "hVH:D:M:P:L:F", long_options, &option_index);
|
||||
|
||||
if (c == -1) break; /* Exit from `while (1)' loop. */
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case 'h': /* Print help and exit. */
|
||||
cmdline_parser_print_help ();
|
||||
cmdline_parser_free (&local_args_info);
|
||||
exit (EXIT_SUCCESS);
|
||||
|
||||
case 'V': /* Print version and exit. */
|
||||
cmdline_parser_print_version ();
|
||||
cmdline_parser_free (&local_args_info);
|
||||
exit (EXIT_SUCCESS);
|
||||
|
||||
case 'H': /* . */
|
||||
|
||||
|
||||
if (update_arg( (void *)&(args_info->host_arg),
|
||||
&(args_info->host_orig), &(args_info->host_given),
|
||||
&(local_args_info.host_given), optarg, 0, "127.0.0.1", ARG_STRING,
|
||||
check_ambiguity, override, 0, 0,
|
||||
"host", 'H',
|
||||
additional_error))
|
||||
goto failure;
|
||||
|
||||
break;
|
||||
case 'D': /* . */
|
||||
|
||||
|
||||
if (update_arg( (void *)&(args_info->decrypt_port_arg),
|
||||
&(args_info->decrypt_port_orig), &(args_info->decrypt_port_given),
|
||||
&(local_args_info.decrypt_port_given), optarg, 0, "10020", ARG_INT,
|
||||
check_ambiguity, override, 0, 0,
|
||||
"decrypt-port", 'D',
|
||||
additional_error))
|
||||
goto failure;
|
||||
|
||||
break;
|
||||
case 'M': /* . */
|
||||
|
||||
|
||||
if (update_arg( (void *)&(args_info->m3u8_port_arg),
|
||||
&(args_info->m3u8_port_orig), &(args_info->m3u8_port_given),
|
||||
&(local_args_info.m3u8_port_given), optarg, 0, "20020", ARG_INT,
|
||||
check_ambiguity, override, 0, 0,
|
||||
"m3u8-port", 'M',
|
||||
additional_error))
|
||||
goto failure;
|
||||
|
||||
break;
|
||||
case 'P': /* . */
|
||||
|
||||
|
||||
if (update_arg( (void *)&(args_info->proxy_arg),
|
||||
&(args_info->proxy_orig), &(args_info->proxy_given),
|
||||
&(local_args_info.proxy_given), optarg, 0, "", ARG_STRING,
|
||||
check_ambiguity, override, 0, 0,
|
||||
"proxy", 'P',
|
||||
additional_error))
|
||||
goto failure;
|
||||
|
||||
break;
|
||||
case 'L': /* username:password. */
|
||||
|
||||
|
||||
if (update_arg( (void *)&(args_info->login_arg),
|
||||
&(args_info->login_orig), &(args_info->login_given),
|
||||
&(local_args_info.login_given), optarg, 0, 0, ARG_STRING,
|
||||
check_ambiguity, override, 0, 0,
|
||||
"login", 'L',
|
||||
additional_error))
|
||||
goto failure;
|
||||
|
||||
break;
|
||||
case 'F': /* . */
|
||||
|
||||
|
||||
if (update_arg((void *)&(args_info->code_from_file_flag), 0, &(args_info->code_from_file_given),
|
||||
&(local_args_info.code_from_file_given), optarg, 0, 0, ARG_FLAG,
|
||||
check_ambiguity, override, 1, 0, "code-from-file", 'F',
|
||||
additional_error))
|
||||
goto failure;
|
||||
|
||||
break;
|
||||
|
||||
case 0: /* Long option with no short option */
|
||||
case '?': /* Invalid option. */
|
||||
/* `getopt_long' already printed an error message. */
|
||||
goto failure;
|
||||
|
||||
default: /* bug: option not considered. */
|
||||
fprintf (stderr, "%s: option unknown: %c%s\n", CMDLINE_PARSER_PACKAGE, c, (additional_error ? additional_error : ""));
|
||||
abort ();
|
||||
} /* switch */
|
||||
} /* while */
|
||||
|
||||
|
||||
|
||||
FIX_UNUSED(check_required);
|
||||
|
||||
cmdline_parser_release (&local_args_info);
|
||||
|
||||
if ( error_occurred )
|
||||
return (EXIT_FAILURE);
|
||||
|
||||
return 0;
|
||||
|
||||
failure:
|
||||
|
||||
cmdline_parser_release (&local_args_info);
|
||||
return (EXIT_FAILURE);
|
||||
}
|
||||
/* vim: set ft=c noet ts=8 sts=8 sw=8 tw=80 nojs spell : */
|
196
cmdline.h
Normal file
196
cmdline.h
Normal file
@ -0,0 +1,196 @@
|
||||
/** @file cmdline.h
|
||||
* @brief The header file for the command line option parser
|
||||
* generated by GNU Gengetopt version 2.23
|
||||
* http://www.gnu.org/software/gengetopt.
|
||||
* DO NOT modify this file, since it can be overwritten
|
||||
* @author GNU Gengetopt */
|
||||
|
||||
#ifndef CMDLINE_H
|
||||
#define CMDLINE_H
|
||||
|
||||
/* If we use autoconf. */
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h> /* for FILE */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#ifndef CMDLINE_PARSER_PACKAGE
|
||||
/** @brief the program name (used for printing errors) */
|
||||
#define CMDLINE_PARSER_PACKAGE "wrapper"
|
||||
#endif
|
||||
|
||||
#ifndef CMDLINE_PARSER_PACKAGE_NAME
|
||||
/** @brief the complete program name (used for help and version) */
|
||||
#define CMDLINE_PARSER_PACKAGE_NAME "wrapper"
|
||||
#endif
|
||||
|
||||
#ifndef CMDLINE_PARSER_VERSION
|
||||
/** @brief the program version */
|
||||
#define CMDLINE_PARSER_VERSION "1.2.0"
|
||||
#endif
|
||||
|
||||
/** @brief Where the command line options are stored */
|
||||
struct gengetopt_args_info
|
||||
{
|
||||
const char *help_help; /**< @brief Print help and exit help description. */
|
||||
const char *version_help; /**< @brief Print version and exit help description. */
|
||||
char * host_arg; /**< @brief (default='127.0.0.1'). */
|
||||
char * host_orig; /**< @brief original value given at command line. */
|
||||
const char *host_help; /**< @brief help description. */
|
||||
int decrypt_port_arg; /**< @brief (default='10020'). */
|
||||
char * decrypt_port_orig; /**< @brief original value given at command line. */
|
||||
const char *decrypt_port_help; /**< @brief help description. */
|
||||
int m3u8_port_arg; /**< @brief (default='20020'). */
|
||||
char * m3u8_port_orig; /**< @brief original value given at command line. */
|
||||
const char *m3u8_port_help; /**< @brief help description. */
|
||||
char * proxy_arg; /**< @brief (default=''). */
|
||||
char * proxy_orig; /**< @brief original value given at command line. */
|
||||
const char *proxy_help; /**< @brief help description. */
|
||||
char * login_arg; /**< @brief username:password. */
|
||||
char * login_orig; /**< @brief username:password original value given at command line. */
|
||||
const char *login_help; /**< @brief username:password help description. */
|
||||
int code_from_file_flag; /**< @brief (default=off). */
|
||||
const char *code_from_file_help; /**< @brief help description. */
|
||||
|
||||
unsigned int help_given ; /**< @brief Whether help was given. */
|
||||
unsigned int version_given ; /**< @brief Whether version was given. */
|
||||
unsigned int host_given ; /**< @brief Whether host was given. */
|
||||
unsigned int decrypt_port_given ; /**< @brief Whether decrypt-port was given. */
|
||||
unsigned int m3u8_port_given ; /**< @brief Whether m3u8-port was given. */
|
||||
unsigned int proxy_given ; /**< @brief Whether proxy was given. */
|
||||
unsigned int login_given ; /**< @brief Whether login was given. */
|
||||
unsigned int code_from_file_given ; /**< @brief Whether code-from-file was given. */
|
||||
|
||||
} ;
|
||||
|
||||
/** @brief The additional parameters to pass to parser functions */
|
||||
struct cmdline_parser_params
|
||||
{
|
||||
int override; /**< @brief whether to override possibly already present options (default 0) */
|
||||
int initialize; /**< @brief whether to initialize the option structure gengetopt_args_info (default 1) */
|
||||
int check_required; /**< @brief whether to check that all required options were provided (default 1) */
|
||||
int check_ambiguity; /**< @brief whether to check for options already specified in the option structure gengetopt_args_info (default 0) */
|
||||
int print_errors; /**< @brief whether getopt_long should print an error message for a bad option (default 1) */
|
||||
} ;
|
||||
|
||||
/** @brief the purpose string of the program */
|
||||
extern const char *gengetopt_args_info_purpose;
|
||||
/** @brief the usage string of the program */
|
||||
extern const char *gengetopt_args_info_usage;
|
||||
/** @brief the description string of the program */
|
||||
extern const char *gengetopt_args_info_description;
|
||||
/** @brief all the lines making the help output */
|
||||
extern const char *gengetopt_args_info_help[];
|
||||
|
||||
/**
|
||||
* The command line parser
|
||||
* @param argc the number of command line options
|
||||
* @param argv the command line options
|
||||
* @param args_info the structure where option information will be stored
|
||||
* @return 0 if everything went fine, NON 0 if an error took place
|
||||
*/
|
||||
int cmdline_parser (int argc, char **argv,
|
||||
struct gengetopt_args_info *args_info);
|
||||
|
||||
/**
|
||||
* The command line parser (version with additional parameters - deprecated)
|
||||
* @param argc the number of command line options
|
||||
* @param argv the command line options
|
||||
* @param args_info the structure where option information will be stored
|
||||
* @param override whether to override possibly already present options
|
||||
* @param initialize whether to initialize the option structure my_args_info
|
||||
* @param check_required whether to check that all required options were provided
|
||||
* @return 0 if everything went fine, NON 0 if an error took place
|
||||
* @deprecated use cmdline_parser_ext() instead
|
||||
*/
|
||||
int cmdline_parser2 (int argc, char **argv,
|
||||
struct gengetopt_args_info *args_info,
|
||||
int override, int initialize, int check_required);
|
||||
|
||||
/**
|
||||
* The command line parser (version with additional parameters)
|
||||
* @param argc the number of command line options
|
||||
* @param argv the command line options
|
||||
* @param args_info the structure where option information will be stored
|
||||
* @param params additional parameters for the parser
|
||||
* @return 0 if everything went fine, NON 0 if an error took place
|
||||
*/
|
||||
int cmdline_parser_ext (int argc, char **argv,
|
||||
struct gengetopt_args_info *args_info,
|
||||
struct cmdline_parser_params *params);
|
||||
|
||||
/**
|
||||
* Save the contents of the option struct into an already open FILE stream.
|
||||
* @param outfile the stream where to dump options
|
||||
* @param args_info the option struct to dump
|
||||
* @return 0 if everything went fine, NON 0 if an error took place
|
||||
*/
|
||||
int cmdline_parser_dump(FILE *outfile,
|
||||
struct gengetopt_args_info *args_info);
|
||||
|
||||
/**
|
||||
* Save the contents of the option struct into a (text) file.
|
||||
* This file can be read by the config file parser (if generated by gengetopt)
|
||||
* @param filename the file where to save
|
||||
* @param args_info the option struct to save
|
||||
* @return 0 if everything went fine, NON 0 if an error took place
|
||||
*/
|
||||
int cmdline_parser_file_save(const char *filename,
|
||||
struct gengetopt_args_info *args_info);
|
||||
|
||||
/**
|
||||
* Print the help
|
||||
*/
|
||||
void cmdline_parser_print_help(void);
|
||||
/**
|
||||
* Print the version
|
||||
*/
|
||||
void cmdline_parser_print_version(void);
|
||||
|
||||
/**
|
||||
* Initializes all the fields a cmdline_parser_params structure
|
||||
* to their default values
|
||||
* @param params the structure to initialize
|
||||
*/
|
||||
void cmdline_parser_params_init(struct cmdline_parser_params *params);
|
||||
|
||||
/**
|
||||
* Allocates dynamically a cmdline_parser_params structure and initializes
|
||||
* all its fields to their default values
|
||||
* @return the created and initialized cmdline_parser_params structure
|
||||
*/
|
||||
struct cmdline_parser_params *cmdline_parser_params_create(void);
|
||||
|
||||
/**
|
||||
* Initializes the passed gengetopt_args_info structure's fields
|
||||
* (also set default values for options that have a default)
|
||||
* @param args_info the structure to initialize
|
||||
*/
|
||||
void cmdline_parser_init (struct gengetopt_args_info *args_info);
|
||||
/**
|
||||
* Deallocates the string fields of the gengetopt_args_info structure
|
||||
* (but does not deallocate the structure itself)
|
||||
* @param args_info the structure to deallocate
|
||||
*/
|
||||
void cmdline_parser_free (struct gengetopt_args_info *args_info);
|
||||
|
||||
/**
|
||||
* Checks that all the required options were specified
|
||||
* @param args_info the structure to check
|
||||
* @param prog_name the name of the program that will be used to print
|
||||
* possible errors
|
||||
* @return
|
||||
*/
|
||||
int cmdline_parser_required (struct gengetopt_args_info *args_info,
|
||||
const char *prog_name);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
#endif /* CMDLINE_H */
|
25
import.h
25
import.h
@ -32,6 +32,24 @@ static inline union std_string new_std_string(const char *s) {
|
||||
return str;
|
||||
}
|
||||
|
||||
static inline struct std_vector new_std_vector(void *begin) {
|
||||
struct std_vector vector = {
|
||||
.begin = begin,
|
||||
.end = begin + 1,
|
||||
};
|
||||
vector.end_capacity = vector.end;
|
||||
return vector;
|
||||
}
|
||||
|
||||
static inline union std_string new_std_string_short_mode(const char *str) {
|
||||
short str_size = strlen(str);
|
||||
union std_string std_str = {
|
||||
.mark = str_size << 1,
|
||||
};
|
||||
strcpy(std_str.str, str);
|
||||
return std_str;
|
||||
}
|
||||
|
||||
static inline const char *std_string_data(union std_string *str) {
|
||||
if ((str->mark & 1) == 0) {
|
||||
return str->str;
|
||||
@ -215,6 +233,13 @@ extern void _ZN8FootHill24defaultContextIdentifierEv(void *);
|
||||
extern void _ZN21RequestContextManager9configureERKNSt6__ndk110shared_ptrIN17storeservicescore14RequestContextEEE(
|
||||
struct shared_ptr *);
|
||||
|
||||
extern struct shared_ptr *_ZN22SVPlaybackLeaseManager12requestAssetERKmRKNSt6__ndk16vectorINS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS7_IS9_EEEERKb(
|
||||
void *, void *, unsigned long *, struct std_vector *, uint8_t *
|
||||
);
|
||||
extern int _ZNK23SVPlaybackAssetResponse13hasValidAssetEv(void *);
|
||||
extern struct shared_ptr *_ZNK23SVPlaybackAssetResponse13playbackAssetEv(void *);
|
||||
extern union std_string *_ZNK17storeservicescore13PlaybackAsset9URLStringEv(void *, uint8_t *);
|
||||
|
||||
const char *const android_id = "dc28071e981c439e";
|
||||
const char *const fairplayCert = "MIIEzjCCA7agAwIBAgIIAXAVjHFZDjgwDQYJKoZIhvcNAQEFBQAwfzELMAkGA1UEBhMCVVMxEz"
|
||||
"ARBgNVBAoMCkFwcGxlIEluYy4xJjAkBgNVBAsMHUFwcGxlIENlcnRpZmljYXRpb24gQXV0aG9y"
|
||||
|
209
test.c → main.c
209
test.c → main.c
@ -5,20 +5,28 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "import.h"
|
||||
#include "cmdline.h"
|
||||
#ifndef MyRelease
|
||||
#include "subhook/subhook.c"
|
||||
#endif
|
||||
|
||||
static struct shared_ptr apInf;
|
||||
static size_t passLen;
|
||||
static char *amUsername, *amPassword;
|
||||
static uint16_t port;
|
||||
static uint8_t leaseMgr[16];
|
||||
struct gengetopt_args_info args_info;
|
||||
char *amUsername, *amPassword;
|
||||
|
||||
int file_exists(char *filename) {
|
||||
struct stat buffer;
|
||||
return (stat (filename, &buffer) == 0);
|
||||
}
|
||||
|
||||
static void dialogHandler(long j, struct shared_ptr *protoDialogPtr,
|
||||
struct shared_ptr *respHandler) {
|
||||
@ -74,9 +82,35 @@ static void credentialHandler(struct shared_ptr *credReqHandler,
|
||||
credReqHandler->obj)),
|
||||
need2FA ? "true" : "false");
|
||||
|
||||
int passLen = strlen(amPassword);
|
||||
|
||||
if (need2FA) {
|
||||
printf("2FA code: ");
|
||||
scanf("%6s", amPassword + passLen);
|
||||
if (args_info.code_from_file_flag) {
|
||||
fprintf(stderr, "[!] Enter your 2FA code into rootfs/data/code.txt\n");
|
||||
fprintf(stderr, "[!] Example command: echo -n 114514 > rootfs/data/2fa.txt\n");
|
||||
fprintf(stderr, "[!] Waiting for input...\n");
|
||||
int count = 0;
|
||||
while (1)
|
||||
{
|
||||
if (count >= 20) {
|
||||
fprintf(stderr, "[!] Failed to get 2FA Code in 60s. Exiting...\n");
|
||||
exit(0);
|
||||
}
|
||||
if (file_exists("/data/2fa.txt")) {
|
||||
FILE *fp = fopen("/data/2fa.txt", "r");
|
||||
fscanf(fp, "%6s", amPassword + passLen);
|
||||
remove("/data/2fa.txt");
|
||||
fprintf(stderr, "[!] Code file detected! Logging in...\n");
|
||||
break;
|
||||
} else {
|
||||
sleep(3);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
printf("2FA code: ");
|
||||
scanf("%6s", amPassword + passLen);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t *const ptr = malloc(80);
|
||||
@ -112,6 +146,12 @@ static inline void init() {
|
||||
// raise(SIGSTOP);
|
||||
fprintf(stderr, "[+] starting...\n");
|
||||
setenv("ANDROID_DNS_MODE", "local", 1);
|
||||
if (args_info.proxy_given) {
|
||||
fprintf(stderr, "[+] Using proxy %s", args_info.proxy_arg);
|
||||
setenv("http_proxy", args_info.proxy_arg, 1);
|
||||
setenv("https_proxy", args_info.proxy_arg, 1);
|
||||
}
|
||||
|
||||
static const char *resolvers[2] = {"1.1.1.1", "1.0.0.1"};
|
||||
_resolv_set_nameservers_for_net(0, resolvers, 2, ".");
|
||||
#ifndef MyRelease
|
||||
@ -363,8 +403,6 @@ void handle(const int connfd) {
|
||||
}
|
||||
|
||||
extern uint8_t handle_cpp(int);
|
||||
static char *selfPath;
|
||||
static char *portStr;
|
||||
|
||||
inline static int new_socket() {
|
||||
const int fd = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, IPPROTO_TCP);
|
||||
@ -376,8 +414,8 @@ inline static int new_socket() {
|
||||
setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval));
|
||||
|
||||
static struct sockaddr_in serv_addr = {.sin_family = AF_INET};
|
||||
serv_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||
serv_addr.sin_port = htons(port);
|
||||
inet_pton(AF_INET, args_info.host_arg, &serv_addr.sin_addr);
|
||||
serv_addr.sin_port = htons(args_info.decrypt_port_arg);
|
||||
if (bind(fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) == -1) {
|
||||
perror("bind");
|
||||
return EXIT_FAILURE;
|
||||
@ -388,8 +426,8 @@ inline static int new_socket() {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
fprintf(stderr, "[!] listening 127.0.0.1:%d\n", port);
|
||||
close(STDOUT_FILENO);
|
||||
fprintf(stderr, "[!] listening %s:%d\n", args_info.host_arg, args_info.decrypt_port_arg);
|
||||
// close(STDOUT_FILENO);
|
||||
|
||||
static struct sockaddr_in peer_addr;
|
||||
static socklen_t peer_addr_size = sizeof(peer_addr);
|
||||
@ -423,24 +461,141 @@ inline static int new_socket() {
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
selfPath = argv[0];
|
||||
if (argc != 2) {
|
||||
if (argc != 4) {
|
||||
fprintf(stderr, "usage: %s [port] ([username] [password])\n",
|
||||
argv[0]);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
amUsername = argv[2];
|
||||
passLen = strlen(argv[3]);
|
||||
amPassword = malloc(passLen + 7);
|
||||
strcpy(amPassword, argv[3]);
|
||||
|
||||
const char* get_m3u8_method_play(uint8_t leaseMgr[16], unsigned long adam) {
|
||||
union std_string HLS = new_std_string_short_mode("HLS");
|
||||
struct std_vector HLSParam = new_std_vector(&HLS);
|
||||
static uint8_t z0 = 0;
|
||||
struct shared_ptr ptr_result;
|
||||
_ZN22SVPlaybackLeaseManager12requestAssetERKmRKNSt6__ndk16vectorINS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS7_IS9_EEEERKb(
|
||||
&ptr_result, leaseMgr, &adam, &HLSParam, &z0
|
||||
);
|
||||
|
||||
if (ptr_result.obj == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
port = atoi(portStr = argv[1]);
|
||||
|
||||
if (_ZNK23SVPlaybackAssetResponse13hasValidAssetEv(ptr_result.obj)) {
|
||||
struct shared_ptr *playbackAsset = _ZNK23SVPlaybackAssetResponse13playbackAssetEv(ptr_result.obj);
|
||||
if (playbackAsset == NULL || playbackAsset->obj == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
union std_string *m3u8 = malloc(sizeof(union std_string));
|
||||
if (m3u8 == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *playbackObj = playbackAsset->obj;
|
||||
_ZNK17storeservicescore13PlaybackAsset9URLStringEv(m3u8, playbackObj);
|
||||
|
||||
if (m3u8 == NULL || std_string_data(m3u8) == NULL) {
|
||||
free(m3u8);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *m3u8_str = std_string_data(m3u8);
|
||||
if (m3u8_str) {
|
||||
char *result = strdup(m3u8_str); // Make a copy
|
||||
free(m3u8);
|
||||
return result;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void handle_m3u8(const int connfd) {
|
||||
while (1)
|
||||
{
|
||||
uint8_t adamSize;
|
||||
if (!readfull(connfd, &adamSize, sizeof(uint8_t))) {
|
||||
return;
|
||||
}
|
||||
if (adamSize <= 0) {
|
||||
return;
|
||||
}
|
||||
char adam[adamSize];
|
||||
for (int i=0; i<adamSize; i=i+1) {
|
||||
readfull(connfd, &adam[i], sizeof(uint8_t));
|
||||
}
|
||||
char *ptr;
|
||||
unsigned long adamID = strtoul(adam, &ptr, 10);
|
||||
const char *m3u8 = get_m3u8_method_play(leaseMgr, adamID);
|
||||
if (m3u8 == NULL) {
|
||||
fprintf(stderr, "[.] failed to get m3u8 of adamId: %ld\n", adamID);
|
||||
writefull(connfd, "\n", sizeof("\n"));
|
||||
} else {
|
||||
fprintf(stderr, "[.] m3u8 adamId: %ld, url: %s\n", adamID, m3u8);
|
||||
char *with_newline = malloc(strlen(m3u8) + 2);
|
||||
if (with_newline) {
|
||||
strcpy(with_newline, m3u8);
|
||||
strcat(with_newline, "\n");
|
||||
writefull(connfd, with_newline, strlen(with_newline));
|
||||
free(with_newline);
|
||||
}
|
||||
free((void *)m3u8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void *new_socket_m3u8(void *args) {
|
||||
const int fd = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, IPPROTO_TCP);
|
||||
if (fd == -1) {
|
||||
perror("socket");
|
||||
}
|
||||
const int optval = 1;
|
||||
setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval));
|
||||
|
||||
static struct sockaddr_in serv_addr = {.sin_family = AF_INET};
|
||||
inet_pton(AF_INET, args_info.host_arg, &serv_addr.sin_addr);
|
||||
serv_addr.sin_port = htons(args_info.m3u8_port_arg);
|
||||
if (bind(fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) == -1) {
|
||||
perror("bind");
|
||||
}
|
||||
|
||||
if (listen(fd, 5) == -1) {
|
||||
perror("listen");
|
||||
}
|
||||
|
||||
fprintf(stderr, "[!] listening m3u8 request on %s:%d\n", args_info.host_arg, args_info.m3u8_port_arg);
|
||||
// close(STDOUT_FILENO);
|
||||
|
||||
static struct sockaddr_in peer_addr;
|
||||
static socklen_t peer_addr_size = sizeof(peer_addr);
|
||||
while (1) {
|
||||
const int connfd = accept4(fd, (struct sockaddr *)&peer_addr,
|
||||
&peer_addr_size, SOCK_CLOEXEC);
|
||||
if (connfd == -1) {
|
||||
if (errno == ENETDOWN || errno == EPROTO || errno == ENOPROTOOPT ||
|
||||
errno == EHOSTDOWN || errno == ENONET ||
|
||||
errno == EHOSTUNREACH || errno == EOPNOTSUPP ||
|
||||
errno == ENETUNREACH)
|
||||
continue;
|
||||
perror("accept4");
|
||||
|
||||
}
|
||||
|
||||
handle_m3u8(connfd);
|
||||
|
||||
if (close(connfd) == -1) {
|
||||
perror("close");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
cmdline_parser(argc, argv, &args_info);
|
||||
|
||||
init();
|
||||
const struct shared_ptr ctx = init_ctx();
|
||||
if (argc == 4 && !login(ctx)) {
|
||||
if (args_info.login_given) {
|
||||
amUsername = strtok(args_info.login_arg, ":");
|
||||
amPassword = strtok(NULL, ":");
|
||||
}
|
||||
if (args_info.login_given && !login(ctx)) {
|
||||
fprintf(stderr, "[!] login failed\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
@ -452,5 +607,9 @@ int main(int argc, char *argv[]) {
|
||||
_ZN22SVPlaybackLeaseManager12requestLeaseERKb(leaseMgr, &autom);
|
||||
FHinstance = _ZN21SVFootHillSessionCtrl8instanceEv();
|
||||
|
||||
pthread_t m3u8_thread;
|
||||
pthread_create(&m3u8_thread, NULL, &new_socket_m3u8, NULL);
|
||||
pthread_detach(m3u8_thread);
|
||||
|
||||
return new_socket();
|
||||
}
|
@ -0,0 +1 @@
|
||||
GITKEEP
|
@ -0,0 +1 @@
|
||||
GITKEEP
|
16
wrapper.c
16
wrapper.c
@ -1,6 +1,6 @@
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include <errno.h>
|
||||
#include <sched.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/stat.h>
|
||||
@ -23,10 +23,6 @@ int main(int argc, char *argv[], char *envp[]) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (argc > 2) {
|
||||
system("rm -r ./rootfs/data/data/com.apple.android.music/files/");
|
||||
}
|
||||
|
||||
if (chdir("./rootfs") != 0) {
|
||||
perror("chdir");
|
||||
return 1;
|
||||
@ -39,24 +35,22 @@ int main(int argc, char *argv[], char *envp[]) {
|
||||
chmod("/system/bin/linker64", 0755);
|
||||
chmod("/system/bin/main", 0755);
|
||||
|
||||
if (unshare(CLONE_NEWPID)) {
|
||||
perror("unshare");
|
||||
return 1;
|
||||
}
|
||||
child_proc = fork();
|
||||
if (child_proc == -1) {
|
||||
perror("fork");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (child_proc > 0) {
|
||||
close(STDOUT_FILENO);
|
||||
wait(NULL);
|
||||
wait(NULL); // Parent waits for the child process to terminate
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Child process logic
|
||||
mkdir("/data/data/com.apple.android.music/files", 0777);
|
||||
mkdir("/data/data/com.apple.android.music/files/mpl_db", 0777);
|
||||
execve("/system/bin/main", argv, envp);
|
||||
perror("execve");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
9
wrapper.ggo
Normal file
9
wrapper.ggo
Normal file
@ -0,0 +1,9 @@
|
||||
package "wrapper"
|
||||
version "1.2.0"
|
||||
|
||||
option "host" H "" string optional default="127.0.0.1"
|
||||
option "decrypt-port" D "" int optional default="10020"
|
||||
option "m3u8-port" M "" int optional default="20020"
|
||||
option "proxy" P "" string optional default=""
|
||||
option "login" L "username:password" string optional
|
||||
option "code-from-file" F "" flag off
|
Reference in New Issue
Block a user