
Psycho
Moderators-
Posts
12,164 -
Joined
-
Last visited
-
Days Won
130
Everything posted by Psycho
-
The answer is "it depends". It depends on what you want to do. In Googles case they are apparently maintaining a history of the passwords used. I'm a little surprised by that, but it is not an uncommon process for enterprise level software that prevents users from reusing the last n number of passwords. If you do not plan on utilizing any feature where old passwords are needed then you don't need to maintain that data. The same logic applies to your question regarding the token - with one caveat. DELETE operations are expensive in terms of performance. If you don't need to delete a piece of data, then don't bother. Since the registration and reset processes will both use a token, that means that all users will need a token at some point. Plus, I would assume that no user would ever need two tokens concurrently. To keep things simple, you could simply have a token field in the "user" table. After someone has used a token, set the token field to an empty string or a NULL value (or setting the extirpation date to null or a prior date would work too). I would also expect that you also have some data in the table to know if a user has been registered or not: password confirmed field, registration Boolean, etc. So, when the token is used you could use that data to determine whether to run the registration logic or the password reset logic.
-
Redirect for Directories without index.html
Psycho replied to xProteuSx's topic in Apache HTTP Server
Or you could move these directories to a location that is not publicly accessible and implement a simple "download script" that allows users to access the files. By using a download script you can also implement authentication/logging/ext to add additional security measures if warranted. -
What is the source of these arrays? Are you retrieving data from a database? If so, there will definitely be a better way to combine the data than combining arrays. Also, as others have said, the data has no context. In your example of: [32347] => 8 => 5 => 484 What does the 8, 5 and 484 represent? Besides, your example seems to indicate that you want each value to be a sub array of the preceding value. Perhaps it should look more like this [32347] => (8, 5, 484) Or this: [32347] => ( 'time' =>8, 'amount' =>5, 'foo' => 484 ) With your original data, here is a possible solution <?php $array1 = array(32347 => 8, 22188 => 3, 37493 => 4, 37201 => 7); $array2 = array( array( array(32347, 28470, 35319, 37493), array(5, 2, '', 4), array(484, 383, 315, 320) ) ); $newArray = array(); foreach($array1 as $key => $value) { $newArray[$key][] = $value; foreach($array2 as $subArray) { //extract the first array index (with the keys) $keyArray = array_shift($subArray); //Get the index for the key - if exists $keyIndex = array_search($key, $keyArray); //If the key exists, get the other values in the sub array if($keyIndex !== false) { foreach($subArray as $valuesArray) { if(isset($valuesArray[$keyIndex])) { $newArray[$key][] = $valuesArray[$keyIndex]; } } } } } echo "<pre>" . print_r($newArray, 1) . "</pre>"; ?> Output Array ( [32347] => Array ( [0] => 8 [1] => 5 [2] => 484 ) [22188] => Array ( [0] => 3 ) [37493] => Array ( [0] => 4 [1] => 4 [2] => 320 ) [37201] => Array ( [0] => 7 ) )
-
You state Do you get those results on the same source and destination directories? Aside from your specific issue, I see some things that could be improved. $result = ($dir === false ? false : true); if ($result !== false) { The condition for setting $result will return a Boolean (true/false), so there is no need to create a ternary operator to assigne true/false. Plus, since $result will only be true/false, there is no need for the explicit type check on the if() condition. Additionally, the reuse of $result for many things throughout the logic could lead to confusion. But, more importantly, there is no error handling within the code when errors do occur. So, of course you don't know what the problem may be. One problem in your code that may be the source of the copy problem is the check in the if() condition for $result for the while loop condition. if (( $file != '.' ) && ( $file != '..' ) && $result) Because in the loop there is this: $result = copy($src . '/' . $file,$dst . '/' . $file); If that copy fails for any file it will skip all other files in the source directory because $result will never get reset (i.e. will be false for the rest of the execution). So, my guess is that there is a file that can't be copied for some reason (locked?) that is causing your problems. This is exactly what I was referring to above about reusing the same variable for different things. Here is a quick rewrite that fixes some problems and adds some error handling. This is not ready for production use (should never display system errors to the user), but it should give you an idea of what the problem may be static public function recurse_copy($src, $dst) { $dir = opendir($src); //Open the source directory if (!$dir) { echo "Unable to open source directory '{$src}'"; return false; } //Create the destination directory if (!is_dir($dst)) { if(!@mkdir($dst)) { echo "Unable to create destingation directory '{$dst}'"; return false; } } //Copy the files while(false !== ( $file = readdir($dir)) ) { if (( $file == '.' ) || ( $file == '..' )) { //Skip . and .. continue; } //Create variables instead of concatenating same strings multiple times $srcPath = $src.'/'.$file; $dstPath = $dst.'/'.$file; if ( is_dir($srcPath) ) { $result = self::recurse_copy($srcPath, $dstPath); } else { if(!copy($srcPath, $dstPath)) { echo "Error copying file '{$srcPath}'<br>\n"; } } set_time_limit(5); } closedir($dir); return true; }
-
Should exceptions be thrown based on user input?
Psycho replied to NotionCommotion's topic in PHP Coding Help
Right, but . . . you also have this public function getValidatedData($data) { if(!isset($data['city'])){throw new USERException("City field is missing.");} if(!$this->isACity($data['city'])){throw new USERException("$data[city] is not a valid city.");} // ... return ['city'=>$data['city'],'etc'=>123]; } The FIRST "error" will throw an exception and go strait to the catch condition. In the specific two conditions you gave in the example it is not a problem, because if the value is empty then there is no need to check if the value if valid. But, you follow that with the // ... which I assume to be other form validations. That is where the problem exists. Let's say there was another validation to check the state value. If a user submitted a form with no city and no state, the check for the city field would throw the exception and go to the catch logic. The logic would never validate the state field. What would result is you would provide the user an error message that the city field is required. They then enter a value and submit the form only to then be told that the state is required. Check form submissions for all such validations. Then if any fail, provide the user with a response that shows all the errors to be resolved. Example $errors = array(); $city = trim($_POST['city']); if($city == '') { $errors[] = "City is required"; } elseif(!$this->isACity($city)) { $errors[] = "The selected city is not valid"; } $state = trim($_POST['state']); if($state =='') { $errors[] = "State is required"; } elseif(!$this->isAState($state)) { $errors[] = "The selected state is not valid"; } if(!empty{$errors)) { //Provide all the errors to the user to resolve } else { //All form validations passed, process the data } -
And why is that? You should never run queries in loops as they are expensive from a performance aspect and can bring your site to a crawl based on the amount of data and usage. In this case, you should instead run ONE query for all the applicable user IDs in your list. You are already grouping by the user ID anyway. Plus, the currently query doesn't even use the user ID, so each iteration of the loop is apparently running the exact same query.
-
Should exceptions be thrown based on user input?
Psycho replied to NotionCommotion's topic in PHP Coding Help
Also, there is a usability problem in that code. Form validations should not stop at the first validation error found. It should check for all possible errors and then notify the user of all the problems they need to resolve. -
I'm pretty sure the "visibility: hidden" CSS property will leave the element in the DOM as well as the page will still act as if the element is there. Whereas the "display" attribute removes the element. (or maybe I have those backwards). In any event, I was curious as to how opacity = 0 would differ from visibility = none. For example, I wondered if text could be selected on the page, if it would print, etc. I've found that for opacity=0 and visibility=none the output (mostly) looks and behaves similarly. In both instances the hidden content takes up the space as if it was displayed. However, there is a difference. You CAN select the content that is hidden using opacity=0 whereas the content hidden using the visibility=hidden you cannot. There is one caveat though. You can't select part of that content, you have to select a visible element before and after the content using opacity=0 and the hidden content will also be selected (confirmed via a Copy\Paste). Here's the code I used to test with Display None: [<span style="display: none;">DisplayNone</span>]<br> Visibility Hidden: [<span style="visibility: hidden;">VisibilityHidden</span>]<br> Opacity 0: [<span style="opacity: 0;">Opacity0</span>]<br> Opacity .5: [<span style="opacity: .5;">Opacity.5</span>]<br> I'm not sure I see a definitive use for one vs. the other unless you believe that the user selecting the page content is a legitimate scenario. In which case you would want to use the appropriate style based on whether you wanted them to copy that content or not.
-
Um, you linked to this post. I'm guessing that was a mistake.
-
No disrespect to @maxxd, but there are some details not covered 1. Since OP did not mention if JQuery is being used, I will point that out. The JQuery library will need to be included (if not already) if you want to use JQuery code (which is a good idea to learn anyway) 2. The on() handler requires that the elements have already been initialized before that code is loaded in order to be applied. So, the code would need to be wrapped in a $(document).ready() handler or something similar. 3. The use of opacity seems odd to me. From a CSS perspective the hidden or display attributes would seem more logical options. But, if JQuery is being used there are the built in hide() and show() methods. 4. The biggest issue is that code will only display the element when loc5 is selected. I have to assume that when the user selects any other value the element should go back to being hidden. 5. Lastly, since the values that hide the element can change over time, rather than setting a default display value in CSS and assuming that the initial value will always use that style, I think it would be better to have the change function executed onload. That way if the initial value is one that should be hidden or shown it will be taken care of. For example, if the form is being used to edit an existing record and that record has a value of 5, then the initial state of the 2nd select list should be to be displayed. Here is a fully functioning example script <!DOCTYPE html> <html> <head> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.2/jquery.min.js"></script> <script> $(document).ready(function(){ //Create event handler for onchange event $('#location').on('change',function(){ //Array of values that should hide 2nd element var hiddenVals = ['loc5']; //Change hide/show status of 2nd element if(jQuery.inArray( $(this).val(), hiddenVals ) != -1) { $('#second').show(); } else { $('#second').hide(); } }); //Run event handler on page load $('#location').change(); }); </script> </head> <body> <select id="location" name="drop"> <option value="loc1">Location 1</option> <option value="loc2">Location 2</option> <option value="loc3">Location 3</option> <option value="loc4">Location 4</option> <option value="loc5">Location 5</option> <option value="loc6">Location 6</option> <option value="loc7">Location 7</option> </select> <select id="second" name="term"> <option value="OPT1">Option 1</option> <option value="OPT2">Option 2</option> <option value="OPT3">Option 3</option> <option value="OPT4">Option 4</option> </select> </body> </html>
-
I don't think you read Kicken's response - at least not correctly. In your DATABASE TABLE, you need a field for the time a record is submitted. The field should be a TIMESTAMP field type with a default value of CURRENT_TIMESTAMP. Then, whenever a new record is created, the current timestamp will be populated int he field for that record without having to include any logic in the INSERT query. Then, when you retrieve records you would use that timestamp to determine whether to display the contents or not. You could just query the records that are more than two days old, as Kicken suggests, but I would expect that if a user has submitted a record that the page should let them see that. So, I would query for the record for the user. If none exists, tell them that. If one does exist, check the timestamp. If the timestamp is less than 2 days old, then show a message that their submission is being processed. Else, show the content.
-
Not really. As I stated above, the target for the form already has arguments on the URL and since the method is GET the intent is for the form fields to be appended to the target URL. Of course, you didn't have any form fields, but the scenario does not have strait forward solution. Based on my reading of the official specs for the form method of GET it is ambiguous as to what should exactly happen If the browser was to render the URL exactly to that definition it would be a malformed URL. Example: <form action="http://domain.com/somepage.php?foo=1" method="get"> <input type="text" name="bar" value="2"> If that code was posted and the full URL was compiled per the specs it would end up as domain.com/somepage.php?foo=1?bar=2 So, the application processing the form needs to detect that there is already a question mark in the defined target and make a decision. Either 1) Remove the existing data after the existing question mark and append the form field data or 2) Append the form field data to the full target URL using a plus sign.
-
Have you used var_dump() on $_POST and $_GET to see exactly what is sent? I don't use Apple products, so I can't be sure, but I'm guessing that either the phone OS or the email client on the phone may be filtering the parameters. Most email programs will not show images by default because spammers can attach different parameters (or use slightly different URLs) to the image URL to individually identify which users have opened the emails. Perhaps the behavior you are experiencing is some sort of similar implementation to protect users. Then again, since the method is GET, the intent would be for any form fields to be included in the URL - but you have already included variables in the URL via the action parameter. Perhaps that is causing some confusion in how the form is handled in the email. Why not change the method to POST. There are not fields in the form, so the variables in the action parameter would still be accessed via GET anyway.
-
On the subdomain.domain.com page you've posted above, the code within the if condition ends with the comment // do login I'm assuming there is more code there that you left out for posting purposes. But, what exactly does that code do? Is there an exit or redirect at the end? If not, then the code will proceed on after the code block and display the login form. But, assuming that the rest of that code is perfectly fine, then your problem is likely that the condition check to see if there was a submission is not returning true. Try putting this at the beginning of that page and see what is displayed to verify what data is passed/ received. var_dump($_REQUEST); exit(); Of course, after I just typed all of that, I think I see your problem: $username = $_REQUEST['username ']; There is a space at the end of the array index name - so there is no username for the code to access. This tells me that the logic to perform the login is faulty and is not reporting an error when no username is supplied (either unset or empty). And here's another possible problem: if(isset($_POST['Submit']) && $_POST['Submit'] == "Secure_Login") The code is looking for a variable with the name Submit. However, your form uses a submit button not an input field with a type of submit. I didn't think buttons passed values. But, you shouldn't use the submit button to check if a form was posted anyway. You can check the $_SESSION['REQUEST_METHOD'] to see if a form was POSTed
-
1. This HTML is messed up. The Child UL element is NOT within an LI element. 2. The width of 30% for the nav container causes the parent links to wrap if the page width is not big enough (which will cause further problem with the 'dropdown' child elements). I set it at a fixed 500px to prevent problems in my test code - change to whatever works for you 3. The padding of 50px seems to be excessive. I think that was a mistake. I changed it to 5px Here is your same code with fixes for the above issues. I stripped out all the unrelated elements <html> <head> <style type="text/css"> nav { padding-top:2%; width:500px; height:27px; margin-left:auto; margin-right:auto; } nav ul { list-style-type:none; } nav li { float: left; } nav > ul li a { padding-left: 5px; } nav > ul > li:hover > ul { display:block; } nav > ul > li > ul { display:none; position:absolute; } </style> </head> <body> <header> <nav> <ul> <li><a href="#">Home</a></li> <li><a href="#">About Us</a> <ul> <li><a href="#">Agents</a></li> <li><a href="#">Locations</a></li> </ul> </li> <li><a href="#">Services</a></li> <li><a href="services.php" tabindex="3" accesskey="S">Services</a></li> <li><a href="quote.php" tabindex="4" accesskey="Q">Get A Quote</a></li> <li><a href="contact.php" tabindex="5" accesskey="C">Contact</a></li> </ul> </nav> </header> </body> </html>
-
Requesting multiple data requests in a single REST request
Psycho replied to NotionCommotion's topic in PHP Coding Help
If I am understading the question correctly, I would suggest returning the data in a multi-dimensional array (in JSON or whatever format you want to use) E.g. Sent: {"item":"a", "limit":123} Received: {"john":{"MIN":4,"MAX",18,"SUM",140},"Mary":{"MIN":6,"MAX",12,"SUM",120}} The back-end query would run this $sql="SELECT name, MIN($item) as minVal, MAX($item) as maxVal, SUM($item) as sumVal FROM my_table WHERE $limit<123 GROUP BY name"; . . . or maybe I am not understanding the issue. -
Chrisj, the code you posted is only for the FORM which the user will interact with to send data to the server. So, "yes" to your first question you can add an option like you have shown. But, that is only half of the problem. Somewhere within the "search.php" page (or other code that is included on that page) there is logic to use the data sent by the user. There will be some code that takes the value of $_GET['type'] and uses it to query for the right records. What he provided is only an example as we have no clue how that logic is currently built. You will need to figure that out or at least provide us the relevant code. Look in the "search.php" file for a reference to $_GET['type'] and a query to retrieve the records.
-
So, instead of asking for clarification on the response you were given in another forum, you decided to ask the same question on a different forum. But, I will give you this advice: $username=$_SESSION['username']; $sql=mysql_query("SELECT student_name FROM register WHERE student_username='$username'"); $ee=mysql_fetch_array($sql); ?> <i class="fa fa-folder-open"></i><b> Hello ! </b>Welcome Back <b><?php echo $ee['student_name']; ?> </b> If you want to display the student_name on every/most page(s), then you should be storing that in the session data so you don't need to do a query just to show that data.
-
I wasn't implying you didn't know how to use Google. I didn't know what the problem was at first. What I was trying to highlight was that the key was to identify the source of the problem. It was only by adding additional elements (in this case borders) that allowed me to clearly see what the cause was. Only then was I able to do a Google search with the appropriate terms. As for that properly not being fully supported, I'm not sure how accurate the data is on that page. I "fixed" the issue using that property and tested it in a Chrome browser. But, according to that linked page the property isn't supported in Chrome. I'd suggest testing it on the current versions of the main browsers. The only other solution that comes to mind right now would be to put each anchor within a DIV/SPAN with properties so they won't split across columns. It may take some trial and error.
-
I had no clue that such a CSS property even existed. I just implemented good debugging skills to identify the problem. Then used Google to find a solution. Being a good programmer is not about remembering everything - it's about being able to find a solution. FYI: To identify the problem I put a border around the outside div and a different color border around the anchor tags. When doing that, I was able to "see" what was happening with the rendered content as the page was re-sized. Then I simply did a Google search for "Prevent text breaking across columns". The very first result gave me the answer.
-
It should not be used for password hashing or for verifying data integrity - with respect to potentialy malicious data. MD5 still has legitimate uses and the fact that it is fast is actually a benefit. I have used it many times for various applications: - Checking for duplicate files or if the contents of files have changed - When creating a service that receives data that has complex actions to be performed, I might store an MD5 has on the original data. Then on subsequent receipts check to see if the same data has been received previously (based on the hash). If so, take no action. Otherwise process the data as needed. - Used as a key or token generator It's all about using the right tool for the job. It just so happens that MD5 is no longer the right tool for some jobs. But, it is still regularly mentioned for password hashing in tutorials and forums. So, just saying "don't use it" is the easier approach to help stop that behavior.
-
There are two aspects that cause this problem: 1) As the page gets thinner, so do the columns. When that happens the records with the longer names no longer fit into a column. Before you filter the records, if you make the page narrower, the record "Fiona Joy (aka Fiona Joy Hawkins)" won't fit on a single line and has a line break. However, it stays in the same column only because the columns are so long. If it was the record at the end of the column, it could very well be in two columns. 2) Once the page is filtered with just the long records - if the record needs to break across several lines due to a narrow page, the following lines of text will naturally flow to the next column. Within the artist.css file, find the definition for "#artist_page .artist_full_list a" and add an entry for the "break-inside" property #artist_page .artist_full_list a { display: block; padding: 4px; break-inside: avoid-column; /* ADD THIS */ /*margin: 0 10px 2px 0;*/ } That should make sure that the anchor tags do not flow across multiple columns. It worked on a test page from your code, but I didn't try a lot of different configurations in data.
-
I assume you didn't really mean to hash the last name $lname = md5(mysql_real_escape_string($_POST['lname'])); Just to be clear: MD5 was only "cracked" with respect to collisions. For example, one use for a hash is to provide a hash for a file so that file can be made available for download from multiple independent sites. by performing a hash on the downloaded file and comparing against the hash from the originator you can be assured that the file you downloaded has not been tampered with. The weakness discovered could allow a malicious user to generate another file in such a way as to generate the same hash. No "crack" exists that makes MD5 more susceptible to preimages - i.e. determining the original value from the hash (although it should not be used for passwords for other reasons - see below). The flaw that does exist with MD5 is that it is fast. Therefore, a malicious user can use a brute force approach to run millions/billions of combinations to try and find "a value" that generates the same hash. There is no 100% certainty that the value found that produces the same hash is the exact same source value, but when dealing whith passwords, it doesn't matter. 1) The logic typically is just looking for a source that ultimately creates the same hash, so it doesn't matter if it is really the same password or not. 2) When dealing with passwords, the min-max lengths and the available character set make the universe of possible values a finite number. It would not be impossible to run every possible combination of values (even for different salts) in a reasonable amount of time. Any hashing method can be brute forced - which is why you want to use a method that is slow; so the time required to go through all possible values would take an extraordinary amount of time. That is why users should use complex passwords. If an attacker has a DB full of hashed passwords, they could simply do a brute force using a dictionary attack of common words to find matches.
-
You should NOT have a way to recover passwords. Passwords should only be able to be reset. If they can be recovered, that means that you have the ability to access their password (even if it is encrypted) - which may be used on different sites. That is a significant security flaw. Passwords should be hashed (with an appropriate salt) sometimes referred to a one-way encryption. Even if your site doesn't contain sensitive information, you have a responsibility to your users to strenuously protect their passwords. Many people use the same passwords in multiple places, so if a hacker was to obtain user credentials from your site, they could try the same credentials on other sites (e.g. banking). Note: Do not try to create your own hashing process. Do your research and find one that is already vetted. If a user forgets their password, they should have to "request" a reset by entering their username or email address. That request will send an email (to the registered email for the user account) with a link to reset their password. The link will contain a token that makes it good only a for a limited amount of time. That link will take them to a page where they can answer their security question(s) and then set a new password. Of course, there always needs to be a way (typically through support) to access an account in edge scenarios: someone left the firm, user no longer has that email address, etc. One other thing. The process to request a reset should not leak information. If the user enters a username or email address that does not exist, the response should be the same as if it did. E.g. "An email has been sent to reset your password". If the email does not exist in your system (user entered the wrong email), you could still send an email to the address stating something like "An attempt was made to reset a password using this email address, but it does not exist in our system". Why do all of that? A malicious user could use your password reset request page to data mine email addresses or user IDs by posting values and checking the responses. At best they may just want to have valid emails to spam. At worst, they may be looking for valid user IDs for the purpose of compromising your application.
-
mac_gyver's response was correct, but you may have missed the point when trying to understand it with complex data. Let me give an example Instead of an array like this array( 'AAA' => ( 'week' => 'week1', 'value' => 'valueA' ) 'AAA' => ( 'week' => 'week2', 'value' => 'valueB' ) 'BBB' => ( 'week' => 'week1', 'value' => 'valueC' ) 'BBB' => ( 'week' => 'week2', 'value' => 'valueD' ) ) It should be like this array( 'AAA' => ( weeks => ( 'week1' => 'valueA', 'week2' => 'valueB' ) ) 'BBB' => ( weeks => ( 'week1' => 'valueC', 'week2' => 'valueD' ) ) ) This can be accomplished by adding some logic to the code that builds the array. I didn't test mac_gyver's solution. It looks like it would work, but I would do it a little differently to make it easier to understand. NOTE: Don't use variable names such as "$array" - give them meaningful names to help you know what they contain and the type of variable. I assume you have a foreach() or some other type of loop, so this may need some tweaking. Other assumptions: 1) The The records are ordered by date. 2) The is that for every employee the same "weeks" exist in the data. If not, some additional logic would be needed. But, this should get you started <?php //Create array to hold the restructured data $payrollAry = array(); //Process the data into a structured array foreach($resultSet as $row) { //If this is the first employee record for this ID, set the top-level array values if(!isset($payrollAry[$row->IdEmployee])) { $payrollAry[$row->IdEmployee] = array( 'name' => $row->employeeName, 'weeks' = array() ); } //Add the weekly data to the sub array (by date) for the current employee $date = date("jS M Y", strtotime($row->Year.'W'.str_pad($row->Week, 2, 0, STR_PAD_LEFT).' +6 days')); $payrollAry[$row->IdEmployee]['weeks'][$date] = "{$row->CurrencySymbol}{$row->Wage}"; } //Create output for the data $wageOutput = ''; //Create the header row output $wageOutput .= "<tr><th> </th>"; //Use the first element in array to get the dates for the header $firstRecord = current($payrollAry); forech($firstRecord['weeks'] as $date => $value) { $wageOutput .= "<th>{$date}</th>"; } $wageOutput .= "</tr>\n"; //Create output for employees foreach($payrollAry as $employeeID => $employeeData) { $wageOutput .= "<tr>\n"; //Add employee name $wageOutput .= "<td>{$employeeData['name']}</td>\n"; //Add employee wages for each week foreach($employeeData['weeks'] as $wages) { $wageOutput .= "<td>{$wages}</td>\n"; } $wageOutput .= "</tr>\n"; } ?>