php time validation without zero in hours - php

I want to validate for a 24 hour format.
The below code accepts 1:05:24 which is wrong, as it should instead only accept 01:05:24
try
{
foreach ($arr as $key=>$item)
{
if (date('H:i:s', strtotime($item[1])))
{
} else {
throw new Exception('Invalid Time Format');
}
}
}
catch (Exception $e)
{
echo $exp = $e->getMessage();
}

The following use of preg_match will differentiate between the two cases you have mentioned.
However, note that neither this nor the method that you mentioned in the question will correctly detect an invalid time such as 00:99:99.
If you require that, you need a different method, the easiest of which is probably to parse out the numbers and run this function on it.
<?php
$mydate_bad = "1:05:70";
$mydate_good = "01:05:24";
print (preg_match("/^\d\d:\d\d:\d\d$/", $mydate_bad)); # Returns 0
print (preg_match("/^\d\d:\d\d:\d\d$/", $mydate_good)); # Returns 1
?>

Based on the code you've provided, one way would be the following:
$php_date = date('H:i:s', strtotime($item[1]));
if ($php_date && $php_date == $item[1]) {
// valid date
}
This will check that a date could be created as in your code, and it will also ensure that the resulting date in the format H:i:s corresponds to what the user entered.
However, in terms of user-friendliness, if you can create a date from the user input, it might be better just to accept it and add the leading 0 yourself if it is missing. Simply use $php_date in favor of $item[1] afterwards.

Related

Symfony 6.0 time format problem database upload

There were some problems with symfony over time. unfortunately, this is not the first time I have run into this. Has anyone ever encountered this problem? If so, thank you for your help.
Controller.php
if($xml = simplexml_load_file($feedUrl)) {
$result["chanel"] = $xml->xpath("/rss/channel/item");
foreach($result as $key => $attribute) {
$i=0;
foreach($attribute as $element) {
$ret[$i]['title'] = (string)$element->title;
$ret[$i]['category'] = (string)$element->category;
$ret[$i]['link'] = (string)$element->link;
$ret[$i]['pubDate'] = json_decode(json_encode($element->pubDate), TRUE);
$ret[$i]['enclosure'] = (array)$element->enclosure;
$ret[$i]['description'] = (string)$element->description;
$i++;
}
}
}
foreach ($ret as $feed){
$newnews = new Newsfeed();
$newnews->setTitle($feed['title']);
$newnews->setCategory($feed['category']);
$newnews->setLink($feed['link']);
$newnews->setDescription($feed['description']);
$newnews->setDate(date("Y-m-d h:i:sa", strtotime($feed['pubDate'][0])));
$newnews->setImage($feed['enclosure']['#attributes']['url']);
$newnews->setSource('2');
$entityManager->persist($newnews);
$entityManager->flush();
}
This problem
The date() function returns a string, so this line won't work:
$newnews->setDate(date("Y-m-d h:i:sa", strtotime($feed['pubDate'][0])));
You can probably just use:
$newnews->setDate(new \DateTimeImmutable($feed['pubDate'][0]));
I have had this problem before. For me, when working with only Dates (no time) it was kind of misleading the fact that MySQL and thus doctrine annotations have the Date type, but PHP/Symfony does not.
As mentioned by Chris, the date() function returns a string, but the class DateTime is your friend here.
Even when it is called DateTime, this class allows formatting and you can indeed, for example, retrieve only a date with it. An example would be:
$date = new DateTime('2000-01-01 12:30:25');
echo $date->format('Y-m-d');
Or in your case, in which you DO want to return the time part too:
$pubDate = new DateTime($feed['pubDate'][0])->format('Y-m-d h:i:sa');
$newnews->setDate($pubDate);
Which can be easily transformed into a one-liner.
This will show only what you ask for in the format() function.
There is one trickiness though. In my country at least, it is very common to format dates with a slash (/), but DateTime->format() will not work with Y/m/d, so keep it in mind and check for the correct format here if you are going to be using slashes.

Return true/false if word in URL matches specific word

I currently use:
if(strpos($command->href,§current_view) !== false){
echo '<pre>true</pre>';
} else {
echo '<pre>false</pre>';
}
$command->href will output something like this: /path/index.php?option=com_component&view=orders Whereas
§current_view is outputting orders. These outputs are dynamically generated, but the scheme will always be the same.
What I need to do is return true/false if the words from $current_view match the view=orders in the URLs from $command->href. The issue with my code is, that it doesnt match anything.
What is the correct way to do this?
Please note that the $command->href and the whole code is inside a while function, that pass multiple URLs and this only needs to match the same ones.
Breaking it down to a simple example, using your code and variable values.
$current_view = 'orders';
$command = '/path/index.php?option=com_component&view=orders';
if(strpos($command,$current_view) !== false){
echo '<pre>true</pre>';
}
else {
echo '<pre>false</pre>';
}
The oputput is "true".
Now, go and debug the REAL values of $command->href and $current_view...
I'm pretty confident that the values are not what you think they are.
Does something like:
if(substr($command->href, strrpos($command->href, '&') + 6) == $current_view)
accomplish what you are after?
To explain, strpos get the last instance of a character in a string (& for you, since you said it always follows the scheme). Then we move over 6 characters to take "&view=" out of the string.
You should now be left with "orders" == "orders".
Or do you sometimes include some arguments after the view?
Try parsing url, extracting your view query string value and compare it to $current_view
$query= [];
parse_str(parse_url($command->href)['query'], $query);
if($current_view === $query["view"])
echo '<pre>true</pre>';
} else {
echo '<pre>false</pre>';
}

Checking Users HTML form input with PHP

I am creating a web application that takes in a user input (Scientific Paper DOI) and queries a database to display a graph. I've been trying to limit the connections made to the database since its on a remote server (private DMZ with web server) by checking the user input if it matches a correct DOI.. if it doesn't then no connection to the database will be made, I hope this will help speed up the application if there are many users at once making queries.
Pseudo: All paper DOIs start with "10.1103/" because they are all physics papers. This part I have implemented correctly using substr. Next I want to check every character in the input to make sure it only consists of only these characters:
Letter
Number
"/"
"."
Example DOIs:
10.1103/RevModPhys.9.1
10.1103/RevModPhys.76.1015
10.1103/PhysRevLett.95.208304
Here is my code:
function checkDOI($doi) {
if (substr($doi, 0, 8) != "10.1103/") {
echo "Invalid DOI";
return false;
}
for ($n = 0; $n < strlen($doi)+1; $n++) {
if ( !ctype_alnum($doi[n]) && $doi[n] != "." && $doi[n] != "/") {
echo "Invalid DOI";
return false;
}
}
echo "Valid DOI";
return true;
}
if(isset($_POST['submit'])) {
$doi_input = $_POST['doi_input'];
checkDOI($doi_input);
}
I am working with PHP and javascript for the very first time, the pseudo is fairly simple but for some reason, there is something wrong with the 2nd if statement. Not sure if I can really do that. The Echos are just for tests.
Do you think doing this check for every input will slow down the application significantly? Is it worth it to limit the amount of connections to mysql?
The bottom of the code will be modified once I have this working to only query the database if checked returns true.
Thanks for the help!
to check every character in the input to make sure it only consists of only these characters
I suggest you to use preg_match.Try this:
$value="10.1103/RevModPhys.9.1";
if(preg_match("/^[a-zA-Z0-9\/.]+$/", $value)){
echo "match found";
}else{
echo "no match found";
}
Check here: Demo
For more info: preg_match
Your error is $doi[n], it is not an array and should it be the index is invalid.
So use a function like
$chars_doi = str_split($doi);
Before the loop to get an array of characters then use in your loop
$chars_doi[$n]
So you should have something like:
$chars_doi = str_split($doi);
$size = sizeof($chars_doi) - 1;
for ($n = 0; $n < $size; $n++) {
if (!ctype_alnum($chars_doi[$n]) && $chars_doi[$n] != "." && $chars_doi[$n] != "/") {
echo "Invalid DOI";
return false;
}
}
Little tip, avoid use functions such as strlen / sizeof as a loop argument or it will get called at each iteration. It is better for performance to store the value in a variable beforehand.
I would just do:
if (! preg_match ('#^10\.1103/[\p{L}\p{N}.-_]+$#', $doi)) {
... // bad
return;
}
// good
Reference:
http://www.php.net/manual/en/reference.pcre.pattern.syntax.php
http://php.net/manual/en/regexp.reference.unicode.php

Unable to catch XML exception/error in PHP

I am not able to catch exception with below code. Can anyone help me with this thing?
try
{
$xml_emp_name = $xpath->evaluate("//EMPLOYEES[ID='" . $emp_id . "']/EMP-NAME/text()")->item(0)->nodeValue;
}
catch(Exception $e)
{
echo "Error: " . $e->getMessage();
}
DOMXPath::evaulate does not throw exceptions. domxpath evaluate
If the expression is malformed or the contextnode is invalid, DOMXPath::evaluate() returns FALSE.
Try
$xml_emp_name = $xpath->evaluate("//EMPLOYEES[ID='" . $emp_id . "']/EMP-NAME/text()");
if(!$xml_emp_name){
echo 'Error';
}else{
$name = $xml_emp_name->item(0)->nodeValue;
}
You try to access a property on a non-object if evaulate fails and returns false.
Your code is prone to xpath injection. Fix that first. The error then goes away automatically (because the xpath can not become syntactically invalid). Also you need to check/validate return values.
So you're missing the basic principles of input validation and return value validation. All you need to do is to take more care.
Input validation:
You directly inject the variable $emp_id into the xpath string for substitution:
"//EMPLOYEES[ID='" . $emp_id . "']/EMP-NAME/text()"
However at that place you can not have a single quote inside that string. Instead check the input value (Validation) or filter/streamline it (Sanitization). For exampe, validate that it does not contain a single quote or sanitize for a numeric value. Here the second:
$expression = sprintf('//EMPLOYEES[ID="%d"]/EMP-NAME/text()', $emp_id);
$result = $xpath->evaluate($expression);
This little call to sprintf() takes care that only numeric integer values are being used. They never contain quotes, so the expression is always valid. Invalid values that are no number will become 0. As it's the general principle to never assign the ID 0 this should normally not cause any issue in a well designed system. If you want to do the filtering more granular please see Data Filtering in the PHP manual.
return value validation
In your code you just take over the return value of the result with very little checks (actually no checks). That is wrong. For each method or function you use you need to look it up in the PHP manual and check the documentation for all possible return values. Here the method is DOMXpath::evaluate(), click the link and locate the Return Values section. You find this for each method and function in the PHP manual.
When you read the documentation also figure out which kind of error-handling a method makes use of. Does it throws exceptions (and if yes, which ones?) or does it show an error-condition with it's return value (like in your case)? This information is needed to decide whether to do try/catch as you did (and which is wrong because it does not throw exceptions) or if you need to check the return value:
$expression = sprintf('//EMPLOYEES[ID="%d"]/EMP-NAME/text()', $emp_id);
$result = $xpath->evaluate($expression);
if (!$result) {
throw new Exception(
sprintf('No such employee (id: %s)', var_export($emp_id, true))
);
}
This example turns a falsy return value into an exception with an individual exception message. You also might want to consider a different exception, the SPL offers some pre-defined exceptions.
I hope this answer helps you to deal with this issue and forthcoming ones.
->evaluate will for some reason not throw any exceptions, so what I would advise is to check if the result is false, then throw an exception:
if (($xml_emp_name = $xpath->evaluate("//EMPLOYEES[ID='" . $emp_id . "']/EMP-NAME/text()") ) !== false) {
$xml_emp_name = $xml_emp_name->item(0)->nodeValue;
}
else {
// Throw Exception
}

Store a user-input date string as datetime

I'm using php, and need to parse a date string formatted as dd/mm/yyyy and store it in MySql.
How can I convert the string to a datetime variable in a MySql table?
Probably the best way would be using this: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html#function_str-to-date
SELECT STR_TO_DATE('04/31/2004', '%m/%d/%Y');
-> '2004-04-31'
Or equivalent PHP functions like:
http://www.php.net/manual/en/function.date-parse-from-format.php (from PHP 5.3)
A generic PHP function would look like
function convertDate($dateString) {
return date('Y-m-d H:i:s',strtotime(str_replace('/','-',$dateString)));
}
or
function convertDate($dateString) {
$a = explode($dateString('/'));
return "{$a[2]}-{$a[1]}-{$a[0]} 00:00:00";
}
First of all you should store a configuration for the required format date, maybe something like this:
Knowing that the ISO_DATE FORMAT is "Y-m-d"
You must save the output configuration somehow, at least the separator.
If you know the separator and you know the format into which the date is entered than you can validate it using checkdate(), and also transform it into the ISO standard by exploding the values by the predefined separator.
I have a validation object that tells me if a field is of a certain type (String,Date,Datetime,Integer,Float) then formats the parameters sent to SQL :
as an example, let's say i get this array from my html form into PHP:
$_POST["DATA"] = array("name"=>"Koko bongo","age"=>12,"graduation_date"=>"12/06/1986");
and we define a validation array, like this:
$validator= array("name"=>"string","age"=>"integer","graduation_date"=>"date");
I have a configuration for each table which makes this automated but you can do it customly inplace by having an evalAndFormatType function that works like this
function evalAndFormatType($value,$type) {
switch strtolower($type) {
case "integer":
$item = is_numeric($value) && !strstr($value,DECIMAL_SEPARATOR) ? intval($item) :false;
break;
case "Date":/*we suppose that somehow we now the order, how you do it it is your decision: configuration array,constants etc*/
$check = explode(DATE_SEPARATOR,$value);
$item = sizeof($check) == 3 && checkdate(intval($check[1]),intval($check[0]),intval($check[2])) ? $check[2]."-".$check[1]."-".$check[0] : false;
break;
default:
throw Exception("Unknown type ".$type);
break;
}
return $item;
}
now, in your code you can say
$_DATA = $_POST["DATA"]; // the previously defined array
$errMsg = array();
foreach($_DATA as $k=>$v) {
$_DATA[$k] = evalAndFormat($v,$validator[$k]);
if($_DATA[$k] === false) {
$errMsg[$k] = "requires type ".$validator[$k];
}
}
if(empty($errMsg)){
$sql= ....WHATEVER USING THE INFO
} else {
return $errMsg;
/*this can be used to show errors nicely near your text boxes by parsing the expected keys or sending it by JSON etc
or
you could create a string out of it by using locale data that you might have which could output something like
Required fields: Graduation date[invalid type],Name,Age ... etc
"/
I hope this answers your question and also explains my "strange" approach on it.
}

Categories