PHP strstr() returns only one line - php

first of all: I really love this site and I think this is the best forum for programming :)
Now to my problem, which I try to display using code and comments:
$file = fopen ($URL, "r");
// $URL is a string set before, which is correct
// Also, I got the page-owners permission to acquire the page like that
if (!$file)
{
echo "<p>Could not open file.\n";
exit;
}
while (!feof ($file))
{
$buffer = fgets($file);
$buffer= strstr($buffer, "Montag</b>");
// If I don't use this line, the whole page gets displayed...
// If I use this line, only the first line after the needle gets displayed
echo $buffer;
}
fclose($file);
So basically, I'm able to display the whole page, or one line after the needle, but not everything after the needle....
I tried to find a solution using the PHP Reference, the Stackoverflow Search engine and of course google, but I couldn't find a solution, thanks for everybody willing to help me.
Greetings userrr3

Extracting text from the file
You are only grabbing one line at a time from the file using fgets() DOCs if you want the whole file then use file_get_contents() DOCs instead:
$file = file_get_contents($URL);
$buffer= strstr($file, "Montag</b>");
// If I don't use this line, the whole page gets displayed...
// If I use this line, only the first line after the needle gets displayed
echo $buffer;
Grabbing your text
This can be achieved using PHPs substr() DOCs function combined with strpos() DOCs:
$buffer = substr($buffer, strpos($buffer, 'Montag</b>'));
This will grab all the text after the first occurrence of the needle Montag</b>.
Putting it all together
$file = file_get_contents($URL);
$buffer = substr($file, strpos($buffer, 'Montag</b>'));
echo $buffer;

Related

PHP replace line at the top of a text file with fgets

I'd like to use php to open a file and replace just one line that will be near the top. Since it's near the top I don't want to read the whole file into memory. Here is what I've tested but I think I am not understanding how to backspace over the line once I identify it using strpos():
<?php
$file = "test-file.php";
$new_value = "colors:orange green violet;";
$fhandle = fopen($file, "r+") or die("Unable to open file!");
$replaced = "false";
while ($replaced === "false") {
$line = fgets($fhandle);
if (strpos($line, "colors:")) { //find the colors line
//Should I be moving the file pointer back here?
//Once I find the line, how do I clear it?
$line = $new_value;
fputs($fhandle, $line);
$replaced = "true";
}
}
fclose($fhandle);
?>
Contents of test-file.php:
fruit:apples bananas;
colors:red blue green;
cars:ford chevy;
Note: Each line in test-file.php ends with a semicolon.
You will need to read the whole file in, in order to overwrite that line, because the file you describe is a set of non-fixed lines (or put another way is a stream of characters). You won't be able to replace a part of it in-place, of a different size, without affecting characters in other lines.
You don't have to read the whole thing into memory all at once. The fgets() approach lets you read just a line at a time. The least memory intensive way to do this is to write all values to a new file, then delete (unlink()) the old file, and rename() the new file to the old filename.

What is the most efficient PHP way to read first and last line of a file?

I'm trying to open a file and determine if it is valid. It's valid if the first line is START and the last line is END.
I've seen different ways of getting the last line of a file, but it does not pay particular attention to the first line either.
How should I go about this? I was thinking of loading the file contents in an array and checking $array[0] and $array[x] for START and END. But this seems to be a waste for all the junk that could possibly be in the middle.
If its a valid file, I will be reading/processing the contents of the file between START and END.
Don't read entire file into an array if it is not needed. If file can be big you can do it that way:
$h = fopen('text.txt', 'r');
$firstLine = fgets($h);
fseek($h, -3, SEEK_END);
$lastThreeChars = fgets($h);
Memory footprint is much lower
That's from me:
$lines = file($pathToFile);
if ($lines[0] == 'START' && end($lines) == 'END') {
// do stuff
}
Reading whole file with fgets will be efficient for small siles. iF ur file is big then:
open It and read first line
use tail (i didn't check it but it looks OK) function I found in php.net in fseek documentation

PHP Creating dynamic pdf

Im trying to create a dynamic pdf using php,
I can load the pdf once the form is submitted but soon as I try to edit the pdf it fails to load
I shortened the code to keep it straight forward
PDF Structure
Your Name is : <<NAME>>
PHP Dynamic Script
set_time_limit(180);
//Create Variable Names
$name = $_POST['name'];
function pdf_replace($pattern, $replacement, $string) {
$len = strlen($pattern);
$regexp = '';
for($i = 0; $i <$len; $i++) {
$regexp .= $pattern[$i];
if($i < $len - 1) {
$regexp .= "(\)\-{0,1}[0-9]*\(){0,1}";
}
}
return ereg_replace ($regexp, $replacement, $string);
}
header('Content-Disposition: filename=cert.pdf');
header('Content-type: application/pdf');
//$date = date('F d, Y');
$filename = 'testform.pdf';
$fp = fopen($filename, 'r');
$output = fread($fp, filesize($filename));
fclose($fp);
//Replace the holders
$output = pdf_replace('<<NAME>>', $name, $output);
echo $output;
If I comment out the output it loads the form fine but soon as I try to run the function to replace the placeholder it fails to load. Anyone do something like this before?
I've tried your code and I can assume there are one of the following reasons that can cause the problem:
When you call pdf_replace() PHP returns Deprecated notice on ereg_replace() function. This breaks PDF structure and cause PDF fail to load. This function is deprecated since PHP 5.3.0. Simple solution is to start using preg_replace() instead.
function pdf_replace($pattern, $replacement, $string) {
return preg_replace('/'.preg_quote($pattern,'/').'/', $replacement, $string);
}
In case you can't do it then the solution is to either edit php.ini file and edit error_reporting parameter. You can add "^ E_DEPRECATED" to your current config value to disable Deprecated notices. Other option is to add error_reporting() at the beginning of your script with appropriate value.
I do not see the PDF you use but some PDF generators encode PDF source. In this case it is a problem to find text there. For example I've tried "Print to PDF" feature on Mac and I was not able to find plain text in source there. So either fopen or ereg_replace can complain about wrong file format. In this case you should use some library that can work with PDF in more clever manner. I prefer FPDF but there are plenty of such libraries.
I'm a web designer and I use ezPDF to create pdf files for making reports and views it in any browsers. Here's a webpage that i looked for the tutorials: http://www.weberdev.com/get_example.php3?ExampleID=4804
I hope this would be helpful :)
Your code is seemingly having two problems.
First of all, ereg_replace() is a DEPRECATED function. Due to this the php script is throwing an error and the error message breaks the pdf structure. Change the function to preg_replace() and it should work.
Secondly, I tried your code with a sample pdf-form. It seems that ereg_replace() cannot process some characters. In the pdf-form that I used, this function truncates the string(the pdf-form data) after it meets a specific character namely, ยง. Thats why even if you suppress the the error using error_reporting(E_ALL ^ E_DEPRECATED);,
the code will not work even then.
So, you better go for preg_replace();
<?php
set_time_limit(180);
//Create Variable Names
$name = $_POST['name'];
function pdf_replace($pattern, $replacement, $string) {
$len = strlen($pattern);
$regexp = '';
for($i = 0; $i <$len; $i++) {
$regexp .= $pattern[$i];
if($i < $len - 1) {
$regexp .= "(\)\-{0,1}[0-9]*\(){0,1}";
}
}
return preg_replace ($regexp, $replacement, $string);
}
header('Content-Disposition: filename=cert.pdf');
header('Content-type: application/pdf');
//$date = date('F d, Y');
$filename = 'testform.pdf';
$fp = fopen($filename, 'r');
$output = fread($fp, filesize($filename));
//fclose($fp);
//Replace the holders
$output = pdf_replace('<<NAME>>', $name, $output);
echo $output;
?>
It is not possible to replace a text string in a PDF without very specific requirements on the original PDF document.
Some comments on such project:
A PDF document uses byte offsets to allow fast access to specific objects within the document. By changing a string these offsets will get invalid and the PDF document can be seen as damaged.
At the end most content streams in a PDF document are compressed. So the string you are searching for is (maybe) in one of these streams and not "visible".
A string you "see" after a PDF is rendered has not to be the same as in the PDF source.
The replaced/new string may use characters which are not available in the used font or they are matched to other characters by an separate encoding.
And much more things to consider...
why you are not using str_replace?
please check if this code is working for you (assumed you can see the words you want to replace in simple text editor):
// hide all errors so there will be no errors output which will break your PDF file
error_reporting(0);
ini_set("display_errors", 0);
//Create Variable Names
$name = $_POST['name'];
$filename = 'testform.pdf';
$fp = fopen($filename, 'r');
$output = fread($fp, filesize($filename));
fclose($fp);
//Replace the holders
$output = str_replace('<<NAME>>', $name, $output);
// I added the time just to avoid browser caching of the PDF file
header('Content-Disposition: filename=cert'.time().'.pdf');
header('Content-type: application/pdf');
echo $output;
There are many PHP projects to generate dynamic PDF files using PHP, why you dont use them, why you are using this regular expression?, probably you will have some designs you will
have to add in the future to the pdf such as tables logos and stuff and the easiest way is to convert HTML to PDF.
If you are looking for performance and almost %100 of look alike the HTML and CSS you have you should use wkhtmltopdf its free and easy to use it runs on your server but it is not PHP it is executable file that you will have to execute it from your PHP code.
http://wkhtmltopdf.org/
another alternative is to use is pure PHP unlike the previous which is executable
http://www.tcpdf.org/
I used both and prefer the wkhtmltopdf because its faster and priciest in HTML and CSS

How to add additional text to file php

This is my code:
$open = fopen('emails.txt', 'w+');
if ($open) {
$content = "$first $last <$email>,";
if (fwrite($open, $content)) {
// ...
}
}
However, when I run this, it just replaces the text I already have in the file. How do I just add to the file, instead of replacing it?
You have to open the file in append mode, by passing a as the second parameter to fopen():
$open = fopen("emails.txt", 'a');
Then, data you write to the file will be appended to the end of the file, preserving data that was previously written to the file.
If you're only appending one block of text into the file at every request, you could look into file_put_contents() as well:
file_put_contents('emails.txt', $content, FILE_APPEND);
Shorter than having to write fopen(), fwrite() and fclose(), though the latter is more or less optional :)

Efficient flat file searching in PHP

I'd like to store 0 to ~5000 IP addresses in a plain text file, with an unrelated header at the top. Something like this:
Unrelated data
Unrelated data
----SEPARATOR----
1.2.3.4
5.6.7.8
9.1.2.3
Now I'd like to find if '5.6.7.8' is in that text file using PHP. I've only ever loaded an entire file and processed it in memory, but I wondered if there was a more efficient way of searching a text file in PHP. I only need a true/false if it's there.
Could anyone shed any light? Or would I be stuck with loading in the whole file first?
Thanks in advance!
5000 isn't a lot of records. You could easily do this:
$addresses = explode("\n", file_get_contents('filename.txt'));
and search it manually and it'll be quick.
If you were storing a lot more I would suggest storing them in a database, which is designed for that kind of thing. But for 5000 I think the full load plus brute force search is fine.
Don't optimize a problem until you have a problem. There's no point needlessly overcomplicating your solution.
I'm not sure if perl's command line tool needs to load the whole file to handle it, but you could do something similar to this:
<?php
...
$result = system("perl -p -i -e '5\.6\.7\.8' yourfile.txt");
if ($result)
....
else
....
...
?>
Another option would be to store the IP's in separate files based on the first or second group:
# 1.2.txt
1.2.3.4
1.2.3.5
1.2.3.6
...
# 5.6.txt
5.6.7.8
5.6.7.9
5.6.7.10
...
... etc.
That way you wouldn't necessarily have to worry about the files being so large you incur a performance penalty by loading the whole file into memory.
You could shell out and grep for it.
You might try fgets()
It reads a file line by line. I'm not sure how much more efficient this is though. I'm guessing that if the IP was towards the top of the file it would be more efficient and if the IP was towards the bottom it would be less efficient than just reading in the whole file.
You could use the GREP command with backticks in your on a Linux server. Something like:
$searchFor = '5.6.7.8';
$file = '/path/to/file.txt';
$grepCmd = `grep $searchFor $file`;
echo $grepCmd;
I haven't tested this personally, but there is a snippet of code in the PHP manual that is written for large file parsing:
http://www.php.net/manual/en/function.fgets.php#59393
//File to be opened
$file = "huge.file";
//Open file (DON'T USE a+ pointer will be wrong!)
$fp = fopen($file, 'r');
//Read 16meg chunks
$read = 16777216;
//\n Marker
$part = 0;
while(!feof($fp)) {
$rbuf = fread($fp, $read);
for($i=$read;$i > 0 || $n == chr(10);$i--) {
$n=substr($rbuf, $i, 1);
if($n == chr(10))break;
//If we are at the end of the file, just grab the rest and stop loop
elseif(feof($fp)) {
$i = $read;
$buf = substr($rbuf, 0, $i+1);
break;
}
}
//This is the buffer we want to do stuff with, maybe thow to a function?
$buf = substr($rbuf, 0, $i+1);
//Point marker back to last \n point
$part = ftell($fp)-($read-($i+1));
fseek($fp, $part);
}
fclose($fp);
The snippet was written by the original author: hackajar yahoo com
are you trying to compare the current IP with the text files listed IP's? the unrelated data wouldnt match anyway.
so just use strpos on the on the full file contents (file_get_contents).
<?php
$file = file_get_contents('data.txt');
$pos = strpos($file, $_SERVER['REMOTE_ADDR']);
if($pos === false) {
echo "no match for $_SERVER[REMOTE_ADDR]";
}
else {
echo "match for $_SERVER[REMOTE_ADDR]!";
}
?>

Categories