Valid Javascript: function document.onkeydown(...)? - javascript

I'm trying to set up a HikVision IP-based camera for some work I'm doing and it refuses to log in to the camera (the login button appears to do nothing).
The reason for this, when I break out the Chrome debugger console and investigate a bit deeper, is that the inbuilt login.js file (the one supplied by the camera) contains the code:
function document.onkeydown()
{
and the browser is complaining that the . is an invalid token in this context.
So my first question is simple: is this valid or invalid Javascript?
If it's invalid, I just have to track down the developer for a good talking to :-)
If it's valid, how do I get Chrome to stop complaining so that it can continue to process the rest of the file (including the definition of login function which is what would normally be called when I click on the login button)?
And, if it's not invalid and I don't want to wait around for a vendor fix, is it viable to just replace the login page and the Javascript file with local ones?
In other words, have those two files on my desktop (using 127.0.0.1) but have them reference all the other ones on the camera itself (192.0.0.whatever).
So, rather than accessing http://camera.com/page/login.asp which contains:
<script type="text/javascript" src="../script/login.js" />
<script type="text/javascript" src="../script/other.js" />
<script type="text/javascript" src="../script/again.js" />
I'd instead access file://login.htm, which would contain:
<script type="text/javascript" src="my_good_login.js" />
<script type="text/javascript" src="http://camera.com/script/other.js" />
<script type="text/javascript" src="http://camera.com/script/again.js" />

There is a problem with the firmware for some early HikVision cameras, in version 4.x.
The best solution is to upgrade the firmware to 5.2 where the Javascript code in the firmware is fixed.
This can be done with the SPD tool from HikVision itself.
However, if that's not an option, the scheme suggested should work. You just have to ensure that you correctly copy the errant firmware files off the camera onto your local box. That means:
Making an exact copy of the top-level page and errant login Javascript file locally (meaning on your host machine rather than the camera). This is probably as simple as just cut'n'pasting the browser source for both into new files(a).
Fixing the local copy of the errant login Javascript file, replacing document.onkeydown with the correct onkeydown.
Ensuring that you use the local top-level page from your browser rather than the on-camera one: this will ensure it uses the local login Javascript file.
Having that top-level page use your fixed login Javascript file: given it is a relative URL, that should work without change.
Ensuring the local top-level page accesses the other files on the camera: this will entail replacing the relative URLs with absolute ones.
(a) The only worrying possibility is the fact your current top-level page is an ASP one, whereas this process gets its HTML output fro creating the local top-level file. If the ASP file on the camera simply generates the same HTML each time, you'll be file.
However, if it's more complicated than that, you may have to do something tricky like extract the HTML from the camera each time with a script and massage it to change the URL accesses within a local page. Then access that local page from the browser. This could be automated but it's starting to get a little more difficult.
So, all in all, an upgrade to later fixed firmware is probably still the best option.

Related

Cannot load local office.js

As this answer suggested, I want to modify a little bit office.js.
So I copied the content of https://appsforoffice.microsoft.com/lib/1/hosted/office.js to local, such that https://localhost:3000/static/office.js shows well the content.
Then, I make a very simple file test.html:
<html>
<head>
<!--<script src="https://appsforoffice.microsoft.com/lib/1/hosted/office.js"></script>-->
<script type="text/javascript" src="https://localhost:3000/static/office.js"></script>
</head>
<body>
haha
</body>
</html>
Loading https://localhost:3000/static/test.html with remote office.js in a browser shows Warning: Office.js is loaded outside of Office client
o15apptofilemappingtable.js:11, and loading it in an Office add-in works well.
However, loading https://localhost:3000/static/test.html with local office.js in a browser shows Uncaught SyntaxError: Unexpected token <
o15apptofilemappingtable.js:1, and loading it in an Office add-in gives an error Add-in Error Something went wrong and we couldn't start this add-in. Please try again later or contact your system administrator.
So does anyone know what's wrong here? Is it possible to make our own local version of office.js?
See my answer in the linked question. Essentially, no, you should not be making your own local copy of "office.js". But if you did want a local copy -- which we already offer on NuGet and, more recently, on NPM (https://www.npmjs.com/package/#microsoft/office-js) -- you would need all the associated files in that directory as well, not just Office.js itself.
See https://unpkg.com/#microsoft/office-js#1.1.1/dist/ for a listing of the files and folders that make up Office.js. Not all (in fact, not most) are used in any given session, but you do want the whole set of files since different ones are loaded in different circumstances.

FileMaker Web Viewer javascript step fails when used as a local file: window.open()

I ran into an odd issue with a bit of Javascript that is running in a Web Viewer (WV) in a FileMaker database. (For those that don't know, FileMaker is an integrated UI/DB platform which has a 'web viewer' object, which is a cut down version of a web browser that runs inside the solution. It is NOT a full web browser.)
We have had this WV+Javascript working for quite a while now, in files that are hosted using FileMaker Server (FMS). There's a button on a layout that opens a pop-out window that contains this web viewer. This web viewer is a media player, with pause/play buttons; it has some special functions for capturing the current video position and reporting it back to the database: it has some buttons and reads keystrokes, and calls back to the open FMP file to affect changes there. Again, this has been working fine when the file is hosted on FMS.
But then we wanted to make a trial/demo version of this file, and have the user run it locally or offline. In testing this offline file it was noticed that the pop-out window web viewer stopped calling back to the open file. (FileMaker Pro also registers a new URL scheme, "fmp://". This can be used to make callbacks to the database from web viewers that are inside that database. So the code was changed to use the '$' reference in the "fmp://" URL, which causes the FileMaker client software to reference the currently open file of the given name.) But even with that fixed, there was one step that was failing still.
To effect these 'callback' events from the WV+javascript to the FM file, the javascript was using this code:
window.open('fmp://' + fmdbHost + '/' + fmdbFilename + '?script=keyPressed&param=' + e.keyCode, 'form_b');
(Here, the variable 'fmdbhost' = "$", as noted; 'fmdbFilename' =(nameoftheopenfile); 'e.keyCode'=(keypressed); "form_b" is an iframe that is defined in the HTML of the page.) This code (when it's working on the hosted environment) does not actually open a new window; that's OK, I don't want it to open a new window. It just a technique used to execute the URL and trigger functionality in the FileMaker world.
My solution/workaround, was to instead use this code:
window.location.href = ( 'fmp://' + fmdbHost + '/' + fmdbFilename + '?script=keyPressed&param=' + e.keyCode );
This appears to work out just fine, but I'm curious to know why the original step was failing when it's run locally. This was working if the file was hosted...so why would that fail if the file is being run locally? Does it do some kind of URL verification, and not like the "fmp://" or perhaps the "$" part? If so...why isn't it doing this when using 'window.location'? (If I used the original 'fmdbHost' definition - which used an IP Address - it would at least execute the window.open() method and attempt to open the "fmp://" URL. It's just that when run locally this ended up being the wrong file - it needs to use the "$" reference to affect the currently open file.)
The specification for 'window.open()' indicates that the second parameter is a window name (sounds more like a reference to the new window). So in the original code the 'form_b' reference is attempting to reuse the iframe defined in the HTML as the conduit for the call. But is that iframe even an actual window 'reference' initially? Does something parse the DOM and extract iframes and add them to the list of current 'windows'?
I'm using FM 15.01 for testing/development, on OS X 10.11.6. Ultimately, this will have to run on Windows as well...but that can be ignored for now.
Thanks,
J

Force browser to refresh javascript code while developing an MVC View?

Pretty straight-forward, I'm developing an MVC5 application and have noticed (lately) that my Browser appears to be caching the JavaScript code I have on the view within #section Scripts { }.
Currently I am developing with Chrome and I have tried CTRL+F5 & CTRL+SHFT+R which reloads the page, but the alert() I uncommented within the javascript code is still rendering as commented. I also tried going to my localhost through Incognito Mode as well as other Browsers (Firefox, IE) and am getting the same behavior. This is my /Home/Index.cshtml View, which is the default View which loads when the application starts. I have also tried adding some extra HTML text into the page and again the new code is not taking effect/showing.
My current Chrome version is Version 41.0.2272.118 m if anyone has any ideas what might be going on?
UPDATE:
I have gone under the Developer Tools => General Settings in Chrome and checked [X] Disable cache (while DevTools is open) and then repeatedly (with DevTools still open) tried CTRL+SHFT+R and CTRL+F5 with the same results of before where my changes are not taking effect.
UPDATE 2:
With DevTools open I have also held the Refresh button down and tried Normal/Hard/and Empty Cache & Hard Reload options all with the same result. For simplicity of testing I added an alert in the below to dispaly as soon as the page loads (and currently no alert comes up):
$(document).ready(function () {
alert("Test");
// Other Code/Functions -- No Error showing in Console
});
If you are using Bundling from MVC, you have two options to disable caching:
Use BundleTable.EnableOptimizations. This instructs the bundling to minify and optimize your bundle even while debugging. It generates a hash in the process, based on the content of the script, so your customers browsers can cache this file for a long time. It will generate a whole different hash the next time your file changes, so your customers can see your changes. The downside is that your script will become unreadable and you won't be able to debug it, so this might not be your best option.
Use System.Web.Optimization.BundleTable.Bundles.ResolveBundleUrl("url", true) to resolve your script's URL, the second parameter (true) is requiring a hash to be generated with the URL, thus, preventing caching from your browser when you change the file. This is exactly the same hash generated in the first option, but without minifying.
I created a small demo showing that the second option prevents caching from happening, the trick is getting the hash generated from your script's content without minifying your script.
I created a script file called myscript.js with this content:
$(document).ready(function () {
alert('a');
});
Then I added this to my BundleConfig.cs:
// PLEASE NOTE this is **NOT** a ScriptBundle
bundles.Add(new Bundle("~/bundles/myscripts").Include(
"~/Scripts/myscript*"));
If you add a ScriptBundle, you will get a minified response again, since ScriptBundle is just a Bundle using JsMinify transformation (source). That's why we just use Bundle.
Now you can just add your script using this method to resolve the script URL with the hash appendend. You can use the Script.Render
#Scripts.Render(System.Web.Optimization.BundleTable.Bundles.ResolveBundleUrl("~/bundles/myscripts", true))
Or the script tag:
<script src="#System.Web.Optimization.BundleTable.Bundles.ResolveBundleUrl("~/bundles/myscripts", true)"></script>
Either way will generate a URL with a hash to prevent caching:
After editing my file:
You might want to add a no_cache variable after your script url like:
<script src="js/stg/Stg.js?nocache=#random_number"></script>
If you manage to put a random number to the place i indicated, the browser will automatically download the latest version of the script after an F5
A quick trick that solves this problem consists of opening the script file in a new tab, then refresh it on this page.
If you happen to have Chrome dev tools open it will even refresh it there.
From dev tool you can even easily right click-open in new tab the script.

How to start two or more custom URL Protocol from Javascript

I have an old html page that creates a script file and executes it using:
fsoObject = new ActiveXObject("Scripting.FileSystemObject")
wshObject = new ActiveXObject("WScript.Shell")
I am trying to modify it and make it usable also from other browsers. If you know the answer stop reading and please answer. If there is no quick answer, here is the description of my attempts. I was successful in doing the job, but only when the script is shorter than 2000 characters. I need help for scripts longer than 2000 characters.
The webpage is for internal use only, so it is easy for me to create a custom URL protocol on each computer that runs a VBScript file from a network drive.
I created my custom URL Protocol that starts a VBScript file like this:
Windows Registry Editor Version 5.00
[HKEY_CLASSES_ROOT\MyUrlProtocol]
"URL Protocol"=""
#="Url:MyUrlProtocol"
"UseOriginalUrlEncoding"=dword:00000001
[HKEY_CLASSES_ROOT\MyUrlProtocol\DefaultIcon]
#="C:\\Windows\\System32\\WScript.exe"
[HKEY_CLASSES_ROOT\MyUrlProtocol\shell]
[HKEY_CLASSES_ROOT\MyUrlProtocol\shell\open]
[HKEY_CLASSES_ROOT\MyUrlProtocol\shell\open\command]
#="C:\\Windows\\System32\\WScript.exe \"X:\\MyUrlProtocol.vbs\" \"%1\""
In MyUrlProtocol.vbs I have this:
MsgBox "The length of the link is " & Len(WScript.Arguments(0)) & " characters"
MsgBox "The content of the link is: " & WScript.Arguments(0)
When I click on click me I see two messages, so everything works well (tested with Chrome and IE in Windows 7.)
It works also when I execute document.getElementById("test").click()
I thought this could be the solution: I would pass the text of the script to the VBS static script, which would create the dynamic script and run it, but with this system I can't pass more than ~2000 characters.
So I tried to split the text of the script in chunks smaller than 2000 characters and simulate several clicks on the link, but only the first one works.
So I tried with xmlhttp.open("GET","MyUrlProtocol:test",false);, but Chrome says Cross origin requests are only supported for HTTP.
Is it possible to pass more than 2000 characters to a VBScript script via a custom URL protocol?
If not, is it possible to call several custom URL protocols in sequence?
If not, is there another way to create a script file and run it from Javascript?
EDIT 1
I found a solution, but in Chrome only works when it likes, so I'm back to square one.
The code below in IE executes the script 4 times (correct), but in Chrome only the first execution runs.
If I change it to delay += 2000, then Chrome usually runs the script 2 times, but sometimes 1 and sometimes 3 or even 4 times.
If I change it to delay += 10000, then it usually runs the script 4 times, but sometimes misses one.
The function is always executed 4 times, both in Chrome and IE. What is weird is that the sr.click() sometimes does nothing and the function execution continues.
<HTML>
<HEAD>
<script>
var delay;
function runScript(text) {
setTimeout(function(){runScript2(text)}, delay);
delay += 100;
}
function runScript2(text) {
var sr = document.getElementById('scriptRunner');
sr.href='intelliclad:'+text;
sr.click();
}
function test(){
delay = 0;
runScript("uno");
runScript("due");
runScript("tre");
runScript("quattro");
}
</script>
</HEAD>
<BODY>
<input type="button" value="Run test" onclick="test()">
scriptRunner
</BODY>
</HMTL>
EDIT 2
I tried with Luke's suggestion of setting the next timeout from inside the call back but nothing changed (IE works always, Chrome whenever it likes).
Here is the new code:
var scripts;
var delay = 2000;
function runScript() {
var sr = document.getElementById('scriptRunner');
sr.href = 'intelliclad:' + scripts.shift();
sr.click();
if(scripts.length)
setTimeout(function() {runScript()}, delay);
}
function test(){
scripts = ["uno", "due", "tre", "quattro"];
runScript();
}
Some background: The page asks for the shape of a panel, which can be just a few parameters [nfaces=1, shape1='square', width1=100] or hundreds of parameters for panels with many faces, many slots, many fasteners, etc. After asking for all the parameters a script for our internal 3D CAD (which can be larger than 20KB) is generated and the CAD is started and asked to execute the script.
I would like to do all on the client side, because the page is served by a Domino web server, which can't even dream of managing such a complex script.
I didn't read your whole post...have an answer:
I too wish that custom url protocols can handle long urls. They simply do not. IE is even worse as some OSs only accept 800 chars.
So, here's the solution:
For long urls, only pass a single use token. The vbscript uses the token
and does a url get to your web server to get all of the data.
This is the only way I've been able to successfully pass lots of data around. If you ever find a clearer solution, please remember to post it here.
Update:
Note that this is the best way I have found to deal with the url protocol limitations. I too wish this was not necessary. This does work and works well.
You mentioned Dominos, so possibly you need something in a POS environment... I create a web based POS system, so we could face a lot of the same issues.
Suppose you want a custom url to print a pdf to the default printer without the annoying popup window. We need to do this thousands of times a day...
When building the web page, add the print button which when pressed calls the custom url: myproto://printpdf?id=12345&tocken=onetimetoken
this will execute your vbscript on the local desktop
in your vbscript, parse the arguments and react. In this case, your command is printpdf and the id is 123456 and you have a onetime tocken key.
have the vb script to an https get to: https://mydomain.com/APIs/printpdf.whatever?id=12345&key=onetimetoken
check the credentials based on the ip address and token, if all aligns, then return the contents of the pdf (you may want to convert the pdf to a byte array string)
now the vbscript has the pdf, assemble it and write it to a temp folder then execute a silent pdf print command (I use Sumatra PDF http://blog.kowalczyk.info/software/sumatrapdf/free-pdf-reader.html)
mission accomplished.
Since I do know what you what to do in your custom url and the general workflow, I can only describe how I've solved the sort url issue.
Using this technique, the possibilities are limitless. You have full control over the local computer running the web browser, you have a onetime use token which grants access to a web API with can return any sort of information you program.
You could write a custom url protocol to turn on the pizza oven if you wanted :)
If you are not able to create the server side code which is listening for vbscript's get request then this would not work.
You might be able to pass the data from the browser to the vbscript using the clipboard.
Update 2:
Since in this case the data is on the client (one single form can define hundreds of parameters), the server API doesn't know what to answer to the vb script request. So the workflow described above must be preceded by these two steps:
The onkeypress event executes a submit to send the current parameters to the server
The server replies with the refreshed form, adding to the body onload a call to a function which uses another submit to call the custom url, as described on point 1 listed above.
Update 3:
stenci, what you've added (in Update 2) will work. I would do it like this:
user presses a button saying I'm done editing the form
ajax post the form to the server
the server saves the data and attaches unique key to the datastore
the server returns the key to ajax callback function
now the client has a single use key and invokes the url schema passing the key
vbscript does an https get to the server and passes the key
server returns the data to the vbscript
It is a bit long winded. Once coded it will work like a charm.
The only other alternative I can see is to copy the form data to the clipboard using something like: http://zeroclipboard.org/
and then in vbscript see if you can read the clipboard like: Use clipboard from VBScript
How about creating an iFrame for each instance?
Something like this:
function runScript(text) {
var iframe = document.createElement('iframe');
iframe.src = 'intelliclad:'+text;
document.body.appendChild(iframe);
}
function test(){
runScript("uno");
runScript("due");
runScript("tre");
runScript("quattro");
}
You can then use css styling to make these iframes transparent / hidden.
You might not like this answer, but I've used this method in the past and it works.
Instead of relying on ActiveX, consider using a Java Applet, and JNI.
Basically, you have to make sure the native scripts you want to run are available on your client machine, along with a JNI wrapper.
The applet will have to be at least self signed, for the browser to allow it to load and access a native library. Once the JNI libraries are loaded, you can easily call methods from the page / applet.
As a consequence of using Java, you could possibly use the same applet for windows as well as linux clients, provided of course you have native libraries present on the respective clients.
This series of articles talks about precisely your problem : http://www.javaworld.com/article/2076775/java-security/escape-the-sandbox--access-native-methods-from-an-applet.html
P.S the article is really old, but the concept remains unchanged.

Forcing cache refresh after modifying head.js javascript calls?

I am using head.js and using the below file to initiate the javascript file calls:
<script src="/scripts/load.js" type="text/javascript"></script>
In the load.js file I have the following code:
head.js(
{livechat: "/scripts/livechat.js"},
{jquery: "http://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"},
{jquerytools: "http://cdn.jquerytools.org/1.2.5/full/jquery.tools.min.js"},
{slider: "/scripts/jquery.nivo.slider.pack.js"},
{prettyphoto: "/scripts/jquery.prettyPhoto.js"},
{sliderfunctions: "/scripts/slidercode.js"},
{functions: "/scripts/functions.js"}
);
My problem is, even though I removed the livechat line, the chat box is still appearing on all my website pages unless I manually clear the browser cache. My concern is that I no longer utilize the livechat service and I do not want the visitors to be confused by seeing the livechat box appear but not function correctly.
Is there any way to tell head.js that there has been a change in the files being loaded and to refresh browser cache or something?
You could put something along the lines of this:
<script src="/scripts/load.js?date=123456789" type="text/javascript"></script>
Adding a query string to this file should trick the browser into thinking it's something it hasn't seen before.

Categories