-
Posts
4,207 -
Joined
-
Last visited
-
Days Won
209
Everything posted by Jacques1
-
This class doesn't make a lot of sense in its current form. It pretends to be a generic class for generating security tokens, but then at the same time it's strictly bound to the session (even a particular session implementation). I think your confusion regarding static methods reflects this underlying design issue. Either turn this into a generic class which simply generates a security token and isn't limited to any particular use case. In this case you probably won't need an object at all, because a function will do the job just fine. Or put all those functionalities into the Session class.
-
Well, did you read the PDO tutorial from above? It's all explained there. Start rewriting the code, and when you have specific problems, ask here. Some of the code is pretty weird, by the way. Why on earth do you use a persistent connection when you close it right away? Why do you use persistent connections at all? You do realize that the “p” stands for “persistent”, right? And of course you'll have to get rid of all the old baggage like register_globals. Those bugs/features no longer exist in PHP.
-
As I already said, I strongly recommend PDO over MySQLi. The problem of MySQLi is that it's very cumbersome and, of course, limited to the MySQL database system. PDO is a unified interface for different database systems, and it's much more comfortable in many aspects. A prepared statement in PDO: $books_stmt = $database->prepare(' SELECT title FROM books WHERE author = :author_id AND EXTRACT(YEAR FROM publication_date) = :year '); $books_stmt->execute(array( 'author_id' => $author_id, 'year' => $publication_year, )); foreach ($books_stmt as $book) { echo html_escape('The title of the book is ' . $book['title']); } Pretty straightforward, right? You only need two methods: prepare() and execute(). Now the same thing with MySQLi: $books_stmt = $database->prepare(' SELECT title FROM books WHERE author = ? AND EXTRACT(YEAR FROM publication_date) = ? '); $books_stmt->bind_param('ii', $author_id, $publication_year); $books_stmt->execute(); $books_stmt->bind_result($title); while ($books_stmt->fetch()) { echo html_escape('The title of the book is ' . $title); } That's ... not exactly straightforward. Now you need five methods: prepare(), bind_param(), execute(), bind_result() and fetch(). There's no reason for using MySQLi (except maybe for very special cases). I think people only do it because the name sounds familiar.
-
How to add single quote instead of double quote?
Jacques1 replied to mark107's topic in PHP Coding Help
Is there any reason why the looks of the document are so super-important for you? XML doesn't care whether it's a single or a double quote. Both delimit attributes, and that's it. -
Hi, merely appending an “i” to all your mysql_* function calls isn't a good idea. While this may work as a quick hack to get rid of the deprecation warnings, it doesn't get you anywhere in the long run. The whole point of the new database extensions is to introduce new features like the already mentioned prepared statements. If you use none of them, well, you might as well stick to the old extension and turn off the warnings. In addition to that, MySQLi is very cumbersome to work with when you're actually starting to make use of the new features. A single prepared statement requires something around 5 function calls. I think that's the point when many people regret their decision. You should actually compare the to new extensions and choose wisely. Personally, I recommend PDO. It's much more comfortable and offers a unified interface for every mainstream database system, not just MySQL. There also a detailed tutorial for how to switch from the old MySQL extension to PDO.
-
This doesn't make a lot of sense. Not sure if you're trying to force the syntax of some other language on PHP. What is “number”? A string? Then it must be enclosed in quotes. You should actually see plenty of errors on the screen telling you about missing constants (because a single word in PHP is a constant). If you're not seeing those errors, then your configuration is broken. You need to set display_errors to On and error_reporting to -1 in your php.ini. What is this weird ''.$_POST['number'].'' What do you expect this to do? All user input already is a string, because HTTP doesn't know anything about PHP data types and just sends everything as a string. But even if it was an integer, why would you convert this to a string? What's the point of that?
-
The very last attempt: First of all, you need two queries. Not one. Two. One query for the authors, one for the books. Just like in your first post. OK? Now comes the “magic”: Instead of putting the authors into $output and the books into $output1 (which logically leads to “two outputs”), you put them all into $output. So you have one variable. Not two. One. OK? So the result sets of two queries go into one variable, just like you wanted. Not sure why this is so hard to understand.
-
Are you guys joking? In mathematics, we have this thing called multiplication. PHP can do it, too: $_SESSION['cart']['weight'] += $_POST['cartquantity'] * $row['weight']; But it's not a good idea to add the total weight in the session, anyway. What if the user reduces the quantity? Then you have a lot of trouble getting the exact weight difference and reducing that number again. Store the quantity and calculate the totals when needed.
-
Hi, I think you shouldn't use this code at all. Whoever wrote the “tutorial” knows less about PHP than you do. It's clearly the work of an amateur who has just started with PHP himself. You definitely cannot use this on an actual website. And you cannot use it for learning either, because the code is heavily outdated and simply bad. I understand that it's tempting to just copy and paste some PHP code from a random website and adjust it to your needs. But you have to realize that a lot of those “tutorial writers” have absolutely no idea what they're doing. Most of the time, the tutorial itself is just the copy of the copy of the copy of some crap code from the 90s. Trying to learn PHP from this is like trying to learn nuclear physics from Paris Hilton. You should write your own code. Yes, this takes some time and may seem less convenient. But you'll actually learn the language and become better. When you steal code from tutorials, all you do is perpetuate low quality. Learn PHP. For a login system, you'll need to know the following: how to access a MySQL database from PHP the basics of web security (prepared statements, HTML-escaping etc.) how to securely hash passwords And of course the basics of HTML and possibly JavaScript. The Mozilla Developer Network will be helpful with that. Keep away from “w3schools”. I you have any questions, I'm sure people will gladly help you.
-
Not sure why this is so difficult to understand. You're using $_SERVER['HTTP_HOST'], right? You seem to believe that this value is defined by the server and can be relied upon, but it's actually set by the client. In other words, this value is provided by the person who visits your website. It's just as untrustworthy as a URL parameter, a form field or whatever. I could connect to your server right now and make $_SERVER['HTTP_HOST'] equal “localhost”. Now your application thinks it's running on your laptop and uses the root account of the database. That's obviously a problem. To fix this vulnerability, I suggested that you create a PHP constant which tells your application whether it should run in development mode or in live mode. That is, on your laptop you write define('DEVELOPMENT_MODE', true); And on your live server, you write define('DEVELOPMENT_MODE', false); SInce this constant cannot be manipulated by the user, you can rely upon it and use it to distinguish between live mode and development mode: <?php if (DEVELOPMENT_MODE) { $database = new mysqli('localhost', 'dev_account', '...', 'dev_db'); } else { $database = new mysqli('localhost', 'live_account', '...', 'live_db'); } OK? What I'm saying is that you cannot trust $_SERVER['HTTP_HOST'], This value comes from the user and can be anything they want.
-
Hi, trq's answer is the correct one, but I think there are couple of dangerous misconceptions which should be cleared up. Using SHA-256 to hash passwords is completely and utterly wrong. It's so sad that everybody perpetuates this myth of SHA-2 being the “good” algorithm while MD5 is the “bad” one. Both are just as bad for this task. The brute-force tool oclHashcat can calculate 1.5 billion SHA-256 hashes per second on an old gamer PC. That means trying out every single alphanumeric password (lowercase and uppercase) with a length between 6 and 8 characters takes less than 2 days. By then, pretty much all passwords should be broken. And this is only the computing power of some script kiddie. A professional attacker could buy an ASIC for a few hundred dollars and get hundreds of billions of hashes per second. It's easy to see that using a general-purpose hash algorithm like MD5 or SHA-2 is simply pointless given the performance of current hardware. None of those algorithms was ever meant for hashing passwords. They're designed for digital signatures, which means they need to run very efficiently on very poor hardware like smartcards. When dealing with passwords, efficiency is the last thing you want, because this only helps the attacker. A single value which gets mixed into all passwords is not a salt at all. The whole purpose of a salt is to be globally unique so that each hash must be attacked separately. When you only have one value for all hashes, you defeat that purpose entirely. So all you got is the “secrecy” of your constant value. But how secret is it really? It's right in your application, readable by the webserver. What makes you so sure that an attacker who just broke into your database is unable to get the string? I wouldn't bet on that. Given those two major mistakes, I strong, strongly recommend that you keep away from any home-made hashing scheme. There are proven solutions which actually work and don't depend on questionable assumptions. The current de-facto standard is the bcrypt algorithm. It was specifically designed to be computationally expensive and has a variable “cost factor” which can be increased as hardware becomes better. There are no secret values involved apart from the password itself. Even if an attacker knows everything about your system, they still haven't gained anything with regard to the hashes. So, yes, the password_compat library is the way to go if you don't have PHP 5.5 yet. Note, however, that you need at least PHP 5.3.7, because previous versions have a critical bug in the bcrypt implementation. Besides password_compat, there's also PHPass, but it's somewhat obsolete.
-
Not exactly the smartest idea, especially when you ask people to identify the data. Not really. Obviously you've again changed the actual data and replaced it with your “Some data” dummy string. We cannot help you when you only give us some fantasy data which is totally different from your actual data. How are we supposed to debug this? I understand that you may not want to hand out your real data, but then you'll have to fix it yourself.
-
This is not JSON. It looks like the serialization format of PHP, but then it's incomplete. The “a:<number of elements>:” in front of the outermost array is missing, so you can't just run this through unserialize(). Are you sure this is the exact string from the database? How does the plugin parse the string?
-
WTF? He asked the exact same question on Monday on Devshed, got some pretty extensive answers and seemed to be satisfied. Now he's starting all over again? I thought we cleared that up, chauhanRohit?
-
Need help with validating ISBN 13 Processing Page of PHP program?
Jacques1 replied to jameshay's topic in PHP Coding Help
Help you how? What's your question? No offense, but as far as I can tell, you didn't do anything except copy and paste my code. But that was for ISBN-10, so it's useless here. Do you understand how the ISBN-13 check digit works? I mean the general logic, not the code.- 1 reply
-
- php
- validation
-
(and 3 more)
Tagged with:
-
Need help with redirect... Will not display mysqli_fetch_assoc ?
Jacques1 replied to RandomNsanity's topic in PHP Coding Help
Some parts of the code don't make a lot of sense, though. First of all, you're mixing MySQLi with the old mysql_* functions. Those are two entirely different extensions which cannot be used together. I really wonder why everybody tries this. This die(mysql_error()) stuff itself is a particularly bad anti-pattern which somehow gets copied and pasted around without anybody ever thinking about it. Do you realize that this will print the exact MySQL error message on the screen of your users? Why would you do that? The internal settings of your database are really none of your users' business. Handing them out will help attackers and irritate legitimate users. I don't know about you, but if I see something like “Could not connect to ...” with some cryptic data on a website, I get the feeling those guys don't really have their system under control. Last but not least, you really need to start using prepared statements to securely pass PHP values to queries. Security is one of the core goals of MySQLi. If you don't use it at all, well, why did you even switch to MySQLi? A sanitzied version of the code would look something like this: <?php // turn on exceptions in MySQLi driver so that you don't have to manually check every query for errors $database_driver = new mysqli_driver(); $database_driver->report_mode = MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT; // connect to the database $database = new mysqli('localhost', 'YOUR_USER', 'YOUR_PASSWORD', 'YOUR_DB'); // set the character encoding of the connection $database->set_charset('utf8'); $link_query = $database->query(' SELECT id , link FROM links_table ORDER BY count ASC -- not exactly the best name , id ASC LIMIT 1 '); $link = $link_query->fetch_assoc(); // update the access count with a prepared statement $update_count_stmt = $database->prepare(' UPDATE links_table SET count = count + 1 WHERE id = ? '); $update_count_stmt->bind_param('i', $link['id']); $update_count_stmt->execute(); // redirect the user header('Location: ' . $link['link']); exit; // omit closing PHP tag, because it's not needed and may introduce unwanted whitespace -
In your code above, you're relying on $_SERVER['HTTP_HOST'] to distinguish between “development mode” and “live mode”. But this variable is defined by the user. It comes from the Host header of the HTTP request and can be set to anything the user wants, including “localhost”. That means any visitor is able to get into your development mode and take advantage of the increased privileges. This is obviously a huge security vulnerability and must be fixed. The easiest and most robust solution is to make a boolean constant named something like “DEVELOPMENT_MODE” and manually set it to the right value. Actually, an application should never have root access to the database. This role is only for database administration.
-
Hi, what you want is a framework like Laravel, Yii, Symfony or whatever. Those already implement all the low-level boilerplate stuff (database access, user authentication, URL routing etc.) and provide a high-level API for you to use. If you just want a particular functionality, look for a library. For example, the Symfony people have published their security features as a separate module which can be included in existing projects.
-
Hi, those are two entirely different problems. Prepared statements protect the queries against SQL injections (when used correctly), but they don't do anything about cross-site scripting. That's not their job. The risk of people injecting JavaScript code must be dealt with separately. Unfortunately, you can't just escape everything, because you said you want to have syntax highlighting through <code> elements. This is much more complicated and risky. I strongly recommend that you do not try to implement this on your own but rather use an established library which takes care of the security. The first library I found with a quick search was GeSHi, but I haven't looked into its security yet.
-
Need help with Processing Page of PHP program
Jacques1 replied to jameshay's topic in PHP Coding Help
Hi, I assume the “code” you've shown us is just pseudo-code? Because obviously this isn't valid PHP syntax. I think you're approaching this the wrong way. Instead of writing down a bunch of code and then stop and wonder how on earth you need to assemble this, you should first get clear about what you want to do. Don't write a single line of PHP until you have a very good idea of how your program should look like. It also helps to leave out unimportant stuff at first. Do the error checking later. It's more important to get the ISBN check itself right. My suggestion would be to forget about the form, the error checking and whatnot and just write down the check. A function is perfect for this: <?php function isValidISBN10($isbn) { $sum = 0; for ($i = 0; $i < 10; $i++) { if ($isbn[$i] === 'X') { $value = 10; } else { $value = $isbn[$i]; } $sum += ($i + 1) * $value; } // now the final check } When you got this running, then you add all the other special functionalities.- 2 replies
-
- php
- validation
-
(and 2 more)
Tagged with:
-
A redirect is done with a Location header: header('Location: https://yoursite.com/some_page'); exit;
-
Hi, first of all, there's a massive security hole: The Host header is defined by the user and can be set to anything they want. They may very well get through with "localhost", and then they have root access to your database. If you want a debugging mode, make a constant. I don't think the code ever worked, because the $mysqli variable simply isn't accessible from the constructor. The best solution is to actually pass it to the constructor. That's what method parameters are for. Another (rather ugly) solution is to import the global variable with the global keyword or through the $GLOBALS array.
-
Please don't use this die(mysql_error()) stuff. I understand this has almost become a meme in the PHP world, but if you think about it, it's downright harmful. Internal database error messages are not meant for end users. They contain technical information about your database which are simply none of the users' business. When you display them on the screen, you irritate legitimate users and at the same time make life easier for attackers. PHP already has an error mechanism: trigger_error(). This will send the message to the right source according to the PHP configuration. On a development machine, you'll want to see the message right on the screen. In a live environment, you do not want it on the screen but in a log file. But the real solution is of course to drop the legacy functions altogether as already suggested by requinix.
-
As we already said, it doesn't work like that. Using INSERT IGNORE requires a UNIQUE constraint, but you cannot have a UNIQUE constraint which regards multiple columns as one big column. And your check doesn't work when there are multiple requests trying to insert the same value at the same time. Those will all be accepted. However: If you just want a quick hack which works most of the time, you might give this a try. But be aware that you may very well end up with duplicate entries. This is a hack, not a correct solution.
-
Hi, I fear you've chosen a very, very bad tutorial. The whole code is just awful and may only be used as an example of what you should not do: The mysql_* functions are obsolete since more than 10 years and will be removed in the future. Do not use them for new projects! Nowadays, we use PDO or MySQLi. There's no security whatsoever. They just throw everything together to see what happens. If this was on an actual server, it would be compromised in a matter of minutes. There's no formatting, and the mixture of PHP and HTML makes this thing absolutely incomprehensible. I think you should throw this away and not even try to understand it. If you already have tried out databases, wouldn't it make more sense to build upon that and write your own code? I would do this: Create a test database or use your old one. Establish a connection to it with PDO. The link above explains how. Or check out this thread. Make a simple query like SELECT * FROM test. Fetch the rows and display them. (again check the link). Now try some variations: Add a WHERE clause, select specific columns, fetch only one row etc. After this, look at prepared statements as a mechanism to securely pass PHP values to queries. Try this out by passing a value through the URL.