-
-
Notifications
You must be signed in to change notification settings - Fork 7
feat(HikVision): hack JSVideoPlugin script prevent throw exception #795
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,8 +1,7 @@ | ||||||||||||||||||||||||||||||||||
| import { addScript } from '../BootstrapBlazor/modules/utility.js'; | ||||||||||||||||||||||||||||||||||
| import { addScript, registerBootstrapBlazorModule } from '../BootstrapBlazor/modules/utility.js'; | ||||||||||||||||||||||||||||||||||
| import Data from '../BootstrapBlazor/modules/data.js'; | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| export async function init(id) { | ||||||||||||||||||||||||||||||||||
| await addScript('./_content/BootstrapBlazor.HikVision/jsVideoPlugin-1.0.0.min.js'); | ||||||||||||||||||||||||||||||||||
| await addScript('./_content/BootstrapBlazor.HikVision/webVideoCtrl.js'); | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| if (window.$ === void 0) { | ||||||||||||||||||||||||||||||||||
|
|
@@ -26,6 +25,29 @@ export async function init(id) { | |||||||||||||||||||||||||||||||||
| return true; | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| const hackJSResize = function () { | ||||||||||||||||||||||||||||||||||
| const originalResize = JSVideoPlugin.prototype.JS_Resize; | ||||||||||||||||||||||||||||||||||
| JSVideoPlugin.prototype.JS_Resize = function (e, t) { | ||||||||||||||||||||||||||||||||||
| const { szId } = this.oOptions; | ||||||||||||||||||||||||||||||||||
| if (document.getElementById(szId)) { | ||||||||||||||||||||||||||||||||||
| return originalResize.call(this, e, t); | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
| } | |
| } | |
| return undefined; |
Copilot
AI
Dec 6, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider checking if JSVideoPlugin exists before attempting to hack its prototype. If the script is not loaded, this could throw a ReferenceError.
Copilot
AI
Dec 6, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unused variable originalDestroy.
| const originalDestroy = JSVideoPlugin.prototype.JS_DestroyPlugin; |
Copilot
AI
Dec 6, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo in variable name: origianlSendRequestProxy should be originalSendRequestProxy. The letter 'a' and 'l' are swapped.
| const origianlSendRequestProxy = this.oPlugin.oRequest.oRequest.sendRequest; | |
| this.oPlugin.oRequest.oRequest.sendRequest = function (r) { | |
| if (this.oWebSocket && WebSocket.OPEN === this.oWebSocket.readyState) { | |
| return origianlSendRequestProxy.call(this, r); | |
| const originalSendRequestProxy = this.oPlugin.oRequest.oRequest.sendRequest; | |
| this.oPlugin.oRequest.oRequest.sendRequest = function (r) { | |
| if (this.oWebSocket && WebSocket.OPEN === this.oWebSocket.readyState) { | |
| return originalSendRequestProxy.call(this, r); |
Copilot
AI
Dec 6, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo in variable name: origianlSendRequestProxy should be originalSendRequestProxy. The letter 'a' and 'l' are swapped (same typo as line 41).
| const origianlSendRequestProxy = this.oPlugin.oRequest.oRequest.sendRequest; | |
| this.oPlugin.oRequest.oRequest.sendRequest = function (r) { | |
| if (this.oWebSocket && WebSocket.OPEN === this.oWebSocket.readyState) { | |
| return origianlSendRequestProxy.call(this, r); | |
| const originalSendRequestProxy = this.oPlugin.oRequest.oRequest.sendRequest; | |
| this.oPlugin.oRequest.oRequest.sendRequest = function (r) { | |
| if (this.oWebSocket && WebSocket.OPEN === this.oWebSocket.readyState) { | |
| return originalSendRequestProxy.call(this, r); |
Copilot
AI
Dec 6, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The hacked sendRequest function doesn't return anything when the WebSocket is not open. This could lead to unexpected behavior for callers expecting a return value. Consider returning a default value or explicitly handling this case.
| } | |
| } | |
| // Explicitly return a default value when WebSocket is not open | |
| return null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
issue (bug_risk): Overriding JS_DestroyPlugin bypasses the original implementation and ignores its arguments.
This override replaces JSVideoPlugin.prototype.JS_DestroyPlugin without ever calling originalDestroy, and it always invokes this.oPlugin.JS_DestroyPlugin(true) regardless of n. This changes the method’s contract and may break callers or future upstream changes that depend on the argument. Please preserve the original behavior by delegating to originalDestroy with the original arguments (potentially after wrapping sendRequest).
Copilot
AI
Dec 6, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider checking if JSVideoPlugin exists before attempting to hack its prototype. If the script is not loaded, this could throw a ReferenceError.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion: Prototype hacks are applied every time initWindow resolves, which can repeatedly reassign the same methods.
hackJSResize and hackJSDestroyPlugin patch JSVideoPlugin.prototype, and initWindow can run multiple times, causing the same prototype methods to be reassigned on each successful init. This adds unnecessary repetition and makes it harder to see when the patch is applied. Consider a module-level guard (e.g. let jsPluginPatched = false) so the prototype is patched only once.
Suggested implementation:
}
let jsPluginPatched = false;
const initWindow = id => { if (result.inited === false || (result.inited && result.iWndIndex !== -1)) {
clearInterval(handler);
if (!jsPluginPatched) {
hackJSResize();
hackJSDestroyPlugin();
jsPluginPatched = true;
}
resolve(result);
}
Copilot
AI
Dec 6, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The hack functions are called unconditionally, even when result.inited === false. Consider only applying these hacks when initialization succeeds to avoid potential errors when the plugin is not properly initialized.
| hackJSResize(); | |
| hackJSDestroyPlugin(); | |
| if (result.inited === true) { | |
| hackJSResize(); | |
| hackJSDestroyPlugin(); | |
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unused import registerBootstrapBlazorModule.