Skip to content

Commit 8f20052

Browse files
committed
fix patch function
1 parent 3c0c0f6 commit 8f20052

File tree

2 files changed

+100
-40
lines changed

2 files changed

+100
-40
lines changed

qbittorrent-nox-static.sh

Lines changed: 50 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1750,13 +1750,15 @@ _apply_patches() {
17501750

17511751
# Process local patches - never overwrites/updates files, only user does this
17521752
_process_local_patches() {
1753-
# Always start fresh with patch file
1754-
true > "${patch_file}"
17551753
local has_content=false
1754+
local temp_patch="${patch_file}.tmp"
1755+
1756+
# Start fresh with temp file
1757+
true > "${temp_patch}"
17561758

17571759
# Step 1: Check if main patch file exists (highest priority for base)
17581760
if [[ -f "${patch_dir}/patch" && -s "${patch_dir}/patch" ]]; then
1759-
cat "${patch_dir}/patch" > "${patch_file}"
1761+
cat "${patch_dir}/patch" > "${temp_patch}"
17601762
has_content=true
17611763
fi
17621764

@@ -1767,11 +1769,11 @@ _apply_patches() {
17671769

17681770
if _curl "${patch_url}" -o "${tmp_patch}"; then
17691771
if [[ ${has_content} == true ]]; then
1770-
printf '\n\n# Merged from URL: %s\n' "${patch_url}" >> "${patch_file}"
1772+
printf '\n\n# Merged from URL: %s\n' "${patch_url}" >> "${temp_patch}"
17711773
else
1772-
printf '# Downloaded from URL: %s\n' "${patch_url}" > "${patch_file}"
1774+
printf '# Downloaded from URL: %s\n' "${patch_url}" > "${temp_patch}"
17731775
fi
1774-
cat "${tmp_patch}" >> "${patch_file}"
1776+
cat "${tmp_patch}" >> "${temp_patch}"
17751777
rm -f "${tmp_patch}"
17761778
has_content=true
17771779
else
@@ -1789,17 +1791,23 @@ _apply_patches() {
17891791
if [[ ${#additional_patches[@]} -gt 0 ]]; then
17901792
for patch_src in "${additional_patches[@]}"; do
17911793
if [[ ${has_content} == true ]]; then
1792-
printf '\n\n# Merged from: %s\n' "${patch_src##*/}" >> "${patch_file}"
1794+
printf '\n\n# Merged from: %s\n' "${patch_src##*/}" >> "${temp_patch}"
17931795
else
1794-
printf '# From: %s\n' "${patch_src##*/}" > "${patch_file}"
1796+
printf '# From: %s\n' "${patch_src##*/}" > "${temp_patch}"
17951797
has_content=true
17961798
fi
1797-
cat "${patch_src}" >> "${patch_file}"
1799+
cat "${patch_src}" >> "${temp_patch}"
17981800
done
17991801
fi
18001802

1801-
# Final validation
1802-
[[ ${has_content} == true && -s ${patch_file} ]]
1803+
# Final validation and atomic move
1804+
if [[ ${has_content} == true && -s ${temp_patch} ]]; then
1805+
mv "${temp_patch}" "${patch_file}"
1806+
return 0
1807+
else
1808+
rm -f "${temp_patch}"
1809+
return 1
1810+
fi
18031811
}
18041812

18051813
# Download remote patches function
@@ -1812,6 +1820,12 @@ _apply_patches() {
18121820

18131821
local qbt_patches_url_branch
18141822
qbt_patches_url_branch="$(_git_git ls-remote -q --symref "https://github.com/${qbt_patches_url}" HEAD | awk '/^ref:/{sub("refs/heads/", "", $2); print $2}')"
1823+
1824+
# Validate branch name for security (allow alphanumeric, dash, underscore, dot)
1825+
if [[ ! ${qbt_patches_url_branch} =~ ^[a-zA-Z0-9._-]+$ ]]; then
1826+
printf '%b\n' " ${unicode_red_circle} Invalid branch name detected: ${qbt_patches_url_branch}"
1827+
return 1
1828+
fi
18151829
local remote_base="https://raw.githubusercontent.com/${qbt_patches_url}/${qbt_patches_url_branch}/patches/${app_name}/${app_version[${app_name}]}"
18161830
local api_url="https://api.github.com/repos/${qbt_patches_url}/contents/patches/${app_name}/${app_version[${app_name}]}"
18171831
local downloaded=false
@@ -1821,7 +1835,7 @@ _apply_patches() {
18211835
local dir_api_url="${1}"
18221836
local local_path="${2}"
18231837
local temp_json
1824-
temp_json="${patch_dir}/temp_listing_$(basename "${local_path}").json"
1838+
temp_json="${patch_dir}/temp_listing_$$_$(basename "${local_path}").json"
18251839

18261840
if _curl "${dir_api_url}" -o "${temp_json}" 2> /dev/null; then
18271841
# Parse JSON to extract entries
@@ -1836,6 +1850,13 @@ _apply_patches() {
18361850
mapfile -t types < <(printf '%s\n' "${type_matches}" | sed 's/.*"type"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/')
18371851
mapfile -t urls < <(printf '%s\n' "${url_matches}" | sed 's/.*"download_url"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/')
18381852

1853+
# Validate array lengths match before processing
1854+
if [[ ${#names[@]} -ne ${#types[@]} ]] || [[ ${#names[@]} -ne ${#urls[@]} ]]; then
1855+
printf '%b\n' " ${unicode_yellow_circle} Array length mismatch in JSON parsing, skipping"
1856+
rm -f "${temp_json}"
1857+
return 1
1858+
fi
1859+
18391860
# Process each entry
18401861
for i in "${!names[@]}"; do
18411862
local name="${names[i]}" type="${types[i]}" url="${urls[i]}"
@@ -1889,18 +1910,27 @@ _apply_patches() {
18891910
else
18901911
method="patch"
18911912
fi
1892-
printf '%b\n\n' " ${unicode_red_circle} Applying: ${color_cyan_light}${1##*/}${color_end} using ${color_yellow_light}${method}${color_end}"
1913+
printf '\n%b\n\n' " ${unicode_green_circle} Applying: ${color_cyan_light}${1##*/}${color_end} using ${color_yellow_light}${method}${color_end}"
18931914
if [[ ${method} == "git" ]] && git -C "${qbt_dl_folder_path}" apply --check "${1}" &> /dev/null; then
1894-
git -C "${qbt_dl_folder_path}" apply "${1}"
1915+
if git -C "${qbt_dl_folder_path}" apply "${1}"; then
1916+
printf '\n%b\n\n' " ${unicode_green_circle} Patch applied successfully using git"
1917+
else
1918+
printf '\n%b\n\n' " ${unicode_red_circle} Failed to apply patch using git"
1919+
return 1
1920+
fi
18951921
else
18961922
_pushd "${qbt_dl_folder_path}"
1897-
patch -p1 < "${1}"
1923+
if patch -p1 < "${1}"; then
1924+
printf '\n%b\n\n' " ${unicode_green_circle} Patch applied successfully using patch"
1925+
else
1926+
printf '\n%b\n\n' " ${unicode_red_circle} Failed to apply patch using patch"
1927+
_popd
1928+
return 1
1929+
fi
18981930
_popd
18991931
fi
19001932
}
19011933

1902-
[[ ${source_default[${app_name}]} == "folder" && ! -d "${qbt_cache_dir}/${app_name}" ]] && printf '\n'
1903-
19041934
# Method 1: Source directory method (highest priority)
19051935
if [[ -d "${patch_dir}/source" && -n "$(ls -A "${patch_dir}/source" 2> /dev/null)" ]]; then
19061936
printf '%b\n' " ${unicode_green_circle} Using source directory method"
@@ -1938,7 +1968,7 @@ _apply_patches() {
19381968
elif [[ -f "${patch_dir}/Jamfile" ]]; then
19391969
cp -f "${patch_dir}/Jamfile" "${jamfile_dest}"
19401970
else
1941-
local remote_jamfile="https://raw.githubusercontent.com/${qbt_patches_url}/${qbt_patches_url_branch:-main}/patches/${app_name}/${app_version[${app_name}]}/Jamfile"
1971+
local remote_jamfile="https://raw.githubusercontent.com/${qbt_patches_url}/${qbt_patches_url_branch}/patches/${app_name}/${app_version[${app_name}]}/Jamfile"
19421972
_curl "${remote_jamfile}" -o "${jamfile_dest}" 2> /dev/null
19431973
fi
19441974
fi
@@ -2075,7 +2105,7 @@ _download_folder() {
20752105
# Force clean clone if patches are detected
20762106
if [[ -f ${patch_file} && -s ${patch_file} ]] || [[ -f "${patch_dir}/url" ]] || [[ -d "${patch_dir}/source" && -n "$(ls -A "${patch_dir}/source" 2> /dev/null)" ]]; then
20772107
needs_clean_clone=true
2078-
[[ -d ${qbt_dl_folder_path} ]] && printf '%b\n' " ${unicode_yellow_circle} Forcing clean clone due to patches"
2108+
[[ -d ${qbt_dl_folder_path} ]] && printf '\n%b\n' " ${unicode_yellow_circle} Forcing clean clone due to patches"
20792109
fi
20802110

20812111
# Remove the source files in the build directory if present before we download or copy them again
@@ -2261,7 +2291,7 @@ _download_file() {
22612291
rm -rf "${qbt_install_dir:?}/${archive_dir_name}" "${qbt_install_dir}/${app_name}.tar.xz"
22622292
elif [[ ${needs_clean_extract} == true ]]; then
22632293
# Clean up without archive validation when forcing clean extract
2264-
[[ ${needs_clean_extract} == true ]] && printf '%b\n' " ${unicode_yellow_circle} Forcing clean extraction due to patches"
2294+
[[ ${needs_clean_extract} == true ]] && printf '\n%b\n' " ${unicode_yellow_circle} Forcing clean extraction due to patches"
22652295
elif [[ -f ${qbt_dl_file_path} ]]; then
22662296
_error_tag "${app_name}" "Failed to safely extract archive directory name from ${qbt_dl_file_path}"
22672297
fi

qbt-nox-static.bash

Lines changed: 50 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1750,13 +1750,15 @@ _apply_patches() {
17501750

17511751
# Process local patches - never overwrites/updates files, only user does this
17521752
_process_local_patches() {
1753-
# Always start fresh with patch file
1754-
true > "${patch_file}"
17551753
local has_content=false
1754+
local temp_patch="${patch_file}.tmp"
1755+
1756+
# Start fresh with temp file
1757+
true > "${temp_patch}"
17561758

17571759
# Step 1: Check if main patch file exists (highest priority for base)
17581760
if [[ -f "${patch_dir}/patch" && -s "${patch_dir}/patch" ]]; then
1759-
cat "${patch_dir}/patch" > "${patch_file}"
1761+
cat "${patch_dir}/patch" > "${temp_patch}"
17601762
has_content=true
17611763
fi
17621764

@@ -1767,11 +1769,11 @@ _apply_patches() {
17671769

17681770
if _curl "${patch_url}" -o "${tmp_patch}"; then
17691771
if [[ ${has_content} == true ]]; then
1770-
printf '\n\n# Merged from URL: %s\n' "${patch_url}" >> "${patch_file}"
1772+
printf '\n\n# Merged from URL: %s\n' "${patch_url}" >> "${temp_patch}"
17711773
else
1772-
printf '# Downloaded from URL: %s\n' "${patch_url}" > "${patch_file}"
1774+
printf '# Downloaded from URL: %s\n' "${patch_url}" > "${temp_patch}"
17731775
fi
1774-
cat "${tmp_patch}" >> "${patch_file}"
1776+
cat "${tmp_patch}" >> "${temp_patch}"
17751777
rm -f "${tmp_patch}"
17761778
has_content=true
17771779
else
@@ -1789,17 +1791,23 @@ _apply_patches() {
17891791
if [[ ${#additional_patches[@]} -gt 0 ]]; then
17901792
for patch_src in "${additional_patches[@]}"; do
17911793
if [[ ${has_content} == true ]]; then
1792-
printf '\n\n# Merged from: %s\n' "${patch_src##*/}" >> "${patch_file}"
1794+
printf '\n\n# Merged from: %s\n' "${patch_src##*/}" >> "${temp_patch}"
17931795
else
1794-
printf '# From: %s\n' "${patch_src##*/}" > "${patch_file}"
1796+
printf '# From: %s\n' "${patch_src##*/}" > "${temp_patch}"
17951797
has_content=true
17961798
fi
1797-
cat "${patch_src}" >> "${patch_file}"
1799+
cat "${patch_src}" >> "${temp_patch}"
17981800
done
17991801
fi
18001802

1801-
# Final validation
1802-
[[ ${has_content} == true && -s ${patch_file} ]]
1803+
# Final validation and atomic move
1804+
if [[ ${has_content} == true && -s ${temp_patch} ]]; then
1805+
mv "${temp_patch}" "${patch_file}"
1806+
return 0
1807+
else
1808+
rm -f "${temp_patch}"
1809+
return 1
1810+
fi
18031811
}
18041812

18051813
# Download remote patches function
@@ -1812,6 +1820,12 @@ _apply_patches() {
18121820

18131821
local qbt_patches_url_branch
18141822
qbt_patches_url_branch="$(_git_git ls-remote -q --symref "https://github.com/${qbt_patches_url}" HEAD | awk '/^ref:/{sub("refs/heads/", "", $2); print $2}')"
1823+
1824+
# Validate branch name for security (allow alphanumeric, dash, underscore, dot)
1825+
if [[ ! ${qbt_patches_url_branch} =~ ^[a-zA-Z0-9._-]+$ ]]; then
1826+
printf '%b\n' " ${unicode_red_circle} Invalid branch name detected: ${qbt_patches_url_branch}"
1827+
return 1
1828+
fi
18151829
local remote_base="https://raw.githubusercontent.com/${qbt_patches_url}/${qbt_patches_url_branch}/patches/${app_name}/${app_version[${app_name}]}"
18161830
local api_url="https://api.github.com/repos/${qbt_patches_url}/contents/patches/${app_name}/${app_version[${app_name}]}"
18171831
local downloaded=false
@@ -1821,7 +1835,7 @@ _apply_patches() {
18211835
local dir_api_url="${1}"
18221836
local local_path="${2}"
18231837
local temp_json
1824-
temp_json="${patch_dir}/temp_listing_$(basename "${local_path}").json"
1838+
temp_json="${patch_dir}/temp_listing_$$_$(basename "${local_path}").json"
18251839

18261840
if _curl "${dir_api_url}" -o "${temp_json}" 2> /dev/null; then
18271841
# Parse JSON to extract entries
@@ -1836,6 +1850,13 @@ _apply_patches() {
18361850
mapfile -t types < <(printf '%s\n' "${type_matches}" | sed 's/.*"type"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/')
18371851
mapfile -t urls < <(printf '%s\n' "${url_matches}" | sed 's/.*"download_url"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/')
18381852

1853+
# Validate array lengths match before processing
1854+
if [[ ${#names[@]} -ne ${#types[@]} ]] || [[ ${#names[@]} -ne ${#urls[@]} ]]; then
1855+
printf '%b\n' " ${unicode_yellow_circle} Array length mismatch in JSON parsing, skipping"
1856+
rm -f "${temp_json}"
1857+
return 1
1858+
fi
1859+
18391860
# Process each entry
18401861
for i in "${!names[@]}"; do
18411862
local name="${names[i]}" type="${types[i]}" url="${urls[i]}"
@@ -1889,18 +1910,27 @@ _apply_patches() {
18891910
else
18901911
method="patch"
18911912
fi
1892-
printf '%b\n\n' " ${unicode_red_circle} Applying: ${color_cyan_light}${1##*/}${color_end} using ${color_yellow_light}${method}${color_end}"
1913+
printf '\n%b\n\n' " ${unicode_green_circle} Applying: ${color_cyan_light}${1##*/}${color_end} using ${color_yellow_light}${method}${color_end}"
18931914
if [[ ${method} == "git" ]] && git -C "${qbt_dl_folder_path}" apply --check "${1}" &> /dev/null; then
1894-
git -C "${qbt_dl_folder_path}" apply "${1}"
1915+
if git -C "${qbt_dl_folder_path}" apply "${1}"; then
1916+
printf '\n%b\n\n' " ${unicode_green_circle} Patch applied successfully using git"
1917+
else
1918+
printf '\n%b\n\n' " ${unicode_red_circle} Failed to apply patch using git"
1919+
return 1
1920+
fi
18951921
else
18961922
_pushd "${qbt_dl_folder_path}"
1897-
patch -p1 < "${1}"
1923+
if patch -p1 < "${1}"; then
1924+
printf '\n%b\n\n' " ${unicode_green_circle} Patch applied successfully using patch"
1925+
else
1926+
printf '\n%b\n\n' " ${unicode_red_circle} Failed to apply patch using patch"
1927+
_popd
1928+
return 1
1929+
fi
18981930
_popd
18991931
fi
19001932
}
19011933

1902-
[[ ${source_default[${app_name}]} == "folder" && ! -d "${qbt_cache_dir}/${app_name}" ]] && printf '\n'
1903-
19041934
# Method 1: Source directory method (highest priority)
19051935
if [[ -d "${patch_dir}/source" && -n "$(ls -A "${patch_dir}/source" 2> /dev/null)" ]]; then
19061936
printf '%b\n' " ${unicode_green_circle} Using source directory method"
@@ -1938,7 +1968,7 @@ _apply_patches() {
19381968
elif [[ -f "${patch_dir}/Jamfile" ]]; then
19391969
cp -f "${patch_dir}/Jamfile" "${jamfile_dest}"
19401970
else
1941-
local remote_jamfile="https://raw.githubusercontent.com/${qbt_patches_url}/${qbt_patches_url_branch:-main}/patches/${app_name}/${app_version[${app_name}]}/Jamfile"
1971+
local remote_jamfile="https://raw.githubusercontent.com/${qbt_patches_url}/${qbt_patches_url_branch}/patches/${app_name}/${app_version[${app_name}]}/Jamfile"
19421972
_curl "${remote_jamfile}" -o "${jamfile_dest}" 2> /dev/null
19431973
fi
19441974
fi
@@ -2075,7 +2105,7 @@ _download_folder() {
20752105
# Force clean clone if patches are detected
20762106
if [[ -f ${patch_file} && -s ${patch_file} ]] || [[ -f "${patch_dir}/url" ]] || [[ -d "${patch_dir}/source" && -n "$(ls -A "${patch_dir}/source" 2> /dev/null)" ]]; then
20772107
needs_clean_clone=true
2078-
[[ -d ${qbt_dl_folder_path} ]] && printf '%b\n' " ${unicode_yellow_circle} Forcing clean clone due to patches"
2108+
[[ -d ${qbt_dl_folder_path} ]] && printf '\n%b\n' " ${unicode_yellow_circle} Forcing clean clone due to patches"
20792109
fi
20802110

20812111
# Remove the source files in the build directory if present before we download or copy them again
@@ -2261,7 +2291,7 @@ _download_file() {
22612291
rm -rf "${qbt_install_dir:?}/${archive_dir_name}" "${qbt_install_dir}/${app_name}.tar.xz"
22622292
elif [[ ${needs_clean_extract} == true ]]; then
22632293
# Clean up without archive validation when forcing clean extract
2264-
[[ ${needs_clean_extract} == true ]] && printf '%b\n' " ${unicode_yellow_circle} Forcing clean extraction due to patches"
2294+
[[ ${needs_clean_extract} == true ]] && printf '\n%b\n' " ${unicode_yellow_circle} Forcing clean extraction due to patches"
22652295
elif [[ -f ${qbt_dl_file_path} ]]; then
22662296
_error_tag "${app_name}" "Failed to safely extract archive directory name from ${qbt_dl_file_path}"
22672297
fi

0 commit comments

Comments
 (0)