How do you save information in Javascript programs - javascript

As it may be obvious from my question, I'm very new to creating javascript programs. However I have made a few small programs and so I understand the basics about creating variables and getting input from the user and such. The question that I've had this entire time and have had some trouble getting a clear answer on is how do you keep that information stored after you close the program?
So for example: If the code has X = UsersName and then the user sets X to "Joe Smith" and quits the program, how can I save that data so that the next time the user opens the program the variable X is already Joe Smith?
(This is my first time using StackOverflow to ask a question so hopefully I worded that correctly and followed the proper format)

Assuming you are executing JavaScript in a browser, like most of JavaScript world, not on a server (using e.g. Node.js).
In this scenario, you can
Save a value to window.sessionStorage, which will be available there until the browser tab is closed (thus, probably not what you're after)
Save a value to window.localStorage, which will be available there until either you or the user delete it explicitly
Let a user download it in a form of a file (then reupload it when they want to resume), using a data URI
Post a value to a program running on a web server (using form submission, XMLHTTPRequest, or Web Sockets), which will store it for you in a more (or less) persistent way (a file, a database, a cookie, a variable)

Related

TYPO3 extension: Accessing the TYPO3 session variable from javascript?

This may sound a little unprecise, but is it possible to change the TYPO3 session variable
$GLOBALS["TSFE"]->fe_user->setKey('ses', 't_minus', 0);
from javascript somehow for the variable to be processed within a listAction to specify certain records to be shown or not?
In more detail: I work on an extension for a calendar. The calendar is generated in javascript (that's the part i'm not responsible for). The listAction basically generates a JSON object or records which have a unix timestamp within a specific interval (2 weeks in the past, 3 weeks in the future). The javascript has a button "one week forward"/"one week back". One week back should subtract 604800 (1 week) from the session variable, one week forward add 604800 (1 week) to the session variable.
In the listAction the session variable adjusts the timestamp interval (n weeks forward/backward) or rather which records should be put into the JSON object.
Is it possible to access the session variable from javascript or does this violate safety requirements?
It is not possible to change TYPO3 session content directly via javascript. It may be that you can access the PHP session cookie via javascript - I am not quite sure on that -, but the session variables are stored in the TYPO3 DB. They are serialized and encrypted via PHP and you won't be able to get access on these via Javascript. This is only possible via PHP.
What you could do: create oneWeekForwardAction and oneWeekBackAction in your controller. Read your session cookie and modifie it to your needs. These actions can be activated via Ajax. For this to happen you have to create the appropriate links with the f:uri.action in advance in your Fluid template! Place these strings somewhere in your JSON object. Then you can connect these links to the click events.
Don't forget to generate a special AJAX page type with page.config.disableAllHeaderCode. If you search for this and Ajax you will find examples, f.e. this one:
[http://www.sklein-medien.de/tutorials/detail/erstellung-einer-typo3-extension-mit-ajax-aufruf/]
It is from 2016 und uses Extbase/Fluid.
I would create a PHP function to change this session variable (e.g. with eID functionality) and call the function via AJAX in JavaScript.
More see here: https://seethroughweb.com/ajax-with-typo3/
(Sorry, couldn't find a better manual in english, you need to use the new class names)
It's not a question of safety. The idea of a session is, to bind to the same data on the server over a series of multiple HTTP requests. Javascript lives in the Browser. There is no direct access from JavaScript to the data on the server.
If you are responsible for JS only, it's the job of the other person to provide an interface to the session data for you.
And yes, I think it a good idea to synchronise your calculations in the Browser with the data in the server else calendar datas get quickly out of sync. I would even go that far, that the server should be responsible for this kind of calculations, as it is more reliable than JS. So the guy responsible for PHP should do the main job and provide results to you i.e. via AJAX.

Google Apps Script - how to login and fetch data?

Intro:
I am pretty inexperienced, but recently I have been trying to access some data from a website using Google Apps Scripts. However, to access the data, I must be logged into that website. There have actually been many posts about similar issues before, but none of them were very helpful until I came to this one: how to fetch a wordpress admin page using google apps script. The accepted answer gave a method for saving the cookies and sending them out again in the second request. I basically copied and pasted the code into my own GAS file. Since the problem in that post was logging into Wordpress, I tried that first, and it worked. I had to remove the if statement checking for the response code because 200 was being returned even when I entered the correct combo. I don't know if that was just an error in the post's code or what. In any case, I verified that the second request I made returned information as if I was logged in.
Details about specific site:
The actual website that I am trying to log onto has a some kind of weird hashing method that I haven't seen on any other login pages. When you click submit, the password changes to something really long before going to another page. The opening form tag looks like this:
<form action="/guardian/home.html" method="post" name="LoginForm" target="_top" id="LoginForm" onsubmit="doPCASLogin(this);">
As you can see, it has an "onsubmit" attribute, which I believe will just run "doPCASLogin(this);" when the form is submitted. I decided to play around with the page by just entering javascript into the address bar. What I found was that doing a command like this (after entering in my username and password):
javascript: document.forms[0].submit();
didn't work. So I dug around and found the function "doPCASLogin()" in a javascript file called "md5.js". I believe md5 is some kind of hash algorithm, but that doesn't really matter. The important part of "doPCASLogin()" is this:
function doPCASLogin(form) {
var originalpw = form.pw.value;
var b64pw = b64_md5(originalpw);
var hmac_md5pw = hex_hmac_md5(pskey, b64pw)
form.pw.value = hmac_md5pw;
form.dbpw.value = hex_hmac_md5(pskey, originalpw.toLowerCase())
if (form.ldappassword!=null) {
form.ldappassword.value = originalpw;
}
}
There is some other stuff as well, but I found that it didn't matter for my login. It is pretty obvious that this just runs the password through another function a few times using "pskey" (stored in a hidden input, different on each reload) as a key, and puts these in inputs on the original form ("dbpw" and "ldappassword" are hidden inputs, while "pw" is the visible password entry input). After it does this, it submits. I located this other "hex_hmac_md5()" function, which actually connects to a whole bunch of other functions to hash the password. Anyway, that doesn't matter, because I can just call the "hex_hmac_md5()" from the javascript I type in the address bar. This is the working code that I came up with, I just broke the line up for readability:
javascript:
document.forms['LoginForm']['account'].value="username";
document.forms['LoginForm']['pw'].value="hex_hmac_md5(pskey, b64_md5('password');)";
document.forms['LoginForm']['ldappassword'].value="password";
document.forms['LoginForm']['dbpw'].value="hex_hmac_md5(pskey, 'password')";
document.forms['LoginForm'].submit();
Wherever you see "username" or "password", this just means that I entered my username and password in those spots, but obviously I have removed them. When I discovered that this worked, I wrote a small Chrome extension that will automatically log me in when I go to the website (the login process is weird so Chrome doesn't remember my username and password). That was nice, but it wasn't my end goal.
Dilemma:
After discovering all this about the hashing, I tried just putting in all these values into the HTTP payload in my GAS file, though I was skeptical that it would work. It didn't, and I suspect that is because the values are just being read as strings and the javascript is not actually being run. This would make sense, because running the actual javascript would probably be a security issue. However, why would it work in the address bar then? Just as a side note, I am getting a 200 response code back, and it also seems that a cookie is being sent back too, though it may not be valid. When I read the actual response, it is just the login page again.
I also considered trying to replicate the entire function in my own code after seeing this: How to programmatically log into a website?, but since "pskey" is different on each reload, I think the hashing would have to be done with the new key on the second UrlFetch. So even if I did copy all of the functions into my GAS file, I don't think I could successfully log on because I would need to know the "pskey" that will be generated for a particular request BEFORE actually sending the request, which would be impossible. The only way this would work is if I could somehow maintain one page somehow and read it before sending data, but I don't know how I would do this with GAS.
EDIT: I have found another input, named "contextData", which is the same as "pskey" when the page is loaded. However, if I login once and look at the POST request made using Chrome Developers tools, I can copy all the input values, including "contextData", and I can send another request a second time. Using javascript in the address bar, it looks like this:
javascript:
document.forms['LoginForm']['account'].value="username";
document.forms['LoginForm']['pw'].value="value in field that browser sent once";
document.forms['LoginForm']['ldappassword'].value="password";
document.forms['LoginForm'['dbpw'].value="value in field that browser sent once";
document.forms['LoginForm'['contextData'].value="value in field that browser sent once";
document.forms['LoginForm'].submit();
I can sign into the website as many times as I want in this manner, no matter what "pskey" is, because I am submitting everything directly and no hashing is being done. However, this still doesn't work for me, so I'm kind of stuck. I should note that I have checked the other hidden input fields and I can still log in successfully with the javascript above even after clearing every input in the form.
QUESTIONS:
-was I correct in assuming that the code I was sending was being interpreted as a string?
-why is the new code below that I just recently wrote not working?
-for future reference, how would I use GAS to sign into a site like Google where a randomly generated string is sent in the login form, and must be sent back?
function getData() {
var loginURL = 'login page';
var dataURL = 'page with data';
var loginPayload = {
'account':'same as in previous code block',
'pw':"same as in previous code block",
'ldappassword':'same as in previous code block',
'dbpw':"same as in previous code block",
"contextData":"same as in previous code block",
};
var loginOptions = {'method':'post','payload':loginPayload,'followredirects':false};
var loginResponse = UrlFetchApp.fetch(loginURL,loginOptions);
var loginHeaders = loginResponse.getAllHeaders();
var cookie = [loginResponse.getAllHeaders()["Set-Cookie"]];
cookie[0] = cookie[0].split(";")[0];
cookie = cookie.join(";");
var dataHeaders = {'Cookie':cookie};
var dataOptions = {'method':'get','headers':dataHeaders};
var dataResponse = UrlFetchApp.fetch(dataURL,dataOptions);
Logger.log(dataResponse);
}
some kind of weird hashing method that I haven't seen on any other login pages
This login uses the well-known MD5 hashing algorithm from a base-64 encoded password (of note is that it uses the same password, but lowercased, for what seems like database access dbpw and has an option of sending the plaintext (!) version of the password for LDAP login).
know the "pskey" that will be generated for a particular request BEFORE actually sending the request, which would be impossible
pskey simply stores the key used in computing HMAC signature. There is nothing stopping you from hardcoding it, reading from disk, generating it or fetching from remote whenever and wherever you want (obviously, before the computation).
running the actual javascript would probably be a security issue
Although running untrusted JavaScript code is indeed a security issue, this is not what happened at all in your case. See next point for detailed explanation why. What you should've done, is to actually run the hashing functions (in 2020, Utilities service provides everything you need in that regard) before assigning them to loginPayload properties.
was I correct in assuming that the code I was sending was being interpreted as a string?
Everything you put in quotes (single or double) is treated as a sequence of characters. That's not how Google Apps Script works, this is how ECMAScript (on which it is based) is designed to work. In order to execute the functions "inside" the string, you need to use eval, but please never do that.
Now, in 2020 it took me some time to remember what javascript: protocol meant. This is the only reason why your code executed in the first place - you explicitly told the browser that what follows is JavaScript code to be executed. If someone sees this: please, don't use that ever again.
Google Apps Script is a server-side code and is not executed in the browser environment, therefore, even if you did use the protocol, it would have no effect because no evaluation took place.
why is the new code below that I just recently wrote not working?
Because of all the reasons explained above.
for future reference, how would I use GAS to sign into a site like Google where a randomly generated string is sent in the login form, and must be sent back?
If you are talking about the OAuth / OAuth2.0 authentication protocol, here is an officially endorsed library dedicated for exactly this purpose.

Passing a variable from one page to the next page

I am developing a Question & Answer website where a user is presented five puzzles on a page and the score is calculated using JavaScript as he attempts the questions on the page. The score is saved in a Javascript variable score. I have a paging system like this:
Now when the user clicks on 3 I want to send the variable score to the next page, where I have require scoreUpdateInDatabase.php on each such page such that the score of previous page is made permanent to the databse and the following PHP script presents him the next 5 questions.
How can I pass that score variable in secure way? I can't use GET because the user will modify it. I am satisfied with POST if this can be used, even though POST data can be modified but I just want minimal security.
P.S. Please do not suggest making AJAX call where in one side I will send score and while returning carries next 5 questions. I don't want to use AJAX to refresh content because it is not SEO friendly.
The simplest solution would be cookie based. Writing the value to a session cookie and the reading it.
You could use jquery cookie. It also gives you the option to require https if desired.
Save it in a session. POST would work equally well in this particular case but my preference would be storing it in the session.
The only secure way to do this is to pass the actual answers to the server using a POST or AJAX, do the calculation of the score also on server side and keep it in a SESSION variable.
More information on sessions in PHP
Try looking into Jquery - You should be able to return the value to the server scripting language (as you listed PHP as a tag, I assume you're using PHP). By using Jquery, you can get the javascript variable to the form BEFORE submitting the form to the next page.
Assuming you have used PHP to generate the form to submit initially rather than create the form in javascript. I would use Jquery - to get this file ( http://jquery.com/ ) and to include("jquery.js"); etc... in your PHP script for it to be used.
I would then convert the javascript variable(s) to a php variable and assign this to a hidden field in the form to be submitted to the next page using a $_POST[] variable.
However It will not be SEO friendly (POST and SESSION is not SEO friendly, but you should use them, continue reading)
We are talking of a game. No-one want that the Search engine index the last page of a game... because everyone can search on google (for example) for the last page of your game without playing.
You have to use ajax or post, but don't let google index every page of your game. It's nonsense.
Only the first page of your game should be indexed.

Can you use JavaScript to detect a file download window created server side?

I have a jQuery plugin I use to dynamically create and render a form on a default.aspx asp.net page, then submit it. The page it gets submitted to is a pdf.aspx page. The page builds a PDF then uses Response.Write to write the file (application/pdf) to the browser. I use the same method to render XLSX files to the browser as well. It works really great, but I need a callback or some event to tell the button when to stop spinning. This prevents the user from continuously clicking the Excel or PDF buttons. Does anyone know a way to detect the file dialog window when it was not created using JavaScript? I am also open to other methods of callback from the server side as well.
The way I do that was suggested in response to a question I asked here a while ago by T.J. Crowder. I can't find the response from the last time I wrote this up because the Stackoverflow "search" facility is so incredibly lame, so I'll probably type in a blog post. The basic idea is that your client code (Javascript) should append an extra parameter when it submits the request for the download. The parameter should contain some generated random string (probably just the current timestamp is good enough). The server then looks for that parameter, and when it's preparing the response with the download file it also sets a cookie and gives it that random value.
Right after the submit (or right before; it doesn't really matter), the Javascript code should start an interval timer with a routine to look at the value of document.cookie and see if it contains that random string. As soon as the cookie does contain that string, then you know that the server has sent back its response and that the file download dialog has been presented.

How far can I go with JavaScript?

I need to do as much as possible on the client side. In more details, I would like to use JavaScript to code an interface (which displays information to the user and which accepts and processes response from the user). I would like to use the web serve just to take a date file from there and then to send a modified data file back. In this respect I would like to know if the following is possible in JavaScript:
Can JavaScript read content of a external web page? In other words, on my local machine I run JavaScript which reads content of a given web page.
Can JavaScript process values filled in a HTML form? In other words, I use HTML and JavaScript to generate an HTML form. User is supposed to fill in the form and press a "Submit" button. Then data should be sent to the original HTML file (not to a web server). Then this data should be processed by JavaScript.
In the very end JavaScript will generate a local data-file and I want to send this file to a PHP web server. Can I do it with JavaScript?
Can I initiate an execution of a local program from JavaScript. To be more specific, the local program is written in Python.
I will appreciate any comments and answers.
It could technically, but can't in reality due to the same origin policy. This applies to both reading and writing external content. The best you can do is load an iframe with a different domain's page in it - but you can't access it programmatically. You can work around this in IE, see Andy E's answer.
Yes for the first part, mmmm not really for the second part - you can submit a form to a HTML page and read GET arguments using Javascript, but it's very limited (recommended maximum size of data around 1024 bytes). You should probably have all the intelligence on one page.
You can generate a file locally for the user to download using Downloadify. Generating a file and uploading it to a server won't be possible without user interaction. Generating data and sending it to a server as POST data should be possible, though.
This is very, very difficult. Due to security restrictions, in most browsers, it's mostly not possible without installing an extension or similar. Your best bet might be Internet Explorer's proprietary scripting languages (WScript, VBScript) in conjuction with the "security zones" model but I doubt whether the execution of local files is possible even there nowadays.
Using Internet Explorer with a local file, you can do some of what you're trying to do:
It's true that pages are limited by the same origin policy (see Pekka's link). But this can be worked around in IE using the WinHttpRequest COM interface.
As Pekka mentioned, the best you can manage is GET requests (using window.location.search). POST request variables are completely unobtainable.
You can use the COM interface for FileSystemObject to read & write local text files.
You can use the WScript.Shell interface's Exec method to execute a local program.
So just about everything you asked is attainable, if you're willing to use Internet Explorer. The COM interfaces will require explicit permission to run (a la the yellow alert bar that appears). You could also look at creating a Windows Desktop Gadget (Vista or Win 7) or a HTML Application (HTA) to achieve your goal.
Failing all that, turn your computer into a real server using XAMPP and write your pages in PHP.
see i got what you want to do
best things is do following
choose a javascript library (eg:jquery,dojo,yui etc), i use jquery.this will decrease some of your load
inspite of saving forms data in in a local file, store them in local variables process them and send them to server (for further processing like adding/updating database etc) using XMLHttp request, and when webservice returns data process that data and update dom.
i am showing you a sample
--this is dom
Name:<input type='text' id='name' />
<a href='javascript:void(0)' onClick='submit()'>Submit Form</a>
<br>
<div id='target'></div>
--this is js
function submit()
{
var _name=$('#name').val();// collect text box's data
//now validate it or do any thing you want
callWebservice(_name,_suc,_err);
//above call service fn has to be created by you where you send this data
//this function automatically do xmlHttprequest etc for you
//you have to create it ur self
}
//call this fn when data is sucessfully returned from server
function _suc(data)
{
//webservice has returned data sucessefully
//data= data from server, may be in this case= "Hello user Name"; (name = filled in input box);
//update this data in target div(manipulate dom with new data);
$('#target').html(data);
}
function _err()
{
//call this fn when error occurs on server
}
// in reality most of the work is done using json. i have shown u the basic idea of how to use js to manipulate dom and call servcies and do rest things. this way we avoid page-reloads and new data is visible to viewer
I would answer saying there's a lot you can do, but then in the comment to the OP, you say "I would like to program a group game."
And so, my answer becomes only do on the client side what you are able and willing to double check on the server side. Never Trust the Client!
And I do not want to do my job twice.
If you are going to do things on the client side, you will have to do it twice, or else be subject to rampant cheating.
We had the same question when we started our project.In the end we moved everything we could on the JS side. Here's our stack:
The backend receives and send JSON data exclusively.We use Erlang, but Python would be the same. It handles the authentication/security and the storage.
The frontend, is in HTML+CSS for visual elements and JS for the logic.A JS template engine converts the JSON into HTML. We've built PURE, but there are plenty of others available. MVC can be an overkill on the browser side, but IMO using a template engine is the least separation you can do.
The response time is amazing. Once the page and the JS/CSS are loaded(fresh or from the cache), only the data cross the network for each request.

Categories