From 7b473676a5674119ad6aa39b88118e42cd2e3ab3 Mon Sep 17 00:00:00 2001 From: "Maze.tsz" Date: Wed, 19 Jan 2022 18:23:24 +0800 Subject: [PATCH] Init meta version --- .github/workflows/build.yml | 349 ++++++++++++++------------ .github/workflows/docker.yml | 382 ----------------------------- scripts/build.alpine.release.sh | 4 +- scripts/build.macos.release.sh | 2 +- scripts/build.windows.release.sh | 2 +- scripts/config.termux.sh | 2 +- src/generator/config/subexport.cpp | 66 ++++- src/main.cpp | 5 + src/parser/config/proxy.h | 9 + src/parser/subparser.cpp | 211 ++++++++++++---- src/parser/subparser.h | 7 +- src/version.h | 2 +- 12 files changed, 440 insertions(+), 601 deletions(-) delete mode 100644 .github/workflows/docker.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2a3e38a..2189e8e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,7 +1,7 @@ name: GitHub CI on: [push] -concurrency: +concurrency: group: ${{ github.ref }}-${{ github.workflow }} cancel-in-progress: true @@ -10,126 +10,153 @@ jobs: name: Linux x86 Build runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - name: Add commit id into version - if: ${{ !startsWith(github.ref, 'refs/tags/') }} - run: SHA=$(git rev-parse --short HEAD) && sed -i 's/\(v[0-9]\.[0-9]\.[0-9]\)/\1-'"$SHA"'/' src/version.h - - name: Build - run: docker run --rm -v $GITHUB_WORKSPACE:/root/workdir multiarch/alpine:x86-latest-stable /bin/sh -c "apk add bash git nodejs npm && cd /root/workdir && chmod +x scripts/build.alpine.release.sh && bash scripts/build.alpine.release.sh" - - name: Upload - uses: actions/upload-artifact@v1 - with: - name: subconverter_linux32 - path: subconverter/ - - name: Package Release - if: startsWith(github.ref, 'refs/tags/') - run: tar czf subconverter_linux32.tar.gz subconverter - - name: Draft Release - uses: softprops/action-gh-release@v1 - if: startsWith(github.ref, 'refs/tags/') - with: - files: subconverter_linux32.tar.gz - draft: true + - uses: actions/checkout@v2 + - name: Add commit id into version + if: ${{ !startsWith(github.ref, 'refs/tags/') }} + run: SHA=$(git rev-parse --short HEAD) && sed -i 's/\(v[0-9]\.[0-9]\.[0-9]\)/\1-'"$SHA"'/' src/version.h + - name: Build + run: docker run --rm -v $GITHUB_WORKSPACE:/root/workdir multiarch/alpine:x86-latest-stable /bin/sh -c "apk add bash git nodejs npm && cd /root/workdir && chmod +x scripts/build.alpine.release.sh && bash scripts/build.alpine.release.sh" + - name: Upload + uses: actions/upload-artifact@v1 + with: + name: subconverter_linux32 + path: subconverter/ + - name: Package Release + if: startsWith(github.ref, 'refs/tags/') + run: tar czf subconverter_linux32.tar.gz subconverter + - name: Draft Release + uses: softprops/action-gh-release@v1 + if: startsWith(github.ref, 'refs/tags/') + with: + files: subconverter_linux32.tar.gz + draft: true linux64_build: name: Linux x86_64 Build runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - name: Add commit id into version - if: ${{ !startsWith(github.ref, 'refs/tags/') }} - run: SHA=$(git rev-parse --short HEAD) && sed -i 's/\(v[0-9]\.[0-9]\.[0-9]\)/\1-'"$SHA"'/' src/version.h - - name: Build - run: docker run -v $GITHUB_WORKSPACE:/root/workdir multiarch/alpine:amd64-latest-stable /bin/sh -c "apk add bash git nodejs npm && cd /root/workdir && chmod +x scripts/build.alpine.release.sh && bash scripts/build.alpine.release.sh" - - name: Upload - uses: actions/upload-artifact@v1 - with: - name: subconverter_linux64 - path: subconverter/ - - name: Package Release - if: startsWith(github.ref, 'refs/tags/') - run: tar czf subconverter_linux64.tar.gz subconverter - - name: Draft Release - uses: softprops/action-gh-release@v1 - if: startsWith(github.ref, 'refs/tags/') - with: - files: subconverter_linux64.tar.gz - draft: true + - uses: actions/checkout@v2 + - name: Add commit id into version + if: ${{ !startsWith(github.ref, 'refs/tags/') }} + run: SHA=$(git rev-parse --short HEAD) && sed -i 's/\(v[0-9]\.[0-9]\.[0-9]\)/\1-'"$SHA"'/' src/version.h + - name: Build + run: docker run -v $GITHUB_WORKSPACE:/root/workdir multiarch/alpine:amd64-latest-stable /bin/sh -c "apk add bash git nodejs npm && cd /root/workdir && chmod +x scripts/build.alpine.release.sh && bash scripts/build.alpine.release.sh" + - name: Upload + uses: actions/upload-artifact@v1 + with: + name: subconverter_linux64 + path: subconverter/ + - name: Package Release + if: startsWith(github.ref, 'refs/tags/') + run: tar czf subconverter_linux64.tar.gz subconverter + - name: Draft Release + uses: softprops/action-gh-release@v1 + if: startsWith(github.ref, 'refs/tags/') + with: + files: subconverter_linux64.tar.gz + draft: true armv7_build: name: Linux armv7 Build - runs-on: [self-hosted, linux, ARM64] + runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - name: Add commit id into version - if: ${{ !startsWith(github.ref, 'refs/tags/') }} - run: SHA=$(git rev-parse --short HEAD) && sed -i 's/\(v[0-9]\.[0-9]\.[0-9]\)/\1-'"$SHA"'/' src/version.h - - name: Build - run: docker run -v $GITHUB_WORKSPACE:/root/workdir multiarch/alpine:armv7-latest-stable /bin/sh -c "apk add bash git nodejs npm && cd /root/workdir && chmod +x scripts/build.alpine.release.sh && bash scripts/build.alpine.release.sh" - - name: Upload - uses: actions/upload-artifact@v1 - with: - name: subconverter_armv7 - path: subconverter/ - - name: Package Release - if: startsWith(github.ref, 'refs/tags/') - run: tar czf subconverter_armv7.tar.gz subconverter - - name: Draft Release - uses: softprops/action-gh-release@v1 - if: startsWith(github.ref, 'refs/tags/') - with: - files: subconverter_armv7.tar.gz - draft: true + - uses: actions/checkout@v2 + - name: Set up QEMU + uses: docker/setup-qemu-action@v1 + - name: Add commit id into version + if: ${{ !startsWith(github.ref, 'refs/tags/') }} + run: SHA=$(git rev-parse --short HEAD) && sed -i 's/\(v[0-9]\.[0-9]\.[0-9]\)/\1-'"$SHA"'/' src/version.h + - name: Build + run: docker run -v $GITHUB_WORKSPACE:/root/workdir multiarch/alpine:armv7-latest-stable /bin/sh -c "apk add bash git nodejs npm && cd /root/workdir && chmod +x scripts/build.alpine.release.sh && bash scripts/build.alpine.release.sh" + - name: Upload + uses: actions/upload-artifact@v1 + with: + name: subconverter_armv7 + path: subconverter/ + - name: Package Release + if: startsWith(github.ref, 'refs/tags/') + run: tar czf subconverter_armv7.tar.gz subconverter + - name: Draft Release + uses: softprops/action-gh-release@v1 + if: startsWith(github.ref, 'refs/tags/') + with: + files: subconverter_armv7.tar.gz + draft: true + + armhf_build: + name: Linux armhf Build + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Set up QEMU + uses: docker/setup-qemu-action@v1 + - name: Add commit id into version + if: ${{ !startsWith(github.ref, 'refs/tags/') }} + run: SHA=$(git rev-parse --short HEAD) && sed -i 's/\(v[0-9]\.[0-9]\.[0-9]\)/\1-'"$SHA"'/' src/version.h + - name: Build + run: docker run -v $GITHUB_WORKSPACE:/root/workdir multiarch/alpine:armhf-latest-stable /bin/sh -c "apk add bash git nodejs npm && cd /root/workdir && chmod +x scripts/build.alpine.release.sh && bash scripts/build.alpine.release.sh" + - name: Upload + uses: actions/upload-artifact@v1 + with: + name: subconverter_armhf + path: subconverter/ + - name: Package Release + run: tar czf subconverter_armhf.tar.gz subconverter + - name: Draft Release + uses: softprops/action-gh-release@v1 + with: + files: subconverter_armhf.tar.gz + release: true aarch64_build: name: Linux aarch64 Build - runs-on: [self-hosted, linux, ARM64] + runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - name: Add commit id into version - if: ${{ !startsWith(github.ref, 'refs/tags/') }} - run: SHA=$(git rev-parse --short HEAD) && sed -i 's/\(v[0-9]\.[0-9]\.[0-9]\)/\1-'"$SHA"'/' src/version.h - - name: Build - run: docker run -v $GITHUB_WORKSPACE:/root/workdir multiarch/alpine:aarch64-latest-stable /bin/sh -c "apk add bash git nodejs npm && cd /root/workdir && chmod +x scripts/build.alpine.release.sh && bash scripts/build.alpine.release.sh" - - name: Upload - uses: actions/upload-artifact@v1 - with: - name: subconverter_aarch64 - path: subconverter/ - - name: Package Release - if: startsWith(github.ref, 'refs/tags/') - run: tar czf subconverter_aarch64.tar.gz subconverter - - name: Draft Release - uses: softprops/action-gh-release@v1 - if: startsWith(github.ref, 'refs/tags/') - with: - files: subconverter_aarch64.tar.gz - draft: true + - uses: actions/checkout@v2 + - name: Set up QEMU + uses: docker/setup-qemu-action@v1 + - name: Add commit id into version + if: ${{ !startsWith(github.ref, 'refs/tags/') }} + run: SHA=$(git rev-parse --short HEAD) && sed -i 's/\(v[0-9]\.[0-9]\.[0-9]\)/\1-'"$SHA"'/' src/version.h + - name: Build + run: docker run -v $GITHUB_WORKSPACE:/root/workdir multiarch/alpine:aarch64-latest-stable /bin/sh -c "apk add bash git nodejs npm && cd /root/workdir && chmod +x scripts/build.alpine.release.sh && bash scripts/build.alpine.release.sh" + - name: Upload + uses: actions/upload-artifact@v1 + with: + name: subconverter_aarch64 + path: subconverter/ + - name: Package Release + run: tar czf subconverter_aarch64.tar.gz subconverter + - name: Draft Release + uses: softprops/action-gh-release@v1 + with: + files: subconverter_aarch64.tar.gz + release: true macos_build: name: macOS Build runs-on: macos-latest steps: - - uses: actions/checkout@v2 - - name: Add commit id into version - if: ${{ !startsWith(github.ref, 'refs/tags/') }} - run: SHA=$(git rev-parse --short HEAD) && sed -i -e 's/\(v[0-9]\.[0-9]\.[0-9]\)/\1-'"$SHA"'/' src/version.h - - name: Build - run: bash scripts/build.macos.release.sh - - name: Upload - uses: actions/upload-artifact@v1 - with: - name: subconverter_darwin64 - path: subconverter/ - - name: Package Release - if: startsWith(github.ref, 'refs/tags/') - run: tar czf subconverter_darwin64.tar.gz subconverter - - name: Draft Release - uses: softprops/action-gh-release@v1 - if: startsWith(github.ref, 'refs/tags/') - with: - files: subconverter_darwin64.tar.gz - draft: true + - uses: actions/checkout@v2 + - name: Add commit id into version + if: ${{ !startsWith(github.ref, 'refs/tags/') }} + run: SHA=$(git rev-parse --short HEAD) && sed -i -e 's/\(v[0-9]\.[0-9]\.[0-9]\)/\1-'"$SHA"'/' src/version.h + - name: Build + run: bash scripts/build.macos.release.sh + - name: Upload + uses: actions/upload-artifact@v1 + with: + name: subconverter_darwin64 + path: subconverter/ + - name: Package Release + if: startsWith(github.ref, 'refs/tags/') + run: tar czf subconverter_darwin64.tar.gz subconverter + - name: Draft Release + uses: softprops/action-gh-release@v1 + if: startsWith(github.ref, 'refs/tags/') + with: + files: subconverter_darwin64.tar.gz + draft: true windows64_build: name: Windows x86_64 Build @@ -138,35 +165,35 @@ jobs: run: shell: msys2 {0} steps: - - uses: actions/checkout@v2 - - uses: actions/setup-node@v2-beta - with: - node-version: '12' - - uses: msys2/setup-msys2@v2 - with: - update: true - install: base-devel git mingw-w64-x86_64-gcc mingw-w64-x86_64-cmake mingw-w64-x86_64-libevent mingw-w64-x86_64-pcre2 patch - msystem: MINGW64 - path-type: inherit - - name: Add commit id into version - if: ${{ !startsWith(github.ref, 'refs/tags/') }} - run: SHA=$(git rev-parse --short HEAD) && sed -i 's/\(v[0-9]\.[0-9]\.[0-9]\)/\1-'"$SHA"'/' src/version.h - - name: Build - run: bash scripts/build.windows.release.sh - - name: Upload - uses: actions/upload-artifact@v1 - with: - name: subconverter_win64 - path: subconverter/ - - name: Package Release - if: startsWith(github.ref, 'refs/tags/') - run: 7z a subconverter_win64.7z subconverter/ - - name: Draft Release - uses: softprops/action-gh-release@v1 - if: startsWith(github.ref, 'refs/tags/') - with: - files: subconverter_win64.7z - draft: true + - uses: actions/checkout@v2 + - uses: actions/setup-node@v2-beta + with: + node-version: '12' + - uses: msys2/setup-msys2@v2 + with: + update: true + install: base-devel git mingw-w64-x86_64-gcc mingw-w64-x86_64-cmake mingw-w64-x86_64-libevent mingw-w64-x86_64-pcre2 patch + msystem: MINGW64 + path-type: inherit + - name: Add commit id into version + if: ${{ !startsWith(github.ref, 'refs/tags/') }} + run: SHA=$(git rev-parse --short HEAD) && sed -i 's/\(v[0-9]\.[0-9]\.[0-9]\)/\1-'"$SHA"'/' src/version.h + - name: Build + run: bash scripts/build.windows.release.sh + - name: Upload + uses: actions/upload-artifact@v1 + with: + name: subconverter_win64 + path: subconverter/ + - name: Package Release + if: startsWith(github.ref, 'refs/tags/') + run: 7z a subconverter_win64.7z subconverter/ + - name: Draft Release + uses: softprops/action-gh-release@v1 + if: startsWith(github.ref, 'refs/tags/') + with: + files: subconverter_win64.7z + draft: true windows32_build: name: Windows x86 Build @@ -175,32 +202,32 @@ jobs: run: shell: msys2 {0} steps: - - uses: actions/checkout@v2 - - uses: actions/setup-node@v2-beta - with: - node-version: '12' - - uses: msys2/setup-msys2@v2 - with: - update: true - install: base-devel git mingw-w64-i686-gcc mingw-w64-i686-cmake mingw-w64-i686-libevent mingw-w64-i686-pcre2 patch - msystem: MINGW32 - path-type: inherit - - name: Add commit id into version - if: ${{ !startsWith(github.ref, 'refs/tags/') }} - run: SHA=$(git rev-parse --short HEAD) && sed -i 's/\(v[0-9]\.[0-9]\.[0-9]\)/\1-'"$SHA"'/' src/version.h - - name: Build - run: bash scripts/build.windows.release.sh - - name: Upload - uses: actions/upload-artifact@v1 - with: - name: subconverter_win32 - path: subconverter/ - - name: Package Release - if: startsWith(github.ref, 'refs/tags/') - run: 7z a subconverter_win32.7z subconverter/ - - name: Draft Release - uses: softprops/action-gh-release@v1 - if: startsWith(github.ref, 'refs/tags/') - with: - files: subconverter_win32.7z - draft: true + - uses: actions/checkout@v2 + - uses: actions/setup-node@v2-beta + with: + node-version: '12' + - uses: msys2/setup-msys2@v2 + with: + update: true + install: base-devel git mingw-w64-i686-gcc mingw-w64-i686-cmake mingw-w64-i686-libevent mingw-w64-i686-pcre2 patch + msystem: MINGW32 + path-type: inherit + - name: Add commit id into version + if: ${{ !startsWith(github.ref, 'refs/tags/') }} + run: SHA=$(git rev-parse --short HEAD) && sed -i 's/\(v[0-9]\.[0-9]\.[0-9]\)/\1-'"$SHA"'/' src/version.h + - name: Build + run: bash scripts/build.windows.release.sh + - name: Upload + uses: actions/upload-artifact@v1 + with: + name: subconverter_win32 + path: subconverter/ + - name: Package Release + if: startsWith(github.ref, 'refs/tags/') + run: 7z a subconverter_win32.7z subconverter/ + - name: Draft Release + uses: softprops/action-gh-release@v1 + if: startsWith(github.ref, 'refs/tags/') + with: + files: subconverter_win32.7z + draft: true diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml deleted file mode 100644 index b77876a..0000000 --- a/.github/workflows/docker.yml +++ /dev/null @@ -1,382 +0,0 @@ -name: Publish Docker Image -on: [push] - -concurrency: - group: ${{ github.ref }}-${{ github.workflow }} - cancel-in-progress: true - -jobs: - amd64_build: - name: Build AMD64 Image - runs-on: ubuntu-latest - steps: - - name: Checkout base - uses: actions/checkout@v2 - with: - fetch-depth: 0 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 - - - name: Docker login - uses: docker/login-action@v2 - with: - username: ${{ secrets.DOCKER_USERNAME }} - password: ${{ secrets.DOCKER_PASSWORD }} - - - name: Get commit SHA - id: vars - run: echo "::set-output name=sha_short::$(git rev-parse --short HEAD)" - - - name: Build and export - id: build - if: github.ref == 'refs/heads/master' - uses: docker/build-push-action@v3 - with: - platforms: linux/amd64 - context: scripts/ - tags: tindy2013/subconverter:latest - build-args: | - SHA=${{ steps.vars.outputs.sha_short }} - outputs: type=image,push=true - - - name: Replace tag without `v` - if: startsWith(github.ref, 'refs/tags/') - uses: actions/github-script@v1 - id: version - with: - script: | - return context.payload.ref.replace(/\/?refs\/tags\/v/, '') - result-encoding: string - - - name: Build release and export - id: build_rel - if: startsWith(github.ref, 'refs/tags/') - uses: docker/build-push-action@v3 - with: - platforms: linux/amd64 - context: scripts/ - tags: tindy2013/subconverter:${{steps.version.outputs.result}} - outputs: type=image,push=true - - - name: Save digest - if: github.ref == 'refs/heads/master' - run: echo ${{ steps.build.outputs.digest }} > /tmp/digest.txt - - - name: Save release digest - if: startsWith(github.ref, 'refs/tags/') - run: echo ${{ steps.build_rel.outputs.digest }} > /tmp/digest.txt - - - name: Upload artifact - uses: actions/upload-artifact@v3 - with: - name: digest_amd64 - path: /tmp/digest.txt - - x86_build: - name: Build x86 Image - runs-on: ubuntu-latest - steps: - - name: Checkout base - uses: actions/checkout@v2 - with: - fetch-depth: 0 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 - - - name: Docker login - uses: docker/login-action@v2 - with: - username: ${{ secrets.DOCKER_USERNAME }} - password: ${{ secrets.DOCKER_PASSWORD }} - - - name: Get commit SHA - id: vars - run: echo "::set-output name=sha_short::$(git rev-parse --short HEAD)" - - - name: Build and export - id: build - if: github.ref == 'refs/heads/master' - uses: docker/build-push-action@v3 - with: - platforms: linux/386 - context: scripts/ - tags: tindy2013/subconverter:latest - build-args: | - SHA=${{ steps.vars.outputs.sha_short }} - outputs: type=image,push=true - - - name: Replace tag without `v` - if: startsWith(github.ref, 'refs/tags/') - uses: actions/github-script@v1 - id: version - with: - script: | - return context.payload.ref.replace(/\/?refs\/tags\/v/, '') - result-encoding: string - - - name: Build release and export - id: build_rel - if: startsWith(github.ref, 'refs/tags/') - uses: docker/build-push-action@v3 - with: - platforms: linux/386 - context: scripts/ - tags: tindy2013/subconverter:${{steps.version.outputs.result}} - outputs: type=image,push=true - - - name: Save digest - if: github.ref == 'refs/heads/master' - run: echo ${{ steps.build.outputs.digest }} > /tmp/digest.txt - - - name: Save release digest - if: startsWith(github.ref, 'refs/tags/') - run: echo ${{ steps.build_rel.outputs.digest }} > /tmp/digest.txt - - - name: Upload artifact - uses: actions/upload-artifact@v3 - with: - name: digest_386 - path: /tmp/digest.txt - - armv7_build: - name: Build ARMv7 Image - runs-on: [self-hosted, linux, ARM64] - steps: - - name: Checkout base - uses: actions/checkout@v2 - with: - fetch-depth: 0 - - - name: Set up QEMU - uses: docker/setup-qemu-action@v2 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 - - - name: Docker login - uses: docker/login-action@v2 - with: - username: ${{ secrets.DOCKER_USERNAME }} - password: ${{ secrets.DOCKER_PASSWORD }} - - - name: Get commit SHA - id: vars - run: echo "::set-output name=sha_short::$(git rev-parse --short HEAD)" - - - name: Build and export - id: build - if: github.ref == 'refs/heads/master' - uses: docker/build-push-action@v3 - with: - platforms: linux/arm/v7 - context: scripts/ - tags: tindy2013/subconverter:latest - build-args: | - SHA=${{ steps.vars.outputs.sha_short }} - THREADS=2 - outputs: type=image,push=true - - - name: Replace tag without `v` - if: startsWith(github.ref, 'refs/tags/') - uses: actions/github-script@v1 - id: version - with: - script: | - return context.payload.ref.replace(/\/?refs\/tags\/v/, '') - result-encoding: string - - - name: Build release and export - id: build_rel - if: startsWith(github.ref, 'refs/tags/') - uses: docker/build-push-action@v3 - with: - platforms: linux/arm/v7 - context: scripts/ - tags: tindy2013/subconverter:${{steps.version.outputs.result}} - build-args: | - THREADS=2 - outputs: type=image,push=true - - - name: Save digest - if: github.ref == 'refs/heads/master' - run: echo ${{ steps.build.outputs.digest }} > /tmp/digest.txt - - - name: Save release digest - if: startsWith(github.ref, 'refs/tags/') - run: echo ${{ steps.build_rel.outputs.digest }} > /tmp/digest.txt - - - name: Upload artifact - uses: actions/upload-artifact@v3 - with: - name: digest_armv7 - path: /tmp/digest.txt - - arm64_build: - name: Build ARM64 Image - runs-on: [self-hosted, linux, ARM64] - steps: - - name: Checkout base - uses: actions/checkout@v2 - with: - fetch-depth: 0 - - - name: Set up QEMU - uses: docker/setup-qemu-action@v2 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 - - - name: Docker login - uses: docker/login-action@v2 - with: - username: ${{ secrets.DOCKER_USERNAME }} - password: ${{ secrets.DOCKER_PASSWORD }} - - - name: Get commit SHA - id: vars - run: echo "::set-output name=sha_short::$(git rev-parse --short HEAD)" - - - name: Build and export - id: build - if: github.ref == 'refs/heads/master' - uses: docker/build-push-action@v3 - with: - platforms: linux/arm64 - context: scripts/ - tags: tindy2013/subconverter:latest - build-args: | - SHA=${{ steps.vars.outputs.sha_short }} - THREADS=2 - outputs: type=image,push=true - - - name: Replace tag without `v` - if: startsWith(github.ref, 'refs/tags/') - uses: actions/github-script@v1 - id: version - with: - script: | - return context.payload.ref.replace(/\/?refs\/tags\/v/, '') - result-encoding: string - - - name: Build release and export - id: build_rel - if: startsWith(github.ref, 'refs/tags/') - uses: docker/build-push-action@v3 - with: - platforms: linux/arm64 - context: scripts/ - tags: tindy2013/subconverter:${{steps.version.outputs.result}} - build-args: | - THREADS=2 - outputs: type=image,push=true - - - name: Save digest - if: github.ref == 'refs/heads/master' - run: echo ${{ steps.build.outputs.digest }} > /tmp/digest.txt - - - name: Save release digest - if: startsWith(github.ref, 'refs/tags/') - run: echo ${{ steps.build_rel.outputs.digest }} > /tmp/digest.txt - - - name: Upload artifact - uses: actions/upload-artifact@v3 - with: - name: digest_arm64 - path: /tmp/digest.txt - - build: - name: Build - needs: [amd64_build, x86_build, armv7_build, arm64_build] - runs-on: ubuntu-latest - steps: - - name: Checkout base - uses: actions/checkout@v2 - with: - fetch-depth: 0 - - # https://github.com/docker/setup-qemu-action - - name: Set up QEMU - uses: docker/setup-qemu-action@v2 - - # https://github.com/docker/setup-buildx-action - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 - with: - config-inline: | - [worker.oci] - max-parallelism = 1 - - - name: Download artifact - uses: actions/download-artifact@v3 - with: - path: /tmp/images/ - -# - name: Load image -# if: github.ref == 'refs/heads/master' -# run: | -# docker load --input /tmp/image_amd64/image_amd64.tar -# docker load --input /tmp/image_386/image_386.tar -# docker load --input /tmp/image_armv7/image_armv7.tar -# docker load --input /tmp/image_arm64/image_arm64.tar -# docker image ls -a - - - name: Docker login - uses: docker/login-action@v2 - with: - username: ${{ secrets.DOCKER_USERNAME }} - password: ${{ secrets.DOCKER_PASSWORD }} - -# - name: Get commit SHA -# id: vars -# run: echo "::set-output name=sha_short::$(git rev-parse --short HEAD)" - -# - name: Docker buildx image and push on master branch -# if: github.ref == 'refs/heads/master' -# uses: docker/build-push-action@v3 -# with: -# platforms: linux/amd64,linux/arm/v7,linux/arm64,linux/386 -# context: scripts/ -# tags: tindy2013/subconverter:latest -# build-args: | -# SHA=${{ steps.vars.outputs.sha_short }} -# THREADS=1 -# outputs: | -# type=image,push=true - - - name: Replace tag without `v` - if: startsWith(github.ref, 'refs/tags/') - uses: actions/github-script@v1 - id: version - with: - script: | - return context.payload.ref.replace(/\/?refs\/tags\/v/, '') - result-encoding: string - -# - name: Load release image -# if: startsWith(github.ref, 'refs/tags/') -# run: | -# docker load --input /tmp/image_amd64/image_amd64_release.tar -# docker load --input /tmp/image_386/image_386_release.tar -# docker load --input /tmp/image_armv7/image_armv7_release.tar -# docker load --input /tmp/image_arm64/image_arm64_release.tar -# docker image ls -a - -# - name: Docker buildx image and push on release -# if: startsWith(github.ref, 'refs/tags/') -# uses: docker/build-push-action@v3 -# with: -# platforms: linux/amd64,linux/arm/v7,linux/arm64,linux/386 -# context: scripts/ -# tags: tindy2013/subconverter:${{steps.version.outputs.result}} -# build-args: THREADS=1 -# outputs: type=image,push=true - - - name: Merge and push manifest on master branch - if: github.ref == 'refs/heads/master' - run: python scripts/merge_manifest.py - - - name: Merge and push manifest on release - if: startsWith(github.ref, 'refs/tags/') - run: python scripts/merge_manifest.py ${{steps.version.outputs.result}} diff --git a/scripts/build.alpine.release.sh b/scripts/build.alpine.release.sh index 192a005..b74637a 100644 --- a/scripts/build.alpine.release.sh +++ b/scripts/build.alpine.release.sh @@ -40,7 +40,7 @@ cd .. git clone https://github.com/ToruNiina/toml11 --depth=1 cd toml11 -cmake . +cmake -DCMAKE_CXX_STANDARD=17 . make install -j4 cd .. @@ -48,7 +48,7 @@ export PKG_CONFIG_PATH=/usr/lib64/pkgconfig cmake -DCMAKE_BUILD_TYPE=Release . make -j2 rm subconverter -g++ -o base/subconverter $(find CMakeFiles/subconverter.dir/src/ -name "*.o") -static -lpcre2-8 -levent -lyaml-cpp -L/usr/lib64 -lcurl -lmbedtls -lmbedcrypto -lmbedx509 -lz -lquickjs -llibcron -O3 -s +g++ -o base/subconverter $(find CMakeFiles/subconverter.dir/src/ -name "*.o") -static -lpcre2-8 -levent -lyaml-cpp -L/usr/lib64 -lcurl -lmbedtls -lmbedcrypto -lmbedx509 -lz -lquickjs -llibcron -O3 -s cd base chmod +rx subconverter diff --git a/scripts/build.macos.release.sh b/scripts/build.macos.release.sh index 01aa7ec..d7c3904 100644 --- a/scripts/build.macos.release.sh +++ b/scripts/build.macos.release.sh @@ -41,7 +41,7 @@ cd .. git clone https://github.com/ToruNiina/toml11 --depth=1 cd toml11 -cmake . +cmake -DCMAKE_CXX_STANDARD=17 . make install -j4 cd .. diff --git a/scripts/build.windows.release.sh b/scripts/build.windows.release.sh index 2833671..2d012dc 100644 --- a/scripts/build.windows.release.sh +++ b/scripts/build.windows.release.sh @@ -44,7 +44,7 @@ cd .. git clone https://github.com/ToruNiina/toml11 --depth=1 cd toml11 -cmake -DCMAKE_INSTALL_PREFIX="$MINGW_PREFIX" -G "Unix Makefiles" . +cmake -DCMAKE_CXX_STANDARD=17 -DCMAKE_INSTALL_PREFIX="$MINGW_PREFIX" -G "Unix Makefiles" . make install -j4 cd .. diff --git a/scripts/config.termux.sh b/scripts/config.termux.sh index b83bb9b..12b03ce 100644 --- a/scripts/config.termux.sh +++ b/scripts/config.termux.sh @@ -40,6 +40,6 @@ cd .. git clone https://github.com/ToruNiina/toml11 --depth=1 cd toml11 -cmake -DCMAKE_INSTALL_PREFIX=$PREFIX . +cmake -DCMAKE_CXX_STANDARD=17 -DCMAKE_INSTALL_PREFIX=$PREFIX . make install -j3 cd .. diff --git a/src/generator/config/subexport.cpp b/src/generator/config/subexport.cpp index c6685ee..a96ea5c 100644 --- a/src/generator/config/subexport.cpp +++ b/src/generator/config/subexport.cpp @@ -332,13 +332,71 @@ void proxyToClash(std::vector &nodes, YAML::Node &yamlnode, const ProxyGr break; case "grpc"_hash: singleproxy["network"] = x.TransferProtocol; - singleproxy["servername"] = x.Host; - singleproxy["grpc-opts"]["grpc-service-name"] = x.Path; + singleproxy["servername"] = x.ServerName; + singleproxy["grpc-opts"]["grpc-mode"] = x.GRPCMode; + singleproxy["grpc-opts"]["grpc-service-name"]= x.GRPCServiceName; break; default: continue; } break; + case ProxyType::Vless: + singleproxy["type"] = "vless"; + singleproxy["uuid"] = x.UserId; + singleproxy["tls"] = x.TLSSecure; + if(!x.Host.empty()) + singleproxy["servername"] = x.Host; + if (!x.Flow.empty()) + singleproxy["flow"] = x.Flow; + if(!scv.is_undef()) + singleproxy["skip-cert-verify"] = scv.get(); + switch(hash_(x.TransferProtocol)) + { + case "tcp"_hash: + break; + case "ws"_hash: + singleproxy["network"] = x.TransferProtocol; + if(ext.clash_new_field_name) + { + singleproxy["ws-opts"]["path"] = x.Path; + if(!x.Host.empty()) + singleproxy["ws-opts"]["headers"]["Host"] = x.Host; + if(!x.Edge.empty()) + singleproxy["ws-opts"]["headers"]["Edge"] = x.Edge; + } + else + { + singleproxy["ws-path"] = x.Path; + if(!x.Host.empty()) + singleproxy["ws-headers"]["Host"] = x.Host; + if(!x.Edge.empty()) + singleproxy["ws-headers"]["Edge"] = x.Edge; + } + break; + case "http"_hash: + singleproxy["network"] = x.TransferProtocol; + singleproxy["http-opts"]["method"] = "GET"; + singleproxy["http-opts"]["path"].push_back(x.Path); + if(!x.Host.empty()) + singleproxy["http-opts"]["headers"]["Host"].push_back(x.Host); + if(!x.Edge.empty()) + singleproxy["http-opts"]["headers"]["Edge"].push_back(x.Edge); + break; + case "h2"_hash: + singleproxy["network"] = x.TransferProtocol; + singleproxy["h2-opts"]["path"] = x.Path; + if(!x.Host.empty()) + singleproxy["h2-opts"]["host"].push_back(x.Host); + break; + case "grpc"_hash: + singleproxy["network"] = x.TransferProtocol; + singleproxy["grpc-opts"]["grpc-mode"] = x.GRPCMode; + singleproxy["grpc-opts"]["grpc-service-name"] = x.GRPCServiceName; + break; + default: + continue; + } + break; case ProxyType::ShadowsocksR: //ignoring all nodes with unsupported obfs, protocols and encryption if(ext.filter_deprecated) @@ -412,8 +470,8 @@ void proxyToClash(std::vector &nodes, YAML::Node &yamlnode, const ProxyGr break; case "grpc"_hash: singleproxy["network"] = x.TransferProtocol; - if(!x.Path.empty()) - singleproxy["grpc-opts"]["grpc-service-name"] = x.Path; + singleproxy["grpc-opts"]["grpc-mode"] = x.GRPCMode; + singleproxy["grpc-opts"]["grpc-service-name"] = x.GRPCServiceName; break; case "ws"_hash: singleproxy["network"] = x.TransferProtocol; diff --git a/src/main.cpp b/src/main.cpp index 2dfe4c9..d403d25 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -76,6 +76,11 @@ void chkArg(int argc, char *argv[]) { global.generatorMode = true; } + else if(strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--version") == 0) + { + std::cerr<<"subconverter " VERSION " backend\n"; + return; + } else if(strcmp(argv[i], "--artifact") == 0) { if(i < argc - 1) diff --git a/src/parser/config/proxy.h b/src/parser/config/proxy.h index 5edc1de..dec48c2 100644 --- a/src/parser/config/proxy.h +++ b/src/parser/config/proxy.h @@ -13,6 +13,7 @@ enum ProxyType Shadowsocks, ShadowsocksR, VMess, + Vless, Trojan, Snell, HTTP, @@ -30,6 +31,8 @@ inline String getProxyTypeName(int type) return "SSR"; case ProxyType::VMess: return "VMess"; + case ProxyType::Vless: + return "Vless"; case ProxyType::Trojan: return "Trojan"; case ProxyType::Snell: @@ -70,12 +73,17 @@ struct Proxy String FakeType; bool TLSSecure = false; + String Flow; + bool FlowShow = false; + String Host; String Path; String Edge; String QUICSecure; String QUICSecret; + String GRPCServiceName; + String GRPCMode; tribool UDP; tribool TCPFastOpen; @@ -89,6 +97,7 @@ struct Proxy #define SS_DEFAULT_GROUP "SSProvider" #define SSR_DEFAULT_GROUP "SSRProvider" #define V2RAY_DEFAULT_GROUP "V2RayProvider" +#define XRAY_DEFAULT_GROUP "XRayProvider" #define SOCKS_DEFAULT_GROUP "SocksProvider" #define HTTP_DEFAULT_GROUP "HTTPProvider" #define TROJAN_DEFAULT_GROUP "TrojanProvider" diff --git a/src/parser/subparser.cpp b/src/parser/subparser.cpp index 4a2cf4b..5d4c5c9 100644 --- a/src/parser/subparser.cpp +++ b/src/parser/subparser.cpp @@ -37,7 +37,7 @@ void commonConstruct(Proxy &node, ProxyType type, const std::string &group, cons node.TLS13 = tls13; } -void vmessConstruct(Proxy &node, const std::string &group, const std::string &remarks, const std::string &add, const std::string &port, const std::string &type, const std::string &id, const std::string &aid, const std::string &net, const std::string &cipher, const std::string &path, const std::string &host, const std::string &edge, const std::string &tls, const std::string &sni, tribool udp, tribool tfo, tribool scv, tribool tls13) +void vmessConstruct(Proxy &node, const std::string &group, const std::string &remarks, const std::string &add, const std::string &port, const std::string &type, const std::string &id, const std::string &aid, const std::string &net, const std::string &cipher, const std::string &path, const std::string &host, const std::string &edge, const std::string &tls, const std::string &sni, const std::string &alpn, tribool udp, tribool tfo, tribool scv, tribool tls13) { commonConstruct(node, ProxyType::VMess, group, remarks, add, port, udp, tfo, scv, tls13); node.UserId = id.empty() ? "00000000-0000-0000-0000-000000000000" : id; @@ -46,19 +46,54 @@ void vmessConstruct(Proxy &node, const std::string &group, const std::string &re node.TransferProtocol = net.empty() ? "tcp" : net; node.Edge = edge; node.ServerName = sni; - - if(net == "quic") - { - node.QUICSecure = host; - node.QUICSecret = path; - } - else - { - node.Host = (host.empty() && !isIPv4(add) && !isIPv6(add)) ? add.data() : trim(host); - node.Path = path.empty() ? "/" : trim(path); - } node.FakeType = type; node.TLSSecure = tls == "tls"; + + switch(hash_(net)) + { + case "grpc"_hash: + node.GRPCMode = type.empty() ? "gun" : type; + node.GRPCServiceName = path.empty() ? "/" : urlEncode(urlDecode(trim(path))); + break; + case "quic"_hash: + node.QUICSecure = host; + node.QUICSecret = path.empty() ? "/" : trim(path); + break; + default: + node.Host = (host.empty() && !isIPv4(add) && !isIPv6(add)) ? add.data() : trim(host); + node.Path = path.empty() ? "/" : trim(path); + break; + } +} + +void vlessConstruct(Proxy &node, const std::string &group, const std::string &remarks, const std::string &add, const std::string &port, const std::string &type, const std::string &id, const std::string &aid, const std::string &net, const std::string &cipher, const std::string &flow, const std::string &mode, const std::string &path, const std::string &host, const std::string &edge, const std::string &tls, tribool udp, tribool tfo, tribool scv, tribool tls13) +{ + commonConstruct(node, ProxyType::Vless, group, remarks, add, port, udp, tfo, scv, tls13); + node.UserId = id.empty() ? "00000000-0000-0000-0000-000000000000" : id; + node.AlterId = to_int(aid); + node.EncryptMethod = cipher; + node.TransferProtocol = net.empty() ? "tcp" : type=="http" ? "http": net; + node.Edge = edge; + node.Flow = flow; + node.FakeType = type; + node.TLSSecure = tls == "tls" || tls == "xtls"; + + switch(hash_(net)) + { + case "grpc"_hash: + node.Host = host; + node.GRPCMode = mode.empty() ? "gun" : mode; + node.GRPCServiceName = path.empty() ? "/" : urlEncode(urlDecode(trim(path))); + break; + case "quic"_hash: + node.QUICSecure = host; + node.QUICSecret = path.empty() ? "/" : trim(path); + break; + default: + node.Host = (host.empty() && !isIPv4(add) && !isIPv6(add)) ? add.data() : trim(host); + node.Path = path.empty() ? "/" : urlDecode(trim(path)); + break; + } } void ssrConstruct(Proxy &node, const std::string &group, const std::string &remarks, const std::string &server, const std::string &port, const std::string &protocol, const std::string &method, const std::string &obfs, const std::string &password, const std::string &obfsparam, const std::string &protoparam, tribool udp, tribool tfo, tribool scv) @@ -96,14 +131,17 @@ void httpConstruct(Proxy &node, const std::string &group, const std::string &rem node.TLSSecure = tls; } -void trojanConstruct(Proxy &node, const std::string &group, const std::string &remarks, const std::string &server, const std::string &port, const std::string &password, const std::string &network, const std::string &host, const std::string &path, bool tlssecure, tribool udp, tribool tfo, tribool scv, tribool tls13) +void trojanConstruct(Proxy &node, const std::string &group, const std::string &remarks, const std::string &server, const std::string &port, const std::string &password, const std::string &network, const std::string &mode, const std::string &host, const std::string &path, const std::string &flow, const std::string &tls, tribool udp, tribool tfo, tribool scv, tribool tls13) { commonConstruct(node, ProxyType::Trojan, group, remarks, server, port, udp, tfo, scv, tls13); node.Password = password; node.Host = host; - node.TLSSecure = tlssecure; + node.TLSSecure = tls == "tls" || tls == "xtls";; node.TransferProtocol = network.empty() ? "tcp" : network; node.Path = path; + node.Flow = flow; + node.GRPCMode = mode.empty() ? "gun" : mode; + node.GRPCServiceName = path.empty() ? "/" : urlEncode(urlDecode(trim(path))); } void snellConstruct(Proxy &node, const std::string &group, const std::string &remarks, const std::string &server, const std::string &port, const std::string &password, const std::string &obfs, const std::string &host, uint16_t version, tribool udp, tribool tfo, tribool scv) @@ -115,9 +153,18 @@ void snellConstruct(Proxy &node, const std::string &group, const std::string &re node.SnellVersion = version; } +void explodeVless(std::string vless, Proxy &node) +{ + if(regMatch(vless, "vless://(.*?)@(.*)")) + { + explodeStdVless(vless, node); + return; + } +} + void explodeVmess(std::string vmess, Proxy &node) { - std::string version, ps, add, port, type, id, aid, net, path, host, tls, sni; + std::string version, ps, add, port, type, id, aid, net, path, host, tls, sni, alpn; Document jsondata; std::vector vArray; @@ -162,6 +209,8 @@ void explodeVmess(std::string vmess, Proxy &node) GetMember(jsondata, "host", host); GetMember(jsondata, "sni", sni); + GetMember(jsondata, "alpn", alpn); + switch(to_int(version)) { case 1: @@ -182,14 +231,14 @@ void explodeVmess(std::string vmess, Proxy &node) add = trim(add); - vmessConstruct(node, V2RAY_DEFAULT_GROUP, ps, add, port, type, id, aid, net, "auto", path, host, "", tls, sni); + vmessConstruct(node, V2RAY_DEFAULT_GROUP, ps, add, port, type, id, aid, net, "auto", path, host, "", tls, sni, alpn); } void explodeVmessConf(std::string content, std::vector &nodes) { Document json; rapidjson::Value nodejson, settings; - std::string group, ps, add, port, type, id, aid, net, path, host, edge, tls, cipher, subid, sni; + std::string group, ps, add, port, type, id, aid, net, path, host, edge, tls, cipher, subid, sni, alpn; tribool udp, tfo, scv; int configType; uint32_t index = nodes.size(); @@ -260,7 +309,7 @@ void explodeVmessConf(std::string content, std::vector &nodes) } } } - vmessConstruct(node, V2RAY_DEFAULT_GROUP, add + ":" + port, add, port, type, id, aid, net, cipher, path, host, edge, tls, "", udp, tfo, scv); + vmessConstruct(node, V2RAY_DEFAULT_GROUP, add + ":" + port, add, port, type, id, aid, net, cipher, path, host, edge, tls, "", "", udp, tfo, scv); nodes.emplace_back(std::move(node)); } return; @@ -314,7 +363,8 @@ void explodeVmessConf(std::string content, std::vector &nodes) json["vmess"][i]["streamSecurity"] >> tls; json["vmess"][i]["security"] >> cipher; json["vmess"][i]["sni"] >> sni; - vmessConstruct(node, V2RAY_DEFAULT_GROUP, ps, add, port, type, id, aid, net, cipher, path, host, "", tls, sni, udp, tfo, scv); + json["vmess"][i]["alpn"] >> alpn; + vmessConstruct(node, V2RAY_DEFAULT_GROUP, ps, add, port, type, id, aid, net, cipher, path, host, "", tls, sni, alpn, udp, tfo, scv); break; case 3: //ss config json["vmess"][i]["id"] >> id; @@ -725,9 +775,9 @@ void explodeHTTPSub(std::string link, Proxy &node) void explodeTrojan(std::string trojan, Proxy &node) { - std::string server, port, psk, addition, group, remark, host, path, network; + std::string server, port, psk, addition, group, remark, host, path, network, mode, flow, tls; tribool tfo, scv; - trojan.erase(0, 9); + trojan.erase(0, trojan.find("://") + 3); string_size pos = trojan.rfind("#"); if(pos != trojan.npos) @@ -747,25 +797,35 @@ void explodeTrojan(std::string trojan, Proxy &node) if(port == "0") return; - host = getUrlArg(addition, "sni"); - if(host.empty()) - host = getUrlArg(addition, "peer"); + host = getUrlArg(addition, strFind(addition,"sni") ? "sni" : strFind(addition,"host") ? "host" : "peer"); tfo = getUrlArg(addition, "tfo"); scv = getUrlArg(addition, "allowInsecure"); group = urlDecode(getUrlArg(addition, "group")); + tls = getUrlArg(addition,"security"); + flow = getUrlArg(addition,"flow"); + //Case WS if(getUrlArg(addition, "ws") == "1") { path = getUrlArg(addition, "wspath"); network = "ws"; } + //Case GRPC + if(getUrlArg(addition, "type") == "grpc") + { + mode = getUrlArg(addition,"mode"); + path = getUrlArg(addition, "serviceName"); + network = "grpc"; + } + if(remark.empty()) remark = server + ":" + port; + if(group.empty()) group = TROJAN_DEFAULT_GROUP; - trojanConstruct(node, group, remark, server, port, psk, network, host, path, true, tribool(), tfo, scv); + trojanConstruct(node, group, remark, server, port, psk, network, mode, host, path, flow, tls, tribool(), tfo, scv); } void explodeQuan(const std::string &quan, Proxy &node) @@ -831,7 +891,7 @@ void explodeQuan(const std::string &quan, Proxy &node) if(path.empty()) path = "/"; - vmessConstruct(node, group, ps, add, port, type, id, aid, net, cipher, path, host, edge, tls, ""); + vmessConstruct(node, group, ps, add, port, type, id, aid, net, cipher, path, host, edge, tls, "",""); } } @@ -839,7 +899,7 @@ void explodeNetch(std::string netch, Proxy &node) { Document json; std::string type, group, remark, address, port, username, password, method, plugin, pluginopts; - std::string protocol, protoparam, obfs, obfsparam, id, aid, transprot, faketype, host, edge, path, tls, sni; + std::string protocol, protoparam, obfs, obfsparam, id, aid, transprot, faketype, host, edge, path, tls, sni, flow, alpn, mode; tribool udp, tfo, scv; netch = urlSafeBase64Decode(netch.substr(8)); @@ -901,7 +961,7 @@ void explodeNetch(std::string netch, Proxy &node) sni = GetMember(json, "ServerName"); if(group.empty()) group = V2RAY_DEFAULT_GROUP; - vmessConstruct(node, group, remark, address, port, faketype, id, aid, transprot, method, path, host, edge, tls, sni, udp, tfo, scv); + vmessConstruct(node, group, remark, address, port, faketype, id, aid, transprot, method, path, host, edge, tls, sni, alpn, udp, tfo, scv); break; case "Socks5"_hash: username = GetMember(json, "Username"); @@ -916,13 +976,15 @@ void explodeNetch(std::string netch, Proxy &node) httpConstruct(node, group, remark, address, port, username, password, type == "HTTPS", tfo, scv); break; case "Trojan"_hash: - host = GetMember(json, "Host"); + host = GetMember(json, "Servername"); + if (host.empty()) + host = GetMember(json, "Host"); path = GetMember(json, "Path"); transprot = GetMember(json, "TransferProtocol"); tls = GetMember(json, "TLSSecure"); if(group.empty()) group = TROJAN_DEFAULT_GROUP; - trojanConstruct(node, group, remark, address, port, password, transprot, host, path, tls == "true", udp, tfo, scv); + trojanConstruct(node, group, remark, address, port, password, transprot, mode, host, path, flow, tls, udp, tfo, scv); break; case "Snell"_hash: obfs = GetMember(json, "OBFS"); @@ -940,9 +1002,10 @@ void explodeNetch(std::string netch, Proxy &node) void explodeClash(Node yamlnode, std::vector &nodes) { std::string proxytype, ps, server, port, cipher, group, password; //common - std::string type = "none", id, aid = "0", net = "tcp", path, host, edge, tls, sni; //vmess + std::string type = "none", id, aid = "0", net = "tcp", path, host, edge, tls, sni, alpn; //vmess std::string plugin, pluginopts, pluginopts_mode, pluginopts_host, pluginopts_mux; //ss std::string protocol, protoparam, obfs, obfsparam; //ssr + std::string flow, mode; //trojan std::string user; //socks tribool udp, tfo, scv; Node singleproxy; @@ -969,7 +1032,7 @@ void explodeClash(Node yamlnode, std::vector &nodes) singleproxy["alterId"] >>= aid; singleproxy["cipher"] >>= cipher; net = singleproxy["network"].IsDefined() ? safe_as(singleproxy["network"]) : "tcp"; - singleproxy["servername"] >>= sni; + sni = singleproxy["servername"].IsDefined() ? safe_as(singleproxy["servername"]) : ""; switch(hash_(net)) { case "http"_hash: @@ -1004,7 +1067,7 @@ void explodeClash(Node yamlnode, std::vector &nodes) } tls = safe_as(singleproxy["tls"]) == "true" ? "tls" : ""; - vmessConstruct(node, group, ps, server, port, "", id, aid, net, cipher, path, host, edge, tls, sni, udp, tfo, scv); + vmessConstruct(node, group, ps, server, port, "", id, aid, net, cipher, path, host, edge, tls, sni, alpn, udp, tfo, scv); break; case "ss"_hash: group = SS_DEFAULT_GROUP; @@ -1117,9 +1180,11 @@ void explodeClash(Node yamlnode, std::vector &nodes) singleproxy["password"] >>= password; singleproxy["sni"] >>= host; singleproxy["network"] >>= net; + singleproxy["flow"] >>= flow; switch(hash_(net)) { case "grpc"_hash: + singleproxy["grpc-opts"]["grpc-mode"] >>= mode; singleproxy["grpc-opts"]["grpc-service-name"] >>= path; break; case "ws"_hash: @@ -1131,7 +1196,7 @@ void explodeClash(Node yamlnode, std::vector &nodes) break; } - trojanConstruct(node, group, ps, server, port, password, net, host, path, true, udp, tfo, scv); + trojanConstruct(node, group, ps, server, port, password, net, mode, host, path, flow, tls, udp, tfo, scv); break; case "snell"_hash: group = SNELL_DEFAULT_GROUP; @@ -1155,7 +1220,7 @@ void explodeClash(Node yamlnode, std::vector &nodes) void explodeStdVMess(std::string vmess, Proxy &node) { - std::string add, port, type, id, aid, net, path, host, tls, remarks; + std::string add, port, type, id, aid, net, path, host, tls, sni, alpn, remarks; std::string addition; vmess = vmess.substr(8); string_size pos; @@ -1169,7 +1234,7 @@ void explodeStdVMess(std::string vmess, Proxy &node) const std::string stdvmess_matcher = R"(^([a-z]+)(?:\+([a-z]+))?:([\da-f]{4}(?:[\da-f]{4}-){4}[\da-f]{12})-(\d+)@(.+):(\d+)(?:\/?\?(.*))?$)"; if(regGetMatch(vmess, stdvmess_matcher, 8, 0, &net, &tls, &id, &aid, &add, &port, &addition)) return; - + sni = getUrlArg(addition, "servername"); switch(hash_(net)) { case "tcp"_hash: @@ -1193,7 +1258,58 @@ void explodeStdVMess(std::string vmess, Proxy &node) if(remarks.empty()) remarks = add + ":" + port; - vmessConstruct(node, V2RAY_DEFAULT_GROUP, remarks, add, port, type, id, aid, net, "auto", path, host, "", tls, ""); + vmessConstruct(node, V2RAY_DEFAULT_GROUP, remarks, add, port, type, id, aid, net, "auto", path, host, "", tls, "",""); + return; +} + +void explodeStdVless(std::string vless, Proxy &node) +{ + std::string add, port, type, id, aid, net, flow, mode, path, host, tls, remarks; + std::string addition; + vless = vless.substr(8); + string_size pos; + + pos = vless.rfind("#"); + if(pos != vless.npos) + { + remarks = urlDecode(vless.substr(pos + 1)); + vless.erase(pos); + } + const std::string stdvless_matcher = R"(^([\da-f]{4}(?:[\da-f]{4}-){4}[\da-f]{12})@\[?([\d\-a-zA-Z:.]+)\]?:(\d+)(?:\/?\?(.*))?$)"; + if(regGetMatch(vless, stdvless_matcher, 5, 0, &id, &add, &port, &addition)) + return; + + tls = getUrlArg(addition,"security"); + net = getUrlArg(addition,"type"); + flow = getUrlArg(addition,"flow"); + + switch(hash_(net)) + { + case "tcp"_hash: + case "ws"_hash: + case "h2"_hash: + type = getUrlArg(addition, "headerType"); + host = getUrlArg(addition, strFind(addition,"sni") ? "sni" : "host"); + path = getUrlArg(addition, "path"); + break; + case "grpc"_hash: + host = getUrlArg(addition, "sni"); + path = getUrlArg(addition, "serviceName"); + mode = getUrlArg(addition, "mode"); + break; + case "quic"_hash: + type = getUrlArg(addition, "headerType"); + host = getUrlArg(addition, strFind(addition,"sni") ? "sni" : "quicSecurity"); + path = getUrlArg(addition, "key"); + break; + default: + return; + } + + if(remarks.empty()) + remarks = add + ":" + port; + + vlessConstruct(node, XRAY_DEFAULT_GROUP, remarks, add, port, type, id, aid, net, "auto", flow, mode, path, host, "", tls); return; } @@ -1238,7 +1354,7 @@ void explodeShadowrocket(std::string rocket, Proxy &node) if(remarks.empty()) remarks = add + ":" + port; - vmessConstruct(node, V2RAY_DEFAULT_GROUP, remarks, add, port, type, id, aid, net, cipher, path, host, "", tls, ""); + vmessConstruct(node, V2RAY_DEFAULT_GROUP, remarks, add, port, type, id, aid, net, cipher, path, host, "", tls, "",""); } void explodeKitsunebi(std::string kit, Proxy &node) @@ -1276,7 +1392,7 @@ void explodeKitsunebi(std::string kit, Proxy &node) if(remarks.empty()) remarks = add + ":" + port; - vmessConstruct(node, V2RAY_DEFAULT_GROUP, remarks, add, port, type, id, aid, net, cipher, path, host, "", tls, ""); + vmessConstruct(node, V2RAY_DEFAULT_GROUP, remarks, add, port, type, id, aid, net, cipher, path, host, "", tls, "",""); } bool explodeSurge(std::string surge, std::vector &nodes) @@ -1311,7 +1427,7 @@ bool explodeSurge(std::string surge, std::vector &nodes) { std::string remarks, server, port, method, username, password; //common std::string plugin, pluginopts, pluginopts_mode, pluginopts_host, mod_url, mod_md5; //ss - std::string id, net, tls, host, edge, path; //v2 + std::string id, net, tls, host, edge, path, sni, alpn, mode, flow; //v2 std::string protocol, protoparam; //ssr std::string version, aead = "1"; std::string itemName, itemVal, config; @@ -1540,7 +1656,7 @@ bool explodeSurge(std::string surge, std::vector &nodes) } } - vmessConstruct(node, V2RAY_DEFAULT_GROUP, remarks, server, port, "", id, aead, net, method, path, host, edge, tls, "", udp, tfo, scv, tls13); + vmessConstruct(node, V2RAY_DEFAULT_GROUP, remarks, server, port, "", id, aead, net, method, path, host, edge, tls, "", "", udp, tfo, scv, tls13); break; case "http"_hash: //http proxy server = trim(configs[1]); @@ -1606,7 +1722,7 @@ bool explodeSurge(std::string surge, std::vector &nodes) } } - trojanConstruct(node, TROJAN_DEFAULT_GROUP, remarks, server, port, password, "", host, "", true, udp, tfo, scv); + trojanConstruct(node, TROJAN_DEFAULT_GROUP, remarks, server, port, password, "", mode, host, "", flow, tls, udp, tfo, scv); break; case "snell"_hash: server = trim(configs[1]); @@ -1821,7 +1937,7 @@ bool explodeSurge(std::string surge, std::vector &nodes) if(remarks.empty()) remarks = server + ":" + port; - vmessConstruct(node, V2RAY_DEFAULT_GROUP, remarks, server, port, "", id, aead, net, method, path, host, "", tls, "", udp, tfo, scv, tls13); + vmessConstruct(node, V2RAY_DEFAULT_GROUP, remarks, server, port, "", id, aead, net, method, path, host, "", tls, "", "", udp, tfo, scv, tls13); break; case "trojan"_hash: //quantumult x style trojan link server = trim(configs[0].substr(0, configs[0].rfind(":"))); @@ -1868,8 +1984,9 @@ bool explodeSurge(std::string surge, std::vector &nodes) } if(remarks.empty()) remarks = server + ":" + port; - - trojanConstruct(node, TROJAN_DEFAULT_GROUP, remarks, server, port, password, "", host, "", tls == "true", udp, tfo, scv, tls13); + if(host.empty() && !isIPv4(server) && !isIPv6(server)) + host = server; + trojanConstruct(node, TROJAN_DEFAULT_GROUP, remarks, server, port, password, "", mode, host, "", flow, tls, udp, tfo, scv, tls13); break; case "http"_hash: //quantumult x style http links server = trim(configs[0].substr(0, configs[0].rfind(":"))); @@ -2069,6 +2186,8 @@ void explode(const std::string &link, Proxy &node) explodeSSR(link, node); else if(strFind(link, "vmess://") || strFind(link, "vmess1://")) explodeVmess(link, node); + else if(strFind(link, "vless://") || strFind(link, "vless1://")) + explodeVless(link, node); else if(strFind(link, "ss://")) explodeSS(link, node); else if(strFind(link, "socks://") || strFind(link, "https://t.me/socks") || strFind(link, "tg://socks")) @@ -2077,7 +2196,7 @@ void explode(const std::string &link, Proxy &node) explodeHTTP(link, node); else if(strFind(link, "Netch://")) explodeNetch(link, node); - else if(strFind(link, "trojan://")) + else if(strFind(link, "trojan://") || strFind(link, "trojan-go://")) explodeTrojan(link, node); else if(isLink(link)) explodeHTTPSub(link, node); diff --git a/src/parser/subparser.h b/src/parser/subparser.h index 5d236a9..fa02648 100644 --- a/src/parser/subparser.h +++ b/src/parser/subparser.h @@ -20,19 +20,22 @@ enum class ConfType Local }; -void vmessConstruct(Proxy &node, const std::string &group, const std::string &remarks, const std::string &add, const std::string &port, const std::string &type, const std::string &id, const std::string &aid, const std::string &net, const std::string &cipher, const std::string &path, const std::string &host, const std::string &edge, const std::string &tls, const std::string &sni, tribool udp = tribool(), tribool tfo = tribool(), tribool scv = tribool(), tribool tls13 = tribool()); +void vmessConstruct(Proxy &node, const std::string &group, const std::string &remarks, const std::string &add, const std::string &port, const std::string &type, const std::string &id, const std::string &aid, const std::string &net, const std::string &cipher, const std::string &path, const std::string &host, const std::string &edge, const std::string &tls, const std::string &sni, const std::string &alpn, tribool udp = tribool(), tribool tfo = tribool(), tribool scv = tribool(), tribool tls13 = tribool()); +void vlessConstruct(Proxy &node, const std::string &group, const std::string &remarks, const std::string &add, const std::string &port, const std::string &type, const std::string &id, const std::string &aid, const std::string &net, const std::string &cipher, const std::string &flow, const std::string &mode, const std::string &path, const std::string &host, const std::string &edge, const std::string &tls, tribool udp = tribool(), tribool tfo = tribool(), tribool scv = tribool(), tribool tls13 = tribool()); void ssrConstruct(Proxy &node, const std::string &group, const std::string &remarks, const std::string &server, const std::string &port, const std::string &protocol, const std::string &method, const std::string &obfs, const std::string &password, const std::string &obfsparam, const std::string &protoparam, tribool udp = tribool(), tribool tfo = tribool(), tribool scv = tribool()); void ssConstruct(Proxy &node, const std::string &group, const std::string &remarks, const std::string &server, const std::string &port, const std::string &password, const std::string &method, const std::string &plugin, const std::string &pluginopts, tribool udp = tribool(), tribool tfo = tribool(), tribool scv = tribool(), tribool tls13 = tribool()); void socksConstruct(Proxy &node, const std::string &group, const std::string &remarks, const std::string &server, const std::string &port, const std::string &username, const std::string &password, tribool udp = tribool(), tribool tfo = tribool(), tribool scv = tribool()); void httpConstruct(Proxy &node, const std::string &group, const std::string &remarks, const std::string &server, const std::string &port, const std::string &username, const std::string &password, bool tls, tribool tfo = tribool(), tribool scv = tribool(), tribool tls13 = tribool()); -void trojanConstruct(Proxy &node, const std::string &group, const std::string &remarks, const std::string &server, const std::string &port, const std::string &password, const std::string &network, const std::string &host, const std::string &path, bool tlssecure, tribool udp = tribool(), tribool tfo = tribool(), tribool scv = tribool(), tribool tls13 = tribool()); +void trojanConstruct(Proxy &node, const std::string &group, const std::string &remarks, const std::string &server, const std::string &port, const std::string &password, const std::string &network, const std::string &mode, const std::string &host, const std::string &path, const std::string &flow, const std::string &tls, tribool udp = tribool(), tribool tfo = tribool(), tribool scv = tribool(), tribool tls13 = tribool()); void snellConstruct(Proxy &node, const std::string &group, const std::string &remarks, const std::string &server, const std::string &port, const std::string &password, const std::string &obfs, const std::string &host, uint16_t version = 0, tribool udp = tribool(), tribool tfo = tribool(), tribool scv = tribool()); void explodeVmess(std::string vmess, Proxy &node); +void explodeVless(std::string vless, Proxy &node); void explodeSSR(std::string ssr, Proxy &node); void explodeSS(std::string ss, Proxy &node); void explodeTrojan(std::string trojan, Proxy &node); void explodeQuan(const std::string &quan, Proxy &node); void explodeStdVMess(std::string vmess, Proxy &node); +void explodeStdVless(std::string vless, Proxy &node); void explodeShadowrocket(std::string kit, Proxy &node); void explodeKitsunebi(std::string kit, Proxy &node); /// Parse a link diff --git a/src/version.h b/src/version.h index f8a9792..89ff6b1 100644 --- a/src/version.h +++ b/src/version.h @@ -1,6 +1,6 @@ #ifndef VERSION_H_INCLUDED #define VERSION_H_INCLUDED -#define VERSION "v0.7.2" +#define VERSION "v0.7.2 Meta" #endif // VERSION_H_INCLUDED