Session not incrementing correctly - php

I've been working on a little project that has gotten me turned on and off regarding mood. The problem which I've been having all from the start before I remade the application is that I try to increment a session called 'Score', but for some reason it won't increment. At a time I managed to get this working, but in the little time it did I didn't manage to find the root of the problem.
The application is just a simple word repeater/practicer. I have wordlists in .txt format which the application picks up, cuts out the lines and gives each word it's own session. Then it picks a random word and shows it to the user. If the word (array index) has already been used, it will be in an "used" array and cannot be chosen again.
When the user is presented a word, he is to type in the correct corresponding english (phonetic) word. After submitting the script will check if the POST value given corresponds with the answer stored in a session for that word.
Now, there is a session called 'Score'. This session is not changed unless User's Answer == Session's Answer (which is tested to work correctly). However, when those two answers are the same, the session does not increase. I have tried to use ++;, +1; and += 1;, none of which seems to be working. Also, I made the form submit to an external file to try and lessen the pain to see logic, in case you wondered.
I fail to see where I might have missed the logic and would be very grateful for any help as this project started off as something fun but has now just become a hassle:
Wordlists are structured like this: Cyrillic(RU) | Phonetic(RU) | English(answer).
HTML (index.php): http://pastebin.com/3ePLtzuj
PHP (engine.php): http://pastebin.com/pyXR2U2s
POST->PHP (wordcheck.php): http://pastebin.com/ZZxgkHkJ

wordcheck.php: check if $answer == $result is really true: var_dump($answer == $result);
your engine.php isn't included in your wordcheck.php if that does matter
check the existence of your session vars, before using them - like: $wordNum = isset($_SESSION['wordNum']) ? $_SESSION['wordNum'] : 0;

Related

PHP setting var to only a portion of a string

I have a panel I'm making that will use session data from another forum to give it permissions. Basically when the user logs into our forum and the session and trust is created on the forum, they can click on the panel and the panel will check their browser cookie for the session id and trust id. It then takes that trust id and checks the forum's database for the user id associated with that trust. Then takes the session id and verifies that it belongs to that user id. The issue is that when I get the session id, the associated user id is part of a blob that i have to cast in order to get the data from the field. So I get a result like this:
('7c64c90413beb7d139c64ccc8b13380b',
'a:12:{s:12:"sessionStart";i:1454075264;s:2:"ip";s:4:"b???";s:11:"sessionCsrf";s:16:"-2Yx13nBLdstUj4H";
s:7:"user_id";i:20;
s:13:"password_date";i:1453353041;s:16:"previousActivity";i:1454072099;s:13:"trophyChecked";b:1;s:16:"promotionChecked";b:1;s:16:"dismissedNotices";a:0:{}s:15:"lastNoticeReset";i:0;s:13:"canAdminUsers";b:1;s:20:"userModerationCounts";a:2:{s:5:"total";i:0;s:13:"lastBuildDate";i:1454075264;}}'),
I know there is a lot there, but I singled out the part that matters to me. The first column returned is the session id, which im using to verify the user id, but the user id is in the middle of that all that crap in the second column. So you can see where I single out the definition, what I want to do is just assign that "20" after "user_id;i:" to a variable and discard the rest. I'm sure this is simply done, but at this point I think I'm just nuking it out and spinning wheels. I was thinking explode, but the structure of that data seems like that's not an option.
That data is simply the result of a PHP serialize() call. You can pass it to unserialize(), which will provide you with an array containing the values.
<?php
$str = 'a:12:{s:12:"sessionStart"…etc…etc…i:1454075264;}}';
$arr = unserialize($str);
var_dump($arr['user_id']);
In case you’re trying to extract the value from within MySQL alone, for some reason I’ve done something similar with an awful query containing lots of nested SUBSTR() and LOCATE() just two weeks ago. I wouldn’t recommend it. Especially because in my case I was doing a one-off reporting query, while you’re trying to do authentication with it. People might try to use specially crafted cookies to circumvent your string extraction and gain illegitimate access.

how to get the old session?

I have a post form with captcha based on session for example the code know is Ujkd9 after refreshing the code become Hi8P4 .
And this is the problem. If someone post the form the captcha code of the input become old, how to get the old session ?
Well you can't, but you could save the older session into another session key creating a copy of that session, by example :
$_SESSION['session_copy'] = $_SESSION['current'];
I'm assuming your captcha code is being made on the fly and output via some image making in PHP. Your problem is that once you make the image and output it, you have no way to figure out what the CAPTCHA value actually is?
Since I have absolutely no knowledge of what your application structure, or database looks like, I can give you recommendations based on what I would do:
If I can assume that your PHP script looks something like this:
$captcha_string = make_hash(); // This function could just be the consolidation of your step in making the hash. I don't know, so it's going to be generic.
make_captcha_image($captcha_string); // Again, I don't know exactly how this goes, so I have to assume.
In layman's terms, you are going to need to store that somewhere. But Where? Now, I want it kept in mind that I've never particularly worked with Captcha directly, so I'm not 100% on what the "best practices" are, and I also don't know what you're doing, so these are probably going to be vague answers for a vague question. There are roughly 3 options, the way I see it.
1. Database Storage
Realistically, I would probably use a database as a first go-to. In my database I would have a table named captcha, with the following definition:
CREATE TABLE captcha (captcha_id int unique not null auto_increment, session_id VARCHAR(100) NOT NULL, captcha_string VARCHAR(6) NOT NULL)
Note: I don't know what length the session_id() function will return, and I am currently unable to check. If you know how long the session id is, change the length on session_id to match. Similarly for captcha_string I don't know how many letters your captcha will have. Change the definition to fit your uses.
What you are going to do, in words is:
Query the database with the current session_id to see if a captcha image exists.
set the information in a variable, I am using $captcha_data
If $captcha_data is populated with information, use its captcha string, otherwise, create a new on and store it.
Note that for this example, I assume that your database connection, whatever type it is, sits in an object named $db I am using no particular type of database, just methods I use in my own database class. The definitions would look similar for yours, but probably not exact.
$session_id = session_id();
$sql = "SELECT * FROM captcha WHERE session_id='".mysqli_real_escape_string($session_id)."'";
$result = $db->query($sql);
if($result!==false){
$captcha_data = $db->fetchrow($result);
}
$db->free_result($result);
$captcha_string = (isset($captcha_data['captcha_string'])) ? $captcha_data['captcha_string'] : make_hash(); // This function could just be the consolidation of your step in making the hash. I don't know, so it's going to be generic.
if(!isset($captcha_data['captcha_id'])){
$sql = "INSERT INTO captcha (session_id, captcha_string) VALUES('".mysqli_real_escape_string($session_id)."','".mysqli_real_escape_string($captcha_string)."')";
$db->query($sql);//You should check that this query is successful in your code, but for brevity I am skipping it.
}
make_captcha_image($captcha_string); // Again, I don't know exactly how this goes, so I have to assume.
Now keep in mind, I would probably add a date or time column to the captcha data so that I could delete values from accounts that haven't been used in some months, just to keep size down, but that's something I leave to you.
2. $_SESSION Storage
I can't say I recommend this option. It's effectively the same as my previous answer, just without the database interactions.
In words, we are doing the following:
Checking if the $_SESSION['captcha_id'] value is set, if so, use it. If not, create it.
This code is going to look very odd, so I recommend looking up Ternary Operators
//Assuming your session_start() is at the top of the page
$captcha_id = $_SESSION['captcha_id'] = (isset($_SESSION['captcha_id'])) ? $_SESSION['captcha_id'] : make_hash();
make_captcha_image($captcha_string);
3. File System Storage
I'd like to say that if this is the option you're choosing you've got some life decisions to make. This should not be used. Ever. Seriously.
That being said, the basic premise here is
See if a file with the current session_id exists.
if it does, read it's contents and use them as the hash for the image
else, create a new hash, create and populate the data in the file.
How that looks in Code:
$session_id = session_id();
if(file_exists('temp/'.$session_id.'.php')){
$captcha_string = $captcha_data = file_get_contents('temp/'.$session_id.'.php');
}else{
$captcha_string = hash();
file_put_contents('temp/'.$session_id.'.php',$captcha_string);
}
make_captcha_image($captcha_string);
Just to reiterate: don't use this method. I am supplying this answer simply and solely because your question asked HOW to keep the captcha from changing.

Storing online exam results in sessions in PHP

I'm working on online free examination website. Using PHP, jQuery & session I'm displaying questions with choices on front end. If user clicks any choice among displayed choices (radio buttons with same name for all choices as obvious) I'm storing selected question number & choice (as answer1/answer2 up to answer2) in session variable, adding current quesno & choice to previous one.
The problem is if I want to change the answer which I'vE already answered, it's just appending as new result instead of updating.
I've tried to loop through that session variable but stuck. The following is the data format I'm storing into session variable.
if( $_POST['qno'] && $_POST['choice'] ){
$ques_no = $_POST['qno'];
$selected_choice = $_POST['choice'];// choices in radio buttons with name choice
if( isset($_SESSION['result']) ){
//here i'm trying to loop though $_SESSION['result'] to check the below format
>> ','.$ques_no.',' << in session so that it can be changed, i stuck here.
$_SESSION['result']=$_SESSION['result'].','.$ques_no.','.$selected_choice.'|';
}else{
$_SESSION['result'] = ','.$ques_no.','.$selected_choice.'|';
}
}
If this procedure is OK to follow please tell me the process of loop through and check whether that pattern existed in session or not; if it is wrong procedure please guide me.
The easiest way to accomplish this is to make $_SESSION['result'] an array rather than a string. Then you don't have to worry about if statements at all, except to make sure $_SESSION['result'] exists, you just assign the value in a single step and you're done:
if (!isset($_SESSION['result'])) $_SESSION['result'] = array();
$_SESSION['result'][$ques_no] = $selected_choice;
Just make sure you edit your other code to interpret $_SESSION['result'] as an array, or else you'll get some unexpected results.
I prefer you buy available online scripts in market as starting point for it. This will save you time, cost and testing efforts.
Below is one of the fine scripts that I worked it and it worked like charm. Using this as base I developed a online testing portal of over 1000 users using computer adaptive test.
http://codecanyon.net/item/online-skills-assessment/9379895
It is a good starting point for people looking to develop Online Exam System.

Resorting id field in database after deleting data

I have a problem. I created a database (my_database), created a table inside it(members), and created fields (id, name, lastname, address). The id field is set to auto-increment. Now I have 5 rows, which means id has a value of 1, 2, 3, 4 and 5. When I delete id 3, then what's left is '1 2 4 5'. My question is what should I do to resort '1 2 4 5' to '1 2 3 4'? Any help would be much appreciated.
Update: I have to do this resorting because on my site I am displaying all the members using loop and accessing the id number. Or is it even possible to get the id of a data? Example I have data this data: id=2, lastname=clyde, address=switzerland. How can I get the id value just by the lastname value?
You really don't want to do that for a number of reasons.
First off, things might go wrong if a page is open. Let's say a user is on the edit page of the entry with id = 4 when you delete the entry with id = 3 and update the ids as you suggest. Now, when the editing person hits submit, the id will be taken from his page and he will be updating the new entry 4 instead of the old entry 4. Now this is a blunt and simple example, but beyond those there are lots more things that can go wrong at this level.
Secondly, there is a lot of work involved when programming this. First, you need to update your columns. Then, you also need to make sure MySQL knows what number to give the next entry. And then all of that has to work in an environment that makes sure we don't get quite as many problems with the point mentioned above (which is quite a hard thing). This is a lot of work compared to the alternative of not doing anything.
The third problem is that there is a huge performance overhead. Imagine having a database with thousands upon thousands of entries, and then removing an entry with a low id. Suddenly, all entries with higher ids have to be updated. This might well mean that your site becomes unresponsive because it is doing this task and can't handle too much else at the same time (in fact, in order to make sure that we don't get problems like in the first point, we have to make sure that we don't do anything else at the same time (or make sure we work on different copies of the data or something) because we could end up with a result that comes from during this whole update process.
My suggestion would be in line with what others are saying: just leave it as it is and do not worry about this. auto_increment is meant for just one purpose: giving each value a unique identifier easily. Use this identifier to identify and refer to the same entry only. Perhaps one could also make a case about sorting on these identifiers, but no further than to have a certain order (and even then people will disagree with this use of it).
Instead of trying to update the ids, we should look for another place to solve this problem. If the problem is purely how you feel about it, that's easy. You may not feel good about it, but you just need to convince yourself that updating all those ids is not the solution you are looking for. If you use the numbers elsewhere, the problem can be a little more complex to solve. However, there is always the possibility of using PHP to generate numbers for each entry, which most definitely is the logical place to do so if the numbers are used in the generating of your html content. If you provide more details about where you use the sequential numbers, a look could be taken at how to solve it in that case.
You could do an UPDATE query but mostly developers just leave the id's as is. You can do the numbering in the PHP if it's important to you.
You can either manually update id value by the following statement :
update members set id = (id-1) where id > 3;
or my advice would be to leave as it is. Its not causing any ambuiguity.

Best way to store user permissions?

Designing a fairly complicated site with a lot of ajax running on a single page. I have reached the point where some user's need to have specific permission to do things and some need to be stopped from the action. I have set up user roles in my database and all is working fine, but I wonder if there is an easier/safer method for me to store each permission.
Currently, when a user logs in their specific permissions are grabbed from the db and loaded into a session array. To check if the user has permission, I simply check to see if the permission is contained in the array. This seems sluggish, and almost like I am missing a better solution.
Also, sessions can apparently be edited by the user... is there a safer method?
I have thought running a query for each check, but that could greatly increase the load time for a simple ajax request.
I am open to any and all ideas. Thanks.
First and foremost, the user cannot edit Session variables. The only thing that is saved on the user's machine is a Session ID. That ID is then used by the server to grab key/value pairs that are stored ONLY on the server. From a client's standpoint, it is impossible to change values on a whim.
Second, I would not worry too heavily on a database connection. Avoid repeating yourself, but don't worry too much about the first connection.
Finally, my favorite way to do multiple permissions without creating roles is to use binary math. Some people like this, some people don't, but I find it useful.
To use this method, imaging that we define the following values:
CAN_EDIT_SOMETHING = 1 // Powers of 2
CAN_SEE_SOMETHING_ELSE = 2
CAN_DO_ADMIN_STUFF = 4
... = 8
To give people multiple permissions, use binary OR
PERMISSIONS = CAN_EDIT_SOMETHING | CAN_DO_ADMIN_STUFF
To illustrate how this works, we can look at the bits:
0b0001
OR 0b0100
---------
0b0101
To check if someone has a permission, use binary AND
if( PERMISSIONS & CAN_EDIT_SOMETHING != 0 ) {
}
To see how this works, we look at the bits again
0b0101
AND 0b0001
----------
0b0001 // Not equal to 0. They must have that permission!
The final benefit of this method is that it allows you to combine multiple permissions easily into "meta-permissions"
// If both EDIT_SOMETHING and ADMIN_STUFF are tasks that an admin
// can perform, we can combine them easily
//
IS_FULL_ADMIN = CAN_EDIT_SOMETHING | CAN_DO_ADMIN_STUFF
// We can then use this value exactly as we do any other permission
//
PERMISSIONS = IS_FULL_ADMIN | CAN_SEE_SOMETHING ELSE
Use it if you want, but it is a nice trick to have in your arsenal.
Seems OK to me! You could look at some software to enhance your session chache peformance.
Querying the DB every time is not as bad as it sounds! Firstly you probably need to connect to the DB anyway, secondly if you queried the users permisions when they signed in then the chances are that all the relevent rows are sitting in the buffer and no IO is required, thirdly a query for a single permision for a single user is going to be a lot lighter than a query for all permisions for a user.
Your explanation of the model seems a bit confused. Permission is the product of the subject authorization and the object authorization. Do you really store these products for every combination of subject and object? That's a very inefficient solution and very hard to manage.
Also, sessions can apparently be edited by the user
WTF?????!!!!
Session data should only ever be changed by the methods you define in your code - if users are able to modify any part of the session data in any way they like then this is the first problem you need to address - until you do, it will be virtually impossible to rely on any part of your authentication/authorization method unless you move authentication completely out of the domain of your application code (BTW: this is not the right way to fix the problem).
Certainly searching a very large array (not sure of the actual breakpoint - but in the region of n=1000 - but there are lots of variables affecting this) can be significantly slower than fetching the results from a database.
Its hard to say what you're doing wrong without understanding how your current system works. Is it one of these?

Categories