Jump to content

kicken

Gurus
  • Posts

    4,704
  • Joined

  • Last visited

  • Days Won

    179

Everything posted by kicken

  1. Every class you create that extends your dbconnect class will be creating it's own separate connection to the database. If you're using several of these classes in a page load then that would mean several separate connections. What you should do is have those classes accept an instance of your dbconnect class as a parameter to their constructor. class secondClass { private $db; public function __construct(dbconnect $db){ $this->db=$db; } } $db=new dbconnect(); $sc = new secondClass($db);
  2. Seems like it's working fine for me. However, you should not be using tables for layout.
  3. The point of storing the expiration date is so that you can check it when you lookup the token later and reject expired tokens. You cannot rely on the cookie being deleted by the browser at the requested time, so you must check for yourself if the token is expired or not. $stmt = $pdo->prepare(" SELECT users.name, users.user_id, tokenHash FROM user_token, users WHERE tokenHash = ? AND expires > NOW() AND users.user_id = user_token.user_id "); $stmt->execute([sha1($_COOKIE["token"])]); $db_query = $stmt->fetch();
  4. Then just set $itemName equal to an empty string after you assign to your entry to the $json array. That way, on the first loop, $itemName will contain the site name but on future loops it'll be empty.
  5. Don't, because that structure makes no sense. If you want one suite entry with several bookings, then structure the data that way so you have a JSON output that looks like this: [ { "name":"Suite 1", "bookings": [ { "desc":"Booking #835", "values":[{ "from":"09\/08\/2022", "to":"09\/14\/2022", "label":"Single Room", "desc":"john@smith.com", "customClass":"ganttRed" }] }, { "desc":"Booking #833", "values":[{ "from":"09\/06\/2022", "to":"09\/09\/2022", "label":"Ensuite", "desc":"fred@west.com", "customClass":"ganttRed" }] } ] } ] There doesn't seem to be much point in your "values" key being an array either. I would remove that extra level and just make values the object.
  6. If you want multi-device support, you need to move your cookie_token field out of your users table and into another table so that you can have multiple active tokens. For example create table user_token ( UserId int not null, TokenHash varchar(255) not null, Expires datetime, primary key (UserId, TokenHash) ); Whenever you generate a new token, insert a row into that table. When you need to validate the token, look for it in the table and make sure it's not expired.
  7. Your code could be simplified. Your cookie token is essentially a long random password so you should treat it as such and use the password functions to hash and verify it. Your isRemembered function can be simplified to a single statement. You also have the $pdo parameter which is unused and should be removed. function isRemembered() { return isset($_COOKIE["remember"]); } Any time you find yourself writing code like if (<some condition>){ return true; } else { return false; } you can simplify that to just return <some condition>. If you update your code to use the password functions, you'll need to re-factor your tokenLoggedIn function and your token storage format. With proper hashing, you can't just look up the record in the DB by hashing the input like you are currently doing. The reason is that each hash includes some random data called a Salt which will make the input different from what you stored. This means you need to store either the username or the user ID into your cookie as well. This could be either a separate cookie, or just as a part of the token cookie. I'll assume storing the ID and token separated by a ; in my example rewrite below. Once gain, your final if/return can be simplified. function tokenLoggedIn($pdo) { //Extract user id and token from the cookie. [$user_id, $token] = explode(';', $_COOKIE['token'], 2); //Lookup the stored hash $stmt = $pdo->prepare("SELECT cookie_token FROM users WHERE user_id=?"); $stmt->execute([$user_id]); $info = $stmt->fetch(); //Compare the token in the cookie against the stored hash. return password_verify($token, $info['cookie_token']); } For your final bit of code that puts it all together, I'd suggest ordering the code as this: Check if the user has a valid logged in session If not, check for the token cookie and try to log them in using it If the cookie is missing/invalid, send them to the login page. This way you only need to spend the time checking and validating the cookie once to start the session. After that it's a simple matter of checking the session exists and is valid. Having both $_COOKIE['remember'] and $_COOKIE['token'] is unnecessary. You only need one which would hold your token. Since your isRemembered() function has been reduced to a single line, it's also unnecessary, you can just inline that check. You'd then end up with something like this: //If no valid session exists if (($_SESSION['loggedin']??false) !== true){ if (isset($_COOKIE['token']) && tokenLoggedIn($pdo)){ //Cookie is valid, setup the session $_SESSION['loggedin'] = true; } else { //No or invalid cookie, send to login page. header("location: login.php"); exit; } } For a little extra security, I would consider generating a new cookie token when the previous one has been successfully used to start a session. This would help guard against the cookie being leaked and used in the future by a third party. You could also limit each token to only be valid for a specific length of time (a few days or a week for example) for the same reason.
  8. You should not be putting user's input directly into your query. Doing so opens you up to SQL Injection attacks. Use parameter binding to create a safe query with the user's input.
  9. I'm not familiar with Mint, but here are some things to check in your phpinfo output. extension_dir - Should specify /usr/include/php/XXXXX/ext if that is where your pdo.so file is located. All your extensions should be in the same directory. Scan this dir for additional .ini files - should specify /etc/php/7.2/apache2/conf.d which is where the configuration files for your extensions would be located. There should be a file (or symlink) here for PDO, make sure it exists. Additional .ini files parsed - Should list the files in the conf.d directory, and the PDO file should be in the mix. If some part of that isn't true then either there's some configuration error to be sorted out or Mint just does things differently.
  10. Are you calling your create_cookie function somewhere prior to trying to read the cookie? The code you posted doesn't, so undefined would be expected.
  11. You can get them from the releases area.
  12. Using SQL Server with PDO_SQLSRV I generally just do something like this for an IN list. $placeholders = implode(', ', array_fill(0, count($_POST['jobs']), '?')); $sql = 'select ... from ... where Id in ('.$placeholders.')'; $stmt=$pdo->prepare($sql); $stmt->execute($_POST['jobs']); Pretty simple. I'd assume something similar would work with odbc_*.
  13. The response data could be anything. JSON is common so there's a method on the response object to parse it, but you could get whatever data you wanted as either text or binary data. You should be looking at the Content-type header to find out what the type is and react accordingly. Because those functions immediately return a promise, which is an action which won't fail. The failure comes later and the promise is rejected, which you handle with .catch() as described in your other thread.
  14. Not sure what you mean by that. Just take the list of flavors the user voted for and add them to your votes table as three rows. If you want to preserve the order of the selections to determine first/second/third choice then that'd be another column on the votes table that saves the rank (1/2/3).
  15. The console might report the error simply because it's failed network request and thus something a developer might be interested in. All that you should really be concerned with is if your code is working as expected or not. A clean console log isn't really that important (or always possible).
  16. If all you want is a simple count of votes, then just make one table that lists your flavors one per row with a second column that is a counter for the number of votes. If you want to record additional data about the vote (such as who voted to prevent duplicates, or time that they voted) then you need two tables, one for your list of flavors and one for the votes. The votes table would have a single row per vote and that row would contain the flavor that was voted for and any additional data you want to save. Then to get your results, query the votes table for the row count grouped by flavor.
  17. There are multiple ways to deal with errors, it depends on what you need / want. This isn't necessarily anything unique to fetch() in particular, this is just how Promises in general work (which many things make use of these days). The approach I did allows the .then function to still run, just without a response (or the fake response) which might be handy if you have logic in there you want to perform whether the request is successful or not. If you want to just bypass the .then function entirely if there is an error, you can put the .catch after it instead of before it. If you don't want to do any error handling here, then exclude the .catch in this function and leave it up to the caller to add a .catch of their own to handle errors. A quick rundown of how things work if it helps: A promise is created and returned by some function, that function then will do something in the background and either resolves (success) or rejects (error) the promise. Calling .then registers a function that will accept the resolved value of the promise and returns a new promise which will resolve with whatever the function returns Calling .catch registers a function that will accept the rejected value of the promise and returns a new promise which will resolve with whatever the function returns. Throwing an exception in either of your .then or .catch handlers will result in the next promise being rejected with what exception as the value. So when you get a promise back from a function, can create a chain of .then/.catch processing to either simply do something with the results, or to transform the result in some way. It can take a bit of time to get used to the syntax/logic flow, and some people just find it too confusing or too messy. That's why async/await were created, to help bring to code back to a more traditional style and flow. They come with their own confusion though if you don't understand how promises in general work, as such I suggest learning .then/.catch and once comfortable with that moving on to async/await if you want.
  18. If you catch the error then whatever value you return from the .catch method will be passed to your .then method as response. Since you're not returning anything, response is undefined. You can either check that response has a value (like I did in the example) or return a mock response object with .ok set to false. function requests(url) { return fetch(url).catch(function(error) { console.log("caught error: "+error); return {ok: false}; }) .then(function(response) { if (!response.ok) { throw new Error(`Request failed with status ${response.status}`); } return response.json(); }); }
  19. You could try and find some PDF reader program that would let you print a PDF automatically. On a windows machine, you could try the official Acrobat Reader and execute it with the /p /h flags: exec("Acrobat.exe /p /h yourfile.pdf"); This is what the right click -> print option does in explorer.
  20. There was an incident a few years back. You can read about it here.
  21. You need to use beginPath() before you start to draw something. Add a call to beginPath after you save the context.
  22. Is this a request to a website or is it a request for some internal file in your extension? It might behave differently, not sure. In any event, if it's triggering the .catch method instead of your .then method, then you probably just need to restructure things slightly. If you return a value from the .catch, and put a .then after it then you can ignore the error. Essentially like doing try/catch. For example: function requests(url){ return fetch(url).catch(function(error){ if (/*use error to determine if it's a is 404*/){ return null; //Return some value to continue } else { throw error; //Otherwise forward the error } }).then(function(response){ return response?response.json():null; }); } I don't know how you'd check for the specific error you want to ignore, but if you console.log(error) and look at it's properties you can probably figure something out.
  23. Yes, your function should be called when hitting a 404 error and response.ok would be false. To detect if the error is a 404 vs something else, you can inspect the response.status property. function requests(url) { return fetch(url).then(function(response) { if (response.ok){ return response.json(); } else if (response.status === 404){ //Do something } else { throw new Error(`Request failed with status ${response.status}`); } }); }
  24. Lookup a Responsive Design Tutorial. Your questions are all extremely broad and basically impossible to provide an answer to. To be honest you kind of sound like someone who just got a web development job but doesn't actually know anything about web development. You really need to learn how to ask a question properly.
  25. You need to find some API or other method of integrating with whatever CRM software you're using. Contact the company that develops the CRM software and ask them how to do it.
×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.