'Open in application' on a web page from a WebDAV URL - javascript

tl; dr: Is it possible without installing additional software on the client (e.g. proprietary protocol handlers, browser plugins etc.) to link to a document's WebDAV URL on a web page and have the browser starting the associated application (in my case limited to MS Office or LibreOffice) and having the application reading the document directly from the WebDAV URL? My usage scenario is limited to MS Office documents, but it is important that the solution also works if LibreOffice instead of MS Office is installed on the client as the application configured to handle MS Office documents.
The most obvious solution to simply place a link to the WebDAV URL on the web page does not work. The browser does not realize that it is not a plain HTTP URL and shows its regular 'do you want to download or open this file' behaviour. If I open the document from the browser, the browser still downloads the document to a temporary folder and starts the associated application in such a way that the downloaded document is opened from the temp folder. The relevant difference is that if you edit and save the document, it is only saved back to the temp folder on the client and not saved to the original WebDAV URL as intended.
I find it a little bit strange that I seem to be the only one having this problem, I have at least not found much information or discussion when searching the net.
I few close, but not quite fitting solutions are:
The WebDAV AJAX library from IT Hit. The library offers a JavaScript API to do exactly what I need. If I ignore that the library is quite expensive, it does however require additional software to be installed on the client, which in my case is not acceptable.
Confluence is according to the documentation offering the functionality I request, also without installing additional software on the client, but I have found no details on how it is actually solved technically.
MS Office installs by default protocol handlers, which allows me to use URLs like ms-word:ofe|u|https://my.webdav.server/path/to/doducment.docx on the web page. Some discussions on the internet seem to indicate that LibreOffice is supposed to support these URLs, but my tests show that it is not the case, not even under Windows.
LibreOffice installs (at least under Windows, allegedly not under Linux) a protocol handler for vnd.libreoffice.command. I could alternate between ms-word:ofe|u| and vnd.libreoffice.command and almost achieve what I am looking for, but there is no JavaScript API to query the installed protocol handlers, so I have no way to check which office suite is installed on the client machine and decide which of the two protocol handlers I can use.
Anyone out there with a better suggestion how to achieve this?

Related

How to ensure that JavaScript page does not communicate

I created a small JavaScript application for which I reused some (quite large) JavaScript resources that I downloaded from the internet.
My application runs in the browser like other interactive web applications but works entirely offline.
However, I intend to enter some private information in the application which it shall visualize. Since I cannot ultimately trust the JavaScript pieces that I downloaded, I wonder if there is a JavaScript option to make sure that no data is downloaded and, in particular, uploaded to the web.
Note that I am aware that I can cutoff the local internet connection or perhaps change browser settings or use an application firewall, but this would not be a solution that suits my needs. You may assume that the isolation of a browser instance is save, that is no other, possibly malicious, web sites can access my offline JavaScript application or the user data I enter. If there is a secure way to (automatically) review the code of the downloaded resources (e.g. because communication is possible only via a few dedicated JavaScript commands that I can search for) that would be an acceptable solution too.
You should take a look at the Content Security Policy (CSP) (see here and here). This basically blocks every connection from your browser to any other hosts, unless explicitely allowed. Be aware that not all browsers support CSP, which leads to potential security problems.
Reviewing the library code might be difficult because there are many ways to mask such code pieces.
Find it yourself by watching your browser's network activity while your application is in action.
There are more than enough tools to do this. Also, if you know how to use netstat command line tool, it is readily shipped with windows.
Here is one cool chrome extension which watches the traffic of the current tab.
https://chrome.google.com/webstore/detail/http-trace/idladlllljmbcnfninpljlkaoklggknp
And, here is another extension which can modify the selected traffic.
https://chrome.google.com/webstore/detail/tamper-chrome-extension/hifhgpdkfodlpnlmlnmhchnkepplebkb?hl=en
You can set the filters and modify all requests/responses happening in your page.
If you want to write an extension to block requests yourself, check this answer out.

How can a Chrome extension save many files to a user-specified directory?

I'm working on a Chrome extension to be used as an internal tool. Its required behavior is:
As a page action, enable an address bar icon when looking at certain intranet pages.
when the user clicks the icon, identify all files of a certain media type (say, .jpg) on the page, and
silently save them all to a directory on the user's local drive.
This question has been asked before, but the answer then was "use NPAPI", and NPAPI is now derelict.
So, what is the currently available way to achieve this? The ones I've looked at are:
The chrome.FileSystem API --- but this does not save files in any user-accessible location. Instead the stored files are hidden behind obfuscated names in an undocumented directory. User requires that the files be stored under their original names in an accessible directory.
The HTML5 download attribute, by creating a data: URL and programmatically clicking it. This pops up a "save as..." dialog for each file, which is unacceptable when there are a hundred assets on a single page. User requires that the files be downloaded without further interaction beyond the single icon click.
The Chrome Download API, but that is only available in the beta and dev channels. User requires this extension work with mainstream Chrome.
Use the Native Messaging API by creating a small .exe that simply saves a file to disk, and then pass the .jpg as a blob to it. This seems very cumbersome and I am not even sure how to reliably pass large blobs to EXEs like that.
Is there another approach I can try?
You've done quite a lot of research. Indeed, regular web pages cannot write to the user's filesystem without any plugins or extensions. Also, the HTML5 Filesystem API only provides access to a virtual filesystem, as you've observed.
However, you are confusing the chrome.fileSystem API with the HTML5 FileSystem API. Unlike the HTML FileSystem API, Chrome's fileSystem (app) API can directly write to the user's filesystem (e.g. ~/Documents or %USERPROFILE%\Documents), specified by the user.
This API is only available to Chrome apps, not extensions. This is not a problem, especially since you're developing an internal tool, because you can install the app and extension, and use message passing to communicate between the extension (page action) and app (file system access) (example).
About chrome.downloads: Since your extension is internal, you can probably force users to get on the beta/dev channel in order to use this API. The only limitation of this API is that the files will be saved in (a subdirectory of) the user-defined Downloads folder.
EDIT: The chrome.downloads API is now avaiable in all channels, including the stable branch (since Chrome 31).
I am afraid that you have done your homework, meaning you looked at all possible alternatives.
The best way to achieve exactly what you want, would be (as you mentioned) using a supporting native app and communicating through Native Messaging. BTW, since bandwidth is rarely a problem on intranets, you might find it simpler to pass the resources (e.g. images) URLs and have the app download and save them.
(Yes, it will be more cumbersome than simply developing an extension, but one's got to do what they've got to do, right ?)
On the other hand, if you are willing to sacrifice a little bit of user's experience over simplicity of development, I suggest combining the HTML5 goodies (that allow you to create and download a file locally) with a JS zipping library (e.g. JSZip), so the user only has to download a single zip file (and is only prompted once). BTW, if the user wishes, he/she can choose to always download the files without prompting (but you knew that already).
Use the Native Messaging App idea.
The native app is cumbersome and a pain to write because documentation is poor, and unless you get the JSON formatting exactly correct on both ends you will not see anything in a console because stdin and stdout are taken over.
But, you will be happier when it is done because you can use standard tools (e.g., Windows Explorer, a hex editor, TeamViewer...) to view, move, and delete files, and otherwise see what is going on. Chrome's sand-boxed file system works, but seems to now be a dead-end (no other browsers have picked it up). No one is likely to develop third-party tools for it. Of course you probably don't need tools once everything is working, but until then, debugging is a nightmare because you need to write code (and quite a lot of code) just to track what files are in what directories, file versions, remaining disk space...
Another solution for internal (or may be non-internal) usage is to connect to a websocket server, local or remote.
You can put it in both background.js or content.js (use wss:// for https://)
var ws = new WebSocket('ws://echo.websocket.org');
// var ws = new WebSocket('ws://127.0.0.1:9000');
ws.onmessage = function(res) {
console.log('received data:', res.data);
};
ws.onopen = function() {
ws.send('hello');
};

Start a background process with javascript

In general I am aware that one cannot call system libraries or dll's from javascript in browser. But in many of the application's I see browser starting other processes. For example:
As soon as I open Google Plus, it starts the googletalkplugin.exe (from folder C:\Users\Jatin\AppData\Local\Google\Google Talk Plugin) in the background. (Can be viewed in Resource monitor)
The same with facebook video chat. For the first time, it asks me to install a plugin and later when I start a chat, it starts a process.
On torrent sites, they provide magnet links. Clicking on torrent magnet link, it opens my systems default torrent client.
In a way, the same with flash and applet.
How do browsers trigger another process and communicate with it? Is there any open standard I am missing?
Ultimately I wish to do video, audio recording with screencast. For screen-recording, Java applet looks like the only solution but applet has its own Issues.
The flash player and applets use plugins, which are native applications to the OS, (i.e. (mostly) not JavaScript), they are not extensions but plugins. For Chrome see chrome://plugins/ to see the list of installed plugins.
For writing a browser plugin, refer to How to write a browser plugin?
The torrent link is totally different, they are done by registering an url protocol to handle. In other words, you say to the computer that, from now on, I will run any urls which have protocol of torrent, i.e.: starts with torrent://. See: Uri Scheme
When the browser sees the uri, it knows that is not handling torrent protocol itself, so it delegates that to OS, which knows what to do with it.
If the browser did know how to handle that, it probably would not delegated that to OS. For example: Google Chrome can handle mailto: links just well without registering mailto protocol to be handled by OS.
You can do this by writing a plugin. It's possible to write plugins that work on most popular browsers, using the same C++ code, using a library called Firebreath
Naturally there is no pre-existing standard plugin that allows the page to start any external application, because that would be a massive security hole and no (sane) user would agree to install such a plugin.
You have to write a specific plugin with capabilities carefully limited to what you need, so the user can agree to let you use just those capabilities. Again, think about how another page might exploit those capabilities before going down this route.

Least complicated way to get full file paths with Javascript

This has been asked a lot of times already: I need to get the full file path via a web-page. The use case is an application running on the same machine as the browser (i.e. the application starts a local HTTP server and fires up the browser.) File-paths are of course valid and the same for both client/server now. The use case it that the user selects a file and then the server process does some computation on it, and the input files are typically large (read: several GiB in size.)
The easiest thing would be to directly access the path using , but for security reasons, this is disabled. I'm looking now for the least intrusive workaround to this problem. The target browser in question is Chrome. I'm fine if the user has to click "accept" once on some security warning, as long as I can ensure that it won't appear again.
Do I have to write an extension, NSPlugin, can I use some special header magic to mark my page as "local", is there some security setting I can set? The less the client has to do the better, and I would prefer some "click here to allow access ..." solution above everything else. Can I directly install an extension from the server process that would do this (after the user clicks accept?)
Is it possible to do this with a Java applet/Flash? That would be the easiest solution, and clients are guaranteed to have Flash installed (as it is bundled in Chrome...)
You can create Java applet for tasks like this and self-sign it. User will have to allow it to run, but then you will be able to access applet's function that will return file path string via Javascript.
Clearly file io on the client's system is forbidden from JavaScript. If this wasn't the case it would be absolutely trivial to hack every web browser that visits your website.
Battlefiled 3 is controlled though the browser. To do this EA wrote a browser extension for the top three browsers. But that's resource intensive. If you just care about chrome you can use an addon, and for that i suggest using the NPAPI.
And as MOleYArd said, Java is a good solution and probably more common than an extension or addon.

Sharing one JavaScript file among several domains

Problem definition:
Server is an embedded system with no access to Internet.
Each server is managed by web interface which uses JavaScript.
Each server has a local copy of JQuery library.
Clients (browsers) are connected to embedded systems (servers) via a very slow connection.
Clients have the latest browsers (HTML5, CSS3, JavaScript 1.8.5)
Clients are not connected to Internet either.
Clients can't access multiple servers at the same time (servers are in distant locations and most probably a client can only access one server and nothing else, but later that day the client may go to another location and connect to another server).
Each server has an IP address (not necessarily in the same range) and no DNS name.
Every time the client connects to an embedded server, it fetches all the files including the huge JQuery library (huge=~90KB)
Question:
The JQuery library is too big for this slow connection but one-time download is acceptable. However, we don't want the clients to download it every time they connect to each new server. The JQuery on all these devices is the same. But apparently the browser cache is domain based. How can we cache the JQuery library so that the client doesn't have to download the JQuery every time it connects to a new server?
just link to it in one place...
for example, if you have a single server, http://1.2.3.4/ that you want to designate as your CDN, put jQuery on it, and link to it in your scripts using <script src="http://1.2.3.4/jquery.min.js"></script>
you could link it to the ip in your link tag. The server does not have to have access to that access or anything, and so all the clients will geht the jquery from the same server all the time and so it is cached.
Here is a simple solution: All your customers must edit their /etc/hosts file (Google for where you can find it on Windows) and put a line like this in their config:
1.2.3.4 jquery-from-closest-server.com
Each client must figure out the closest server which has jQuery and replace 1.2.3.4 with its IP address.
In your HTML code, always use the link http://jquery-from-closest-server.com/jquery.js
To be safe, you may want to register jquery-from-closest-server.com for those customers which do have Internet access.
When the browser asks for the file, it will use /etc/hosts to resolve the IP address. Since the domain name will be the same for all your embedded devices (changes in the IP address are ignored by the browser), the script will be downloaded once for all clients.
Note that this means you can never upgrade to a newer version of jQuery. The problem is that you'd have to replace it on all embedded devices at the same time because there is no telling from which server the customers are downloading it from.
If that bothers you (and it will in about four months after you discovered the first serious bug), here is another solution: Instead of serving the HTML from your embedded device, distribute a static web app (a set of HTML files and JavaScript) which customer can install in their desktop. Use AJAX and iframes to replace parts of the static web app with data from your embedded device.
Advantages:
very fast (no downloads at all)
only little code on the embedded device
easy upgrade strategy
No deadlocks when you need to upgrade either the embedded devices or your controller app.
[EDIT] PS: Consider to compress jQuery with gzip. That leaves you with a 33KB file. All HTML5 browsers can decode compressed files, you just have to tell them by setting the necessary HTTP headers.
Apparently there is no standard way to include JQuery in our project so we chose to replace JQuery with a smaller similar library. These are the options:
JQuery mobile is a better fit for our project since it has a smaller size and can do almost everything we need from JQuery.
Zepto.js is also another suitable replacement.
JQuip is a stripped down version of JQuery that can help our specific project.

Categories

Resources