Reading Text Files from Local Directory in Javascript - javascript

I'm working on a Chrome extension and I want to take data from text files that will be in the same directory as the Javascript files with the functionality (that is, read the text files in as strings and use those for analysis of some kind). I'm pretty new to Javascript, so I've been trying to figure out how to do this--it seems that FileReader won't work since the user isn't uploading the files I'm using, and I'm not sure how XML HTTPRequest would be useful in this situation. Thank you!
tldr; I want to read text files in the same directory as a Javascript file in as strings.
update: The file is not a file from the user's file system, but one that's packed with the extension! So the folder that contains the HTML file and the Javascript file will also contain the text files.

Someone correct me if I'm wrong but as far as I know this is not possible in JavaScript due to security concerns.
If it were, a web page could grab any file on your file system without your consent or without you knowing. This is a major security concern so I dont believe it is possible.
A user must be given the option to choose a file from their file system knowingly.

You can try:
function readTextFile(file)
{
var rawFile = new XMLHttpRequest();
rawFile.open("GET", file, false);
rawFile.onreadystatechange = function ()
{
var allText = rawFile.responseText;
alert(allText);
}
rawFile.send(null);
}
And specify file:// in the same directory as a Javascript file

Due to browser security standard you cant access any file from your (HDD) at all.
Please try using this chrome API
https://developer.chrome.com/apps/app_storage#filesystem-manifest

Related

Why can't I embed a PDF from my local machine on my website?

I'm working on a website where the users can solve a practice exam.
My client wants to include a div next to the exam with a PDF viewer.
The idea is that the user can select a PDF file from his local machine and it will be loaded into the PDF viewer next to the exam.
I made it work using pdf.js and pdfobject.
The problem is that both options require the PDF file to be uploaded to our server.
Due to intellectual property law, that is unacceptable to our client.
They want the PDF file to be embeded without uploading it to our server. So it has to be loaded directly from the user's machine.
I found that it can't be done. All the plugins I tried require a virtual url, and will not accept a physic one (file:///local/path/file.pdf).
I don't want to just tell my client "it can't be done". I would like to know a technical explanation of why can't it be done.
If somebody knows a way to make it work it would be better!
This is a security policy. Issues it defends against include:
Allowing sites to detect your operating system by checking default installation paths
Allowing sites to exploit system vulnerabilities (e.g., C:\con\con in Windows 95/98)
Allowing sites to detect browser preferences or read sensitive data
Try to load it in a <iframe> with the URL of the PDF as src. But it might fail because of the client's browser's security policy. So this is brittle at best.
Maybe you can use HTML5 localstorage to upload the file to a "safe" location ("safe" as far as the browser is concerned).
PDFJS.getDocument() supports "a typed array (Uint8Array)
already populated with data or parameter object." So upload to local storage, get the document as bytes from there and then pass it to pdf.js.
Related:
https://hacks.mozilla.org/2012/02/saving-images-and-files-in-localstorage/
You might be able to do this, if the browser supports it. Take a look at the FileReader object. If the user's browser supports that, you can allow the user to select a file and reference that file in code. Something like this works for me in Firefox:
$('input[type=file]').change(function () {
if (window.FileReader) {
var input = this;
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function (e) {
$(input).next('iframe').attr('src', e.target.result);
}
reader.readAsDataURL(input.files[0]);
}
}
});
So if you have a input type="file" followed by an iframe then this will allow the user to select the file, and once it's selected it will load it into the iframe as a base64-encoded data URI.
Example here.

Again: how can I read a file using javascript

I could not find out why this part of my code doesn't work:
var loc = window.location.pathname;
var dir = loc.substring(0, loc.lastIndexOf('/'));
var FilePath = dir + "/" + FileName;
var file = new File("FilePath");
var reader = new FileReader();
reader.onload = function(e) {FileText = reader.result;}
reader.readAsText(file);
alert (FileText);
The intention is, I think, clear: FilePath contains the filename of a file (passed via parameter FileName) containing logging data (a plain ASCII text file, with one line per log entry), the file is located in the same directory as the web page is (loc), and I want to embed the text into my html document somewhere further down the code.
Since the logged lines are of different kinds (e.g. errors, warning, other blabla ...) each line needs to be parsed and processed.
I intended to split FileText into an array, and loop through it. I cannot, however, get readastext to work. Though, according to FireFox debugger, FilePath does contain the correct string, I get the NS_ERROR_FAILURE, which I, according to the sparse documentation I found about it, must consider to be the 'zillionst stupid way to say "File not found".
I found tons of other posts from people messing with the file API, and tons of snippets taken from the mozilla docs which don't help me out. I read that there are maybe other ways to read a file, e.g. through Ajax, JQuery ... but before I go that way ... is it really, really absolutely impossible to accomplish what I want using just plain JavaScript, and if it is possible, who can provide a code snippet?
Thanks very much,
Armin.
You have quotes around "FilePath":
var file = new File("FilePath");
This means it's going to try to load a file with the path "FilePath".
Pretty sure this is what you want:
var file = new File(FilePath);
On the other hand, Quentin is absolutely right. You're not going to be able to access local files if this code is running in a web page.
Since you are using window.location.pathname i assume that you are in a browser and want to use that code to "navigate" to files on the server based on the URL path.
I think your whole approach is wrong, and it would be a security issue to have something like that possible.
The File API can be used strictly on files selected by the user, and not on any file. The MDN description is self-explanatory:
Using the File API, which was added to the DOM in HTML5, it's now possible for web content to ask the user to select local files, then read the contents of those files. This selection can be done by either using an HTML element, or by drag and drop.
Yes, you can specify a path to any file in the File constructor method, but that doesn't mean you can access any file. Another excerpt from MDN:
This only works from privileged code, so web content can't do it. This protects users from the inherent security risks associated with allowing web content free access to the contents of their disks. If you pass a path to the File constructor from unprivileged code (such as web content), an exception will be thrown.
This code did the trick:
var objXMLhttp = new XMLHttpRequest()
objXMLhttp.open("GET",strFileName,true);
objXMLhttp.send();
and, in addition, an objXMLhttp.onreadystatechange=function() ... event handler must be implemented, which is the code acutally receiving the data, like so:
objXMLhttp.onreadystatechange=function()
{
if (objXMLhttp.readyState==4 && objXMLhttp.status==200)
{
var arrContents = objXMLhttp.responseText.split("\n"); // gotcha!
....
}
}
Easy win is to do an ajax request for the path...you should have your page that contains the js and files served by a web server. Any other way needs other priveleges and if you were to get files from a users computer without an uploader or anything like that would be a security breach

is there a do/workaround XML requests without HTTP

I want to get the string from a file in javascript but it doesnt' work. The error says that it is because Cross origin requests are only supported for HTTP. So the only reason this doesn't work is evidently because the HTML page isnt online. Is there a way to read a .txt file into a string that can workaround this issue
this is the code that doesn't work:
function readTextFile(file)
{
var File = new XMLHttpRequest();
File.open("GET", file, true);
File.send(null);
Text = File.responseText;
return Text;
}
At line 6 is stops and display the error.
Thanks in advance:)
You cannot use it for a local file for security reasons I believe, it should work as long as you make the file variable a valid http url to the file. You can use xampp / wampp / mamp / etc to create a local webserver and run it from there !
that way your link can be like http://localhost/link/to/file.txt

Access local file with html5 FileReader

I'm trying to make an offline app that reads text from a text file that is stored locally. I understand this is possible with html5 and FileReader. I want to hard-code the relative path. I have read the docs and all them them are based on an array of FileList. But since I am just doing one file with a static path, I can't make sense of it. This is silly, I know, but what I have so far:
var file = "data/data";
var reader = new FileReader();
reader.readAsText(file);
alert(reader.String);
The FileReader API lets you read files selected by the user in a file input.
It does not let the author of a webpage choose files from their visitor's systems to read. That would be a security risk.
This is possible using ActiveX, which isn't too hard to do if you've never worked with it. Check this out for more info: http://msdn.microsoft.com/en-us/library/2z9ffy99(v=vs.84).aspx
Just means the user will probably have to agree to let ActiveX run.. which admittedly might scare a few away. So it depends upon how much you actually need it.

Drupal Filefield won't upload javascript files?

I've got a site where individual pages might require some javascript or CSS files hooked into their heads. I'm trying to keep everything client side when it comes to managing this process, rather than getting on the FTP and sorting everything out in the code so I need to be able to upload css and js files.
I've got CCK filefield up and running, and it works with css files, but it refuses to upload .js files. It instead seems to view every .js as ".js.txt" and then the file appears on the server as thisismyfile.js.txt
Not ideal...
Does anyone know how to work around this. Is it a mime type problem with Drupal or the server, or is Drupal set up to avoid script uploads and n00b hack attacks.
Once the files are uploaded I intend to use PHP mode on the page or node to call drupal_add_css and drupal_add_js.
Looking at the field_file_save_file() function in field_file.inc from filefield module, you can find the following snippet
// Rename potentially executable files, to help prevent exploits.
if (preg_match('/\.(php|pl|py|cgi|asp|js)$/i', $file->filename) && (substr($file->filename, -4) != '.txt')) {
$file->filemime = 'text/plain';
$file->filepath .= '.txt';
$file->filename .= '.txt';
}
So yes, it's a 'security thing', as Jeremy guessed.
You could patch that RegEx for an immediate 'fix', but that would remove this otherwise useful security check completely for all filefields used on the site.
So a more specific workaround might be a better approach. Since you want to add the files via drupal_add_js() calls from code anyways, you might as well do the renaming there, adding some kind of verification to make sure you can 'trust' the file (e.g. who uploaded it, whatever).
Edit: Concerning options to rename (and alternatives) when calling drupal_add_js():
For renaming the file, look into the file_move() function. A problem with this would be that it won't update the corresponding entry in the files table, so you would have to do that also, if the move operation succeeded. (The filefield just stores the 'fid' of the corresponding entry in the files table, so you'd need to find it there by 'fid' and change the 'filename', 'filepath' and 'filemime' entries according to your rename/move)
Alternatively, you could just load the content of the *.js.txt file and add that string with the 'inline' option of drupal_add_js(). This would be less 'elegant' and could be a performance hit, but if those are not important criteria in your specific case, it is less trouble.
Yet another option would be just passing the *.js.txt file as is to drupal_add_js(), ignoring the 'wrong' extension. A short local test showed that this works (at least in firefox). This might be the 'least effort' solution, but would need some additional testing concerning different browser behavior concerning usage of 'misnamed' js files.
Allowing Drupal to upload javascript files would be a security risk, which is also why it doesn't allow you to do it, but instead appends the .txt extension. The reason is that js files are executable along with php, pl, py, cgi, asp. So if Drupal could upload those files to the server, it would be possible for evil doers to upload a file and run it doing all kinds of nasty things on your server, basically anything is possible. Best thing would be to find a different way of uploading files which are secure.
I had a similar need, and found a way to get around the security by first changing the 'allow_insecure_uploads' variable value by running this line of code in your hook_install:
variable_set('allow_insecure_uploads', 1);
Then in a module add this function
/**
* Implementation of FileField's hook_file_insert().
*/
function MODULE_NAME_file_insert(&$file) {
//look for files with the extenstion .js.txt and rename them to just .js
if(substr($file->filename, -7) == '.js.txt'){
$file_path = $file->filepath;
$new_file_path = substr($file_path, 0, strlen($file_path)-4);
file_move($file_path, $new_file_path);
$file->filepath = $file_path;
$file->filename = substr($file->filename, 0, strlen($file->filename)-4);
$file->filemime = file_get_mimetype($file->filename);
$file->destination = $file->filepath;
$file->status = FILE_STATUS_TEMPORARY;
drupal_write_record('files', $file);
}
What this does is in the hook_insert call it checks if a file has the extension ".js.txt". If it does it copies it to a new location and renames it. This is after the security check so its ok. I don't think you need to worry about the cache clear deleting your js files as long as you don't put them in the files/js directory. Create your own directory for you module and you should be ok.
I faced this situation when I wanted to allow .js file to be upload as is (without .txt and with 'application/javascript' mimetype) for a specific field. Also, I didn't wanted to alter Drupal core... of course.
So I needed to create a module implementing hook_file_presave(). This also work for Multiupload File Widget, since its hook is on file_save().
Note that you would have to replace MYMODULE_NAME and MYFIELD_NAME by your own values.
function MYMODULE_NAME_file_presave($file) {
// Bypass secure file extension for .js for field_additional_js field only
if((isset($file->source) && strpos($file->source, "MYFIELD_NAME") !== FALSE) && substr($file->filename, strlen($file->filename) - 7) == ".js.txt") {
// Define new uri and save previous
$original_uri = $file->uri;
$new_uri = substr($file->destination, null, -4);
// Alter file object
$file->filemime = 'application/javascript';
$file->filename = substr($file->filename, null, -4);
$file->destination = file_destination($new_uri, FILE_EXISTS_RENAME);
$file->uri = $file->destination;
// Move fil (to remove .txt)
file_unmanaged_move($original_uri, $file->destination);
// Display message that says that
drupal_set_message(t('Security bypassed for .js for this specific field (%f).', array('%f' => $file->filename)));
}
}
Drupal also "munges" javascript files. To prevent Drupal from automatically adding underscores to the filename there is a hidden variable that is checked before the filename is "munged".
Setting the variable to 1 solves the issue for me (along with altering the REGEX in includes/file.inc).
I hate hacking core, but this seems like a poor design to me. Javascript files are not server side scripts like php, py, pl, cgi, and asp.
You can use the allowed file extensions settings to prevent php and other server side scripts from being uploaded.
eg:
variable_set('allow_insecure_uploads', 1);
See:
http://api.drupal.org/api/function/file_munge_filename/6
So uploading .js files to the files directory is pretty much impossible.
Even if you manage to get .js files uploaded cleanly, these files will get deleted when the cache is cleared.
Any js files that live inside the files directory will be deleted whenever the drupal_clear_js_cache() function is executed.
http://api.drupal.org/api/function/drupal_clear_js_cache/6
So Drupal sees .js files living in the file uploads directory as temporary.
Now I understand why they are appending ".txt", it is to prevent them from being removed when the cache is cleared.
So as a compromise I guess I will just be uploading .js files manually (via FTP) to the /misc folder. :(

Categories

Resources