Basically I am making a websocket chatting application in PHP and i have made a div that shows all online users.But the problem with my code is when a new user enters the room , he just can see the names of the users entering the room after him and cant see the name of users entered be4 him.
For instance , if Batman,Joker and Robin entered the room respectively then Joker can see robin's name but cant see Batman's Name in the userList.
Here is my code:
Client Side:
<div style="height:760px; width:200px; margin-left:450px;border-style:solid;"id='userlist'>
</div>
This is the DIV element where i want my userlist.
JS code:
var msg = {
name: myname,
color : '<?php echo $colours[$user_colour]; ?>'
};
websocket.send(JSON.stringify(msg));
Then server recieve this data and Heres the part of the server side code:
$tst_msg = json_decode($received_text); //json decode
$user_name = $tst_msg->name; //sender name
$response_text = mask(json_encode(array('name'=>$user_name)));
send_message($response_text); //function to send data to the client side
Now heres the client side code for recieving the data:
websocket.onmessage = function(ev) {
var msg = JSON.parse(ev.data);
var uname = msg.name; //user name
//code to check if same name doesnt appear twice
if(!$('#userlist:has(li.'+uname+')').length>0){
$('#userlist').append('<li class="'+uname+'" >'+uname+'</li>');
}
};
What can be a workaround to solve this problem? Any ideas? Hope I made sense.
With your current code this is what is happening
Batman enters room - script fires to append current users to list - noone is there so nothing is appended.
Joker enters room - script is fired and it is appended to batman - but the script has fired to add batman already so Joker doesn't know batman is there.
A script will not store temporary information
i.e. if you EXPLICITLY declare users = batman, robin, joker - the script knows this.
BUT if you fire a script and store them in a array or similar in that script the second the script has finished running it forgets what you have stored.
Hope that helps - just remember 'SCRIPTS CANNOT REMEMBER ANYTHING I TELL THEM WITHOUT HELP' - it will make it more obvious that you need a storage mecahnism for temporary stuff.
Hope that helps and good luck!
Related
I'm building a message system to learn how it works, and I've already got
pretty much everything. I can log in and make a post on a board, but now I would like to be able to edit it. The back-end is ready, it receives a POST request
Basically what I need to do is check if the currently logged in user is the author of a certain post from Javascript to show or hide the edit button. I know how to tell if the user is logged in from PHP so that it blocks requests if you aren't the author, but I can't hide or show the buttons as the posts are dinamically generated from a <template> using JS.
Login snippet:
$_SESSION["userid"] = $userid;
Edit check PHP snippet (kinda pseudo-code):
if ($_POST["action"] == "modifypost" && isset($_POST["postid"]) && isset($_POST["content"]))
{
$post = get_post($_POST["postid"]);
if ($post.userid != $_SESSION["userid"])
{
die("you are not allowed");
}
//MySQL queries
}
Post dynamic generation (abbreviated):
function add_post(post) {
var t = document.querySelector('#historypost');
t.content.querySelector(".content").innerHTML = post.content;
var clone = document.importNode(t.content, true);
document.body.appendChild(clone);
}
I had originally thought of setting a variable with the user ID from HTML with <script> and <?php ?>, but then the user would be able to manually set that variable from the console and show the buttons.
I had originally thought of setting a variable with the user ID from HTML with <script> and <?php ?>
Yes, this is one correct approach. Basically, use PHP to tell JavaScript which posts actually belong to the current user.
but then the user would be able to manually set that variable from the console and show the buttons
True. There is no way to secure information from user-meddling once you've sent it to the browser. This is because the user is in control of what gets executed in the browser. Instead of thinking of the button visibility as a security feature, think of it as a convenience -- something to make the user experience more pleasing.
Application security is really enforced on the server. Just make sure that one user is not allowed to edit another user's posts, and do not trust what comes from the browser. Verify inputs.
Ideally, I would prefer to put the post rendering logic inside the server-side.
But as your solution is focused in javascript, an option makes PHP render a javascript variable that tells if the user is the post author.
Example:
Inside your PHP file, in the HTML render part you can do this:
<script>var isAuthor = '<?php echo ($post.userid == $_SESSION["userid"])'; ?></script>
Doing this you will have javascript script variable called isAuthor, that will have value "1" is the user is the author.
-
But as I said, this doesn't look like a good approach to solve the problem. It's something that PHP can handle better, without expose your logic to the client.
Let's say I have two users, "Matt" & "Kevin". Matt wants to message Kevin, by clicking a chat button to send Kevin a direct message a chat box boots up, he sends a message and Kevin receives it.
I generate the chat id by taking the person who sent it (Matt) and the person who received the message (Kevin) and concatenating it into an id.
var me = "Matt";
var user = "Kevin";
var uniqueChatID = me+user;
As I save the message server side (with mongoDB) the message object has a chatID of MattKevin. So now when I want to get back to that chat I can pull in all messages with the chatID of MattKevin.
This works fine, until Kevin wants to boot up a chat with Matt, then the id becomes KevinMatt. Now I am referencing a different chat, it's backwards. So If I want to pass uniqueChatID to get the messages it will pull a different set.
var me = "Kevin";
var user = "Matt";
var uniqueChatID = me+user;
So I am curious how can I set this up a bit better so that my program knows, ok Matt and Kevin have a chat, so if Matt messages Kevin it pulls in their chat or visa versa, Kevin messages Matt and it gets the same messages?
Sort them alphabetically:
var me = "Kevin";
var user = "Matt";
var uniqueChatID = [me, user].sort().join('');
That said, while this technically works, I'd recommend you do a little housekeeping - ensure they're always lowercase, and ensure on your db that you enforce unique usernames. Or, I'd even suggest giving the user a unique identifier (like a UUID) and use that instead to create the UCID:
var me = CurrentUser.uuid(); // 8cb3ebb8-30f9-11e5-a151-feff819cdc9f
var targetUser = Chat.targetUser(); // Matt: 9bc1ef9c-6719-4041-afd3-c5b87c90690d
var uniqueChatID = [me, targetUser].sort().join(',');
// 8cb3ebb8-30f9-11e5-a151-feff819cdc9f,9bc1ef9c-6719-4041-afd3-c5b87c90690d
And lastly, if your db supports relationships or connections, your best option is to separate chat table/collection for each chat and "connect" (or create a relationship) between both users and the chat. Then the next time you go and load it up, the connection will lead you to a unique chat that's connected to both users.
I think you approach is too complex. Furthermore, it looks like you want to embed the individual chat messages into the document bearing the created _id. The problem here is that there is a 16 MB size limit on BSON documents at the time of this writing. Upon reaching this limit, your users simply could not communicate any more. Increasing the size of documents may also lead to frequent document relocations, which is a very costly operation unless you use the new WiredTiger storage engine introduced in version 3.0 of MongoDB.
So we need a more scalable approach.
Here is how I would do it:
User:
{
_id: "Kevin",
email: "kevin#example.com"
/* Put further user details as you see fit*/
}
Message:
{
_id: new ObjectId(),
from: "Kevin",
/* You might want to have multi-person chats, hence the array */
to: ["Matt"],
ts: new ISODate(),
message: "Hi, Matt!"
}
Index:
db.messages.ensureIndex({from:1,to:1,ts:1})
Query for reconstructing all messages a user received:
var user = "Matt"
db.messages.find({"to": user}).sort({ts:1})
Now you can iterate over the result set and open a chat window for each "from" you find.
Query for reconstructing a defined chat
var user = "Matt"
var sender = "Kevin"
db.messages.find({"from": sender, "to":user}).sort({ts:1})
will give you all messages sent to Matt by Kevin, ordered by time. Since both queries should utilize the index, they should be pretty fast. You can use .limit(x) to query only the last x messages sent to user.
With this approach, you don't need an artificial _id, the index created allows you to do every query related to the participants efficiently and the messages can be sorted in order. Because each message is saved individually and does not change any more, you can store an almost indefinite number of messages and bypass the document relocation problem.
I have an intranet site with multiple page links linking to other pages within the site on each page. The issue is that if I login to my profile for example I have no problem, but if I click on a link to say my index page or recent news page or whatever it takes me to the page but I get logged out and I have to login again. I've found out that linking between pages out works if the user's password is "something"
I have two versions of this site, the only difference is that they connect to different databases. On one domain everything works fine, on the other is when I get this issue.
This is at the top of every page for connections to the database and checking to see if the user has the right credentials and just some functions. I think the issue should be with the code checking the user credentials and or starting the session.
<?php
// Connect To Secure Login
$cfgProgDir = 'phpSecurePages/';
include($cfgProgDir . "secure.php");
//These are the includes needed to make the php page run
// this file connects to the database
include("includes/connect.inc.php");
// This file holds all the custom functions
include("includes/functions.inc.php");
This is the config file
$cfgIndexpage = '/index.php';
$cfgServerHost = '********************'; // MySQL hostname
$cfgServerPort = ''; // MySQL port - leave blank for default port
$cfgServerUser = '*********'; // MySQL user
$cfgServerPassword = '**********'; // MySQL password
$cfgDbDatabase = '******'; // MySQL database name containing phpSecurePages table
$cfgDbTableUsers = 'members'; // MySQL table name containing phpSecurePages user fields
$cfgDbLoginfield = 'firstName'; // MySQL field name containing login word
$cfgDbPasswordfield = 'password'; // MySQL field name containing password
$cfgDbUserLevelfield = 'permission'; // MySQL field name containing user level
// Choose a number which represents the category of this users authorization level.
// Leave empty if authorization levels are not used.
$cfgDbUserIDfield = 'id'; // MySQL field name containing user
/****** Data ******/
/* this data is necessary if no database is used */
$cfgLogin[1] = ''; // login word (username)
$cfgPassword[1] = ''; // password
$cfgUserLevel[1] = '0'; // user level
and the connect file ($connect) just connects the my DB
Any suggestions on what the issue could be? :)
It probably means your session is getting destroyed somewhere or cookies aren't being set.
I didn't dwelve much into the code (It's a bit messy) but... secure.php include checklogin.php on line 67. On checklogin.php file, Line 37, session_start() is called and it is called again on your config file.
It should raise a warning so, if you haven't seen it, you're either using an old version of PHP or you don't have error reporting enabled.
You should enable error reporting and check for any notice or warning.
Rigth now i'm creating my own website and there need to be a log in function. I've made a sign up page that retrieves data from the input fields and now comes the problem. I don't know how to save the passwords and username etc. Is it possible to save this into a text file and every time i open the website it retrieves this data? So, yes how do i do this and if this can't is there another way?
Here you see the code it retrieves. These variables need to be safed in a text file and retrieved next time website will be opend
var voornaam = document.getElementById("voorn").value;
var achternaam = document.getElementById("achtern").value;
var mail = document.getElementById("mail").value;
var password = document.getElementById("pass").value;
var gender = document.getElementById("iGender").value;
Solution:
Use a Database to save this information. Here a some Databases Mongo DB and Firebase
https://www.firebase.com/
Here's a course for Firebase http://www.codecademy.com/en/tracks/firebase
In addition to hashing the password, you probably want to be storing this information in a database. You will then have to add some logic to your application so that when a user logs in to your website, the values they enter into the log in form are checked against the values stored in the database when they signed up. In very general terms, that is probably the most standard architecture to get a log in functionality up and running.
You will have to write a service on your server that takes the form values, checks them against a database and then updates the HTML accordingly.
You could create a cookie and read it when the page loads: http://www.w3schools.com/js/js_cookies.asp
Create: document.cookie = "voornaam="+voornaam
Read: $(function(){ voornaam = document.cookie.replace("voornaam=",""); })
EDIT:
To save objects, you can use the JSON-library like so:
document.cookie = JSON.stringify({foo:"bar"}); cookieObject = JSON.parse(document.cookie);
But have in mind that the user can read and manipulate this cookie...
Apologies for the NOOB question but I’m still learning.
Firstly I’m not asking for someone to program the following problem for me or to give me the code. I’m merely looking for a bit of help with the logic and a bit of advice.
What I am trying to do
This is just an example, what I am trying to do is different but will use the same logic: I am trying to display a movie poster on my website, the user can than rate that movie between 0 - 5 stars, his/her rating will be recorded in a database, along with other users’ ratings. When he/she has finished his/her rating, a new movie poster needs to be displayed where he/she can again rate the poster and so it goes on until he/she is tired of rating movies.
The Logic
I AM ASSUMING I will need to use PHP here to store and retrieve the data
A Table will be created which contains different images and ratings corresponding to that movie’s rating, along with the number of users who rated the movie to calculate the average for the total rating
The Problem
How do I get the image to change once the user rated the image?
Is it possible to change an image src onclick with PHP like it is with Javascript?
If so how do I do it? Is it possible that I will need to use a combination of PHP and Javascript here?
Any help or advice will be greatly appreciated. Thank you in advance.
You definitely need to use both javascript and PHP to accomplish this.
I would approach it like this:
a) Use jQuery javascript library to make the javascript easier.
b) Write some javascript which responds to the user selecting a rating. You'd probably need to bind to the onClick event of your rating buttons.
c) When a rating button is clicked, the javascript functions should use jQuery.ajax to send the selected rating to the server via an HTTP POST. The data sent to the server would probably need to contain an ID to identify the movie, an ID to represent the user (so you can stop people voting more than once for the same movie), and the rating they chose.
d) On the server-side, you can write a PHP script to handle the vote submissions. It would check for the movie, and user ids, (stored in PHP's $_POST variable), and then save the rating to some database. It could then also send a response back to the client which would contain the next movie id, and the next poster. I would recommend you use json_encode to store this info in a way that's easy for the javascript to interpret.
e) Finally, back on the client side, your javascript code can react to the data sent back by PHP, by putting up a message like 'thank you for your vote', then changing the movie details on screen to replace them with the new one.
Your client-side code would look something a bit like this:
<img id="movie-poster" src="movie poster src" />
<ul>
<li class="rating-button">1</li>
<li class="rating-button">2</li>
<li class="rating-button">3</li>
<li class="rating-button">4</li>
<li class="rating-button">5</li>
</ul>
<script>
var currentUserId;
var currentMovieId;
$('.rating-button').on('click',function() {
$.ajax({
url: "URL of PHP script here",
type: 'post',
data: {'movieId':currentMovieId, 'userId':currentUserId, 'rating':$(this).text()},
dataType: 'json',
success: function(response) {
// this runs after your PHP script has responded
// update your page with the new movie here
alert('thanks for voting');
currentMovieId = response.newMovieId;
$('#movie-poster').attr('src',response.newMoviePosterSrc);
}
});
}
</script>
Your PHP script would look something a bit like this (you'll have to figure out all the database and user authentication bits yourself)
<?php
$user_id = $_POST['userId'];
$movie_id = $_POST['movieId'];
$rating = $_POST['rating'];
// check that the user is allowed to vote - possibly examine cookie for this
// check that rating is between 0 and 5
// check that the movie exists
// store results of vote in database
// load up another random movie from the database and send it back (in JSON format)
// assume details of new movie are in $new_movie =
header('Content-type: application/json');
echo json_encode(array('newMovieId'=> new movie id here, 'newMoviePosterSrc' => URL of new poster here));
exit;
You should also add some error handling to that code. EG, messages to display if there's a connection problem, or the movie ID isn't recognised or something.
This page has more info on how to select a random row from your database - IE to select at random the next poster to show:
How to randomly select rows in SQL?
Hopefully that should be enough to get you started.