diff --git a/.github/workflows/unittest.yml b/.github/workflows/unittest.yml index bbebf95f..7f7c36e6 100644 --- a/.github/workflows/unittest.yml +++ b/.github/workflows/unittest.yml @@ -15,7 +15,7 @@ jobs: matrix: os: - windows-latest - python-version: ['3.8', '3.9', '3.10', '3.11', '3.12'] + python-version: ['3.9', '3.10', '3.11', '3.12', '3.13'] steps: - name: 'Set up Python ${{ matrix.python-version }}' uses: actions/setup-python@v4 @@ -34,7 +34,7 @@ jobs: matrix: os: - ubuntu-latest - python-version: ['3.8', '3.9', '3.10', '3.11', '3.12'] + python-version: ['3.9', '3.10', '3.11', '3.12', '3.13'] steps: - name: 'Set up Python ${{ matrix.python-version }}' uses: actions/setup-python@v4 @@ -55,7 +55,7 @@ jobs: matrix: os: - macos-latest - python-version: ['3.8', '3.9', '3.10', '3.11', '3.12'] + python-version: ['3.9', '3.10', '3.11', '3.12', '3.13'] steps: - name: 'Set up Python ${{ matrix.python-version }}' uses: actions/setup-python@v4 diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index f324106e..aea9e8c2 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,18 +1,3 @@ -test 3.8: - image: python:3.8 - stage: test - before_script: - - pip install responses - - pip install -r requirements.txt - - pip install coveralls - script: - - cd ./tests - - coverage run --source=.. --omit=../lib/* ./all_tests.py - when: manual - rules: - - if: $CI_COMMIT_BRANCH == "main" - - if: $CI_COMMIT_BRANCH == "dev" - test 3.9: image: python:3.9 stage: test @@ -73,3 +58,18 @@ test 3.12: - if: $CI_COMMIT_BRANCH == "main" - if: $CI_COMMIT_BRANCH == "dev" +test 3.13: + image: python:3.13 + stage: test + before_script: + - pip install responses + - pip install -r requirements.txt + - pip install coveralls + script: + - cd ./tests + - coverage run --source=.. --omit=../lib/* ./all_tests.py + when: manual + rules: + - if: $CI_COMMIT_BRANCH == "main" + - if: $CI_COMMIT_BRANCH == "dev" + diff --git a/CHANGES.md b/CHANGES.md index 566bdd20..3abd15fa 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,4 +1,10 @@ -### 3.32.13 (2024-12-11 02:15:00 UTC) +### 3.32.14 (2024-12-19 01:45:00 UTC) + +* Change validate get_image path +* Change remove Python 3.8 and add Python 3.13 to Gitlab and Github CI tests + + +### 3.32.13 (2024-12-11 02:15:00 UTC) * Fix ignore empty SEASON_RESULT entries * Change add support for Python 3.9.21, 3.10.16, 3.11.11, 3.12.8 diff --git a/sickgear/helpers.py b/sickgear/helpers.py index 4f765cb2..e7c5b5e4 100644 --- a/sickgear/helpers.py +++ b/sickgear/helpers.py @@ -25,6 +25,7 @@ import socket import time import uuid import sys +from pathlib import Path import sickgear from . import db, logger, notifiers @@ -177,6 +178,19 @@ def has_image_ext(filename): pass return False +def is_sickgear_dir(path): + # type: (str) -> bool + """ + validate that a path is a sickgear subpath + :param path: path to check + """ + path = Path(os.path.realpath(os.path.abspath(path))) + sickgear_path = Path(sickgear.PROG_DIR) + sickgear_data_path = Path(sickgear.DATA_DIR) + if sickgear_data_path in path.parents or sickgear_path in path.parents: + return True + return False + def is_first_rar_volume(filename): """ diff --git a/sickgear/webserve.py b/sickgear/webserve.py index a1f927a0..2bdf6e12 100644 --- a/sickgear/webserve.py +++ b/sickgear/webserve.py @@ -55,7 +55,8 @@ from .anime import AniGroupList, pull_anidb_groups, short_group_names from .browser import folders_at_path from .common import ARCHIVED, DOWNLOADED, FAILED, IGNORED, SKIPPED, SNATCHED, SNATCHED_ANY, UNAIRED, UNKNOWN, WANTED, \ SD, HD720p, HD1080p, UHD2160p, Overview, Quality, qualityPresetStrings, statusStrings -from .helpers import get_media_stats, has_image_ext, real_path, remove_article, remove_file_perm, starify +from .helpers import (get_media_stats, has_image_ext, is_sickgear_dir, real_path, remove_article, remove_file_perm, + starify) from .indexermapper import MapStatus, map_indexers_to_show, save_mapping from .indexers.indexer_config import TVINFO_IMDB, TVINFO_TMDB, TVINFO_TRAKT, TVINFO_TVDB, TVINFO_TVMAZE, \ TVINFO_TRAKT_SLUG, TVINFO_TVDB_SLUG @@ -332,11 +333,12 @@ class BaseHandler(RouteHandler): return True def get_image(self, image): - if os.path.isfile(image): + if None is re.search(r'\.\.[\\/]', image) and has_image_ext(image) and os.path.isfile(image) and is_sickgear_dir(image): mime_type, encoding = MimeTypes().guess_type(image) self.set_header('Content-Type', mime_type) with open(image, 'rb') as img: return img.read() + return self.set_status(404) def show_poster(self, tvid_prodid=None, which=None, api=None): # Redirect initial poster/banner thumb to default images