I'm trying to make some php message sender and receiver Pages.
From the "Admin.php" page, administrator can send messages to the website visitors. And the "receiver.php" page is the visitor's inbox.
Here is the codes:
Admin.php:
<form method="post" action="sender.php">
<input type="text" name="message">
<input type="submit" value="Submit">
</form>
Sender.php:
<?php
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
$message = $POST["message"];
echo "data: {$message}\n\n";
flush();
?>
Receiver.php:
<!DOCTYPE html>
<html>
<body>
<h1>Getting server updates</h1>
<div id="result"></div>
<script>
if(typeof(EventSource) !== "undefined") {
var source = new EventSource("sender.php");
source.onmessage = function(event) {
document.getElementById("result").innerHTML += event.data + "<br>";
};
} else {
document.getElementById("result").innerHTML = "Sorry, your browser does not support server-sent events...";
}
</script>
</body>
</html>
why doesn't this work?
The problem is that you are trying to use "sender.php" to do two things.
From the admin form you need to submit to one php script that will store the messages, in a database of some kind.
Then in "receiver.php" you need to connect to a different PHP script, whose job is to keep polling that database for new entries, and when it sees one it should send it to the client. This latter PHP script will run in an infinite loop.
Related
I like solution in this post Real-Time Html editor with Javascript or editor on this site. Just simple solution without extra functionalities.
How to edit the code to add SAVE/LOAD option? Is there somethin like "downloadable little CMS" to play with HTML/CSS? I want upload it to my hosting, easy access from home/phone/work, I do not want use online services like codepen or Liveweave.
thanks!
EDIT: Due to comments, I will clarify my question. I have some hosting, mySite.com. There is folder with this magic editor, mySite.com/xxx where i have some sample images and some basic css etc.. Im learning html/css, so I developing some basic html temapltes. HTML editor I linked is just fine. Only I need add 3 buttons, NEW/OPEN/SAVE which make new html file/can open it in live editor/and save it. AND I WANT HAVE THIS EASY SOLUTION ON MY OWN HOSTING.
<?php
$fileName = "page.html";
$fileContent = fopen($fileName, "r") or die("Unable to open file!");
if (isset($_POST['text'])) {
file_put_contents($fileName, $_POST["text"]);
}
?>
<!DOCTYPE html><html lang="cs"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1">
<style>
.error {background-color: red; color: white;}
</style>
</head><body>
<form method="POST">
<textarea name="text" class="form-control" rows="20" id="pure">
<?php echo fread($fileContent,filesize($fileName)); ?>
</textarea><br>
<input type="submit" value="submit" />
</form>
<hr>
<div id="compiled"></div>
</body>
</html>
<?php
fclose($fileContent);
?>
<script type="text/javascript">
var h = document.getElementById("pure");
var compiled = document.getElementById("compiled");
h.onkeyup = function() {
compiled.innerHTML = h.value;
pure.classList.toggle("error",
compiled.innerHTML !== h.value);
};
h.onkeyup();
</script>
Its my actual work, real-time html editor from link in my question. File "page.html" must exist.
Added func. to load content from "page.html" file into textarea when page loads..
Added button to save textarea content to "page.html" when done..
Probably not perfect code, and for multiple projects must copy into diferent folders and load one by one :( no popup or form to choose diferent filename easily.. but for now it fits my requirements. I can learn/try/work on html template from home/work/mobile on my own hosting without login into third party service.
Ok, I'm done. Here is my final solution.
real-time html editor
Load/save buttons
automatically load files from /projects/ folder into dropdown list
you can upload files to make new project
no need to modify anything, you can just use it.
Index.php
<?php
$fileName = $_POST['project']?? 'index.html';
$fileContent = fopen("./projects/" . $fileName, "r") or die("Unable to open file!");
if (isset($_POST['text'])) {
file_put_contents("./projects/" . $fileName, $_POST["text"]);
}
?>
<!DOCTYPE html><html lang="cs"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1">
<style>
.error {background-color:red; color:white;}
.dib {display:inline-block;}
</style>
</head><body>
<?php
echo "<form class='dib' method='POST'><select name='project'>";
$path = './projects/';
$files = scandir($path);
$files = array_diff(scandir($path), array('.', '..'));
foreach($files as $file){
echo "<option" . (($fileName == $file)?' selected':'') . ">" . $file . "</option>";
}
echo "</select> <input type='submit' value='Load!'></form>";
?>
<input type='submit' form='content' value='Save!'>
<form class="dib" style="float:right;" action="fileUploadScript.php" method="post" enctype="multipart/form-data">
Upload a File:
<input type="file" name="the_file" id="fileToUpload">
<input type="submit" name="submit" value="Start Upload">
</form>
<p style='margin:auto; text-align:center; width:20%; text-transform:uppercase; font-weight: bold;'><?php echo $fileName?></p>
<br>
<form id="content" method="POST">
<textarea name="text" rows="40" id="pure" style="width:100%;margin-top:8px;" wrap="off">
<?php echo fread($fileContent,filesize("./projects/" . $fileName)); ?>
</textarea><br>
<input type="hidden" name="project" value="<?php echo $fileName; ?>">
</form>
<hr>
<div id="compiled"></div>
</body>
</html>
<?php
fclose($fileContent);
?>
<script type="text/javascript">
var h = document.getElementById("pure");
var compiled = document.getElementById("compiled");
h.onkeyup = function() {
compiled.innerHTML = h.value;
pure.classList.toggle("error",
compiled.innerHTML !== h.value);
};
h.onkeyup();
</script>
fileUploadScript.php
<?php
$currentDirectory = getcwd();
$uploadDirectory = "/projects/";
$errors = []; // Store errors here
$fileExtensionsAllowed = ['jpeg','jpg','txt','bmp','html','htm','rar','zip','7z','doc','docx','xls','xlsx','ppt','pptx','pdf','pptm','png','gif']; // These will be the only file extensions allowed
$fileNamee = $_FILES['the_file']['name'];
$fileSize = $_FILES['the_file']['size'];
$fileTmpName = $_FILES['the_file']['tmp_name'];
$fileType = $_FILES['the_file']['type'];
$tmp = explode('.',$fileNamee);
$fileExtension = strtolower(end($tmp));
$uploadPath = $currentDirectory . $uploadDirectory . basename($fileNamee);
if (isset($_POST['submit'])) {
if (! in_array($fileExtension,$fileExtensionsAllowed)) {
$errors[] = "This file extension is not allowed. Please upload a JPEG or PNG file";
}
if ($fileSize > 4000000) {
$errors[] = "File exceeds maximum size (4MB)";
}
if (empty($errors)) {
$didUpload = move_uploaded_file($fileTmpName, $uploadPath);
if ($didUpload) {
echo "The file " . basename($fileNamee) . " has been uploaded";
} else {
echo "An error occurred. Please contact the administrator.";
}
} else {
foreach ($errors as $error) {
echo $error . "These are the errors" . "\n";
}
}
}
?>
After you save these two files, dont forget make new folder named "projects" and default file called "index.html" in this folder..
I created a google sign in using Google OAuth 2.0, I configure it using Xamp and php to build the database, I built it outside my project, now I want to include the google sign in button in my project but I kept getting errors. From my localhost, I want to add it to my file first and see how it would look in my page before uploading it. Below is my index.php file
<?php
require_once('config.php');
require_once('core/controller.Class.php');
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="uft-8">
<meta name="viewport" content="width=device-width, inital-scale=1">
<title>Login with Google</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" >
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.1.1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-F3w7mX95PdgyTmZZMECAngseQB83DfGTowi0iMjiWaeVhAn4FJkqJByhZMI3AhiU" crossorigin="anonymous">
</head>
<body>
<div class="container" style="margin-top: 100px">
<?php
if(isset($_COOKIE["id"]) && isset($_COOKIE["sess"])){
$Controller = new Controller;
if($Controller -> checkUserStatus($_COOKIE["id"], $_COOKIE["sess"])){
echo $Controller -> printData(intval($_COOKIE["id"]));
echo 'Logout';
}else{
echo "Error!";
}
}else{
?>
<img src="img/20210908_214559.jpg" alt="Logo"
style="display: table; margin: 0 auto; max-width: 150px;">
<form action="" method=:POST>
<div class="form-group">
<label for="exampleInputEmail1">Email Address</label>
<input type="email" class="form-control" id="exampleInputEmail1"
placeholder="Enter email">
</div>
<div class="form-group">
<label for="exampleInputPassword1">Password</label>
<input type="password" class="form-control" id="exampleInputPassword1"
placeholder="Enter password">
</div>
<button type="submit" class="btn btn-primary">Login</button>
<button onClick="window.location = '<?php echo $login_url;?>'" type="button" class="btn btn-danger">Login with Google</button>
</div>
</form>
<?php } ?>
</body>
</html>
It looks like you're expecting to collect the google username and password and then pass that to the google auth engine? That's not the way I've implemented the solution.
Google provide instructions for integrating their sign-in service.
I recommend following those instructions. This will require the following files:
A login page which contains the google sign-in button. You could conceivably add this to any of your existing pages. The relevant code is:
<div class="g-signin2" data-longtitle="true" data-onsuccess="onSignIn"></div>
A javascript file which contains the onSignIn function and a signOut function if you want one. This file handles the redirect to a successful logged in page and also passes the attributes you want to collect from the user's Google account. I'm using XMLHttpRequest, but you could use POST if you wish. This page contains the page that the user will be directed to upon successful login, set in xhr.onreadystatechange = function() {}:
function onSignIn(googleUser) {
var profile = googleUser.getBasicProfile();
var id_token = googleUser.getAuthResponse().id_token;
// console.log('ID: ' + profile.getId()); // Do not send to your backend! Use an ID token instead.
var xhr = new XMLHttpRequest();
xhr.open('POST', 'includes/oauth.php');
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.onreadystatechange = function() {
window.location = "../loggedin.php"; //Redirect to loggedin page on completion of oauth.php. Determine if new user or existing user and process accordingly
}
xhr.send('idtoken=' + id_token + '&googleId=' + profile.getId() + '&name=' + profile.getName() + '&imageURL=' + profile.getImageUrl() + '&email=' + profile.getEmail());
}
function signOut() {
gapi.load('auth2', function() {
gapi.auth2.init().then(function(){
var auth2 = gapi.auth2.getAuthInstance();
auth2.signOut().then(function () {
document.location.href = 'includes/logout.php';
});
});
});
}
A file to handle the authentication (referred to as includes/oauth.php in my javascript file above). Note the settings for $leeway - this caused me a lot of grief figuring out that the clock on my server was slower than the Google auth server's clock!):
require_once '../vendor/autoload.php';
$jwt = new \Firebase\JWT\JWT; //Allow for discrepancies between server and auth times
$jwt::$leeway = 60;
$CLIENT_ID = "ENTER_YOUR_CLIENT_ID_HERE";
$client = new Google_Client(['client_id' => $CLIENT_ID]); // Specify the CLIENT_ID of the app that accesses the backend
$client->setRedirectUri("http://localhost/includes/oauth.php");
$client->addScope("email");
$client->addScope("profile");
if (isset($_POST['idtoken'])){
$id_token = $_POST['idtoken'];
$attempt = 0;
do {
try {
$payload = $client->verifyIdToken($id_token);
$retry = false;
} catch (Firebase\JWT\BeforeValidException $e) {
error_log("JWT server time mismatch. Retry attempt: " . strval($attempt) . "Error: " . $e, 0);
$attempt++;
$retry = $attempt < 3;
}
} while ($retry);
if ($payload) {
$userid = $payload['sub'];
...
YOUR VALIDATION, SESSION SETTING, ETC. CODE HERE
...
} else {
// Invalid ID token
print("Invalid ID token");
}
} else { //Attempt to access this page directly, redirect to Google login page
$auth_url = $client->createAuthUrl();
header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL));
}
The page that will displayed upon successful login. I used an interstitial page here because the authenticated user could be new to my site and need to create a profile, or could be an existing user and want to go about their activities. I look to verify whether a SESSION has been started and whether this includes a successful authentication.
I have a question about the control flow between some JavaScript code running as bound functions within a google spreadsheet - so server side - and a dialog (that happens to be Modal, but Modeless is the same) that is client side.
While the code examples below work fine in that the dialog successfully calls the server side function as per the line below, and the withSuccessHandler works too.
google.script.run.withSuccessHandler(success_callback).getCredentials(this.parentNode)
But what I actually want to achieve is for some server side code to carry on executing once the dialog has gone; ideally from the point the .showModalDialog() function was called, but I'd be happy just passing control back to any server-side function.
Some example software is below; don't forget this works, just not how I want it too! Essentially the event handler for a menu item created by the the OnOpen() function calls a modal dialog to prompt the user for security credentials.
var html = HtmlService.createHtmlOutputFromFile('authorization_dialog');
SpreadsheetApp.getUi()
.showModalDialog(html, 'Authorization Dialog');
The HTML file:
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<form>
Authorization Code:
<input type="text" name="authorization_code"><br><br>
Account ID:
<input type="text" name="account_id"><br><br>
Enter account details...
<br>
<br><br>
<input type="button" value="OK"
onclick="google.script.run.withSuccessHandler(success_callback).getCredentials(this.parentNode)" />
<input type="button" value="Close"
onclick="google.script.host.close()" />
</form>
<script>
// Using this call back prevents the need to hit the Close Button after OK.
function success_callback() {
google.script.host.close(); // Close the dialog.
}
</script>
</body>
</html>
If you don't need a response from the server-side function, simply omit 'withSuccessHandler';
function func_client(){
google.script.run.func_server();
google.script.host.close();
}
In this case, the server-side code will continue executing without locking your client's UI - you can call any other functions inside 'func_server'.
If you'd like to process a response from the first function call, call the second function from 'success_callback'. The dialog will be closed without waiting for the google.script.run to complete, but the server code will continue executing.
In the example below, the 1st server function passes form data back to the client where 'success_callback' immediately invokes another server function that takes a while to complete (it logs each file in my Google Drive);
Client:
<form id="form">
.....
<input type="submit" id="ok" value="OK" />
<input type="button" value="Close" onclick="google.script.host.close()" />
.....
</form>
<script>
window.onload = function(){
document.getElementById("form")
.addEventListener("submit", function(e){
e.preventDefault();
google.script.run
.withSuccessHandler(success_callback)
.logFormData(this);
});
}
function success_callback(response) {
console.log(response);
google.script.run.scanFiles();
google.script.host.close(); // Close the dialog.
}
</script>
Server:
function showDialog(){
var ui = SpreadsheetApp.getUi();
//IMPORTANT: client-side scripts won't be executed
//without calling evaluate() on the HtmlTemplate object before passing it to UI;
var template = HtmlService.createTemplateFromFile("dialog");
var html = template.evaluate();
ui.showModalDialog(html, "dialog");
}
function logFormData(formData){
return formData;
}
function scanFiles() {
var files = DriveApp.getFiles();
var file;
while (files.hasNext()) {
file = files.next();
Logger.log(file.getName() + ": " + file.getMimeType());
}
}
Im in the process of adding the reCaptcha from google to my form. The problem is that even though I have followed the instructions from google. I can still press the Submit button without doing the recaptcha. Any Ideas please heres the relevant code snippets.
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>webpage title</title>
<link rel="stylesheet" type="text/css" href="view.css" media="all">
<script type="text/javascript" src="view.js"></script>
<script src='https://www.google.com/recaptcha/api.js'></script>
</head>
And the this snippet in the form part of the webpage
<div class="g-recaptcha" data-sitekey="xxxxxxmyapikeyxxxxxxx_xxxxxxmyapikeyxxxxxxx"></div>
<li class="buttons">
<input type="hidden" name="form_id" value="1136056" />
<input id="saveForm" class="button_text" type="submit" name="submit" value="Submit" />
</li>
</ul>
</form>
As far as I'm aware I have placed the code in the specified areas of my webpage. One before the closing tag on your HTML template and the snippet at the end of the where I want the reCAPTCHA widget to appear.
I have put the recaptcha before the submit button. There is a part about the server side integration that I do not understand.
[QUOTE]
When your users submit the form where you integrated reCAPTCHA, you'll
get as part of the payload a string with the name "g-recaptcha-response".
In order to check whether Google has verified that user,
send a POST request with these parameters:
URL: https://www.google.com/recaptcha/api/siteverify
secret (required) xxxxxmysecretkeyxxxxxxx
response (required) The value of 'g-recaptcha-response'.
remoteip The end user's ip address.
[/QUOTE]
Can anyone please shed some light on this please.
Thankyou
So we set up the form and make sure your library is included, I prevent the submit button from being clicked while the recaptcha has not been completed and show a tooltip to notify the user it is needed to continue. Then enable it when it has been complete using the callback methods.
login.php
<div class="formContainer">
<script src='https://www.google.com/recaptcha/api.js'></script>
<form action="loginHandler.php" method="post" name="login_form" id="loginForm" class="loginForm">
<h2>Login</h2>
<p><input type="text" required placeholder="Email" name="email"></p>
<p><input type="password" required placeholder="Password" name="password" id="password"></p>
<div class="g-recaptcha" data-callback="captcha_filled"
data-expired-callback="captcha_expired"
data-sitekey="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX">
</div>
<div>
<p class="show-tt" data-toggle="tooltip" title="Complete the reCAPTCHA to login." data-placement="bottom">
<input id="submitLogin" type="submit" value="Login">
</p>
</div>
</form>
</div>
<script>
//prevent submit and show tooltip until captch is complete.
var submit = false;
$("#submitLogin").prop('disabled', true);
function captcha_filled() {
submit = true;
$("#submitLogin").prop('disabled', false);
$(".show-tt").tooltip('destroy');
}
function captcha_expired() {
submit = false;
$("#submitLogin").prop('disabled', true);
showTooltip();
}
function showTooltip () {
$(".show-tt").tooltip('show');
}
</script>
Now we post to loginHandler.php, or wherever your form submits too and then there we will assign your secret key and then verify the request with google.
loginHandler.php
$secret = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
if (isset($_POST["g-recaptcha-response"])) {
$url = 'https://www.google.com/recaptcha/api/siteverify?secret=' . urlencode($secret) .
'&response=' . urlencode($_POST['g-recaptcha-response']) . '&remoteip=' . urlencode($_SERVER['REMOTE_ADDR']);
//ip address is optional
$result = json_decode(file_get_contents($url), true);
if ($result != null && $result['success'] === true) {
//success, handle login/submit data or whatever
} else {
//response is bad, handle the error
header('Location: login.php?error=4');
}
} else {
//captcha response is not set, handle error
header('Location: login.php?error=5');
}
I have two seperate perl documents:
mailcheck.pl
loggingpage.pl
Mailcheck prints out a form in html where the user can put in her/his email and checks if the input is a valid email address. Then it calls upon the loggingpage.pl which saves the email in a logfile and gives out information to the user if the email address was successfully stored.
These are the two documents:
mailcheck.pl:
#!/usr/bin/perl
use strict;
use warnings;
print "Content-type: text/html\n\n";
print <<HTML;
<html>
<head>
<title>Mailcheck</title>
</head>
<body>
<form name="ec" action ="./loggingfiles.pl" method="get">
Email: <input type="text" name="email"> <br>
<input type="button" value="Pruefen" onclick="javascript:emailcheck();">
</form>
<script language="javascript" type="text/javascript">
function emailcheck()
{
var emailoutline = /^[a-z0-9._%+-]+\#[a-z0-9.-]+\.[a-z]{2,4}\$\/\;
var x = document.ec.email.value;
if (emailoutline.test(x))
{
open("./loggingpage.pl);
}
else
{
alert("Dies ist keine richtige eMailadresse!");
}
}
</script>
</body>
</html>
HTML
exit;
loggingpage.pl:
#!/usr/bin/perl
use strict;
use warnings;
use CGI qw(:standart);
#reads the input of the form called "email"
$emailinput = param('email');
#saves the email in the logfile
open(my $ml, ">", "./../logs/maillog.txt") or die "Fehlermeldung";
print $ml scalar(localtime()), " Email: ", $emailinput;
close($ml);
#gives out information about the saving process
if (...) #saving the email in the logfile succeeded
{
print <<HTML;
<html>
<head></head>
<body>
<script language="javascript" type="text/javascript">
alert("Your input has been saved under the following email: " + $emailinput);
</script>
</body>
</html>
HTML
exit;
}
else #gives out warning if information was not stored right
{
print <<HTML;
<html>
<head></head>
<body>
<script language="javascript" type="text/javascript">
alert("Error while saving your input.");
</script>
</body>
</html>
HTML
exit;
}
(I know that the <<HTML (..) HTML blocks cannot have spaces in front of them - in my actual document I have edited the block the right way)
My questions are now:
a. How can I write the if-conditions when I want to see if the email got saved in the logfile?
b. I am not quite sure if the part $emailinput = param('email'); works since I was not able to try it, is it the right way to get the input of the form in mailcheck.pl or do I need to write the code differently?
For you information:
- mailcheck.pl works correctly.
- the saving of the email in the logfile also works fine (i tried it through defining a variable as an email and saving that into the logfile together with the current date...)
So I have solved question a) like this (it seems to be working):
open(my $ml, ">", "./../logs/maillog.txt") or die "Saving Error";
print $ml scalar(localtime()), " Email: ", $emailinput;
close($ml);
#print "\nYour eMail was successfully logged!", $emailinput, "\n\n";
print "Content-type: text/html\n\n";
print <<HTML;
<html>
<head>
<title>Mailcheck2</title>
</head>
<body>
<p>Es wurde die folgende eMail erfolgreich gelogged:</p>
</body>
</html>
HTML
exit;
Now I only need help with question b).
After performing the validation, submit the form using:
document.ec.submit(); // 'ec' is the name of your form
This will send the form data to the page defined in the action attribute of your form.
Better yet, use the onsubmit attribute of the form tag to perform the validation:
<form name="ec" action ="./loggingfiles.pl" method="get" onsubmit="return emailcheck()">
Then modify the validation method to return false on failure:
function emailcheck()
{
var emailoutline = /^[a-z0-9._%+-]+\#[a-z0-9.-]+\.[a-z]{2,4}\$\/\;
var x = document.ec.email.value;
if (!emailoutline.test(x))
{
alert("Dies ist keine richtige eMailadresse!");
return false;
}
}
Do not rely on JavaScript in this way. JS is useful an additional sanity check for your form, but it should not be the only nor the primary means of validating your data.
Instead, put all your data into a single page, and for initial development, remove any JS. Make your form a POST request, and detect when the form is posted to determine if you need to do the validation. You'll need to use your JS validation regex in your perl instead, although eventually you should upgrade to Email::Valid.
After your form and post is working without JavaScript, you can add an onSubmit method if you want to do some clientside verification to duplicate what you've done in perl.