Compare commits

..

No commits in common. "main" and "1.1.4" have entirely different histories.
main ... 1.1.4

16 changed files with 4421 additions and 5555 deletions

View file

@ -1 +1 @@
Please visit the [main document at primary repository](https://github.com/sussy-code/smov/blob/dev/.github/CODE_OF_CONDUCT.md). Please visit the [main document at primary repository](https://github.com/movie-web/movie-web/blob/dev/.github/CODE_OF_CONDUCT.md).

View file

@ -1 +1 @@
Please visit the [main document at primary repository](https://github.com/sussy-code/smov/blob/dev/.github/CONTRIBUTING.md). Please visit the [main document at primary repository](https://github.com/movie-web/movie-web/blob/dev/.github/CONTRIBUTING.md).

6
.github/SECURITY.md vendored
View file

@ -2,9 +2,9 @@
## Supported Versions ## Supported Versions
The latest version of sudo-flix is the only version that is supported, as it is the only version that is being actively developed. The latest version of movie-web is the only version that is supported, as it is the only version that is being actively developed.
## Reporting a Vulnerability ## Reporting a Vulnerability
You can contact the sudo-flix maintainers to report a vulnerability: You can contact the movie-web maintainers to report a vulnerability:
- Report the vulnerability in the [Discord server](https://discord.gg/g742e7Mu2W) - Report the vulnerability in the [movie-web Discord server](https://movie-web.github.io/links/discord)

View file

@ -1,6 +1,6 @@
This pull request resolves #XXX This pull request resolves #XXX
- [ ] I have read and agreed to the [code of conduct](https://github.com/sussy-code/smov/blob/dev/.github/CODE_OF_CONDUCT.md). - [ ] I have read and agreed to the [code of conduct](https://github.com/movie-web/movie-web/blob/dev/.github/CODE_OF_CONDUCT.md).
- [ ] I have read and complied with the [contributing guidelines](https://github.com/sussy-code/smov/blob/dev/.github/CONTRIBUTING.md). - [ ] I have read and complied with the [contributing guidelines](https://github.com/movie-web/movie-web/blob/dev/.github/CONTRIBUTING.md).
- [ ] What I'm implementing was assigned to me and is an [approved issue](https://github.com/sussy-code/smov/issues?q=is%3Aopen+is%3Aissue+label%3Aapproved). For reference, please take a look at our [GitHub projects](https://github.com/sussy-code/smov/projects). - [ ] What I'm implementing was assigned to me and is an [approved issue](https://github.com/movie-web/movie-web/issues?q=is%3Aopen+is%3Aissue+label%3Aapproved). For reference, please take a look at our [GitHub projects](https://github.com/movie-web/movie-web/projects).
- [ ] I have tested all of my changes. - [ ] I have tested all of my changes.

View file

@ -1,6 +1,6 @@
MIT License MIT License
Copyright (c) 2023 sudo-flix Copyright (c) 2023 movie-web
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

View file

@ -1,6 +1,6 @@
# extension # extension
Enhance your experience with just one click Enhance your movie-web experience with just one click
## Running for development ## Running for development

View file

@ -4,7 +4,7 @@
"optional_host_permissions": [ "\u003Call_urls>" ], "optional_host_permissions": [ "\u003Call_urls>" ],
"permissions": [ "storage", "declarativeNetRequest", "activeTab", "cookies" ], "permissions": [ "storage", "declarativeNetRequest", "activeTab", "cookies" ],
"update_url": "https://clients2.google.com/service/update2/crx", "update_url": "https://clients2.google.com/service/update2/crx",
"version": "1.2.0", "version": "1.1.4",
"web_accessible_resources": [ { "web_accessible_resources": [ {
"matches": [ "\u003Call_urls>" ], "matches": [ "\u003Call_urls>" ],
"resources": [ "assets/active.png", "assets/inactive.png" ] "resources": [ "assets/active.png", "assets/inactive.png" ]

View file

@ -1,9 +1,9 @@
{ {
"name": "@movie-web/extension", "name": "@movie-web/extension",
"displayName": "sudo-flix extension", "displayName": "movie-web extension",
"version": "1.2.0", "version": "1.1.4",
"description": "Enhance your streaming experience with just one click", "description": "Enhance your movie-web experience with just one click",
"author": "sudo-flix", "author": "movie-web",
"scripts": { "scripts": {
"dev": "plasmo dev", "dev": "plasmo dev",
"build": "plasmo build", "build": "plasmo build",
@ -16,28 +16,28 @@
"preinstall": "npx -y only-allow pnpm" "preinstall": "npx -y only-allow pnpm"
}, },
"dependencies": { "dependencies": {
"@plasmohq/messaging": "^0.6.2", "@plasmohq/messaging": "^0.6.1",
"@plasmohq/storage": "^1.11.0", "@plasmohq/storage": "^1.9.0",
"plasmo": "0.84.0", "plasmo": "0.84.0",
"react": "18.2.0", "react": "18.2.0",
"react-dom": "18.2.0" "react-dom": "18.2.0"
}, },
"devDependencies": { "devDependencies": {
"@types/chrome": "0.0.251", "@types/chrome": "0.0.251",
"@types/firefox-webext-browser": "^120.0.4", "@types/firefox-webext-browser": "^120.0.0",
"@types/node": "20.9.0", "@types/node": "20.9.0",
"@types/react": "18.2.37", "@types/react": "18.2.37",
"@types/react-dom": "18.2.15", "@types/react-dom": "18.2.15",
"@typescript-eslint/eslint-plugin": "^6.21.0", "@typescript-eslint/eslint-plugin": "^6.15.0",
"@typescript-eslint/parser": "^6.21.0", "@typescript-eslint/parser": "^6.15.0",
"eslint": "^8.57.0", "eslint": "^8.56.0",
"eslint-config-airbnb": "^19.0.4", "eslint-config-airbnb": "^19.0.4",
"eslint-config-prettier": "^9.1.0", "eslint-config-prettier": "^9.1.0",
"eslint-import-resolver-typescript": "^3.6.1", "eslint-import-resolver-typescript": "^3.6.1",
"eslint-plugin-import": "^2.29.1", "eslint-plugin-import": "^2.29.1",
"eslint-plugin-prettier": "^5.2.1", "eslint-plugin-prettier": "^5.1.1",
"eslint-plugin-react": "^7.35.0", "eslint-plugin-react": "^7.33.2",
"eslint-plugin-react-hooks": "^4.6.2", "eslint-plugin-react-hooks": "^4.6.0",
"prettier": "3.0.3", "prettier": "3.0.3",
"typescript": "5.2.2" "typescript": "5.2.2"
}, },

File diff suppressed because it is too large Load diff

View file

@ -5,7 +5,7 @@ import type { BaseResponse } from '~types/response';
import { removeDynamicRules, setDynamicRules } from '~utils/declarativeNetRequest'; import { removeDynamicRules, setDynamicRules } from '~utils/declarativeNetRequest';
import { isFirefox } from '~utils/extension'; import { isFirefox } from '~utils/extension';
import { makeFullUrl } from '~utils/fetcher'; import { makeFullUrl } from '~utils/fetcher';
import { assertDomainWhitelist, canAccessCookies } from '~utils/storage'; import { assertDomainWhitelist } from '~utils/storage';
const MAKE_REQUEST_DYNAMIC_RULE = 23498; const MAKE_REQUEST_DYNAMIC_RULE = 23498;
@ -60,12 +60,6 @@ const handler: PlasmoMessaging.MessageHandler<Request, Response<any>> = async (r
ruleId: MAKE_REQUEST_DYNAMIC_RULE, ruleId: MAKE_REQUEST_DYNAMIC_RULE,
targetDomains: [new URL(url).hostname], targetDomains: [new URL(url).hostname],
requestHeaders: req.body.headers, requestHeaders: req.body.headers,
// set Access-Control-Allow-Credentials if the reqested host has access to cookies
responseHeaders: {
...(canAccessCookies(new URL(url).hostname) && {
'Access-Control-Allow-Credentials': 'true',
}),
},
}); });
const response = await fetch(url, { const response = await fetch(url, {
@ -90,10 +84,7 @@ const handler: PlasmoMessaging.MessageHandler<Request, Response<any>> = async (r
statusCode: response.status, statusCode: response.status,
headers: { headers: {
...Object.fromEntries(response.headers.entries()), ...Object.fromEntries(response.headers.entries()),
// include cookies if allowed for the reqested host 'Set-Cookie': cookies.map((cookie) => `${cookie.name}=${cookie.value}`).join(', '),
...(canAccessCookies(new URL(url).hostname) && {
'Set-Cookie': cookies.map((cookie) => `${cookie.name}=${cookie.value}`).join(', '),
}),
}, },
body, body,
finalUrl: response.url, finalUrl: response.url,

View file

@ -3,7 +3,7 @@ import type { PlasmoMessaging } from '@plasmohq/messaging';
import type { BaseRequest } from '~types/request'; import type { BaseRequest } from '~types/request';
import type { BaseResponse } from '~types/response'; import type { BaseResponse } from '~types/response';
import { setDynamicRules } from '~utils/declarativeNetRequest'; import { setDynamicRules } from '~utils/declarativeNetRequest';
import { assertDomainWhitelist, modifiableResponseHeaders } from '~utils/storage'; import { assertDomainWhitelist } from '~utils/storage';
interface Request extends BaseRequest { interface Request extends BaseRequest {
ruleId: number; ruleId: number;
@ -18,17 +18,6 @@ const handler: PlasmoMessaging.MessageHandler<Request, BaseResponse> = async (re
if (!req.sender?.tab?.url) throw new Error('No tab URL found in the request.'); if (!req.sender?.tab?.url) throw new Error('No tab URL found in the request.');
if (!req.body) throw new Error('No request body found in the request.'); if (!req.body) throw new Error('No request body found in the request.');
// restrict what response headers can be modified
req.body.responseHeaders = Object.keys(req.body.responseHeaders ?? {})
.filter((key) => modifiableResponseHeaders.includes(key.toLowerCase()))
.reduce(
(obj, key) => {
obj[key] = (req.body?.responseHeaders ?? {})[key];
return obj;
},
{} as Record<string, string>,
);
await assertDomainWhitelist(req.sender.tab.url); await assertDomainWhitelist(req.sender.tab.url);
await setDynamicRules(req.body); await setDynamicRules(req.body);
res.send({ res.send({

View file

@ -8,7 +8,7 @@ export function BottomLabel() {
<h3 className="bottom-label"> <h3 className="bottom-label">
{version} {version}
<div className="dot" /> <div className="dot" />
sudo-flix movie-web
</h3> </h3>
); );
} }

View file

@ -8,7 +8,7 @@ export function DisabledScreen() {
<Icon name="warningCircle" /> <Icon name="warningCircle" />
</div> </div>
<p> <p>
The <strong>sudo-flix extension</strong> can not be used on this page The <strong>movie-web extension</strong> can not be used on this page
</p> </p>
</div> </div>
); );

View file

@ -32,7 +32,7 @@ export default function PermissionRequest() {
We need some <br /> browser permissions We need some <br /> browser permissions
</h1> </h1>
<p className="text-color paragraph"> <p className="text-color paragraph">
We don&apos;t like it either, but the sudo-flix extension needs quite a few permissions to function. Listed We don&apos;t like it either, but the movie-web extension needs quite a few permissions to function. Listed
below is an explanation for all permissions we need. below is an explanation for all permissions we need.
</p> </p>
@ -41,7 +41,7 @@ export default function PermissionRequest() {
purple purple
icon={<Icon name="github" />} icon={<Icon name="github" />}
right={ right={
<Button type="secondary" href="https://github.com/sussy-code/browser-ext"> <Button type="secondary" href="https://github.com/movie-web/extension">
Read source code Read source code
</Button> </Button>
} }
@ -66,7 +66,7 @@ export default function PermissionRequest() {
<h3>Network Requests</h3> <h3>Network Requests</h3>
<p className="text-color paragraph"> <p className="text-color paragraph">
This permission allows the extension to instruct the browser how to request data from sites. In more This permission allows the extension to instruct the browser how to request data from sites. In more
technical terms, this allows sudo-flix to modify HTTP headers that it wouldn&apos;t normally be allowed technical terms, this allows movie-web to modify HTTP headers that it wouldn&apos;t normally be allowed
to. to.
</p> </p>
<p className="text-color paragraph"> <p className="text-color paragraph">
@ -76,8 +76,7 @@ export default function PermissionRequest() {
<Card icon={<Icon name="cookie" />}> <Card icon={<Icon name="cookie" />}>
<h3>Read and write cookies</h3> <h3>Read and write cookies</h3>
<p className="text-color paragraph"> <p className="text-color paragraph">
Some sources use cookies for authentication. We need to be able to read and set those cookies. The Some sources use cookies for authentication. We need to be able to read and set those cookies.
extension will only be able to accees the cookies for a few sites we scrape.
</p> </p>
<p className="text-color paragraph"> <p className="text-color paragraph">
You won&apos;t be prompted for this permission, it&apos;s included in Read & change data from all sites. You won&apos;t be prompted for this permission, it&apos;s included in Read & change data from all sites.

View file

@ -1,5 +1,4 @@
import { isChrome } from './extension'; import { isChrome } from './extension';
import { modifiableResponseHeaders } from './storage';
interface DynamicRule { interface DynamicRule {
ruleId: number; ruleId: number;
@ -57,6 +56,11 @@ export const setDynamicRules = async (body: DynamicRule) => {
operation: chrome.declarativeNetRequest.HeaderOperation.SET, operation: chrome.declarativeNetRequest.HeaderOperation.SET,
value: '*', value: '*',
}, },
{
header: 'Access-Control-Allow-Credentials',
operation: chrome.declarativeNetRequest.HeaderOperation.SET,
value: 'true',
},
...mapHeadersToDeclarativeNetRequestHeaders( ...mapHeadersToDeclarativeNetRequestHeaders(
body.responseHeaders ?? {}, body.responseHeaders ?? {},
chrome.declarativeNetRequest.HeaderOperation.SET, chrome.declarativeNetRequest.HeaderOperation.SET,
@ -100,6 +104,11 @@ export const setDynamicRules = async (body: DynamicRule) => {
operation: 'set', operation: 'set',
value: '*', value: '*',
}, },
{
header: 'Access-Control-Allow-Credentials',
operation: 'set',
value: 'true',
},
...mapHeadersToDeclarativeNetRequestHeaders(body.responseHeaders ?? {}, 'set'), ...mapHeadersToDeclarativeNetRequestHeaders(body.responseHeaders ?? {}, 'set'),
], ],
}, },

View file

@ -3,32 +3,16 @@ import { useStorage } from '@plasmohq/storage/hook';
import { makeUrlIntoDomain } from '~utils/domains'; import { makeUrlIntoDomain } from '~utils/domains';
export const DEFAULT_DOMAIN_WHITELIST = []; export const DEFAULT_DOMAIN_WHITELIST = [
'mw.lonelil.ru',
export const modifiableResponseHeaders = [ 'watch.qtchaos.de',
'access-control-allow-origin', 'bmov.app',
'access-control-allow-methods', 'bmov.vercel.app',
'access-control-allow-headers', 'stream.thehairy.me',
'content-security-policy', 'scootydooter.vercel.app',
'content-security-policy-report-only', 'movie-web-me.vercel.app',
'content-disposition',
]; ];
const hostsWithCookiesAccess: RegExp[] = [
/^(?:.*\.)?ee3\.me$/,
/^(?:.*\.)?rips\.cc$/,
/^(?:.*\.)?m4ufree\.(?:tv|to|pw)$/,
/^(?:.*\.)?goojara\.to$/,
/^(?:.*\.)?levidia\.ch$/,
/^(?:.*\.)?wootly\.ch$/,
/^(?:.*\.)?multimovies\.(?:sbs|online|cloud)$/,
];
export function canAccessCookies(host: string): boolean {
if (hostsWithCookiesAccess.some((regex) => regex.test(host))) return true;
return false;
}
export const storage = new Storage(); export const storage = new Storage();
const getDomainWhiteList = async () => { const getDomainWhiteList = async () => {