Jump to content

Psycho

Moderators
  • Posts

    12,145
  • Joined

  • Last visited

  • Days Won

    127

Everything posted by Psycho

  1. Longest last name "known" is 590 characters: http://en.wikipedia.org/wiki/Wolfe+585,_Senior
  2. otuatail, Yeah, I don't think the requests have been very clear. The original post stated The part in red is FALSE and is what started the confusion for me. That regex will not match "O'Brian£$%^&*()", it will only match the first part "O'Brian" and discard the rest. $surname = "O'Brian£$%^&*()"; preg_match('/^[A-Z][\'|A-Z][-|A-Z]{5}/i', $surname, $match); echo $match[0]; //Output: O'Brian£$%^&*() So, I interpreted your request as you were needing the rest of that string. That was my poor interpretation based upon poorly stated requirements. So, I stand behind the statement I think what you meant to ask was that you want the regex to ONLY match entire values where the last part of the expression matches ALL of the remaining characters and there has to be at least 5. That is easily solved a couple of ways. First, you need to add the dollar sign to the end of the expression (before the /) to tell the expression that whatever it matches must continue to the end of the string Second, you need to add logic to match "approved" values past the 5 that it is currently set for. This can be accomplished two ways: 1. The {5} tells the expression to match 5 and only 5 characters. You may know that you can put two values in the curly braces separated by a comma such as {5,10}. That tells the expression that it can match that expression from 5 to 10 times. Well, you can just put the comma in and that tells the expression it must match a minimum of 5 characters to an infinite maximum. 2. You could repeat the last condition and use a * to say it should match 0 or infinite number of matches. Lastly, the [] are being used to define characters to be matched. You are including the pipe character | and I believe you are doing so to be an OR condition. For example, in this [-|A-Z] I think you mean for that to match an underscore OR a letter. However, that doesn't work that way within the brackets. That is telling the regex to match an underscore, a pipe, or a letter. In other words, you don't need the pipe in there. Otherwise you would match "O|Brian" and, using your words, "Whoever heard of someone with a name like that."? Either of these will do what you are asking. /^[A-Z][\'A-Z][-A-Z]{5,}$/i /^[A-Z][\'A-Z][-A-Z]{5}[-A-Z]*$/i However, those will exclude real names. As I said before, trying to verify names is only going to end up invalidating names of real people. But, it's your application, so do what you want. Here are few real names that would not create a match based upon the rules you created: O'Day : Too short since the rules are requiring it to be at least 7 characters De la Hoya : The rules aren't allowing for spaces Day-O'Connor : The rules only allow the apostrophe as the 2nd character Venegás : The rules don't allow characters with diacritics
  3. The parts under #4 do two things, but first let me explain something else first. You didn't supply a field for the stream table for the primary ID. I assume you have one, if not you need to add one. So, I put stream_id as a placeholder. You should typically have a primary ID on all your tables as it is needed for some operations. In this case it is needed to GROUP the records to prevent duplicates. But, I see you added likes_username to the query (again this is the absolute wrong way to do this, you should have the ID for the user record). Are you needing data for all of the likes associated with the stream or are you only needing a count of the likes? If you need the former, it becomes more complicated. If you need the latter, the other two lines in the query are supposed to provide that, but I think I had an error. But, as stated above, I assume your tables have a unique primary key. If not, this almost becomes impossible. If your comments table has a unique key, then this should work to add the COUNT() of likes to the returned data without the duplication of comments (replace the with correct comment_id field name). SELECT s.stream_status, u.user_username AS author_username, u.profile_picture AS author_avatar, c.comments_comment, c.comments_time, uc.user_username AS comment_username, uc.profile_picture AS comment_avatar, likes_username -- 4 -- , COUNT (c.comment_id) AS likes FROM stream s INNER JOIN users u ON u.user_username = s.stream_username LEFT OUTER JOIN comments c ON c.comments_item_id = s.stream_id LEFT OUTER JOIN users uc ON uc.user_username = c.comments_username LEFT OUTER JOIN likes l ON l.likes_item_id = s.stream_id ORDER BY stream_time DESC -- 4 -- GROUP BY (c.comment_id) LIMIT 50 It may seem counter-intuitive to use the comment_id to determine the number of likes. But, as you see from the current results, JOINing the likes onto the rest of the query creates a duplication of the comments to likes. Note: if you had more many-to-one JOIN conditions, I'd probably result to a subquery as adam_bray was suggesting above. If you do need data about the individual records for the likes, then you will have to get the data with the duplication in the result set and you will have to handle it in the processing code.
  4. Without rewriting it all, you can add this: $( document ).ready(function() { $('#submitBtn').attr('disabled', 'disabled'); }); Working example <html> <head> <script type="text/javascript" src="http://code.jquery.com/jquery-1.10.2.min.js"></script> <script> $( document ).ready(function() { $('#submitBtn').attr('disabled', 'disabled'); }); $(function() { $('input.required').click(function() { var unchecked = $('input.required:not(:checked)').length; if (unchecked == 0) { $('#submitBtn').removeAttr('disabled'); } else { $('#submitBtn').attr('disabled', 'disabled'); } }); }); </script> </head> <body> <form action="../page.php?page=1" method="post" name="contact_us" onSubmit="return capCheck(this);"> <table cellpadding="5" width="100%"> <tr> <td width="10" class="required_field">*</td> <td width="80">Your Name</td> <td><input type="text" name="name" maxlength="40" style="width:400px;"/></td> </tr> <tr> <td class="required_field">*</td> <td>Email Address</td> <td><input type="text" name="email" maxlength="40" style="width:400px;"/></td> </tr> <tr> <td></td> <td>Comments:</td> <td><textarea name="comments" style="width: 400px; height: 250px;"></textarea></td> </tr> <tr> <td></td> <td></td> <td> <input type="checkbox" class="required" /> Click to check<br /> <input type='submit' id="submitBtn" value="Submit"> </td> </tr> </table> </form> </body> </html> However, as I said before, you need to modify the page that receives the form post to verify that the checkbox was checked.
  5. No reason to get bent out of shape. If you are asking for free help you have no room to complain on how that help is provided. $surname = "O'Brian"; preg_match('/^[A-Z][\'|A-Z][-|A-Z]{5}.*/i', $surname, $match); echo $match[0]; //Output: O'Brian $surname = "O'Brian£$%^&*()"; preg_match('/^[A-Z][\'|A-Z][-|A-Z]{5}.*/i', $surname, $match); echo $match[0]; //Output: O'Brian£$%^&*()
  6. No. That is the function for enabling/disabling the submit button - which you still need. The problem is that the default state of the submit button needs to be enabled. Then, on page load, use JavaScript to disable it. Although that function could be a little cleaner.
  7. That's a bad way to handle names. You should never modify a name that has been submitted (with the exception of trim()). If you need to restrict certain input, then add validation and error handling. Also, for names, No matter what logic you come up with there will be some people's names that would be considered invalid. People hate that. Why would you assume that the apostrophe would only ever be in the second position? What about accented letters: ö, ò, û, etc.?
  8. Since the "checkbox" field has a class of 'required', I'm guessing it's something like a Terms Of Use type thing where the user must select to acknowledge something in order to submit. @Chrisj: that's not how it should be done. If the user had JS disabled then they would be blocked from using the form. The submit button should not be disabled by default. Have an onload event that uses JS to disable it. Then enable it once they click it. That way you get the process you want for users that have JS enabled. For non JS users they can still submit the form. But, you would add error handling on the receiving page to check if they checked the box or not. If not, send them back to the form with appropriate error messaging.
  9. @Chocu3r, I think he only only wants records where ALL records for each unique lineno ID have a hitcount of 0. In his example above there are two records with a lineno of 3. But, one of them has a value that is not 0. Therefore, all records with a lineno of 3 should be excluded. @c7borg: Use a subquery to select the lineno's which have a non-zero value. Use that result to then select all records that do not use those lineno values. SELECT id, lineno FROM table_name WHERE lineno NOT IN (SELECT DISTINCT lineno FROM table_name WHERE hitcount <> 0)
  10. Um, I stopped reading after the second paragraph. This is not a difficult problem to solve. Query the possible values for the select list. Then while building the options check if any match the currently selected value. If so, make that option selected. You would want to create a function for this. I do have one question regarding the SELECT queries you are using above. Why is there a DISTINCT in the queries for stores and products? Those are the master tables for those respective record types, why would there be duplicates? Second, why are you not pulling the IDs for those records and using those as the values in the select lists? Those records should have a primary ID field which is numeric. Those numeric IDs would then be stored in the shoplist table as foreign keys. You don't store the names/values of those records in the associative tables. There are lots of other issues such as connecting and disconnecting from the database multiple times. Just connect once. You don't need to prepare a query that has no placeholder values. Also, the flow of the logic seems really odd. I see what you are trying to do with the array of fields, but will box you into a corner. A field can have many different types of errors. A single error message will not suffice when you account for all of them. Plus, you're already putting logic into that foreach loop since you want it to do something different from some fields and not others. You are over complicating the logic. If you want some fields to do the same things, create functions and explicitly call them when creating those fields. Here is a complete rewrite of your code in a much more logical format. It won't work out of the box as there were some things not provided above. But, it shouldn't take too much to put in what you need. <?php //Function to create select list options and set selected value if passed function createSelectOptions($optionsAry, $selectedValue=false) { $optionsHTML = ''; foreach($optionsAry as $option) { $selected = ($option['value']==$selectedValue) ? ' selected="selected"' : ''; $optionsHTML .= "<option value='{$option['value']}'{$selected}>{$option['label']}</option>\n"; } return $optionsHTML; } //Since you want the format for the input fields to be the same, //You can create a function to create them function standardInputField($fieldLabel, $fieldName, $fieldValue) { $fieldHTML = "<div class='control-group'>\n"; $fieldHTML .= " <label class='control-label'>{$fieldLabel}</label>\n"; $fieldHTML .= " <div class='controls'>\n"; $fieldHTML .= " <input type='text' name='{$fieldName}' value='{$fieldValue}' />\n"; $fieldHTML .= " </div>\n"; $fieldHTML .= "</div>\n"; return $fieldHTML; } //Connect to database $pdo = Database::connect(); $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // If [submit] isn't clicked - and therfore POST array is empty - perform a SELECT query to bring in // existing values from the table and display, to allow for changes to be made if(!isset($_POST['submit'])) { $sql = "SELECT * FROM shoplist where idnumber = ?"; $query = $pdo->prepare($sql); $query->execute(array($idnumber)); $values = $query->fetch(PDO::FETCH_ASSOC); if(!$values) { $error = 'Invalid ID provided'; } } //Set values for form fields to prev. selected values or defaults $current_store_name = isset($values['store_name']) ? $values['store_name'] : ''; $current_item_description = isset($values['item_description']) ? $values['item_description'] : ''; $qty_pkg = isset($values['qty_pkg']) ? $values['qty_pkg'] : ''; $pkg_of = isset($values['pkg_of']) ? $values['pkg_of'] : ''; $price = isset($values['price']) ? $values['price'] : ''; $flyer_page = isset($values['flyer_page']) ? $values['flyer_page'] : ''; $limited_time_sale = isset($values['limited_time_sale']) ? $values['limited_time_sale'] : ''; $nos_to_purchase = isset($values['nos_to_purchase']) ? $values['nos_to_purchase'] : ''; //Query stores and create select field options $sql = "SELECT store_id AS value, store_name AS label FROM store_master ORDER BY store_name ASC"; $result = $pdo->query($sql); $stores = $result->fetchAll(); $store_options = createSelectOptions($stores, $values['store_name']); //Query products and create select field options $sql = "SELECT product_id AS value, product_name AS label FROM product_master ORDER BY product_name ASC"; $result = $pdo->query($sql); $products = $result->fetchAll(); $product_options = createSelectOptions($products); //Add logic to create error values for fields as needed (the error or empty string) //for each field and store in unique variables to be echo'd within the form ?> <form class="form-horizontal" action="update.php?idnumber=<?php echo $idnumber?>" method="post"> <?php $current_store_name; ?> <br /> <?php echo $current_item_description; ?> <div class="control-group"> <label class='control-label'>Store Name</label> <div class="controls"> <select class="store-name" name="store_name"> <?php echo $store_options; ?> </select> </div> </div> <div class="control-group"> <label class='control-label'>Item Description</label> <div class="controls"> <select class="item-desc" name="item_description"> <option value="">Please select...</option> <?php echo $product_options; ?> </select> </div> </div> <?php echo standardInputField('Qty / Pkg', 'qty_pkg', $qty_pkg); ?> <?php echo standardInputField('Pkg. Of', 'pkg_of', $pkg_of); ?> <?php echo standardInputField('Price', 'price', $price); ?> <?php echo standardInputField('Flyer Page #', 'flyer_page', $flyer_page); ?> <?php echo standardInputField('Limited Time Sale', 'limited_time_sale', $limited_time_sale); ?> <?php echo standardInputField('No(s) to Purchase', 'nos_to_purchase', $nos_to_purchase); ?>
  11. I think the foreach() loop is a problem. I would assume you want the roles of the person to display in a certain order. If the person has been both a player and a coach you likely want one to always display before the other. This layout will not enforce that. I'm not sold on this array of objects within the array. But, I don't know what I would do without more analysis. But, if you are going to do it this way, then put the roles within a subarray of the object with textual keys. It will provide better structure and make the process much easier. You won't need the foreach loop and you can ensure the values will be displayed in the order you specify. I would also put the properties of each role in those subarries rather than [0], [1], [2], etc. I don't know all the details of the information you are collecting for the person. But, let's say you have some generic properties such as name and age. I would store those as $person->name & $person->age. But, let's say you have a role of coach and the coach object has properties such as start_date and refMethod. You could put those into the object such that they would be accessed like so: $person->roles['Referee']->start_date and $person->roles['Referee']->refMethod So, instead of a foreach() loop to try and figure out what data to display, you just need a block of code for each possible role with a check to see if that role exists. if (array_key_exist('Player', $my_person->roles){ echo "I've been a player"; $my_person->roles['Player']->playerMethod; etc } if (array_key_exist('Manager', $my_person->roles){ echo "I've been a manager"; $my_person->roles['Manager']->somemanagerMethod; etc } if (array_key_exist('Referee', $my_person->roles){ echo "I've been a Ref"; $my_person->roles['Referee']->refMethod }
  12. Yep, I understand that. And I don't expect you would have figured out the error through that (reserved words usually catch everyone at least once in the beginning). But, when asking for help it's common courtesy to provide the errors (if you are getting them). In this case I could have told you what the problem was from the query you posted. But, it could have been any number of problems that could not be identified through the query alone.
  13. How do you know there is an error? Did you check for an error from MySQL? If you had, I would have expected you would have provided it. FYI: I know what the problem is, but I'm going to make you work for it. Sorry, I believe in teaching someone to fish as opposed to just giving them one. So, please post the error you receive.
  14. I'm no expert on this. But, I think the problem is MySQL - not PHP. MySQL is returning a string to PHP (not a timestamp). So, whatever you do with the value after you get it back from MySQL really doesn't make any difference. Either you need to tell MySQL in which timezone the value should be returned or you need a way to tell PHP what timezone the source is from in order to modify it for the expected output. Again, not sure the correct method, EDIT: Another option: I know that you can have MySQL return the timestamp as a UNIX timestamp instead of a string value. Then it should be interpreted by PHP as you want. EDIT #2: Look at this: http://www.sitepoint.com/synchronize-php-mysql-timezone-configuration/ Based on the information in that blog, you do need to set the timezone offset for MySQL before executing your queries.
  15. OK, here are a couple examples since I don't know which one you really need: If you want all the records for the last 6 days (inclusive) plus all from today, then you could use this SELECT * FROM table_name WHERE date_field > DATE_SUB(CURDATE(), INTERVAL 6 DAY) So, if you run this at 3PM on a friday it would pull all records starting at 12AM on the previous Saturday. I think this is probably what you want. If you want all the records from seven days ago starting at the same time then you could use this format SELECT * FROM table_name WHERE date_field > DATE_SUB(NOW, INTERVAL 7 DAY) So, if you run it at 3PM on a Friday, it would pull all the records starting from 3PM on the previous Friday. I doubt you want this. If you run it at 1:))PM and then again at 1:05PM on the same day, you could get different results.
  16. First off, you shouldn't need to manually set the date when adding a record. Instead, you can use a timestamp field with a default value of NOW(). Then in your INSERT statements don't even include the datetime as part of the INSERT data. The database will automatically populate that field with the current datetime value. Second, if you want all the records that were created in the last seven days, then there is no need to use BETWEEN. You just need a greater than comparison. Third, the sample query you posted is looking for a comparison of the datetime value on a field called 'data'? Fourth, do you want the time component to be included in this comparison? For example, if you run the query at 1:00PM, do you only want the records created from last Wednesday after 1PM? Or do you want ALL the records created from last Wednesday starting at 12:00AM? Or, maybe you really want today + the last six days inclusive, otherwise you would always be getting between 7 to 7.99999 days of data. Lastly, whichever you want from above, you can dynamically do this int he query - no need to artificially create the start datetime in PHP.
  17. Start by testing your query in your database management utility (e.g. PHPMyAdmin). Once you've verified it is getting the results you expect - THEN use it in your code to create output. Trying to start with a new query and new code to create output only complicates things. However, the code you posted is invalid. There isn't a closing quote mark for the query. Some comments on what I am seeing: Your tables should have an ID column as the primary key. You should not be JOINing tables on data such as username. Also, use better names in your database. "item_id" says nothing about what the id is for. You don't have any table called "items". It makes it hard to read/understand the code with names that are ambiguous. I'm not understanding why slj90 is suggesting the complicated logic around the likes. Should be able to do a JOIN with a GROUP BY. The current query would not work for that subquery because you are trying to JOIN on that subquery using 'likes_item_id', but that value isn't returned in the subquery. Try this query to start with. As written it will only pull data from the streams table. If that works, then remove the comments '-- 1 ---' and run again. It should then display the user information. If that works, then remove the comments with '-- 2 --' and verify the output. Repeat with the comments for 3 and 4 SELECT s.stream_status -- 1 -- , u.user_username AS author_username, u.profile_picture AS author_avatar -- 2 -- , c.comments_comment, c.comments_time -- 3 -- , uc.user_username AS comment_username, uc.profile_picture AS comment_avatar -- 4 -- , COUNT (stream.stream_id) AS likes FROM stream s -- 1 -- INNER JOIN users u ON users.user_username = stream.stream_username -- 2 -- LEFT OUTER JOIN comments c ON c.comments_item_id = stream.stream_id -- 3 -- LEFT OUTER JOIN users uc ON uc.user_username = c.comments_username -- 4 -- LEFT OUTER JOIN likes l ON l.likes_item_id = stream.stream_id ORDER BY stream_time DESC -- 4 -- GROUP BY (stream.stream_id) LIMIT 50
  18. No, it is not. The database isn't going to magically create names, ages, etc. It does automatically create auto-increment IDs. The latter are the types of values that you don't, necessarily, need to validate because you know they will be the type that you expect. As for the names, ages, etc. The values are being entered 'somewhere', but I don't know who is entering or what logic is applied before the data is saved. Although you *could* perform validations/sanitizing before storing the data in the database, you would not want to rely upon that during the output process. Don't create a process that *assumes* something is being done by a separate process.
  19. You could create a foreach() loop, but I wound't. You may only be validating that each field is not empty, but you should have additional validations which won't be the same for each field. For example, I would be validation that the quantity type fields contain a numeric input. By creating a foreach loop you would have to add more logic into the loop to perform some validations for some fields and not for others. That just makes it more complicated. However, it could make sense to create functions for the different types of validations that you could call, as needed, for each applicable field.
  20. #1: Since I have no clue what the source of this information is, the answer would be Yes. Always assume data could be malicious and take appropriate precautions. So, for this you can just use htmlentities() or htmlspecialchars() when outputting those field values. I prefer to 'prepare" the data before outputting - instead of doing it in-line. Plus, put your "Logic" at the top of the page (or even in a separate file) <?php ## PUT ALL THE PHP LOGIC AT THE TOP OF YOUR SCRIPT ## CREATE VARIABLES THAT ARE OUTPUT IN THE HTML OUTPUT $user_list_HTML = ''; $cnt = 0; while ($row = mysqli_fetch_array($result, MYSQLI_ASSOC)) { $cnt++; $name = htmlspecialchars($row['Name']); $age = htmlspecialchars($row['Name']); $city = htmlspecialchars($row['Name']); $cell = htmlspecialchars($row['Name']); $email = htmlspecialchars($row['Name']); $user_list_HTML .= "<tr>\n"; $user_list_HTML .= " <td>{$cnt}</td>\n"; $user_list_HTML .= " <td>{$name}</td>\n"; $user_list_HTML .= " <td>{$age}</td>\n"; $user_list_HTML .= " <td>{$city}</td>\n"; $user_list_HTML .= " <td>{$cell}</td>\n"; $user_list_HTML .= " <td>{$email}</td>\n"; $user_list_HTML .= "</tr>\n"; } ?> <html> <head></head> <body> <table> <tr> <th> S.No. </th> <th> Name </th> <th> Age </th> <th> City </th> <th> Cell </th> <th> Email</th> </tr> <?php echo $user_list_HTML; ?> </table> </body> </html> #2: There is nothing in that code that would make sense to be a link. You would likely want to include the primary ID frm that table and use THAT in the link. Something like echo "<td><a href='get_user_data.php?id={id}'>{$name}</a></td>\n"; And, in that case you could use intval() on the ID, but that probably isn't necessary since the ID would be database defined and would never be set by an external source. However, on the get_user_data,php page you *would* need to add validation to ensure the id passed is valid and/or escaped to prevent SQL injection #3: I would assume the button would do something similar as the link and just pass the id of the record to be processed. So, the same applies. Not necessary to validate on the page that creates the button since the value is programatically created in the database (but it doesn't hurt to add some logic). but, you would definitely need to validate/sanitize on the receiving page.
  21. I have one bit of advice for you. When implementing a feature do NOT start by trying to do it with AJAX. Just use a normal form that you POST and refresh the page. Yes, I know that isn't what you want. But, doing something as simple as receiving a form post and making changes in the database aren't going to be perfect right out of the gate and will likely require some debugging. It is more difficult to debug code when there are multiple technologies involved (PHP, JavaScript, MySQL, etc,). So, make the page work with vanilla HTML and PHP. Once it is working, THEN implement AJAX so the user doesn't have to manually submit the page and refresh.
  22. You would have one table for the users and a separate table for their family members. The family member table would look something like Table B. But, it is customary to have the first field to be the primary ID of the table. So, it would look mire like this: Table: family_members family_member_id (primary key) user_id (foreign key) name . . . additional fields to describe the family member THe above assumes that a family member would belong to one, and only one, user. If a family member can be associated with multiple users, then you would not include the user_if in that table. Instead, you would use a third table to maintain the associations. Each record would contain foreign keys for the users and the family members.
  23. No, it's including less code. WHen you don't use {} for control structures (loops, if, etc.) it only assumes the one line immediately after the control structure is associated with it. <?php try { //open the database $db = new PDO('sqlite:bilgerdb'); $query = "SELECT PropID, PropLocation FROM property WHERE PropCategory = 'Residential' ORDER BY PropListingDate"; $result = $db->query($query); $options = ''; foreach($result as $row) { $options .= "<option value='{$row['PropID']}'>{$row['PropLocation']}</option>"; } } catch (PDOException $e) { print 'Exception: ' .$e->getMessage(); } ?> <form action="sqlPropDisplay.php" method="post" id="Residential"> <select name="ResidentialListMenu" size="7" id="ResidentialListMenu"> <?php echo $options; ?> </select>
  24. Hard to say since you didn't post any code. But, the calculation you posted above is wrong for TWO reason: 1. You have to use parenthesis to ensure the calculations are completed in the order you expect. Otherwise the normal order of operations will take precedence. So, it would be calualted as follows: $payment = $asking + ($doc x $tax) - ($down x $interest / $term) I think you want something like this $payment = (((($asking + $doc) x $tax) - $down) x $interest) / $term However, that is also wrong. You cannot calculate interest across multiple multiple payments like that because the interest is not calculated up front. The interest is calculated each period. So, if the payments are monthly 1/12 of the interest is calculated against the remaining balance each month. The calculations uses some more advanced math. Go do a google search on calculating loan payments to get the correct formula EDIT: Your signature also makes no sense What would be the significance of displaying your ring finger. I think you meant it to be the middle finger, in which case, it would be id = 2. "There are 10 types of people in the world. Those who understand binary and those who don't"
  25. Psycho

    sql injection

    http://code.tutsplus.com/tutorials/why-you-should-be-using-phps-pdo-for-database-access--net-12059
×
×
  • 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.