Fire an event even if browser is closed - javascript

I am currently programming with PHP/HTML/CSS/MYSQL/JAVASCRIPT and i want to perform the following scenario:
Send an email to someone but not by clicking a button "SEND".
I want to build something called "Future Send" that will enable the user to schedule when the email will be send. (for example 5 minutes from now).
This is easy to be accomplished with a Javascript counter that will fire an event when countdown == 0; But this requires that the browser/website must be open.
But what happens in the event that the user writes the email, schedule it for 5 minutes later, and closes the browser or even the computer? The counter will stop and the event will never be fired..
Is there a way to bypass this using the technologies referred above?
Do i have to switch to a different programming language?
Any suggestions?
Thanks in advance.

I have faced a similar case in my production and i made as follow :
1- store the subject, cc, rc, body in a text file
2- name it as follow : timestampToBeSend.txt
3- place it in a pool
4- create a simple PHP script that it will run indefinitely
while (TRUE) {
// find files that they names are less or equal than current timestamp
// if true ? read the contents, delete the file and send mail
// sleep (DESIRED_TIME);
}
This solution works fine from more than 4 years :)

Related

How to call API only when user reload/leave site from the browser alert and not on click of cancel?

I am trying to do an API call when the user is trying to close/reload the browser/tab. I don't want to call the API if the user clicks on cancel. I followed JavaScript, browsers, window close - send an AJAX request or run a script on window closing, but it didn't solve my issue. I followed catching beforeunload confirmation canceled? for differentiating between confirm and cancel. I have no idea how to make the API call when the user reloads/closes the browser and not to call the API when user clicks on cancel. I followed JavaScript, browsers, window close - send an AJAX request or run a script on window closing and tried like
For showing alert on reload or close the tab
<script>
window.addEventListener("onbeforeunload", function(evt){
evt.preventDefault()
const string = '';
evt.returnValue = string;
return string;
})
</script>
and on click of cancel, nothing should happen. If the user is forcefully closing the browser or reloading, the API should be called
<script type="module">
import lifecycle from 'https://cdn.rawgit.com/GoogleChromeLabs/page-lifecycle/0.1.1/dist/lifecycle.mjs';
lifecycle.addEventListener('statechange', function(event) {
if (event.originalEvent === 'visibilitychange' && event.newState === 'hidden') {
var URL = "https://api.com/" //url;
var data = '' //payload;
navigator.sendBeacon(URL, data);
}
});
</script>
But it's not happening. Any help is appreciated. Thanks
Your problem is happening because you're using beforeunload to present a prompt.
I can see that you're handling the beforeunload event properly, so you must already be aware that browser vendors have deliberately limited the ability of script authors to do custom stuff when the user wants to leave the page. This is to prevent abuse.
Part of that limitation is that you don't get to find out what the user decides to do. And there will not be any clever workarounds, either. Once you tell the browser to present the beforeunload prompt, you lose all your power. If the user clicks the Okay button (i.e. decides to leave the page), the browser will refuse to run any more of your code.
Presenting the prompt creates a fork in the road that you are prevented from observing. So, put a laser tripwire there instead of a fork:
window.addEventListener("onbeforeunload", function(evt) {
navigator.sendBeacon(url, payload)
})
This is guaranteed to run when the user actually leaves the page, and only when the user actually leaves the page. But, you sacrifice the ability to try to talk the user out of leaving. You can't have it both ways.
You can't always get what you want, but if you try, sometimes you just might find you get what you need. -- The Rolling Stones
I can only think of one way to accomplish what you need, but it requires help from the server. This is not an option for most people (usually because the beacon goes to a third-party analytics provider who won't do this), but I'm including it here for completeness.
before the beforeunload handler returns, fire a beacon message that says "user is maybe leaving the page"
after firing that beacon, and still before returning, set up a document-wide mousemove handler that fires a second beacon message that says "the user is still here" (and also de-registers itself)
return false to present the prompt
modify your server so that it will reconcile these two events after some kind of delay:
if the server receives beacon 1 and then also receives beacon 2 (within some reasonably short time-frame, e.g. 5 minutes), it means the user tried to leave but then changed their mind, and so the server should delete the record of beacon 1
if the server receives beacon 1 but doesn't receive beacon 2 within the time-frame, then it means the user really did leave, and so the server would rewrite the previous beacon datapoint to say "user actually departed"; you wouldn't need to actually write beacon 2 to your datastore
(Or, depending on expected traffic and your infrastructure, maybe the server just holds the beacon 1 datapoint in RAM for the 5 minutes and commits it to your datastore only if beacon 2 never shows up. Or you could write both beacons to the database and then have a different process reconcile the beacons later. The outcome is identical, but they have different performance characteristics and resource requirements.)
P.S.: Never use "URL" (all caps) as a variable name in javascript. "URL" is actually a useful web API, so if you use that exact variable name, you're clobbering a useful ability. It's just like if you did let navigator = 'Henry'. Yes, it will execute without error, but it shadows a useful native capability.

Can you prevent users editing the chrome.storage.local values in a Chrome extension? What is the best way to store persistent values for an extension?

So I'm working on a Chrome extension for someone else. I don't want to give away specific details about the project, so for I'll use an equivalent example: let's assume it's an extension to run on an image/forum board. Imagine I have variables such as userPoints, isBanned etc. The later being fairly self-explanatory, while the former corresponding to points the user acquires as they perform certain actions, hence unlocking additional features etc
Let's imagine I have code like:
if(accountType !== "banned"){
if(userPoints > 10000) accountType = "gold";
else if(userPoints > 5000) accountType = "silver";
else if(userPoints > 2500) accountType = "bronze";
else if(userPoints <= 0) accountType = "banned";
else accountType = "standard";
}else{
alert("Sorry, you're banned");
stopExtension();
}
Obviously though, it becomes trivial for someone with the knowledge to just browse to the extensions background page and paste chrome.storage.local.set({'userPoints': 99999999}) in the console, hence giving them full access to all the site. And, with the Internet, someone can of course share this 'hack' on Twitter/YouTube/forums or whatever, then suddenly, since all they'd need to do is copy and paste a simple one-liner, you can have 1000s of people, even with no programming experience, all using a compromised version of your extension.
And I realise I could use a database on an external site, but realistically, it would be possible that I would be wanting to get/update these variables such as userPoints 200+ times per hour, if the user was browsing the extentions target site the entire time. So the main issues I have with using an external db are:
efficiency: realistically, I don't want every user to be querying the
db 200+ times per hour
ease-of-getting-started: I want the user to just download the
extension and go. I certainly don't want them to have to sign up. I
realise I could create a non-expiring cookie with for the user's ID
which would be used to access their data in the db, but I don't want
to do that, since users can e.g. clear all cookies etc
by default, I want all features to be disabled (i.e. effectively
being considered like a 'banned' user) - if, for some reason, the
connection with the db on my site fails, then the user wouldn't be
able to use the extension, which I wouldn't want (and just speaking
from experience of my parents being with Internet providers whose
connection could drop 10 times per hour, for some people, failed
connections could be a real issue) - in contrast, accessing data from
the local storage will have like a 99.999% success rate I'd assume,
so, for non-critical extensions like what I'm creating, that's more
than good enough
Still, at least from what I've found searching, I've not found any Chrome storage method that doesn't also allow the user to edit the values too. I would have thought there would be a storage method (or at least option with chrome.storage.local.set(...) to specify that the value could only be accessed from within the extension's context pages, but I've not found that option, at least.
Currently I'm thinking of encrypting the value to increment by, then obfuscating the code using a tool like obfuscator.io. With that, I can make a simple, like 30 character js file such as this
userPoints = userPoints + 1000;
become about 80,000...still, among all the junk, if you have the patience to scroll through the nonsense, it's still possible to find what you're looking for:
...[loads of code](_0x241f5c);}}}});_0x5eacdc(),***u=u+parseInt(decrypt('\u2300\u6340'))***;function _0x34ff36(_0x17398d)[loads more code]...
[note that, since it's an extension and the js files will be stored on the user's pc, things like file size/loading times of getting the js files from a server are irrelevant]
Hence meaning a user wouldn't be able to do something like chrome.storage.local.set({'userPoints': 99999999}), they'd instead have to set it to the encrypted version of a number - say, something like chrome.storage.local.set({'userPoints': "✀ເ찀삌ሀ"}) - this is better, but obviously, by no means secure.
So anyway, back to the original question: is there a way to store persistent values for a Chrome extension without the user being able to edit them?
Thanks

How to avoid same cookie being written multiple times when multiple window is open

I have a simple chat room web app. I want to be able to save chat history into user's cookie using javascript. The problem I just encounter is when user open more than one window, he will be saving chat message multiple times into his cookie. It must be very confusing reading this, please see example below:
There are only two users A and B in the chat room, A is acting normal but B has two windows open, both in the same chat room page. A says "Good Morning", B says nothing and what he see is:
A: Good Morning
Nothing is wrong so far, but when B is saving this into his cookie, because he has two windows open, this message will be saved twice into his cookie. So the next time he come to the chat room, the chat history he sees will be:
A: Good Morning
A: Good Morning
If B opens n windows at the same time, the message is saved n times.
A solution I have in mind is when saving message into cookie, check if the last message in the cookie is the same as the one being saved, if they are the same, don't save it again.
But for cases when a user is truly sending same message multiple times, this will omit the duplicated messages which it shouldn't.
How is this usually solved? I guess users usually can't open two chat room page at the same time but I allow them to do so.
Assign each message a unique ID on the server. Check the local chat history to see if that id exists anywhere in it already.
You could save the time stamp for each message and if the message and the time stamp both matches, then it is a duplicate message.
Here is an example, how to get a timestamp in JavaScript
I talk about my thoughts.Because each window will have cookie.You will into tow history.I think you can set time mark for every history.Everyone can't send tow or multiple message.you can test time mark.then judge this message need to save or no.

How to block the link from malicious bot visitors?

I'm producing an event registration website. When someone click on a link:
Reserve id=10 event
The system is doing a "lock" on this event for ten minutes for this visitor. In that case no one else can reserve this event in next ten minutes. If the payment is done in that time, everything is OK, else the event is unlocked again. I hope the idea is clear.
PROBLEM: When bot (google bot, malicious bot, or angry customer script :P) visits this page, he see this link. Then he enters the page. Then the lock is done...
Also if someone visit recursive: /reserve/1, /reserve/2, /reserve/3, ... He can lock all the events.
I thought about creating a random md5 string for each event. In that case, every event has (next to id) unique code, for example: 1987fjskdfh938hfsdvpowefjosidjf8243
Next, I can translate libraries, to work like this:
<a href="/reserve/1987fjskdfh938hfsdvpowefjosidjf8243" rel="nofollow">
Reserve
</a>
In that case I can prevent the "bruteforce" lock. But the link is still visible for bots.
Then I thought about entering the captcha. And that is the solution. But captchas are... not so great in case of usability and user experience.
I saw few websites with reservation engine working like this. Are they protected? Maybe there is a simple ajax / javascript solution to prevent the bots from reading this as a pure text? I thought about:
Reserve
<script type="text/javascript">
$('#reserve').click(function(e) {
e.preventDefault();
var address = ...;
// something not so obvious to follow?
// for example: md5(ajaxget(some_php_file.php?salt=1029301))
window.location('/reserve/' + address);
});
</script>
But I'm not sure what shall I do there to prevent bots form calculating it. I mean stupid bots will not be able even to follow javascript or jquery stuff, but sometimes, someone wants to destroy something, and if the source is obvious, it can be broken in few lines of code. And whole database of events will be locked down with no reservation option for noone.
CRFS + AJAX POST + EVENT TOKEN generated on each load.
Summary: don't rely on GET requests especially through a elements.
And better if you add some event block rate limits (by IP for instance).
EDIT: (this is a basic sketch)
replace all the href="..." with data-reservation-id=ID
delegate click on the parent element for a[data-reservation-id]
in the callback, simply make a POST ajax call to the API
in the API's endpoint check rate limits using IP for instance
if OK, block the event and return OK, if not return error.
IP-Specific maximum simultaneous reservations
Summary: Depend on the fact that many simple bots operate from one host. Limit the number of simultaneous reservations for a host.
Basic scetch:
Store the requesting IP alongside the reservation
On reservation request count the IP's which have a non-completed reservation.
SELECT Count(ip) FROM reservations WHERE ip=:request_ip AND status=open;
If the number is above a certain threshold, block the reservation.
(this is mostly an expansion of point 4 given in avetist's excellent answer)

Doing some stuff right before the user exits the page

I have seen some questions here regarding what I want to achieve and have based what I have so far on those answer. But there is a slight misbehavior that is still irritating me.
What I have is sort of a recovery feature. Whenever you are typing text, the client sends a sync request to the server every 45 seconds. It does 2 things. First, it extends the lease the client has on the record (only one person may edit at one time) for another 60 seconds. Second, it sends the text typed so far to the server in case the server crashes, internet connection fails, etc. In that case, the next time the user enters our application, the user is notified that something has gone wrong and that some text was recovered. Think of Microsoft or OpenOffice recovery whenever they crash!
Of course, if the user leaves the page willingly, the user does not need to be notified and as a result, the recovery is deleted. I do that final request via a beforeunload event.
Everything went fine until I was asked to make a final adjustment... The same behavior you have here at stack overflow when you exit the editor... a confirm dialogue.
This works so far, BUT, the confirm dialogue is shown twice. Here is the code.
The event
if (local.sync.autosave_textelement) {
window.onbeforeunload = exitConfirm;
}
The function
function exitConfirm() {
var local = Core;
if (confirm('blub?')) {
local.sync.autosave_destroy = true;
sync(false);
return true;
} else {
return false;
}
};
Some problem irrelevant clarifications:
Core is a global Object that contains a lot of variables that are used everywhere.
sync makes an ajax request. The values are based on the values that the Core.sync object contains. The parameter determines if the call should be async (default) or sync.
Edit 1
I did try to separate both things (recovery deletion and user confirmation that is) into beforeunload and unload. The problem there was that unload is a bit too late. The user gets informed that there is a recovery even though it is scheduled to be deleted. If you refresh the page 1 second later, the dialogue disappears as the file was deleted by then.
Did you try this:
if (local.sync.autosave_textelement) {
window.onunload = exitConfirm;
}

Categories

Resources