Compare commits

..
Author SHA1 Message Date
Maksim IvanovandGitHub 0150fa9bc9 Merge pull request #48 from sewi-cpan/fix/tmp-symlink-vuln
Fix predictable /tmp path enabling symlink attack as root
2026-08-17 11:48:57 +03:00
Maksim IvanovandGitHub b22229d589 Merge pull request #49 from FishyW/main
Fix dnf install command in install.sh
2026-08-17 11:48:29 +03:00
WinstonandGitHub 07c8df08c6 Fix dnf install command in install.sh 2026-08-14 11:53:34 +07:00
Sebastian WillingandClaude Sonnet 5 42fe8e0176 Fix predictable /tmp path enabling symlink attack as root
fix-opera.sh runs as root and used a fixed, world-guessable temp
directory (/tmp/opera-fix) created with `mkdir -p`, which succeeds
silently even if the path already exists. A local unprivileged user
could pre-create /tmp/opera-fix as a symlink to a directory they
control and place a malicious libffmpeg.so/libwidevinecdm.so there
ahead of time. When an admin later ran this script, root would copy
the attacker's library into Opera's lib_extra with 0644 perms, where
it gets loaded into every user's browser process on the system.

Switch to `mktemp -d`, which atomically creates a private (0700),
unpredictably-named directory via a bare mkdir() syscall - exclusive
by nature, so it can never adopt a pre-existing path or symlink the
way `mkdir -p` does. Also drop the now-redundant mkdir -p call, since
mktemp already creates the directory.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-11 08:08:40 +02:00
Maksim IvanovandGitHub a0e9672c45 Merge pull request #47 from mubat/mubat-add-chmod-for-fix-opera-sh
make script executable before executing
2026-08-05 20:38:33 +03:00
Oleh SerhiienkoandGitHub 839f0c06c0 make script executable before executing 2026-07-14 10:20:00 +03:00
Maksim IvanovandGitHub ff1e848f40 Update README.md 2026-07-09 15:23:20 +03:00
Maksim IvanovandGitHub 1cfefbdb35 Merge pull request #45 from alpham8/feature/opensuse-support
feature: openSUSE distribution support expect package manager events
2026-05-30 21:27:20 +03:00
Thomas Wunner 0ca3c8c537 match underlying Chromium version to the compatible ffmpeg and widevine version, repeat this procedure for all installed variants of Opera browser by using temp cache for downloaded assets 2026-05-16 16:22:11 +02:00
Thomas Wunner 3eed381155 Merge branch 'main' into feature/opensuse-support
# Conflicts:
#	install.sh
#	scripts/99fix-opera
#	scripts/fix-opera.sh
2026-05-16 14:49:54 +02:00
Thomas Wunner 86fab5688a openSUSE fixes to install scripts 2026-05-16 14:39:36 +02:00
Maksim IvanovandGitHub a46ad6f23a basic support for opera-gx (no autoupdate) 2026-03-20 17:21:53 +03:00
Maksim Ivanov dc5682f9a7 Merge branch 'EvilSupahFly-main' 2026-03-04 20:43:47 +03:00
Maksim Ivanov 62650fe1a8 Fixed errors from PR 2026-03-04 20:42:53 +03:00
EvilSupahFly 2a33d9ba9e Updated README, install.sh 2025-12-30 22:39:15 -05:00
EvilSupahFly fe3ce4eba2 Reworked install / uninstall
Hardened scripts a little, made them more distro agnostic
2025-12-30 19:53:58 -05:00
Thomas Wunner b1726cb9be minor code style and runtime fixes to be more standard-compliant 2025-10-12 08:01:04 +02:00
Maksim Ivanov 5b767c8077 Getting link for latest Widevine from Mozilla Firefox sources 2025-09-14 19:21:07 +03:00
Maksim IvanovandGitHub c905b7d638 Merge pull request #36 from valdineidossantos/fix_jq_syntax
fix: correct jq syntax for fetching latest ffmpeg release URLs
2025-09-03 20:39:28 +03:00
Valdinei Santos 067428f6c2 fix: correct jq syntax for fetching latest ffmpeg release URLs 2025-09-03 10:33:36 -03:00
Maksim IvanovandGitHub ed5dd641d8 fix for release sorting 2025-08-29 06:46:57 +03:00
Maksim IvanovandGitHub 74b21fee16 jq sort_by for getteng latest ffmpeg release 2025-08-28 14:22:22 +03:00
Maksim IvanovandGitHub c71d341623 Merge pull request #34 from EvilSupahFly/main
Fix Widevine 404 by falling back to older available versions
2025-08-28 11:07:25 +03:00
EvilSupahFlyandGitHub 3648b2851f Merge pull request #1 from EvilSupahFly/EvilSupahFly-patch-1
Update fix-opera.sh: Change Widevine download logic to:
 - Iterate through all versions from newest to oldest.
 - Test each candidate URL with curl --fail.
 - Select the first available version.
 - Exit gracefully if none are found.
2025-08-26 19:15:31 -04:00
EvilSupahFlyandGitHub 7290f690c8 Update fix-opera.sh
Change Widevine download logic to:
- Iterate through all versions from newest to oldest.
- Test each candidate URL with curl --fail.
- Select the first available version.
- Exit gracefully if none are found.
2025-08-26 19:13:10 -04:00
Maksim IvanovandGitHub 67c77ad757 Update 99fix-opera
statement fix
2025-01-21 21:20:47 +03:00
Maksim IvanovandGitHub f4bd58a9c5 Update 99fix-opera. Workaround for #28 2024-09-25 10:46:00 +03:00
Maksim Ivanov 91a5ccb80e replaced wget with curl 2024-05-31 21:27:08 +03:00
Maksim IvanovandGitHub f6e3f12c53 Update README.md
added info about jq requirement
2024-05-31 09:17:55 +03:00
Maksim IvanovandGitHub 92a3a3f153 Merge pull request #26 from FishyW/main
wget2 related fixes
2024-05-31 09:14:06 +03:00
fishyW 3de916e3ea replace jq with jq -r 2024-05-31 13:49:48 +10:00
fishyW 2d5105a129 'jq check 2024-05-30 22:38:06 +10:00
fishyW 031316d313 gets rid of which: no pacman message in non arch distributions 2024-05-30 22:34:38 +10:00
fishyW 7212c9490f wget compatibility + jq fix 2024-05-30 22:33:17 +10:00
Maksim IvanovandGitHub 98a86e2c16 Update README.md 2024-01-26 19:37:35 +03:00
Maksim IvanovandGitHub 6fca65a523 Update README.md 2024-01-26 09:40:54 +03:00
Maksim IvanovandGitHub 892b090031 Create uninstall.sh 2024-01-26 09:37:22 +03:00
Maksim IvanovandGitHub 364c391a66 Update README.md 2023-10-21 23:46:24 +03:00
Maksim IvanovandGitHub 60b55b813b Fixed Arch system check 2023-09-15 09:32:25 +03:00
Maksim IvanovandGitHub 423c8ea9ec Removed hardcoded path for Arch systems 2023-09-12 11:20:41 +03:00
Maksim IvanovandGitHub e0e13e6cb1 Merge pull request #18 from kyrbrbik/main
Fix for arch based systems
2023-09-12 11:17:31 +03:00
kyrbrbik 0883b15800 this should be true 2023-09-04 22:08:17 +02:00
kyrbrbik 927444aaaa fixed opera path for arch 2023-09-04 22:05:32 +02:00
Maksim IvanovandGitHub 5fbd2e216e Merge pull request #15 from arielj/fix-readonly-variables
Download files only once, fix issue setting readonly vars
2023-06-11 19:23:41 +03:00
Ariel Juodziukynas e06398b956 Download files only once, fix issue setting readonly vars 2023-06-11 13:02:14 -03:00
Maksim IvanovandGitHub 4b4541cd59 Merge pull request #14 from arielj/fix-array-push
Push elements into array instead of concatenating strings
2023-06-11 18:55:20 +03:00
Ariel Juodziukynas a850c9bb5c Push elements into bash array instead of string concat 2023-06-11 12:44:09 -03:00
Maksim IvanovandGitHub 40513adc42 Merge pull request #13 from kaptcha0/patch-1
Update fix-opera.sh
2023-06-11 12:07:28 +03:00
kaptchaandGitHub 8d56cf17dd Update fix-opera.sh
Added support for multiple Opera versions, mainly the stable and beta versions.
2023-06-10 13:48:26 -04:00
Maksim IvanovandGitHub 976ea8fb35 ffmpeg source for future releases moved
New source https://github.com/Ld-Hagen/nwjs-ffmpeg-prebuilt/releases
2023-01-01 14:50:43 +03:00
Maksim IvanovandGitHub 8dba65eec6 Fixed bad options order for wget 2022-12-30 21:51:57 +03:00
Maksim IvanovandGitHub b77acfb324 Merge pull request #11 from leonmcar1/patch-1
Disable ipv6 for wget
2022-12-26 18:46:42 +03:00
leonmcar1andGitHub 59dc39dfbc wget issues
Within the network where I work, only enabling in wget the --inet4-only the script works.
2022-12-21 13:50:43 +00:00
Maksim IvanovandGitHub 96dcbff82e Fixed message in install.sh 2022-04-22 22:20:37 +03:00
Maksim IvanovandGitHub 5f3fa8273a Disabled main ffmpeg source 2022-04-18 15:08:37 +03:00
Ld-Hagen 58be0f5c1c Readme update, dnf hook fix 2021-10-26 21:57:14 +03:00
Ld-Hagen 52954635c8 Hook for RedHat based systems (using dnf package manager). Untested. 2021-10-26 20:59:59 +03:00
Ld-Hagen 8c64261203 No hardcoded Opera directory in apt hook. Some text messages and readme changes 2021-10-14 18:42:27 +03:00
8 changed files with 443 additions and 139 deletions
+29
View File
@@ -0,0 +1,29 @@
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
### Added
- version-aware ffmpeg selection: detect Opera's bundled Chromium version and download the matching nwjs-ffmpeg release instead of always using the latest
- per-variant Chromium detection via binary inspection (`get_chromium_major`)
- ffmpeg download caching: skip re-download when multiple Opera variants share the same Chromium version
### Changed
- universal shebang bash interpreter to safely find bash on `$PATH`
- Widevine CDM is now downloaded once before the main loop instead of redundantly per variant
- release data is fetched once upfront (`?per_page=50`) and reused for version matching
### Removed
### Fixed
- in the preflight check: Prefer our user-friendly error messages while avoiding double error message from the operating system by redirecting also `stderr` to `/dev/null`
- potential runtime error: prefer `command -v` over `which`-command, which can have different behaviour on different Linux distributions and always use the first result in `PATH` independently of multiple defined commands
- `grep` error when `CDM_FLAG` starts with `--` by adding explicit end-of-options separator (`grep -qF -- "$CDM_FLAG"`)
+45 -14
View File
@@ -1,38 +1,69 @@
> [!WARNING]
> Make sure, you're using latest version of this script. If not, update it (run installation steps again, say "n" when it asks for creating alias).
>
> Since the may, 16th it doesn't get the latest libffmpeg, but checks for version compatibility.
> [!NOTE]
> All future versions of libffmpeg will be posted in https://github.com/Ld-Hagen/nwjs-ffmpeg-prebuilt/releases instead of this repo.
# Fix Opera Linux libffmpeg & WidevineCdm # Fix Opera Linux libffmpeg & WidevineCdm
* Fixes Opera html5 media content including DRM-protected one. * Fixes Opera html5 media content including DRM-protected one.
* This script must be executed all times opera fails on showing html5 media content. * This script must be executed all times opera fails on showing html5 media content.
* On Debian-based and Arch-based distributions it could be started automatically after Opera each update or reinstall. * On Debian-based, RedHat-based and Arch-based distributions it could be started automatically after Opera each update or reinstall.
* Works only with native versions of Opera. Won't work with flatpak/snap releses.
* May not work with opera-beta and opera-develper.
## Requirements ## Requirements
1. **wget** (Is needed for downloading the ffmpeg lib and widevine) 1. **curl** (is needed for downloading the ffmpeg lib and widevine)
```sudo apt install wget```
2. **unzip** (Is needed for unpacking the downloaded file) **unzip** (is needed for unpacking the downloaded file)
```sudo apt install unzip```
2. **git** (Is needed for fetching this script) **git** (is needed for fetching this script)
```sudo apt install git```
**jq** (is needed for parsing JSON from github)
2. (*Optional*) **python3-dnf-plugin-post-transaction-actions** (is needed for autoupdate in RedHat-based systems)
The main installer - `install.sh` - auto-detects your distro and installs the both the appropriate and the optional requirements by itself, if they're missing.
## Usage ## Usage
1. Clone this repo 1. Clone this repo
```git clone https://github.com/Ld-Hagen/fix-opera-linux-ffmpeg-widevine.git``` `git clone https://github.com/Ld-Hagen/fix-opera-linux-ffmpeg-widevine.git`
2. Go to the repo root folder 2. Go to the repo root folder
```cd ./fix-opera-linux-ffmpeg-widevine``` `cd ./fix-opera-linux-ffmpeg-widevine`
3. (*Optional*) Run script. And if it works well go to next step. 3. (*Optional*) Run script. And if it works well go to next step.
```sudo ./scripts/fix-opera.sh``` `chmod +x scripts/fix-opera.sh && sudo ./scripts/fix-opera.sh`
4. Run install script and answer few questions. 4. Make install.sh executable
```sudo ./install.sh``` `chmod +x ./install.sh`
5. Delete the repo 5. Run install script and answer few questions.
```cd .. && rm -rf ./fix-opera-linux-ffmpeg-widevine``` `sudo ./install.sh`
## How to uninstall
1. Clone this repo
`cd /tmp && git clone https://github.com/Ld-Hagen/fix-opera-linux-ffmpeg-widevine.git`
2. Go to the repo root folder
`cd /tmp/fix-opera-linux-ffmpeg-widevine`
3. Make uninstall.sh executable
`chmod +x uninstall.sh`
5. Run uninstallation script. And if it works well go to next step.
`sudo ./uninstall.sh`
+98 -52
View File
@@ -1,4 +1,79 @@
#!/bin/bash #!/usr/bin/env bash
set -euo pipefail
detect_pkg_manager() {
if command -v apt-get >/dev/null 2>&1; then
PKG_MGR="apt"
elif command -v dnf >/dev/null 2>&1; then
PKG_MGR="dnf"
elif command -v pacman >/dev/null 2>&1; then
PKG_MGR="pacman"
elif command -v zypper >/dev/null 2>&1; then
PKG_MGR="zypper"
elif command -v emerge >/dev/null 2>&1; then
PKG_MGR="portage"
else
PKG_MGR="unknown"
fi
if [[ "$PKG_MGR" == "unknown" ]]; then
echo "Unsupported package manager"
exit 1
fi
}
install_deps() {
DEPS=(curl unzip jq)
case "$PKG_MGR" in
apt)
apt-get update
apt-get install -y "${DEPS[@]}"
;;
dnf)
dnf install -y "${DEPS[@]}" python3-dnf-plugin-post-transaction-actions
;;
pacman)
pacman -Sy --needed --noconfirm "${DEPS[@]}"
;;
zypper)
zypper install -y "${DEPS[@]}"
;;
portage)
emerge --ask=n "${DEPS[@]}"
;;
*)
echo "Unsupported package manager. Install dependencies manually:"
echo " ${DEPS[*]}"
exit 1
;;
esac
}
install_hook () {
case "$PKG_MGR" in
apt)
cp -f "$SCRIPT_PATH/scripts/99fix-opera" "$INSTALL_PATH"
ln -sf "$INSTALL_PATH/99fix-opera" /etc/apt/apt.conf.d/99fix-opera
;;
pacman)
cp -f "$SCRIPT_PATH/scripts/fix-opera.hook" "$INSTALL_PATH"
ln -sf "$INSTALL_PATH/fix-opera.hook" /usr/share/libalpm/hooks/fix-opera.hook
;;
dnf)
dnf install -y python3-dnf-plugin-post-transaction-actions
cp -f "$SCRIPT_PATH/scripts/fix-opera.action" "$INSTALL_PATH"
ln -sf "$INSTALL_PATH/fix-opera.action" \
/etc/dnf/plugins/post-transaction-actions.d/fix-opera.action
;;
*)
echo "Automatic hook installation not supported for this system."
return 1
;;
esac
}
if [[ $(whoami) != "root" ]]; then if [[ $(whoami) != "root" ]]; then
printf 'Try to run it with sudo\n' printf 'Try to run it with sudo\n'
exit 1 exit 1
@@ -14,55 +89,44 @@ if ! which unzip > /dev/null; then
exit 1 exit 1
fi fi
if ! which wget > /dev/null; then if ! which curl > /dev/null; then
printf '\033[1mwget\033[0m package must be installed to run this script\n' printf '\033[1mcurl\033[0m package must be installed to run this script\n'
exit 1
fi
if ! which jq > /dev/null; then
printf '\033[1mjq\033[0m package must be installed to run this script\n'
exit 1 exit 1
fi fi
readonly SCRIPT_PATH=$(dirname $(readlink -f $0)) readonly SCRIPT_PATH=$(dirname $(readlink -f $0))
readonly INSTALL_PATH="/root/.scripts" readonly INSTALL_PATH="/root/.scripts"
readonly USER_NAME="$(logname)" readonly USER_NAME="${SUDO_USER:-$(logname)}"
readonly USER_HOME=$(sudo -u $USER_NAME sh -c 'echo $HOME') readonly USER_HOME=$(getent passwd "$USER_NAME" | cut -d: -f6)
mkdir -p $INSTALL_PATH
create_hook () printf 'Installing script to your system...\n'
{
printf 'Choose your Linux distro:\n'
printf ' 1. Debian-based (Debian/Ubuntu/Mint/etc.)\n'
printf ' 2. Arch-based (Arch/Manjaro/etc.)\n'
printf ' 0. Other\n'
while read -p "Your choice: " DISTRIB; do
case $DISTRIB in
"1" )
cp -f $SCRIPT_PATH/scripts/99fix-opera $INSTALL_PATH
ln -sf $INSTALL_PATH/99fix-opera /etc/apt/apt.conf.d/
printf 'Now the script will run automatically every time apt installs or updates Opera.\n'
break;;
"2" )
cp -f $SCRIPT_PATH/scripts/fix-opera.hook $INSTALL_PATH /usr/share/libalpm/hooks
ln -sf $INSTALL_PATH/fix-opera.hook /usr/share/libalpm/hooks/
printf 'Now the script will run automatically every time pacman installs or updates Opera.\n'
break;;
"0" )
printf "Autostart for your Linux distro is currently unsupported\n"
break;;
* )
continue;;
esac
done
}
ptintf 'Installing script to your system...\n' detect_pkg_manager
install_deps
read -p "Enable automatic execution after Opera updates? [y/N] " AUTO
[[ "$AUTO" =~ ^[Yy]$ ]] && install_hook
mkdir -p "$INSTALL_PATH"
cp -f "$SCRIPT_PATH/scripts/fix-opera.sh" "$INSTALL_PATH"
chmod +x "$INSTALL_PATH/fix-opera.sh"
printf 'Would you like to apply Widevine CDM fix? [y/n]' printf 'Would you like to apply Widevine CDM fix? [y/n]'
while read FIX_WIDEVINE; do while read FIX_WIDEVINE; do
case $FIX_WIDEVINE in case $FIX_WIDEVINE in
"y" | "Y") "y" | "Y")
printf 'Setting FIX_WIDEVINE to true...\n' printf 'Setting FIX_WIDEVINE to true...\n'
sed -i '/FIX_WIDEVINE=/s/false/true/g' $SCRIPT_PATH/scripts/fix-opera.sh sed -i '/FIX_WIDEVINE=/s/false/true/g' $INSTALL_PATH/fix-opera.sh
break;; break;;
"n" | "N") "n" | "N")
printf 'Setting FIX_WIDEVINE to false...\n' printf 'Setting FIX_WIDEVINE to false...\n'
sed -i '/FIX_WIDEVINE=/s/true/false/g' $SCRIPT_PATH/scripts/fix-opera.sh sed -i '/FIX_WIDEVINE=/s/true/false/g' $INSTALL_PATH/fix-opera.sh
break;; break;;
* ) * )
printf 'Would you like to apply Widevine CDM fix? [y/n]' printf 'Would you like to apply Widevine CDM fix? [y/n]'
@@ -70,10 +134,6 @@ while read FIX_WIDEVINE; do
esac esac
done done
mkdir -p $INSTALL_PATH
cp -f $SCRIPT_PATH/scripts/fix-opera.sh $INSTALL_PATH
chmod +x $INSTALL_PATH/fix-opera.sh
printf "Would you like to create an alias for user $USER_NAME? [y/n]" printf "Would you like to create an alias for user $USER_NAME? [y/n]"
while read CREATE_ALIAS; do while read CREATE_ALIAS; do
case $CREATE_ALIAS in case $CREATE_ALIAS in
@@ -89,20 +149,6 @@ while read CREATE_ALIAS; do
esac esac
done done
printf "Would you like to run it automatically after each Opera update? [y/n]"
while read CREATE_HOOK; do
case $CREATE_HOOK in
"y" | "Y")
create_hook
break;;
"n" | "N")
break;;
* )
printf "Would you like to create an alias for user $USER_NAME? [y/n]"
continue;;
esac
done
printf "Would you like to run it now? [y/n]" printf "Would you like to run it now? [y/n]"
while read RUN_NOW; do while read RUN_NOW; do
case $RUN_NOW in case $RUN_NOW in
+2 -2
View File
@@ -1,2 +1,2 @@
DPkg::Pre-Invoke {"stat -c %Z $(readlink -f $(which opera)) > /tmp/opera.timestamp";}; DPkg::Pre-Invoke {"stat -c %Z $(readlink -f $(command -v opera)) > /tmp/opera.timestamp 2> /dev/null || echo 0 > /tmp/opera.timestamp";};
DPkg::Post-Invoke {"if [ `stat -c %Z $(readlink -f $(which opera))` -ne `cat /tmp/opera.timestamp` ]; then /root/.scripts/fix-opera.sh; fi; rm /tmp/opera.timestamp";}; DPkg::Post-Invoke {"set NEW_OPERA=`stat -c %Z $(readlink -f $(command -v opera))` || exit 0; set OLD_OPERA=`cat /tmp/opera.timestamp` || exit 0; if [ "$NEW_OPERA" != "$OLD_OPERA" ]; then /root/.scripts/fix-opera.sh; fi; rm -f /tmp/opera.timestamp";};
+1
View File
@@ -0,0 +1 @@
opera-stable:in:/root/.scripts/fix-opera.sh
+2 -1
View File
@@ -10,6 +10,7 @@ Target = opera
Description = Fix video playback in Opera browser Description = Fix video playback in Opera browser
When = PostTransaction When = PostTransaction
Depends = bash Depends = bash
Depends = wget Depends = curl
Depends = unzip Depends = unzip
Depends = jq
Exec = /root/.scripts/fix-opera.sh Exec = /root/.scripts/fix-opera.sh
+195 -60
View File
@@ -1,4 +1,4 @@
#!/bin/bash #!/usr/bin/env bash
if [[ $(whoami) != "root" ]]; then if [[ $(whoami) != "root" ]]; then
printf 'Try to run it with sudo\n' printf 'Try to run it with sudo\n'
@@ -10,101 +10,236 @@ if [[ $(uname -m) != "x86_64" ]]; then
exit 1 exit 1
fi fi
if ! which unzip > /dev/null; then if ! command -v unzip 2>&1 /dev/null; then
printf '\033[1munzip\033[0m package must be installed to run this script\n' printf '\033[1munzip\033[0m package must be installed to run this script\n'
exit 1 exit 1
fi fi
if ! which wget > /dev/null; then if ! command -v curl 2>&1 /dev/null; then
printf '\033[1mwget\033[0m package must be installed to run this script\n' printf '\033[1mcurl\033[0m package must be installed to run this script\n'
exit 1 exit 1
fi fi
if ! command -v jq 2>&1 /dev/null; then
printf '\033[1mjq\033[0m package must be installed to run this script\n'
exit 1
fi
if command -v pacman &> /dev/null; then
ARCH_SYSTEM=true
fi
#Config section #Config section
readonly FIX_WIDEVINE=true readonly FIX_WIDEVINE=true
readonly TEMP_DIR='/tmp' FIX_DIR=$(mktemp -d -t opera-fix.XXXXXXXX)
readonly FFMPEG_SRC_MAIN='https://api.github.com/repos/iteufel/nwjs-ffmpeg-prebuilt/releases' if [[ ! -d "$FIX_DIR" ]]; then
printf 'Failed to create a secure temporary directory\n'
exit 1
fi
readonly FIX_DIR
readonly FFMPEG_SRC_MAIN='https://api.github.com/repos/Ld-Hagen/nwjs-ffmpeg-prebuilt/releases'
readonly FFMPEG_SRC_ALT='https://api.github.com/repos/Ld-Hagen/fix-opera-linux-ffmpeg-widevine/releases' readonly FFMPEG_SRC_ALT='https://api.github.com/repos/Ld-Hagen/fix-opera-linux-ffmpeg-widevine/releases'
readonly WIDEVINE_VERSIONS='https://dl.google.com/widevine-cdm/versions.txt' readonly WIDEVINE_SRC='https://raw.githubusercontent.com/mozilla-firefox/firefox/refs/heads/main/toolkit/content/gmp-sources/widevinecdm.json'
readonly FFMPEG_SO_NAME='libffmpeg.so' readonly FFMPEG_SO_NAME='libffmpeg.so'
readonly WIDEVINE_SO_NAME='libwidevinecdm.so' readonly WIDEVINE_SO_NAME='libwidevinecdm.so'
readonly WIDEVINE_MANIFEST_NAME='manifest.json' readonly WIDEVINE_MANIFEST_NAME='manifest.json'
readonly OPERA_DIR=$(dirname $(readlink -f $(which opera))) OPERA_VERSIONS=()
readonly OPERA_LIB_DIR="$OPERA_DIR/lib_extra"
readonly OPERA_WIDEVINE_DIR="$OPERA_LIB_DIR/WidevineCdm" if [ -x "$(command -v opera)" ]; then
readonly OPERA_WIDEVINE_SO_DIR="$OPERA_WIDEVINE_DIR/_platform_specific/linux_x64" OPERA_VERSIONS+=("opera")
readonly OPERA_WIDEVINE_CONFIG="$OPERA_DIR/resources/widevine_config.json" fi
if [ -x "$(command -v opera-beta)" ]; then
OPERA_VERSIONS+=("opera-beta")
fi
if [ -x "$(command -v opera-gx)" ]; then
OPERA_VERSIONS+=("opera-gx")
fi
get_chromium_major() {
local opera_dir="$1"
local opera_name="$2"
local version=""
for bin in "$opera_dir/$opera_name" "$opera_dir/opera"; do
if [[ -f "$bin" ]]; then
version=$(grep -ao 'Chrome/[0-9]\+' "$bin" 2>/dev/null | head -1 | grep -o '[0-9]\+')
if [[ -n "$version" ]]; then
echo "$version"
return 0
fi
fi
done
return 1
}
get_ffmpeg_url_for_chromium() {
local chromium_major="$1"
local best_tag=""
local best_url=""
for releases_json in "$RELEASES_MAIN" "$RELEASES_ALT"; do
local match
match=$(echo "$releases_json" | jq -r --arg ver "$chromium_major" '
[.[] | select((.body // "") | test("Chromium " + $ver + "\\."))]
| sort_by(.published_at)
| if length > 0 then .[-1] | "\(.tag_name)\t\(.assets[0].browser_download_url)" else empty end
')
if [[ -n "$match" ]]; then
local tag url
tag=$(echo "$match" | cut -f1)
url=$(echo "$match" | cut -f2)
if [[ -z "$best_tag" || "$tag" > "$best_tag" ]]; then
best_tag="$tag"
best_url="$url"
fi
fi
done
if [[ -n "$best_url" ]]; then
printf '%s\t%s' "$best_tag" "$best_url"
return 0
fi
return 1
}
get_latest_ffmpeg_url() {
local url_main url_alt
url_main=$(echo "$RELEASES_MAIN" | jq -rS 'sort_by(.published_at) | .[-1].assets[0].browser_download_url')
url_alt=$(echo "$RELEASES_ALT" | jq -rS 'sort_by(.published_at) | .[-1].assets[0].browser_download_url')
if [[ $(basename "$url_alt") < $(basename "$url_main") ]]; then
echo "$url_main"
else
echo "$url_alt"
fi
}
#Getting download links #Getting download links
printf 'Getting download links...\n' printf 'Getting download links...\n'
##ffmpeg
readonly FFMPEG_URL_MAIN=$(wget -qO - $FFMPEG_SRC_MAIN | grep browser_download_url | cut -d '"' -f 4 | grep linux-x64 | head -n 1) ##Fetch all release data once
readonly FFMPEG_URL_ALT=$(wget -qO - $FFMPEG_SRC_ALT | grep browser_download_url | cut -d '"' -f 4 | grep linux-x64 | head -n 1) RELEASES_MAIN=$(curl -sL4 "$FFMPEG_SRC_MAIN?per_page=50")
[[ $(basename $FFMPEG_URL_ALT) < $(basename $FFMPEG_URL_MAIN) ]] && readonly FFMPEG_URL=$FFMPEG_URL_MAIN || readonly FFMPEG_URL=$FFMPEG_URL_ALT RELEASES_ALT=$(curl -sL4 "$FFMPEG_SRC_ALT?per_page=50")
if [[ -z $FFMPEG_URL ]]; then
printf 'Failed to get ffmpeg download URL. Exiting...\n'
exit 1
fi
##Widevine ##Widevine
if $FIX_WIDEVINE; then if $FIX_WIDEVINE; then
readonly WIDEVINE_LATEST=`wget -qO - $WIDEVINE_VERSIONS | tail -n1` readonly WIDEVINE_URL=$(curl -sL4 $WIDEVINE_SRC | jq -r '.vendors."gmp-widevinecdm".platforms."Linux_x86_64-gcc3".mirrorUrls[0]')
readonly WIDEVINE_URL="https://dl.google.com/widevine-cdm/$WIDEVINE_LATEST-linux-x64.zip"
fi fi
#Downloading files #Downloading Widevine
printf 'Downloading files...\n'
mkdir -p "$TEMP_DIR/opera-fix"
##ffmpeg
wget -q --show-progress $FFMPEG_URL -O "$TEMP_DIR/opera-fix/ffmpeg.zip"
if [ $? -ne 0 ]; then
printf 'Failed to download ffmpeg. Check your internet connection or try later\n'
exit 1
fi
##Widevine
if $FIX_WIDEVINE; then if $FIX_WIDEVINE; then
wget -q --show-progress "$WIDEVINE_URL" -O "$TEMP_DIR/opera-fix/widevine.zip" printf 'Downloading Widevine CDM...\n'
echo -e "From URL: $WIDEVINE_URL\n"
curl -L4 --progress-bar "$WIDEVINE_URL" -o "$FIX_DIR/widevine.zip"
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
printf 'Failed to download Widevine CDM. Check your internet connection or try later\n' printf 'Failed to download Widevine CDM. Check your internet connection or try later\n'
exit 1 exit 1
fi fi
echo "Extracting WidevineCDM..."
unzip -oj "$FIX_DIR/widevine.zip" -d "$FIX_DIR" > /dev/null 2>/dev/null
fi fi
#Extracting files LAST_FFMPEG_TAG=""
printf 'Extracting files...\n'
##ffmpeg
unzip -o "$TEMP_DIR/opera-fix/ffmpeg.zip" -d $TEMP_DIR/opera-fix > /dev/null
##Widevine
if $FIX_WIDEVINE; then
unzip -o "$TEMP_DIR/opera-fix/widevine.zip" -d $TEMP_DIR/opera-fix > /dev/null
fi
#Removing old libraries and preparing directories for opera in ${OPERA_VERSIONS[@]}; do
printf 'Removing old libraries & making directories...\n' echo "Doing $opera"
##ffmpeg EXECUTABLE=$(command -v "$opera")
rm -f "$OPERA_LIB_DIR/$FFMPEG_SO_NAME" if [[ "$ARCH_SYSTEM" == true ]]; then
mkdir -p "$OPERA_LIB_DIR" OPERA_DIR=$(dirname $(cat $EXECUTABLE | grep exec | cut -d ' ' -f 2))
##Widevine elif head -1 "$EXECUTABLE" | grep -q 'bash\|sh'; then
if $FIX_WIDEVINE; then # The executable is a shell wrapper (e.g. openSUSE packages Opera as a wrapper
# script). readlink -f on a script returns the script itself, not the real binary,
# so we parse the LIBDIR variable directly from the wrapper instead.
PARSED_LIBDIR=$(grep '^LIBDIR=' "$EXECUTABLE" | head -1 | sed 's/LIBDIR=//;s/"//g' | sed "s/\\\$PROGNAME/$opera/g")
if [[ -n "$PARSED_LIBDIR" && -d "$PARSED_LIBDIR" ]]; then
OPERA_DIR="$PARSED_LIBDIR"
else
OPERA_DIR=$(dirname $(readlink -f $EXECUTABLE))
fi
else
OPERA_DIR=$(dirname $(readlink -f $EXECUTABLE))
fi
CHROMIUM_MAJOR=$(get_chromium_major "$OPERA_DIR" "$opera")
if [[ -n "$CHROMIUM_MAJOR" ]]; then
printf 'Detected Chromium %s for %s\n' "$CHROMIUM_MAJOR" "$opera"
FFMPEG_MATCH=$(get_ffmpeg_url_for_chromium "$CHROMIUM_MAJOR")
if [[ -n "$FFMPEG_MATCH" ]]; then
FFMPEG_TAG=$(echo "$FFMPEG_MATCH" | cut -f1)
FFMPEG_URL=$(echo "$FFMPEG_MATCH" | cut -f2)
else
printf 'WARNING: No ffmpeg release found for Chromium %s, using latest\n' "$CHROMIUM_MAJOR"
FFMPEG_TAG="latest"
FFMPEG_URL=$(get_latest_ffmpeg_url)
fi
else
printf 'WARNING: Could not detect Chromium version for %s, using latest ffmpeg\n' "$opera"
FFMPEG_TAG="latest"
FFMPEG_URL=$(get_latest_ffmpeg_url)
fi
if [[ "$FFMPEG_TAG" != "$LAST_FFMPEG_TAG" ]]; then
printf 'Downloading ffmpeg (%s)...\n' "$FFMPEG_TAG"
echo -e "From: $FFMPEG_URL\n"
curl -L4 --progress-bar "$FFMPEG_URL" -o "$FIX_DIR/ffmpeg.zip"
if [ $? -ne 0 ]; then
printf 'Failed to download ffmpeg. Check your internet connection or try later\n'
exit 1
fi
echo "Extracting ffmpeg..."
unzip -o "$FIX_DIR/ffmpeg.zip" -d "$FIX_DIR" > /dev/null
LAST_FFMPEG_TAG="$FFMPEG_TAG"
else
printf 'Using cached ffmpeg (%s)\n' "$FFMPEG_TAG"
fi
OPERA_LIB_DIR="$OPERA_DIR/lib_extra"
OPERA_WIDEVINE_DIR="$OPERA_LIB_DIR/WidevineCdm"
OPERA_WIDEVINE_SO_DIR="$OPERA_WIDEVINE_DIR/_platform_specific/linux_x64"
OPERA_WIDEVINE_CONFIG="$OPERA_DIR/resources/widevine_config.json"
#Removing old libraries and preparing directories
printf 'Removing old libraries & making directories...\n'
##ffmpeg
rm -f "$OPERA_LIB_DIR/$FFMPEG_SO_NAME"
mkdir -p "$OPERA_LIB_DIR"
##Widevine
if $FIX_WIDEVINE; then
rm -rf "$OPERA_WIDEVINE_DIR" rm -rf "$OPERA_WIDEVINE_DIR"
mkdir -p "$OPERA_WIDEVINE_SO_DIR" mkdir -p "$OPERA_WIDEVINE_SO_DIR"
fi fi
#Moving libraries to its place #Moving libraries to its place
printf 'Moving libraries to their places...\n' printf 'Moving libraries to their places...\n'
##ffmpeg ##ffmpeg
mv -f "$TEMP_DIR/opera-fix/$FFMPEG_SO_NAME" "$OPERA_LIB_DIR" cp -f "$FIX_DIR/$FFMPEG_SO_NAME" "$OPERA_LIB_DIR"
chmod 0644 "$OPERA_LIB_DIR/$FFMPEG_SO_NAME" chmod 0644 "$OPERA_LIB_DIR/$FFMPEG_SO_NAME"
##Widevine ##Widevine
if $FIX_WIDEVINE; then if $FIX_WIDEVINE; then
mv -f "$TEMP_DIR/opera-fix/$WIDEVINE_SO_NAME" "$OPERA_WIDEVINE_SO_DIR" cp -f "$FIX_DIR/$WIDEVINE_SO_NAME" "$OPERA_WIDEVINE_SO_DIR"
chmod 0644 "$OPERA_WIDEVINE_SO_DIR/$WIDEVINE_SO_NAME" chmod 0644 "$OPERA_WIDEVINE_SO_DIR/$WIDEVINE_SO_NAME"
mv -f "$TEMP_DIR/opera-fix/$WIDEVINE_MANIFEST_NAME" "$OPERA_WIDEVINE_DIR" cp -f "$FIX_DIR/$WIDEVINE_MANIFEST_NAME" "$OPERA_WIDEVINE_DIR"
chmod 0644 "$OPERA_WIDEVINE_DIR/$WIDEVINE_MANIFEST_NAME" chmod 0644 "$OPERA_WIDEVINE_DIR/$WIDEVINE_MANIFEST_NAME"
printf "[\n {\n \"preload\": \"$OPERA_WIDEVINE_DIR\"\n }\n]\n" > "$OPERA_WIDEVINE_CONFIG" printf "[\n {\n \"preload\": \"$OPERA_WIDEVINE_DIR\"\n }\n]\n" > "$OPERA_WIDEVINE_CONFIG"
fi
# Newer Chromium-based Opera versions (110+) no longer read widevine_config.json.
# On zypper-based systems (openSUSE) Opera reads OPERA_FLAGS from /etc/default/opera,
# so we inject --widevine-cdm-path there as well to cover both loading mechanisms.
if command -v zypper &>/dev/null && [[ -f /etc/default/$opera ]]; then
OPERA_DEFAULT="/etc/default/$opera"
CDM_FLAG="--widevine-cdm-path=$OPERA_WIDEVINE_DIR"
if grep -q 'OPERA_FLAGS=' "$OPERA_DEFAULT"; then
# Append the flag if not already present
if ! grep -qF -- "$CDM_FLAG" "$OPERA_DEFAULT"; then
sed -i "s|OPERA_FLAGS=\"\(.*\)\"|OPERA_FLAGS=\"\1 $CDM_FLAG\"|" "$OPERA_DEFAULT"
fi
else
echo "OPERA_FLAGS=\"$CDM_FLAG\"" >> "$OPERA_DEFAULT"
fi
printf "Widevine CDM path added to %s\n" "$OPERA_DEFAULT"
fi
fi
done
#Removing temporary files #Removing temporary files
printf 'Removing temporary files...\n' printf 'Removing temporary files...\n'
rm -rf "$TEMP_DIR/opera-fix" rm -rf "$FIX_DIR"
+61
View File
@@ -0,0 +1,61 @@
#!/bin/bash
set -euo pipefail
#
# This uninstall does NOT remove system packages. It only removes the hooks, aliases and scripts implemented by fix-opera's 'install.sh'.
#
INSTALL_PATH="/root/.scripts"
# --- privilege check ---
if [[ "$(id -u)" -ne 0 ]]; then
echo "Please run this script with sudo or as root"
exit 1
fi
# --- user resolution ---
USER_NAME="${SUDO_USER:-$(logname)}"
USER_HOME=$(getent passwd "$USER_NAME" | cut -d: -f6)
# --- package manager detection ---
detect_pkg_manager() {
if command -v apt-get >/dev/null 2>&1; then
PKG_MGR="apt"
elif command -v dnf >/dev/null 2>&1; then
PKG_MGR="dnf"
elif command -v pacman >/dev/null 2>&1; then
PKG_MGR="pacman"
else
PKG_MGR="unknown"
fi
}
remove_hook() {
case "$PKG_MGR" in
apt)
rm -f /etc/apt/apt.conf.d/99fix-opera
;;
pacman)
rm -f /usr/share/libalpm/hooks/fix-opera.hook
;;
dnf)
rm -f /etc/dnf/plugins/post-transaction-actions.d/fix-opera.action
;;
*)
echo "No supported package manager hook to remove"
;;
esac
}
detect_pkg_manager
remove_hook
# --- remove alias ---
if [[ -f "$USER_HOME/.bashrc" ]]; then
sed -i '/alias fix-opera=.*Opera fix HTML5 media/d' "$USER_HOME/.bashrc"
fi
# --- remove installed files ---
rm -rf "$INSTALL_PATH"
echo "Opera Widevine fix has been removed."