-
Posts
4,207 -
Joined
-
Last visited
-
Days Won
209
Everything posted by Jacques1
-
What errors? This is a plain for loop which is one of the basic features of virtually every language. No offense, but if you know neither PHP nor Perl nor the basics of programming, this task will be tough.
-
You can reuse a variable as often as you want. However, “fn” isn't exactly a particularly meaningful name. This may be OK if your code is so short that one can derive the meaning from the context, but it's generally a good idea to give your variables proper names which speak for themselves. You do a lot of copypasting? That's a bad sign. Use functions to avoid repeating the same logic over and over again. Note that PHP itself has a lot of functions that may be useful. For example, cumbersome low-level file access can often be replaced with a single file_get_contents() or file_put_contents() call.
-
It's the ternary operator. Perl has it as well. The expression $c ? $r_1 : $r_2 yields the value of $r_1 if $c evaluates to true, otherwise it yields the value of $r_2.
-
The script waits until it's allowed to lock the file.
-
C'mon, you've been doing this long enough to understand that “doesn't work” isn't regarded as a valid problem description. When I run your code with error reporting turned on, I get this message: Notice: Object of class DateTime could not be converted to int in [path to script] on line 12 And line 12 is this: for($start_hour; $start_hour <= $end_hour; $start_hour->modify("+60 minutes"));{ Hint: It's the $start_hour <= $end_hour expression. You cannot compare a DateTime object ($start_hour) with an integer ($end_hour). What you can do, though, is compare two DateTime instances. Or you can compare the return value of the getTimestamp() method with another Unix timestamp.
-
“Doesn't work”? What does that mean? You'll have to be more specific. Do you get no result file at all, or are you simply not happy with the file? Are you getting any PHP errors either on the screen or in the error log? Since I have zero information, I'll simply make a guess: You don't get any file at all. Replace the relative upload path (relative to what?) with an absolute path and make sure that PHP actually has write permissions to that folder.
-
PHP actually tells you the exact reason for the error. Activate error reporting (if you haven't already), activate logging, run the script and then check your error log.
-
Only to clarify: The ampersand problem cannot be solved with URL-encoding. If you encode the ampersand, then it loses its functionality. What I meant is that you might want to replace the hard-coded URLs with an intelligent mechanism which takes care of all the low-level details: HTML-escaping of the entire URL (to prevent syntax issues like the ambiguous ampersand), URL-encoding of individual parameters, maybe custom resolution of relative URLs. A simple URL function could look something like this: function app_url($base_url, $parameters = null) { $url = $base_url; if ($parameters) { $url .= '?' . http_build_query($parameters); } return $url; } The http_build_query() function automatically URL-encodes the parameters, so you don't have to do that by hand. Then you simply HTML-escape the whole URL. If you use a template engine like Twig rather than plain PHP, you can leave that job to the engine. For example, your HTML snippet above would look like this: <a href="{{ app_url('record.php', {'id': 4, 'user': 'smith'}) }}"></a> This gives me a correctly encoded, correctly escaped URL, and I don't have to worry about any syntax problems. Of course the benefit is less obvious with simple static URLs that don't have any special characters. Those might as well be prepared by hand. But as your application becomes more complex, it's a good idea to actually solve the problem once and for all.
-
What exactly is your job, .josh? Pop up every few months to publicly bitch about other members? If you have some personal issues with me, send me a private message.
-
You cannot use “~” in fopen() at all. It's not evaluated.
-
You cannot use “~” in fopen().
-
A better way of looping using foreach and switch
Jacques1 replied to AdRock's topic in PHP Coding Help
You didn't think AdRock is intelligent enough to write that down himself? -
Personally, I prefer a simple rule (all literal ampersands must be encoded) over the highly complex ruleset for ambiguous ampersands which differs across HTML versions (and possibly browsers) and was revised several times. Hard-coded URLs aren't a particularly good idea, anyway. How do you do URL-encoding? By hand? How do you reference files in higher directories? By travelling all the way up from the current file? If you just have a bunch of small PHP scripts, this may be good enough. But for anything more complex, I'd think about a proper URL function.
-
You don't have to change anything about the functions. As the names already say, they generate random strings. How this is implemented is irrelevant for now. All you have to do is call random_hex_bytes(16) to get a random filename consisting of 32 hexadecimal characters. Then you build the complete target path of the uploaded file and move it to that location. It should be fairly simple to put this into your code. You just have to change the part where you set the filename.
-
A better way of looping using foreach and switch
Jacques1 replied to AdRock's topic in PHP Coding Help
I only see 2 arrays, not 4. Anyway, all you need to do is create a lookup table which maps each (type, archived) combination to a destination. This is typically done with an associative array: <?php $target_categories = array( 'post' => array( 0 => 'foo', 1 => 'bar', ), 'event' => array( 0 => 'qux', 1 => 'quux', ), ); Or you just store the rows in this nested structure and skip the mapping part. -
If you have a question, then ask. I'll try to clarify. But if you reject the entire reply and expect me to repeat everything in a more newbie-friendly way (whatever that means), it looks like you just want to avoid any effort on your part. You asked how to prevent files from being overwritten. I suggested random filenames and gave you a function to generate those names. So step 1 is to use this function in your code.
-
Do not adopt the user-provided filename at all. This may be interesting meta information to be stored in the database, but it's not suitable for the actual file on your server. Instead, generate a purely random filename or use a reliable number sequence (e. g. an AUTO_INCREMENT column). For example, I usually read 16 bytes from the random number generator of the operating system and encode them as 32 hexadecimal bytes. This gives me unique filenames and eliminates the problem of file collisions. <?php function random_bytes($number_of_bytes) { if (!$number_of_bytes) { trigger_error('Invalid number of bytes.', E_USER_WARNING); return false; } $random_bytes = null; if (function_exists('mcrypt_create_iv')) { $random_bytes = mcrypt_create_iv($number_of_bytes, MCRYPT_DEV_URANDOM); } elseif (function_exists('openssl_random_pseudo_bytes')) { $random_bytes = openssl_random_pseudo_bytes($number_of_bytes); } else { $random_bytes = @file_get_contents('/dev/urandom', false, null, 0, $number_of_bytes); } if ($random_bytes) { return $random_bytes; } else { trigger_error('Failed to generate random bytes.', E_USER_WARNING); return false; } } function random_hex_bytes($number_of_bytes) { return bin2hex(random_bytes($number_of_bytes)); } echo random_hex_bytes(16); You also need to start thinking about security. Right now, you let anybody upload any file to your server. This is a very bad idea. What if the file is a malicious PHP script? What if it's an HTML document which contains malicious JavaScript code? Since you appearently want people to upload images, create a list of acceptable file extensions (“.jpg”, “.png” etc.) and only allow uploads with a correct extension.
-
After match, lookbehind and get some of that too...
Jacques1 replied to mentalist's topic in Regex Help
I understand that you like regexes and want to use them for this task, but they're simply not the right tool. Not even by the lowest standards. Comments are just one “anomaly”. You may also run into ID selectors or URL fragments or whatever. The whole thing is basically a shot in the dark. And since you've made the task even more complex, I fearly you'll quickly end up with a complete mess of buggy, unreadable regexes which nobody can possibly maintain. For what? CSS is an actual language, it has a very specific structure. So what you should do is grab a CSS parser (there are plenty) and make it build a syntax tree. This gives you all the data you need in the right context. -
Writing form output directly to CSV file, bad practice?
Jacques1 replied to garek007's topic in PHP Coding Help
Only the flag. MySQL takes care of all the low-level details. All you need to do is insert the row. -
Writing form output directly to CSV file, bad practice?
Jacques1 replied to garek007's topic in PHP Coding Help
If you want to append data to the same file, you need to at least use an exclusive lock to coordinate write attempts: <?php $user_csv_path = '/path/to/csv'; $user_csv = fopen($user_csv_path, 'a'); if ($user_csv) { /* * Request an exclusive lock on the file. If the file is already locked, * PHP will wait. You may want to cancel the operation instead and ask the * user to retry. In that case, set the LOCK_NB flag. Note, however, that it * doesn't work on Windows. */ if (flock($user_csv, LOCK_EX)) { $data = array('foo', 'bar'); // write to file fputcsv($user_csv, $data); flock($user_csv, LOCK_UN); } else { trigger_error('Failed to obtain exclusive lock on file ' . $user_csv_path); } fclose($user_csv); } else { trigger_error('Failed to open or create file ' . $user_csv_path); } -
Help for writing code without mysql_result
Jacques1 replied to yathrakaaran's topic in PHP Coding Help
Actually, I wonder where you've dug out this addslashes() and mysql_result() stuff. We abandoned that somewhere in the early 2000s together with Netscape Navigator and Java applets. So whatever book or online tutorial or whatever you're currently using: You'll need a new one which reflects today's technology, not the web as it was back in 2000. Quite a lot has changed since. Switching to MySQLi is a good start. However, it's not enough to merely append an “i” to the function names and fix some mysql_result() calls. You'll need to unlearn a lot of old nonsense and learn more modern techniques. Printing MySQL error messages directly on the screen may have been acceptable back in the days of personal home pages, but nowadays, people don't want to be greeted with cryptic warnings about your database issues. What are they supposed to do with this information? Debugging is your job, not theirs. In fact, it might not be the best idea to inform the whole world about your server setup and your database structure. addslashes() was never an acceptable way of escaping values. What this incredibly stupid function does is look for some ASCII characters and blindly prepend an ASCII backslash. What if the input is not ASCII? Then you have a problem. Escaping always depends on the character encoding of the input, which is why PHP introduced the mysql_real_escape_string() function back in 2002. The MySQLi equivalent would be mysqli_real_escape_string(). But like KevinM1 already said, a much more secure alternative is to use prepared statements. A sanitized version of the above code would looks something like this: <?php /* * Make MySQLi throw an exception in case on an error. This way we don't have * to manually check every single action. */ $mysqli_driver = new mysqli_driver(); $mysqli_driver->report_mode = MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT; $database = new mysqli('YOUR_HOST', 'YOUR_USER', 'YOUR_PASSWORD', 'YOUR_DATABASE'); $photos_count_stmt = $database->prepare(' SELECT COUNT(*) FROM gallery_photos WHERE category_name = ? '); $photos_count_stmt->bind_param('s', $category_name); $photos_count_stmt->execute(); $photos_count_stmt->bind_result($photos_count); $photos_count_stmt->fetch(); // the count is now stored in $photos_acount -
Using variable in mysql_query WHERE statement not working
Jacques1 replied to sleepyw's topic in PHP Coding Help
This all doesn't make a lot of sense. First of all, never insert raw user input into a query string. This allows anybody to manipulate the query and fetch sensitive data or even take over your entire server. See SQL injection attacks. This very bug may also be the reason for the errors (whatever those are), because dropping some random PHP variable into a query typically breaks the SQL syntax. Secondly, the mysql_* functions you're using are obsolete since more than 10 years and will be removed in one of the next PHP releases. Didn't you see the big red warnings in the PHP manual? Nowadays, we use PDO or MySQLi. I strongly recommend PDO. Both interfaces support prepared statements as a secure way of passing values from PHP to a query. You're also missing a single quote at the beginning of the query string, and you cannot have embedded variables in a single-quoted query (but since this is wrong in any case, it doesn't really matter). My suggestion would be: Throw away the code, learn PDO and start over. It makes little sense to repair code which was dead on arrival. -
Is it? So far, I've only found three cases where prepared statements in PDO are not supported: Ancient MySQL versions before the year 2004. Ancient PostgreSQL versions before the year 2003. The experimental DBLIB driver. Have you encountered any of those in real life? I haven't. And if there actually are people trying to use PDO with a 10-year-old database system or an experimental driver, I think that's the problem.
-
There are actually two problems: You're violating the basic principles of HTTP. You have no protection against Cross-Site Request Forgery (CSRF) in place. Additionally, you may be vulnerable to Clickjacking. First of all, visiting a URL (or in more technical terms: using the GET method) should not result in any significant data changes. The GET method is strictly for fetching a resource – hence the name. To change data, you need to use the POST method. Triggering actions directly through the URL may be convenient for you, but it's generally a very bad idea: What if the user reloads the page? What if they bookmark the URL? And of course it's very easy for an attacker to make the browser or the user visit the URL. So before anything else, you need to fix those design errors. Then it's time to take care of CSRF protection: Right now, an attacker can trigger arbitrary actions of behalf of another user if they set up a form pointing to your site and then trick the victim into submitting this form. The user doesn't even have to actively click on a “submit” button. This can be done automatically with JavaScript, so merely visiting a page with is controlled by the attacker may be enough to fall victim to a CSRF attack. There's also a related attack called Clickjacking: The attacker embeds your site in a frame, hides the frame behind some fake GUI and makes the user interact with your site through this fake GUI. There are several anti-CSRF techniques: You can generate a random token, store it in the user's session and include it as a hidden parameter in every form. When a form is submitted, you only accept the request if the token parameter is present and matches the token in the session. Due to the Same-Origin Policy, attackers generally cannot “see” the embedded tokens, so they are no longer able to forge a form poiting to your site. Instead of storing the token in the session, you can put it into a cookie. This has a similar effect. However, there are some caveats, so it's not recommended unless you fully understand the implications. To protect yourself against clickjacking, there are again some techniques to choose from: Your webserver can set the X-Frame-Options header to prevent your site from being embedded in frames. This is strongly recommended, because it works fairly reliably in all common browsers. You can use a JavaScript-based “frame buster”. However, this obviously doesn't work if JavaScript is turned off. Depending on the technique, you'll either lose the protection, or the site will not be usable at all. So this approach really only makes sense if your site already requires JavaScript to be turned on.
-
No need for any lookaround magic. The general logic is this: You want the string to start with at least one letter followed by at least one number followed by zero or more numbers or letters, or it should start with at least one number followed by at least one letter followed by zero or more numbers or letters. '/\\A(?:[a-z]+\\d+|\\d+[a-z]+)[a-z\\d]*\\z/i' (I've interpreted “letters” as “letters from the Latin alphabet”)