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
Ld-Hagen f73a02813b First run after install. Some fixes 2021-10-06 20:15:57 +03:00
Ld-Hagen 78c9762d17 Dependencies in Arch hhook 2021-09-26 19:56:31 +03:00
Ld-Hagen c9b8eb396e Dependency check on install. Messages about hook creation. 2021-09-26 19:37:52 +03:00
Ld-Hagen a6d2682300 Formatting 2021-09-25 22:48:13 +03:00
Maksim IvanovandGitHub 08602bd452 Update README.md 2021-09-25 22:32:05 +03:00
Ld-Hagen 7c750ca4ba Installation script, Arch hook 2021-09-25 22:03:43 +03:00
Ld-Hagen 7c5f5ffd5f Script is completely rewritten. Hope new version is more clear 2021-09-25 20:21:37 +03:00
Ld-Hagen 209825c5fd Autodetected Opera path instead of hardcoded. Architecture check 2021-09-25 18:19:17 +03:00
Ld-Hagen e9174eb089 binutils check removed 2021-09-24 22:48:13 +03:00
Ld-Hagen c74624cbc1 Widevine download source changed. No binutils dependency. 2021-09-24 22:22:03 +03:00
10 changed files with 566 additions and 130 deletions
-2
View File
@@ -1,2 +0,0 @@
DPkg::Pre-Invoke {"stat -c %Z /usr/lib/x86_64-linux-gnu/opera/opera > /tmp/opera.timestamp";};
DPkg::Post-Invoke {"if [ `stat -c %Z /usr/lib/x86_64-linux-gnu/opera/opera` -ne `cat /tmp/opera.timestamp` ]; then ~root/.scripts/fix-opera.sh; fi; rm /tmp/opera.timestamp";};
+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"`)
+41 -28
View File
@@ -1,56 +1,69 @@
# Fix Opera Linux ffmpeg & WidevineCdm > [!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.
* Fix Opera html5 media content > [!NOTE]
* It script must be execute all times opera will fails on showing html5 media content. > All future versions of libffmpeg will be posted in https://github.com/Ld-Hagen/nwjs-ffmpeg-prebuilt/releases instead of this repo.
* Now it also fixes WidevineCdm support for DRM video. You can try it on Vevo youtube channel for example.
# Fix Opera Linux libffmpeg & WidevineCdm
* Fixes Opera html5 media content including DRM-protected one.
* This script must be executed all times opera fails on showing html5 media content.
* 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 Chrome) 1. **curl** (is needed for downloading the ffmpeg lib and widevine)
```sudo apt install wget```
2. **unzip**, **binutils** (Is needed for unpacking the downloaded file) **unzip** (is needed for unpacking the downloaded file)
```sudo apt install unzip binutils```
**git** (is needed for fetching this script)
**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*) You may disable **Widevine** fix if one that comes with Opera works well for you. 3. (*Optional*) Run script. And if it works well go to next step.
```sed -i '/FIX_WIDEVINE=/s/true/false/g' ./fix-opera.sh``` `chmod +x scripts/fix-opera.sh && sudo ./scripts/fix-opera.sh`
4. Run script. And if it works well got ot next step. 4. Make install.sh executable
```sudo ./fix-opera.sh``` `chmod +x ./install.sh`
5. Create a **.scripts** folder on **root**'s **home** 5. Run install script and answer few questions.
```sudo mkdir ~root/.scripts``` `sudo ./install.sh`
6. Copy the script into the **.scripts** folder ## How to uninstall
```sudo cp ./fix-opera.sh ~root/.scripts``` 1. Clone this repo
7. Choose one or both options `cd /tmp && git clone https://github.com/Ld-Hagen/fix-opera-linux-ffmpeg-widevine.git`
* (*Optional*) Create an **alias**. And then you'll be able to start it by typing ```fix-opera``` command in terminal.
```echo "alias fix-opera='sudo ~root/.scripts/fix-opera.sh' # Opera fix HTML5 media" >> ~/.bashrc``` 2. Go to the repo root folder
```source ~/.bashrc``` `cd /tmp/fix-opera-linux-ffmpeg-widevine`
* (*Optional*) Autostart after each opera upgrade (Debian-based distros) 3. Make uninstall.sh executable
```sudo cp ./99fix-opera ~root/.scripts``` `chmod +x uninstall.sh`
```sudo ln -s ~root/.scripts/99fix-opera /etc/apt/apt.conf.d/``` 5. Run uninstallation script. And if it works well go to next step.
8. Delete the repo `sudo ./uninstall.sh`
```cd .. && rm -rf ./fix-opera-linux-ffmpeg-widevine```
-93
View File
@@ -1,93 +0,0 @@
#!/bin/bash
# Run using sudo
if [[ $(whoami) != "root" ]]; then
printf 'Try to run it with sudo\n'
exit 1
fi
readonly TEMP_FOLDER='/tmp/'
readonly OPERA_FOLDER='/usr/lib/x86_64-linux-gnu/opera'
readonly FILE_NAME='libffmpeg.so'
readonly ZIP_FILE='.zip'
readonly TEMP_FILE="$TEMP_FOLDER$FILE_NAME"
readonly OPERA_FILE="$OPERA_FOLDER/lib_extra/$FILE_NAME"
readonly FIX_WIDEVINE=true
readonly CHROME_DL_LINK="https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb"
readonly GIT_API_MAIN=https://api.github.com/repos/iteufel/nwjs-ffmpeg-prebuilt/releases
readonly GIT_API_ALT=https://api.github.com/repos/Ld-Hagen/fix-opera-linux-ffmpeg-widevine/releases
if ! which ar > /dev/null && $FIX_WIDEVINE; then
printf '\033[1mbinutils\033[0m package must be installed to fix Widevine\n'
exit 1
fi
if ! which unzip > /dev/null; then
printf '\033[1munzip\033[0m package must be installed to run this script\n'
exit 1
fi
if ! which wget > /dev/null; then
printf '\033[1mwget\033[0m package must be installed to run this script\n'
exit 1
fi
printf 'Getting ffmpeg download Url ...\n'
readonly OPERA_FFMPEG_URL_MAIN=$(wget -qO - $GIT_API_MAIN | grep browser_download_url | cut -d '"' -f 4 | grep linux-x64 | head -n 1)
readonly OPERA_FFMPEG_URL_ALT=$(wget -qO - $GIT_API_ALT | grep browser_download_url | cut -d '"' -f 4 | grep linux-x64 | head -n 1)
if [ `basename $OPERA_FFMPEG_URL_ALT` \< `basename $OPERA_FFMPEG_URL_MAIN` ]; then
readonly OPERA_FFMPEG_URL=$OPERA_FFMPEG_URL_MAIN
else
readonly OPERA_FFMPEG_URL=$OPERA_FFMPEG_URL_ALT
fi
if [ -z "$OPERA_FFMPEG_URL" ]; then
printf 'Failed to get ffmpeg download URL. EXiting...\n'
exit 1
fi
printf 'Downloading ffmpeg ...\n'
wget -q --show-progress $OPERA_FFMPEG_URL -O "$TEMP_FILE$ZIP_FILE"
if [ $? -ne 0 ]; then
printf 'Failed to download ffmpeg. Check your internet connection or try later\n'
exit 1
fi
printf "Unzipping ...\n"
unzip "$TEMP_FILE$ZIP_FILE" -d $TEMP_FILE > /dev/null
printf "Moving file on $OPERA_FILE ...\n"
mkdir -p "$OPERA_FOLDER/lib_extra"
mv -f "$TEMP_FILE/$FILE_NAME" $OPERA_FILE
printf 'Deleting Temporary files ...\n'
find $TEMP_FOLDER -name "*$FILE_NAME*" -delete
if $FIX_WIDEVINE
then
rm -rf "$OPERA_FOLDER/lib_extra/WidevineCdm"
printf "Downloading Google Chrome ...\n"
mkdir "$TEMP_FOLDER/chrome"
cd "$TEMP_FOLDER/chrome"
wget -q --show-progress "$CHROME_DL_LINK"
if [ $? -ne 0 ]; then
printf 'Failed to download Google Chrome. Check your internet connection or try later\n'
exit 1
fi
printf "Extracting Chrome to temporary folder ...\n"
CHROME_PKG_NAME=`basename $CHROME_DL_LINK`
ar x "$CHROME_PKG_NAME"
tar xf data.tar.xz
printf "Installing WidevineCdm ...\n"
cp -R "$TEMP_FOLDER/chrome/opt/google/chrome/WidevineCdm" "$OPERA_FOLDER/lib_extra/"
printf "[\n {\n \"preload\": \"$OPERA_FOLDER/lib_extra/WidevineCdm\"\n }\n]\n" > "$OPERA_FOLDER/resources/widevine_config.json"
printf "Deleting temprorary files ...\n"
rm -rf "$TEMP_FOLDER/chrome"
else
printf "Installing WidevineCdm skipped\n"
fi
Executable
+164
View File
@@ -0,0 +1,164 @@
#!/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
printf 'Try to run it with sudo\n'
exit 1
fi
if [[ $(uname -m) != "x86_64" ]]; then
printf 'This script is intended for 64-bit systems\n'
exit 1
fi
if ! which unzip > /dev/null; then
printf '\033[1munzip\033[0m package must be installed to run this script\n'
exit 1
fi
if ! which curl > /dev/null; then
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
fi
readonly SCRIPT_PATH=$(dirname $(readlink -f $0))
readonly INSTALL_PATH="/root/.scripts"
readonly USER_NAME="${SUDO_USER:-$(logname)}"
readonly USER_HOME=$(getent passwd "$USER_NAME" | cut -d: -f6)
mkdir -p $INSTALL_PATH
printf '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]'
while read FIX_WIDEVINE; do
case $FIX_WIDEVINE in
"y" | "Y")
printf 'Setting FIX_WIDEVINE to true...\n'
sed -i '/FIX_WIDEVINE=/s/false/true/g' $INSTALL_PATH/fix-opera.sh
break;;
"n" | "N")
printf 'Setting FIX_WIDEVINE to false...\n'
sed -i '/FIX_WIDEVINE=/s/true/false/g' $INSTALL_PATH/fix-opera.sh
break;;
* )
printf 'Would you like to apply Widevine CDM fix? [y/n]'
continue;;
esac
done
printf "Would you like to create an alias for user $USER_NAME? [y/n]"
while read CREATE_ALIAS; do
case $CREATE_ALIAS in
"y" | "Y")
echo "alias fix-opera='sudo ~root/.scripts/fix-opera.sh' # Opera fix HTML5 media" >> $USER_HOME/.bashrc
printf "Alias \"fix-opera\" will be available after your next logon.\n"
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]"
while read RUN_NOW; do
case $RUN_NOW in
"y" | "Y")
$INSTALL_PATH/fix-opera.sh
break;;
"n" | "N")
break;;
* )
printf "Would you like to run it now? [y/n]"
continue;;
esac
done
+2
View File
@@ -0,0 +1,2 @@
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 {"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
+16
View File
@@ -0,0 +1,16 @@
# Fix video playback on Opera Upgrade/Install.
[Trigger]
Operation = Install
Operation = Upgrade
Type = Package
Target = opera
[Action]
Description = Fix video playback in Opera browser
When = PostTransaction
Depends = bash
Depends = curl
Depends = unzip
Depends = jq
Exec = /root/.scripts/fix-opera.sh
+245
View File
@@ -0,0 +1,245 @@
#!/usr/bin/env bash
if [[ $(whoami) != "root" ]]; then
printf 'Try to run it with sudo\n'
exit 1
fi
if [[ $(uname -m) != "x86_64" ]]; then
printf 'This script is intended for 64-bit systems\n'
exit 1
fi
if ! command -v unzip 2>&1 /dev/null; then
printf '\033[1munzip\033[0m package must be installed to run this script\n'
exit 1
fi
if ! command -v curl 2>&1 /dev/null; then
printf '\033[1mcurl\033[0m package must be installed to run this script\n'
exit 1
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
readonly FIX_WIDEVINE=true
FIX_DIR=$(mktemp -d -t opera-fix.XXXXXXXX)
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 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 WIDEVINE_SO_NAME='libwidevinecdm.so'
readonly WIDEVINE_MANIFEST_NAME='manifest.json'
OPERA_VERSIONS=()
if [ -x "$(command -v opera)" ]; then
OPERA_VERSIONS+=("opera")
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
printf 'Getting download links...\n'
##Fetch all release data once
RELEASES_MAIN=$(curl -sL4 "$FFMPEG_SRC_MAIN?per_page=50")
RELEASES_ALT=$(curl -sL4 "$FFMPEG_SRC_ALT?per_page=50")
##Widevine
if $FIX_WIDEVINE; then
readonly WIDEVINE_URL=$(curl -sL4 $WIDEVINE_SRC | jq -r '.vendors."gmp-widevinecdm".platforms."Linux_x86_64-gcc3".mirrorUrls[0]')
fi
#Downloading Widevine
if $FIX_WIDEVINE; then
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
printf 'Failed to download Widevine CDM. Check your internet connection or try later\n'
exit 1
fi
echo "Extracting WidevineCDM..."
unzip -oj "$FIX_DIR/widevine.zip" -d "$FIX_DIR" > /dev/null 2>/dev/null
fi
LAST_FFMPEG_TAG=""
for opera in ${OPERA_VERSIONS[@]}; do
echo "Doing $opera"
EXECUTABLE=$(command -v "$opera")
if [[ "$ARCH_SYSTEM" == true ]]; then
OPERA_DIR=$(dirname $(cat $EXECUTABLE | grep exec | cut -d ' ' -f 2))
elif head -1 "$EXECUTABLE" | grep -q 'bash\|sh'; 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"
mkdir -p "$OPERA_WIDEVINE_SO_DIR"
fi
#Moving libraries to its place
printf 'Moving libraries to their places...\n'
##ffmpeg
cp -f "$FIX_DIR/$FFMPEG_SO_NAME" "$OPERA_LIB_DIR"
chmod 0644 "$OPERA_LIB_DIR/$FFMPEG_SO_NAME"
##Widevine
if $FIX_WIDEVINE; then
cp -f "$FIX_DIR/$WIDEVINE_SO_NAME" "$OPERA_WIDEVINE_SO_DIR"
chmod 0644 "$OPERA_WIDEVINE_SO_DIR/$WIDEVINE_SO_NAME"
cp -f "$FIX_DIR/$WIDEVINE_MANIFEST_NAME" "$OPERA_WIDEVINE_DIR"
chmod 0644 "$OPERA_WIDEVINE_DIR/$WIDEVINE_MANIFEST_NAME"
printf "[\n {\n \"preload\": \"$OPERA_WIDEVINE_DIR\"\n }\n]\n" > "$OPERA_WIDEVINE_CONFIG"
# 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
printf 'Removing temporary files...\n'
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."