Problem with exploding text file, using file function - php

function dailyStat(){
$data = "";
$currentTime = time();
$file = file("data/pageStat.txt");
foreach ($file as $row) {
$row = trim($row);
$values = explode("\t", $row);
$loginTime = getTime($values[1], $values[2]);
if ($currentTime - $loginTime <= 84000){
$data.=$row;
}
}
$stat = fopen("data/pageStat.txt", "w");
fwrite($stat, $data);
fclose($stat);
}
function getTime($givenDate, $givenTime){
$date = explode(".", $givenDate);
$time = explode(":", $givenTime);
$hour = intval($time[0]);
$minute = intval($time[1]);
$second = intval($time[2]);
$day = intval($date[0]);
$month = intval($date[1]);
$year = intval($date[2]);
return mktime($hour, $minute, $second, $month, $day, $year); }
Heloo, I have following problem. I want to make a stat page about visits by page on my website in last 24h, but I have problem. Every visit on any page is written in txt file. I showed two functions here, dailyStat() - it should show only visits in last 24 hours, and getTime() - it should find utc from time i txt file.
/biznews/index.php?page=index 05-06-2022 00:24:57 192.163.50.1
This is the exaple of one row in txt file, every column is separated by \t and every row is separated by \n. The problem is that I always get error Undefined array key 1, Undefined array key 2. But I know that those array keys exist because I exploded them. Can someone help, because I don't know what is happening. Note: all paths are correctly.

This practice is highly unsecure and with a simple bot which makes some thousands of requests to your site your server and your hosting account would be banned and down because you can easily consume all inodes in the host file system.
Make a new file for every request is a bad bad bad idea.
Why don't you use Monolog or other package which is easy to use and have an almos perfect implementation of logging facilities.
Use composer and follow https://www.loggly.com/ultimate-guide/php-logging-libraries/
If you need to parse logs you could https://github.com/pulse00/monolog-parser

Related

Display name of the tools provided in the last X days using XPath in PHP

Back at it again with another XML/PHP problem. :)
On my webpage I want to display the names of the tools provided in the last X days. X is a number that will be entered by the user in a textbox, and after clicking the submit button, the names of the tools that have been provided in those last X days will appear.
This will be done by comparing the X value the user enters with the dates in my XML file, and to find the tools that match.
In my XML file, I have a "dateentered" node that stores a random date that I entered:
<tools>
<tool type="..." web-based="..." free="...">
<name>Facebook</name>
<description>...</description>
<url>...</url>
<subjects>...</subjects>
<creators>...</creators>
<category>...</category>
<price>...</price>
<dateentered>2020-12-01</dateentered>
</tool>
</tools>
Next, I created a function in PHP that basically converts the 'Y-M-D' format into days by subtracting the current date from whatever date you enter:
function time2string($timeline) {
$periods = array('day' => 86400);
$ret = '';
foreach($periods AS $name => $seconds){
$num = floor($timeline / $seconds);
$timeline -= ($num * $seconds);
$ret .= $num;
}
return trim($ret);
}
Then, I loaded my xml file using simpleXML:
$xml = simplexml_load_file('tools.xml');
So for example, using the XML code sample above and doing
$days = $xml->xpath("//tool/dateentered");
foreach ($days as $day) {
print (time2string(time()-strtotime($day)));
}
this converts '2020-12-02' to '1' and therefore outputs '1', meaning that the function works as it should.
With XPath, What I want to do is, I want to compare the value the user enters in the textbox with the converted 'dateentered' from my xml, and if they match, then I want to display the tool name.
So something like:
if(isset($_REQUEST["submit"])) {
// time2string function
$f_day = $_REQUEST["days"]; // getting the value the user enters in the textbox
$xml = simplexml_load_file('tools.xml');
// do something here
}
So let's say, using the xml sample I provided above, if the user enters 1 in the textbox, the output should be:
Facebook
How can I solve this?
I'm also open for different approaches besides having to create a function, this is just what I came up with.
Turns out, like #CBroe has said, I don't even need a function that converts date to days, instead, I can take advantage of PHP's date() and strtotime() functions as follows:
<?php
if(isset($_REQUEST["submit"])) {
$xml = simplexml_load_file('tools.xml');
$f_days = $_REQUEST["days"];
$days = date("Y-m-d", strtotime("-$f_days days"));
$xdays = $xml->xpath("//tool[dateentered = '$days']/name");
foreach ($xdays as $name) {
echo "<h1 align='center'>".$name."</h1><br>";
}
}
?>
And this will output:
Facebook

PHP variable between 2 string positions

I have tried searching the forums but still unsure how to do this.
I am extracting a web link from a webpage, and the start and end are always the same but there is a variable i want to get.
E.g http://www.example.com/images/$VARIABLE/image.jpg
$position1 = http://www.example.com/images/
$position2 = image.jpg
I need to get the variable. On the webpage the $position 2 is listed more than once (image.jpg)
I have tried all sorts of things and nothing works so far.
Thank you
$begin = strpos($page, $position1) + strlen($position1);
$end = strpos($page, $position2);
$ImageName = substr($page, $begin, ($end - $begin));
I think the problem is that if image.jpg occurs before http://www.example.com/images/, then just trying to use your code won't work.
A slight fix would be to start the search for $position2 where you found the first part by adding a start point in the strpos() function...
$begin = strpos($page, $position1) + strlen($position1);
$end = strpos($page, $position2, $begin);
$ImageName = substr($page, $begin, ($end - $begin) - 1);
with
$page = "some test image.jpg some more text
blurb that is in the middle http://www.example.com/images/VARIABLE/image.jpg
some even more text image.jpg";
the code finds
VARIABLE
A regex as suggested by #user3783243 may also work, but you may also need a constraint of how long the parameter is likely to be.

Random String Generator that does not repeat in laravel controller

I created this function in my laravel controller.
function incrementalHash($len = 5){
$charset = "0123456789abcdefghijklmnopqrstuvwxyz";
$base = strlen($charset);
$result = '';
$now = explode(' ', microtime())[1];
while ($now >= $base){
$i = $now % $base;
$result = $charset[$i] . $result;
$now /= $base;
}
return substr($result, -5);
}
then I have a function to insert something in the database. this function uses the above function. but every time I use it I get the same result from above function. I tried composer dump-autoload and the result changes. I wonder what is happening? why this method always returns the same result. how can I use this method and not receive the same result without dumping autoload? here is my controller:
public function add_user_create()
{
$user = new User;
$user->user_id = Request()->input('user_id');
$user->user_name = Request()->input('user_name');
$user->fcm = Request()->input('fcm');
$user->email = Request()->input('email');
$user->token = Request()->input('token');
$user->profile_pic = Request()->input('profile_pic');
$user->api_token = str_random(60);
$user->ref_ID = $this->incrementalHash(4);
$user->save();
}
I suggest you to use what Laravel provides to generate a random string. like: strtolower(str_random(4)) as mentioned by #kenken9999
However, Here is why I think it gave same result for you:
I executed your function multiple times and these are the outputs:
becpy
becqa
becqd
becqd
becqe
I think when you checked them they just happend to be same and when you did composer dump-autoload you happened to see a different output.
Let me know If I am wrong.
Did you call this function many times during a very short time? Then I believe the issue is microtime(). This function returns a string separated by a space. The first part is the fractional part of seconds, the second part is the integral part.
Thus, if the function is called during the same second, $now should be the same, based on which $result will not change.
Further, if the function is called during a short time (let's say several seconds), $now would be similar (1283846202 and 1283846203 for example). In this case, only the right part of $result would vary.

How to call date() only once, then display it several times in different formats

I have a page I use as a digital sign driven by a raspberry pi. The page displays the date and time as well as shows the current weather.
I'm calling the date() function three separate times. One is for determining if it's day or night for the weather icons, another is to display the time in larger numbers, and the last is to display the current date.
Is there a way I can just store date() in a single variable, then use it three different ways?
<?php
$page = $_SERVER['PHP_SELF'];
$sec = "10";
//header("Refresh: $sec; url=$page");
$bg = array(); // create an empty array
$directory = "images/"; //the directory all the images are in
$images = glob($directory . "*.jpg"); //grab all of the images out of the directory with .jpg extention
foreach($images as $image)
{
$bg[] = $image;//populate the empty array with an array of all images in the directory folder
}
$i = rand(0, count($bg)-1); // generate random number size of the array
$selectedBg = "$bg[$i]"; // set variable equal to which random filename was chosen
$json_string="http://api.openweathermap.org/data/2.5/weather?lat=49.1985&lon=-113.302&appid=b29961db19171a5d4876c08caea9af0d&units=metric";
$jsondata = file_get_contents($json_string);
$obj = json_decode($jsondata, true);
$now = date('U'); //get current time
$temp = round($obj['main']['temp']);
if($now > $obj['sys']['sunrise'] and $now < $obj['sys']['sunset']){
$suffix = '-d';
}else{
$suffix = '-n';
}
?>
<div id="todaysdatetime">
<div id="todaystime">
<span><?php echo(date("g:i A"));?></span>
</div>
<div id="todaysdate">
<span><?php echo(date("l\, F j<\s\up>S</\s\up>"));echo ' <i class="owf owf-', $obj['weather'][0]['id'].$suffix, '"></i> ', $temp, '°C'; ?></span>
</div>
</div>
You can't really do this, because what you pass to date() is the format you want to display it in. date() is the function you call in order to format a date.
So you can't store the result and use it again, because the result is a human-readable string which is hard to translate back into an internal date representation. What you're doing is already the easiest (and really, the only) way to do it, and also will have minimal impact on your performance.
There are two ways.
Get a timestamp with time() store it in variable and call date('YOUR_FORMAT', $timestamp);
Use class \DateTime and use method format() on the datetime object
Those two options have this advantage that datetime will be always the same and it won't change because of slow execution of the code.

Appending multiple entries to an output file with a crontab using php?

I am writing a script in PHP in which I had to write the system uptime, the current time, and the amount of users logged in the system into a log file, and be updated continually via a crontab.
What I need help with is that I would like the updates to accumulate within the file and be added continually. So far, whenever my script gets executed, the newest update overwrites the previous update.
What I've done is that I tried to declare an array of entries and as I iterate through the array push the contents of the update into the array (It might be a bit of half-baked logic on my part).
My Code:
$fileName = '../so-and-so directory/output.log';
$dt = date('m/d/y');
$time = date('h:i A');
$data = shell_exec('uptime');
$uptime= explode(' up ', $data);
$uptime = explode(', ', $uptime[1]);
$uptime = $uptime[0].','.$uptime[1];
$users = system('w', $who);
$array = new SplFixedArray(3);
$fileLog = fopen($fileName, 'w');
$fileString = "Date: ".$dt. "\n". " Time: ".$time . "\n".
"System uptime ". $uptime ."\n" ."Users " . $users;
foreach ($array as $entry) {
array_push(file_put_contents($fileName, $fileString));
}
fclose($fileLog);
I feel that the solution is very simple but I'm missing it. Would somebody please clue me in?
The "w" filemode truncates the file on open. "a" appends to the end instead. See fopen(3) or the PHP documentation for details.
Also, file_put_contents() is destroying the file. Try fwrite() instead.
drop fopen; simply use
file_put_contents($fileName, $fileString);
file_put_contents will overwrite the existing file by default.
In short:
$fileName = '../so-and-so directory/output.log';
$dt = date('m/d/y');
$time = date('h:i A');
$data = shell_exec('uptime');
$uptime= explode(' up ', $data);
$uptime = explode(', ', $uptime[1]);
$uptime = $uptime[0].','.$uptime[1];
$users = system('w', $who);
$fileString = "Date: ".$dt. "\n". " Time: ".$time . "\n".
"System uptime ". $uptime ."\n" ."Users " . $users;
file_put_contents($fileName, $fileString);
So it turns out that I needed to edit my crontab file as such:
* * * * * such-and-such-script.php >> ../so-and-so directory/output.log 2>&1
To make them append without the previous one being overwritten by the new one. I also lost the fopen() and instead of doing file_put_contents, I did fwrite() into the file. It works great now. Thank you!

Categories