Jump to content

Jacques1

Members
  • Posts

    4,207
  • Joined

  • Last visited

  • Days Won

    209

Everything posted by Jacques1

  1. Variables are case-sensitive, so $row_Recordset1 is not the same as $row_recordset1. But what's much more important: You need to throw away the Dreamweaver stuff and start programming. I totally understand that Dreamweaver is useful for your very first website when you're too afraid to write the HTML markup and PHP code yourself. But you've been doing this for a whole year. Now the auto-generated cruft just gets in your way and prevents you from making progress. And the deprecation problem is not a joke. In 2014, it might have been OK to ignore the advice and keep going. But now PHP 7 is about to be released, and that means a lot of deprecated features (including the old ext/mysql extension) will in fact be removed. The 5.x branch is only supported for 8 more months and will reach end-of-life in 2017.
  2. Are you sure your PHP accepts the deprecated “<?” short tags? This is not the default. Try replacing them with proper “<?php” tags. You also have stray “]” brackets in line 21 and 25. And you keep overwriting your $name variable with different values from $_POST.
  3. Your main problem right now is that your database schema is very poor. Cryptic IDs and language names buried in column names will turn this trivial task into a PITA. So before you do anything, I recommend you fix your database structure. For example: languages - code CHAR(2) PRIMARY KEY (a unique language code, e. g. the two-letter ISO 639-1 code) - name TEXT (e. g. “English”) items (the items to be translated) - id VARCHAR(100) PRIMARY KEY (a textual identifier of the item, e. g. “welcome”) translations - item VARCHAR(100) REFERENCES items (id) - language CHAR(2) REFERENCES languages (code) - translation TEXT - PRIMARY KEY (item, language) So the translations are stored as individual rows and can easily be accessed: item | language | translation --------+----------+---------------- welcome | en | welcome welcome | it | benvenuto welcome | ru | Добро пожаловат SELECT item, translation FROM translations WHERE language = :language_code
  4. $this-> produerMainName = $mainName; You need to get a proper IDE. We can't play the human debugger forever.
  5. That must be the most cumbersome existence check I've ever seen. Why do you want fetchAll() when there's at most one row? Why do you care so much about the fetch style when you just want to know if the result set is empty or not? You just have to check the return value of fetch(). If it's false, there's no row, otherwise there is: $testCompany = 'foo'; $companyStmt = $databaseConnection->prepare(' SELECT 1 FROM companies WHERE company = :company '); $companyStmt->execute([ 'company' => $testCompany ]); $companyExists = (boolean) $companyStmt->fetch(); var_dump($companyExists); Or a slightly cleaner approach using an IN query which already yields a boolean: $testCompany = 'foo'; $companyStmt = $databaseConnection->prepare(' SELECT :company IN ( SELECT company FROM companies ) '); $companyStmt->execute([ 'company' => $testCompany ]); $companyExists = (boolean) $companyStmt->fetchColumn(); var_dump($companyExists);
  6. So the strange hex sequences you talked about in your first post have somehow disappeared, and now all you want to do is convert the input document from ISO 8859-1 (or Windows-1252) to UTF-8? How exactly does iconv() “fail”? No, PHP's file functions are not limited to ASCII. They simply read bytes, so they work for any encoding. This works just fine: <?php header('Content-Type: text/html; charset=utf-8'); $input = file_get_contents('input.html'); $output = utf8_encode($input); echo $output;
  7. The whole IP submission procedure is nonsensical and insecure. What you actually have there is password-based authentication, implemented in a very weird way. Whoever knows the hard-coded “key” can add their IP to the .htaccess file and gain access to the site. So why not drop the whole IP stuff and simply force the user the enter a predefined password? This can be implemented with HTTP Basic Authentication. All you have to do is set up a password database (usually a file called “htpasswd”). When a user initially visits the site, they're asked for the password. After the password has been verified, it's cached for subsequent requests so that the user doesn't have to repeat it. It's also possible to implement passwordless authentication using public-key cryptography, but this might be too advanced for your case.
  8. The PHP_EOL constant represents a newline character (e. g. the ASCII LF character on Linux). This only affects the source code of the HTML document. If you want to start a new line in your rendered document, you need an HTML line break element: <br>. Or better yet, use lists.
  9. By far the easiest approach is Ajax, because that's literally just a few lines of code with no special setup whatsoever. You actually just need one timestamp column and one boolean column to indicate whether the user supports the JavaScript heartbeat feature. The query to select the currently active users would then look like this: SELECT user_id -- or whatever you need FROM users WHERE last_activity >= IF(supports_heartbeat, NOW() - INTERVAL 10 SECOND, NOW() - INTERVAL 15 MINUTE) ; You do the update in every script whenever you resume an active session. Then you'll cover both page views (GET requests) and actions (POST requests). The user is considered offline in one of those three cases: they explicitly log out they support the heartbeat feature but haven't sent a heartbeat within the last 10 seconds they don't support the heartbeat feature and haven't made a request within the last 15 minutes If JavaScript is blocked, the heartbeat feature will simply not be activated. Closing the browser has no effect, because there may still be other tabs/windows, maybe even in a different browser. The implementation is very easy and straightforward, so I'd just give it a try.
  10. I'd approach this from two directions: First off, you should have a timestamp column which you update whenever the user makes a standard HTTP request. On logout, you set the value to NULL. If the last update is within a certain time frame (e. g. 15 minutes), you consider the user active. Additionally, you should implement a “heartbeat” function in JavaScript. This function periodically makes an Ajax request (e. g. every 5 seconds), and the server saves the current timestamp in an additional column. If the last update is within a certain time frame, you consider the user active. The benefit of using both approaches at the same time is that the status is more accurate if JavaScript is turned on, but it still works if JavaScript is blocked.
  11. Have you checked your HTML markup with the above W3C validator? It has 61 errors and triggers 134 warnings, so it's definitely not properly written. What I meant by XHTML is this: You use the XHTML 1.0 doctype, so your document is supposed to be an XHTML document. But instead of actually serving it as application/xhtml+xml, you serve it as text/html and degrade it to HTML. But it's not valid HTML either. It's tag soup. By the way: If you really used XHTML (which you don't), your website wouldn't even be displayed, because XML parsers are extremely strict and don't accept errors. The only reason why you see the page content at all is because it's processed as HTML, and HTML parsers accept pretty much everything. In any case: I strongly recommend that you choose one HTML flavor (I suggest plain HTML) and then fix your document accordingly. You currently have two head elements, so there's obviously something wrong with the way you generate the output with PHP. Avoid ancient attributes like align. Avoid cluttering your markup with inline styles and inline scripts. Use external files instead. And in the case of CSS, use selectors instead of styling every single element. Avoid (mis-)using tables for layout purposes. I understand that it's very convenient, but tables are meant for tabular data, not layouting (use CSS instead). The broken markup isn't necessarily top priority, but you should definitely fix it before the release. Don't rely on browsers to guess what you mean.
  12. Like I said, PHP is a loosely typed language. Implicit type conversion is really the core feature of this language. So, yes, you'll definitely need to take a different approach. Instead of relying on type detection magic, make an explicit distinction between your two cases (maybe a flag will help, maybe you should use two separate functions).
  13. This has nothing to do with is_string() or gettype(). It's simply how arrays work: When you use a string key which happens to be a valid decimal representation, the key is automatically converted to an integer. Why is this a problem? In other words, why do you insist on distinguishing between integers and decimal strings? PHP is a loosely typed language, so this shouldn't matter at all.
  14. This is an HTML markup validator; it has nothing to do with form validation. Why would you want to install this on your server? If you want to validate your markup, simply use the public W3C validator. Or even better: Learn HTML. Currently, you write tag soup. You claim to use XHTML (which is a very strict and very exotic XML-based language), but then you actually send tons of broken plain HTML. I suggest you forget about this XHTML stuff (you never used it in the first place) and write valid HTML: <!DOCTYPE HTML> <html lang="en"> <head> <meta charset="utf-8"> <title>Page title</title> </head> <body> <!-- content goes here --> </body> </html>
  15. You also have to change the encoding of the database connection to UTF-8. This is done with the charset attribute of the PDO DSN string: $dSN = 'mysql:host=localhost;dbname=testdb;charset=UTF8'; $databaseConnection = new PDO($dSN, ...);
  16. You haven't really solved anything, because the code has fundamental problems beyond this little redirect issue. Your code has a time-of-check-to-time-of-use defect (like in your previous thread, by the way): You first check the current warning counter, and if it's below the limit, you allow the user to log in. But who says there haven't been any attempts in the meantime? If an attacker sends a large number of concurrent requests, your application will accept all of them, because it still “sees” the old counter value. After a short while, the counter will be incremented, but then it's already too late. Banning IP addresses is a bad idea, because it doesn't stop attackers and at the same time hurts legitimate users. An attacker can easily switch to a different IP address and start over (botnets are cheap, and there are countless public proxies). But a legitimate user normally uses just a few IP addresses which may be shared by thousands of other people. If one person exceeds the log-in limit, everybody will be banned for an entire month. In other words: After a short while, you'll have locked out half of the world population. This makes no sense whatsoever. The whole implementation is very cumbersome with lots of duplicate code and no clear structure. Personally, I think that brute-force checks are rather pointless and give users a false sense of security. Anyway, if you insist on implementing this, you need a very different approach: Assign a counter to each user account, not each IP address. In addition to that, you could maintain a global counter to recognize attacks against multiple accounts. Apply a less user-hostile form of protection. For example: Instead of banning people, make them solve CAPTCHAs. Or implement small delays. If you insist on bans, use realistic time limits (not a whole month!) and give your users a chance to unlock their account (e. g. via the I-forgot-my-password procedure). The check and the increment of the counter must happen in a single atomic operation so that the limit cannot be circumvented with concurrent requests. For example: // update the counter, and simultaneously save the new value in a user variable $updateLoginAttemptsStmt = $databaseConnection->prepare(' UPDATE users SET login_attempts = (@login_attempts := login_attempts + 1) WHERE user_id = :user_id '); $updateLoginAttemptsStmt->execute([ 'user_id' => $userID, ]); // get the counter value of the previous operation $loginAttempts = $databaseConnection->query('SELECT @login_attempts')->fetchColumn(); if ($loginAttempts <= MAX_LOGIN_ATTEMPTS) { // user may try to log-in } else { echo 'You have exceeded the maximum number of log-in attempts.'; }
  17. Works fine for me in Firefox 42 and Chromium: https://jsfiddle.net/mmm69xfo/ Which browser are you using?
  18. There is no quick solution and no step-by-step guide. You'll actually have to write the code yourself. I'm also not sure why you're so obsessed with JSON. That's just a data format, it doesn't do anything. Whether you use JSON or XML or whatever is an implementation detail and completely irrelevant at this point. You can worry about it later. I'd approach this problem top down. That is, you first need to know what you want. Since your initial description is very vague, I'm not sure if that's the case. The next step is to come up with a sensible high-level architecture. Who provides data for whom? And finally you take care of the implementation. You seem to have it backwards. You're throwing around buzzwords like “REST” or “JSON”, but there's no clear goal beyond “site B shows content from site A” (which applies to roughly 99% of the WWW). And some parts of your description don't really make sense. You've said you don't want your admin users to see your code. What code? And why would they see it?
  19. <?php const DATABASE_DATE_FORMAT = 'Y-m-d'; $input_date = '2015-11-25'; $utc = new DateTimeZone('UTC'); $date = DateTime::createFromFormat(DATABASE_DATE_FORMAT, $input_date, $utc); $output_format = 'm-d-Y'; echo 'Formatted: '.$date->format($output_format);
  20. That's the plan (see reply #2). Except that I'd explicitly parse the input date rather than relying on PHP to figure out the right format.
  21. First off: If the OP chooses your approach, that means he has to go through every single date expression in every single SELECT query and replace the expression with DATE_FORMAT(date, <hard-coded format>). That's already bad enough. But it gets even worse if he decides to replace his personal date format with a different format to make his application ready for the Internet. Now he again has to go through all queries to change the hard-coded format. And that's still just a single hard-coded format. To make the format dynamic or support multiple formats, he needs a prepared statement only to pass the date format to the database system. And what if the same date is used in different contexts with different formats? It's fairly common to fetch data once and then use it multiple times for all kinds of purposes. That's why you should separate the data from the presentation. Rendering dates in different formats is a presentation issue and should be done by the application. The database system only provides an abstract calendar date (which happens to be stored in some SQL-specific format). Only if you accept the metric system.
  22. Your date format is fine. The reply was directed more towards benanamen.
  23. Rendering data is the job of the application. As soon as the OP realizes that there's a world outside of the USA (just kidding), the date format becomes user-dependend. With your approach, that means he'll have to assemble the format in the application, then pass it to the database in every single query to get pre-rendered dates and finally display the dates. It makes a lot more sense to simply get the dates and then render them in whatever way he likes.
  24. Check the manual. The date() function expects a Unix timestamp (i. e. an integer) as the second argument. The hacky approach would be to pass your input date to strtotime(), hope that this function will recognize the format and then pass the resulting Unix timestamp to date(). The correct approach is to actually parse the input date using the date format of MySQL and then reformat the date.
  25. The strtolower() function expects a single ASCII-encoded string. You cannot apply it to an array (but you can use array_map() to apply a function to every element of an array). But why would you even want to make your array elements all-lowercase whenever you access the array? You should already store them this way. Simply write down the URLs with lowercase characters.
×
×
  • 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.