Jump to content

Jacques1

Members
  • Posts

    4,207
  • Joined

  • Last visited

  • Days Won

    209

Everything posted by Jacques1

  1. You shouldn't replace the error setting. You should have both: Turn off emulation, turn on exceptions. Also consider setting the default fetch mode (e. g. to PDO::FETCH_ASSOC). Now you need two separate MATCH conditions (as explained above): WHERE MATCH (items.item_title) AGAINST (:title_query IN BOOLEAN MODE) OR MATCH (brands.brand_name) AGAINST (:brand_query IN BOOLEAN MODE) You need two parameters :title_query and :brand_query, because the same parameter may not appear more than once. But of course you can bind the exact same string $search_query to both parameters.
  2. Yes, but you shouldn't create the wrapper in the constructor, you should receive it as an argument. There I plenty of useful methods I could think of. In your case, a fetchOne() method (a combined prepare/execute/fetch) will effectively eliminate all database-related duplicate code. You can then concentrate on the // do other task.
  3. I'm not joking. When you provide bad example code, you're likely to get bad advice. Garbage in, garbage out. A PDO helper method belongs into a PDO helper class where it can be used everywhere. Putting it into some other class means you'll quickly end up with dozens of specialized helper methods all over the place. So you'll eventually create more duplicate code, not less. class Database { protected $connection; public function __construct($connection) { $this->connection = $connection; } public function execute($query, $parameters = []) { if ($parameters == []) { return $this->connection->query($query); } else { $stmt = $this->connection->prepare($query); $stmt->execute($parameters); return $stmt; } } }
  4. You still have the nonsensical “additional data”. You're using magical return values (false) to indicate errors. This is bad, because it forces the caller to manually check for those return values and increases the risk of missing the error altogether. PHP code in general and critical code in particular should throw exceptions. The class should generally perform a lot more validation. For example, the $filename of the key is currently an arbitrary string which is just appended to the directory. So if the caller asks for /etc/passwd, that's what they get – which is clearly not acceptable. Come up with a sensible pattern for the key identifier (e.g. [a-zA-Z][a-zA-Z0-9]*) and reject anything else. If you're using PHP 7, consider adding type annotations to the method signatures for automatic type validation. Also consider switching to the PSR coding standards. For example, underscore prefixes for protected/private methods are long obsolete, because PHP now has explicit keywords for that. In the long run, the file operations should be in a seperate class so that the crypto class isn't bound to one particular way of storing the keys.
  5. It does match in PHP: <?php const PHONE_REGEX = '/\\A(?:\\+?234|0)?(?:704|803)\\d{7}\\z/'; $input = '2347048134704'; var_dump( preg_match(PHONE_REGEX, $input) ); Every regex engine has its own syntax flavor, and those backslash escapes won't work well outside of a PHP string. So test this with PHP, not some regex site.
  6. It's impossible to tell from your foobar example class. If this class is specifically designed as a PDO wrapper, the code can make a lot of sense. Otherwise it's probably wrong.
  7. You don't call the constructor in other methods. The sole purpose of the constructor is to initialize the object right after it has been created (hence the name), and doing this multiple times can go horribly wrong. Either simply copy and paste the auth check. Or create an extra method which is called in both the constructor and other methods. Actually, an auth check in the constructor doesn't make a lot of sense to begin with.
  8. That's because you're using emulated prepared statements (which is the default). Turn off PDO::ATTR_EMULATE_PREPARES. Your query doesn't involve multiple tables, so there's nothing to be shown. Post the failing query.
  9. The regex syntax is all over the place, and you don't have anchors to prevent matches somewhere in the middle of the input. [+234|234|0] makes no sense. The square brackets denote a list of characters, but you want alternatives: (?:\\+?234|0). Read: Either an optional plus sign followed by 234, or the digit 0. The + character is a meta character in regular expressions and must be escaped. Use the \\A and \\z anchors to match the beginning and end of the input. /\\A(?:\\+?234|0)?(?:704|...)\\d{7}\\z/
  10. I already pointed you to the PHPMailer library. Either learn the basics of PHP and then write your own code. Or hire a professional programmer. Stealing code from random websites and then selling it to your customers when you have no idea what that code does can get you into deep trouble. It's also simply unprofessional.
  11. The whole purpose of prepared statements is that you pass your input to predefined parameters and prevent SQL injections altogether: // a static query template with three parameters: search_query, limit, offset $items_stmt = $db->prepare('SELECT ... AGAINST(:search_query IN BOOLEAN MODE) ORDER BY ... LIMIT :limit OFFSET :offset'); // bind values to the parameters and execute the statement $items_stmt->execute([ 'search_query' => $_GET['sq'], 'limit' => $limit, 'offset' => $offset, ]); So the query is a constant string. Do not assemble dynamic queries from user input, not even when you think you've “sanitized” it. Correct. That's why you need to split the condition into one MATCH ... AGAINST per table and connect them again with OR.
  12. And “not working” means what? The code has all kinds of issues, and I strongly recommend you keep it offline until it's actually ready for production. A live alpha test on the Internet can go horribly wrong. The code is vulnerable to mail header injections, which effectively allows anybody to use your server as an open mail relay and send arbitrary messages (e. g. spam) to arbitrary addresses. Your message is also vulnerable to cross-site scripting attacks (e. g. injection of malicious JavaScript code). Why on earth would you put the passwords of your users and other personal data into a plaintext e-mail? Putting a firstname into the From header makes no sense. The e-mail is coming from your server, so you must use your own address. Use Reply-To if you want to include the user's address. The mail() function in general is bad, because it's far too low-level for the average programmer and the reason for many vulnerabilities. Use a proper mail library and learn the basics of security (escaping, handling passwords etc.). The Internet is in fact open to everybody, not just nice people.
  13. GFY. He walked you through the entire process and explained exactly what you need to do, and now you complain that he doesn't fix the code for you? Do you need help finding the quotes on your keyboard, or what?
  14. <?php $raw_data = ...; $structured_data = []; foreach ($raw_data as $entry) { $structured_data[$entry['state']][$entry['county']][] = $entry['zipcode']; } var_dump($structured_data);
  15. The code is vulnerable to file inclusion attacks: The page ......../path/to/malware is mapped to the path /path/to/malware.php If your server configuration allows remote includes, it's also possible to inject arbitrary code from other servers. Accepting user-provided paths should be avoided at all costs: Whenever possible, the user should only be able to choose from a predefined whitelist of possible paths (like in Destramic's switch statement). If you absolutely must have dynamic paths, then validate the input against a small whitelist of allowed characters (e. g. a-zA-Z0-9_). Reject wrong input, don't try to fix it, because this often goes wrong. Either you've overlooked something, or PHP itself chokes on the input (not long ago, a path could be truncated simply by inserting a NUL character). Instead of the switch statement, you could also use an associative array to map page names to scripts: <?php // mapping of page names to scripts; this also acts as a whitelist of allowed scripts const PAGES = [ 'about' => 'about.php', 'contact_us' => 'contact_us', ]; if (isset($_GET['nav'])) { if (array_key_exists($_GET['nav'], PAGES)) { require __DIR__.'/'.PAGES[$_GET['nav']]; } else { require __DIR__.'/error.php'; } } else { require __DIR__.'/default.php'; } However, none of this will solve your original problem. If you want help with that, you'll need to be more specific. Do you execute the code twice on the server and then literally hide one of the two page sections? Then the error might be caused by naming collisions due to the double inclusions. This would be a bad approach in general, because rendering and sending the exact content is obviously a waste of resources. Check the error log for the exact message and provide the surrounding code so that we can see the context.
  16. My point is that you should have a single class which takes care of the basic crypto infrastructure (key management, algorithm selection, calling libsodium methods, parsing etc.) and provides a simple encrypt($plaintext) and a decrypt($ciphertext) method. On top of that class, you can then build specific security features like encrypted sessions. Right now, all the low-level cryptography happens in the individual feature classes. This isn't sensible, because the basic steps are always the same: Generate a nonce, call the ChaCha20 method etc. So instead of repeating them for every feature, put them into a common class. You must still hash your passwords. Encryption alone is dangerous, because if an attacker manages to obtain the key, they suddenly have an entire database of plaintext passwords. What you can of course do is hash the password and additionally encrypt the hash. This is valid and can provide more security than hashing alone. Encrypting cookies only makes sense if they contain sensitive data – which they really shouldn't. If you just want to prevent users from changing the data, an HMAC is more appropriate. This is essentially a “signature”. In short: confidentiality without integrity/authenticity (not recommended) ⇒ classical encryption, e. g. AES-CBC confidentiality with integrity/authenticity ⇒ authenticated encryption, e. g. ChaCha20 + Poly1305 integrity/authenticity without confidentiality ⇒ HMAC passwords ⇒ password hash algorithm, e. g. bcrypt; optionally encryption In any case, don't overestimate the security of your features, especially since your resources and your experience are limited. There can always be fatal flaws, so expect the worst and write your application as if there were no cryptographic features.
  17. The class architecture doesn't really make sense. There should be one class which takes care of all the low-level cryptography. If you call the libsodium functions in the different subclasses for encrypting sessions, cookies etc., you'll quickly end up with duplicate code. From a cryptography standpoint, there's no difference between encrypting a session and encrypting a cookie. It's just different data. Get rid of the try statements. Not only are they useless and make you lose important information like the error location and the stack trace. They defeat the whole purpose of exceptions, because now you're back having to check return values. It's particularly strange when you throw an exception and then immediately catch it. A low-level cryptography class should not do any JSON-encoding. In fact, you're making the data ambiguous, because it's no longer clear whether it's actually a JSON document or just happens to look like the JSON format. Who says that [42] is a JSON array? Maybe it's supposed to be a literal pair of brackets with a number. Do all the encoding and decoding outside of the class. The angle brackets <> in my format were meant for you, the reader. The actual format is just a colon-separated list of parameters. Since you now use a fixed algorithm, there's no need for a version. If you still want to use versions, don't compare them with < or >, because those operators don't understand the semantics of version numbers. For example, "2.0.0" is considered greater than "10.0.0". It also doesn't really make sense to reject a ciphertext just because there was an unrelated change somewhere in the libsodium library. Your “additional data” parameter for the AEAD algorithm is currently a long random string. This makes no sense. The purpose of the parameter is that you can split the input into two parts: a secret part which should be encrypted and protected from manipulation, and a non-secret part which should only be protected from manipulation. If you don't need this (which is most of the time), simply use an empty string as the additional data. The naming isn't ideal. “get_encryption” and “get_decryption” don't make much sense. When you remove the JSON stuff, you can probably get rid of get_decryption() altogether. And get_encryption() should be renamed to something like parse_ciphertext().
  18. The date() function expects a Unix timestamp (i. e. an integer) as the second parameter. See the PHP manual. Your $start_date is appearently not a Unix timestamp. It may be a MySQL DATE which must be parsed before it can be converted. There may be a WordPress function for it. Otherwise you'll have to parse the date yourself and then reformat it. <?php const MYSQL_DATE_FORMAT = 'Y-m-d'; $input = '2016-08-30'; echo DateTime::createFromFormat(MYSQL_DATE_FORMAT, $input)->format('F d, Y');
  19. Is this a question? A statement?
  20. The code is OK, but it relies on implementation details and may break when libsodium changes its default algorithms. Since the encryption function simply concatenates the nonce and the ciphertext to produce the output, the only way to tell those substrings apart is to rely on a specific length of the nonce. But this length may change at any time. When it does, your application won't be able to decrypt anything until you've figured out which libsodium version you need for your legacy ciphertexts. A more robust and future-proof solution would be to store the nonce and the ciphertext in separate fields and add an extra column for some kind of algorithm identifier (or the libsodium version): \Sodium\version_string(); Alternatively, use a specific algorithm so that you're not dependent on any defaults. If you need a single string, choose an unambiguous format. For example: <version identifier>:<Base64-encoded nonce>:<Base64-encoded ciphertext>
  21. Both forms do exactly the same: The data is submitted to the action URL, which causes that page to be loaded. The problem of your main site is that your navigation is implemented purely with JavaScript. When the target page is loaded, this also resets the JavaScript state. There are two options to fix this: Instead of using classical form submission, you submit the data with Ajax. You change the URL with JavaScript whenever you switch to a different page (via the History API) and make the pages directly accessible through those URLs. For example, the contact page would get the URL /index.php?page=contact. Then you can jump to one specific page in your form. The first one is propably what you want.
  22. If you can't get this to work in your IDE, consider switching to XDebug and a mainstream IDE. PhpStorm is great (but expensive), Netbeans is fine.
  23. It's Poisson distribution, not “possession distribution”. The source code.
  24. We've proposed three different solutions. So what exactly is wrong with those? And as a fourth option, PHP has a statistics extension with a function for calculating the Poisson distribution.
  25. This is about forum posts with embedded BBCodes. As in: foo [url]https://www.youtube.com/watch?v=ABC123[/url] bar [url]http://www.google.com/watch?q=SQL REPLACE[/url] baz Your query would replace every single tag if only the post happens to contain a www.youtube.com somewhere (even outside of tags). @indie: /\[url\](https:\/\/www.youtube.com\/watch\?[^\[]+)\[\/url\]/i Meta characters like square brackets or question marks must be escaped when they're supposed to be literal characters. The actual URL is then available in the first capturing group and can be reinserted into the replace pattern.
×
×
  • 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.