Editing files in PHP - php

Is there a way to append or remove a line of text from a file using PHP.
I am in the process of writing a hosting control panel for my specific web hosting stack and would like to be able to make changes to the files with minimal requirements to touch the file system, and as such would like not to have to rewrite the whole file to add or remove a configuration option.

There is no way to remove a line from a file without first parsing the file into lines and then writing it out again.
You can append to a file by using fopen with the $mode set to 'a'
$fp = fopen('myfile', 'a');

For appending, you should use fopen with the $mode of a.
See this please, on how to delete a line from the file.

Yes, you can open files in append mode:
$fh = fopen('testFile.txt', 'a');
If you now write to the file, the new content gets appended.
See fopen and from this documentation:
'a': Open for writing only; place the file pointer at the end of the file. If the file does not exist, attempt to create it.
Removing the last line is not possible though.

Working with files in PHP is full of pitfalls, particularly wrt concurrency and locking. The fact that you are writing config files implies also that you are exposing tasks normally only available to a user with root privileges over the web. You did not mention these things in your post, but your question is trivial in comparison to addressing these issues.
Regarding your question - although its fairly trivial to implement what you propose (e.g. by exec'ing sed - although you did not did say what OS this is running on) I'd recommend creating a copy of the original file in some other representation - obvious candidates would be a database - where you can apply sequence numbers to the lines and easily create a gap to populate, or a PHP SplDoublyLinkedList stored in the session. Then once the user has effected as many changes as they require, regenerate the file in a single operation from the working representation.
Note that, ultimately, regardless of how you implement the solution the solution will rewrite the entire file - its just a question of how much of this process is exposed within your code.
Bear in mind, that what you are doing is just the same as most php web scripts - except while they manipulate and reqrite HTML, you're doing it with a different file type - so you might want to look at how other PHP templating systems are written, and consider whether you can create a template for your config files.
HTH
C.

If you need to change something in the middle of the file, you have to read it, parse it and save it back. Othwerwise you can only append something to the end of it.
You should not be concerned about the cost of this operation though, as it's a configuration file that won't likely be changed a hundred times every second, it should take negligible time.
If you want more flexibility in access/update/delete I think you should consider moving your configuration file to a database table.

Related

Make a second url link to the same directory as a different url, without copying the content to a second directory?

I have files in a directory, "w", and I want to have those same files accessible from a different directory.
I have a MediaWiki installation in the directory 'w', creating a short url to link to the url 'wiki'. I have the files in the 'w' directory but it can be accessed from http://example.com/wiki. I want to have a second wiki entirely with the url format of http://example.com/second-wiki.
Since MediaWiki uses the content of files from a database the code never actually needs to change, even the LocalSettings.php. I set up a database system, modified the MediaWiki system, and created multi wiki support in a single database, by using a database table with input information such as the url to use. Or even use the same files and add a localsettings.php file to a directory 'w2' but use everything else from the original directory, 'w'. Is this possible? Preferably using .htaccess, or some other equally easy to edit. I don't want any changes to php configuration though.
I believe this may help...... - it is a simple redirect done in PHP so it is easy to edit later, etc.
I'll work with the fact you have a 'w' directory accessed by http://example.com/wiki and you want to access that through http://example.com/second-wiki (where 'magic' will be done to actually open the other URL).
In the 'w2' folder, make an index.php file with the following contents:
<?php
header("Location: ../w");
// NOTE: you may need to make that w/index.php or other pointer
exit();
Now, any time you access http://example.com/second-wiki, you will actually see http://example.com/wiki
Simple and easy to change later if you need to!
Not sure from the question that this is the solution (it fits the topic and some of the question text, though the question text does 'jump around' a bit...) - if it isn't, please rephrase the question to be more clear on just what you are looking for (in one place you say "the code never actually needs to change, even the LocalSettings.php" - then in another you talk about needing separate settings.....) - however, if you are looking for the 'simplest' (IMHO) way to make multiple URLs point to the same folder, this is the way to go - pure PHP and easy to mod later!

PHP file changes its extension to ".suspeced"

I have two php files on server that keep changing their extension over night. For example, file.php changes to file.php.suspected
What these two files have in common is mail() function. For example,
$mail_success = mail($_POST["email_to"], stripslashes($_POST["email_subject"]), stripslashes($_POST["email_body"]), $_app["email_headers"]);
There is nothing else that these files have in common. So, something on the server goes through the files over night and apparently dislikes these files with mail() function, changing their extension or rather adding .suspected extension to .php extension.
After a couple minutes of googling, it looks like a PHP file changing filetypes is the sign of a hacked server. Here is a post on the CPanel forums, where a guy has a similar issue and the other commenters decide that his server had been hacked.
I personally can't give you any advice to secure your site, but perhaps you should head over to SysAdmin or another community and look into making your server more secure.
I'm about 3 years late, but...
I found a piece of WordPress malware that does exactly what you describe.
It's something of a cleaner - it has 56 different functions to decide is a given ".php" file name constitutes code that needs to be rendered inoperable.
One of those indicators is a substring of what you say the two renamed files have in common:
function ryypkex($content)
{
if (strpos($content, " = mail(\$_POST[") !== FALSE) {
return TRUE;
}
If a given filename's contents match a condition, that filename gets its ".php" suffix changed to ".php.suspect".
The two instances of this cleaner that my honey pot caught use the "RC" action of the WSO web shell to immediately execute the cleaner. No on-disk cleaner code will exist. The implication is that you probably need to look for a WSO web shell somewhere in your web apps' code.

php processing of include files

This question has to do with the internal mechanics of the PHP engine. I'm asking it in an effort to understand the file include process.
Say, you got a 20,000 lines include file ( something like "functions_library.php" ) that gets included on all your php scripts.
Does PHP check/verify if that include file is syntactically correct every single time one of your php scripts load that file? Does this process happen at each page load over and over and over again?
Or...
Does PHP pay attention to the file's last modification date? If it turns out that there were no changes to it since the last check, does it simply ignore the checking?
On a default installation, the file will be parsed every single time. However, any production installation of PHP is recommended to have a bytecode cache, such as APC or many others. When bytecode cache is used, the script is parsed the first time and the interpreted code will be stored in memory.
Different configurations may alter how often file modifications are checked. Under some configurations, for very high performance, manual flushing or restarting the web server may be required.
If you include that file, PHP will need to interpret it every time.
PHP will re-interpret the file every time you call include().
This can be tested visually with the use of variables. If you have something like this:
otherScript.php:
<?php echo $foo; ?>
script.php:
<?php
$foo = 1;
include("otherScript.php");
$foo = 2;
include("otherScript.php");
?>
The output will be:
12
This is a poor example, but it should demonstrate the PHP will need to include the contents of the file each time. It is a pretty good guess to state that the PHP interpreter won't keep a copy of the included file in memory for each reference - there can be hundreds of includes per application.
To deal with this specific ideal, however, they provide a method include_once() that will, as the name implies, only include the file one time and prevent it from being included any additional times.

Searching a log file using PHP from input pattern

My problem is to create a search function that can search within a log file.
The pattern is something like this:
node-id > command
-Date-other descriptions
Output starts
Output ends
node-id > another command
Now, the problem I have is to cut the output of one command from one log file and compare it with the output from another log file for comparison. I am not able to find a way to search the content and store it into an array or file for further comparison.
You can't cut stuff from a file, you can only change the file and re-save it (you could potentially cut stuff, depending on your file system, directly manipulating the same, but asking this question here means you don't have such low-level file system experience)
In php it would be something like:
$data = file_get_contents($fileToCutFrom);
// ... modify data here, e.g. if it's xml you might wanna use SimpleXML or DOMDocument or some other xml parser, like ganon ( https://code.google.com/p/ganon/ ) - the later one is pretty good if you know you might have incomplete/invalid xml
file_put_contents($fileToCutFrom, $modifiedData);
// and now append to the other file
file_put_contents($fileToAppendTo, $dataToAppend, FILE_APPEND);
Know however that you might get into serious race conditions if you do this from more than one file, as file_get_contents is not atomic, and neither is file_put_contents, and then you also have the problem of having multiple lines to execute. So if your code might get executed several times at once, you might wanna use a single script instance which does all the "cutting" and appending opening up a socket and the other scripts just send what they need to that file.
Also, if you wanna continuesly do that whenver new data comes in, you might wanna have a look at inotify (linux) or the equivalent on your system (osx also has a file notification service, but I don't know about windows)
If you need something different, you might wanna add information to your question.

PHP - Shortcomings of fwrite?

I am working on a file-handler class and am running into some issues with file streams. Providing functionality for operations such as append and overwrite are a simple matter of changing the mode passed to fopen.
However, providing an easy way to insert, update, and delete is proving to be more challenging. Pretty much, all the problems I'm having is with fwrite.
Insert - As far as I can tell, there is not a way to insert characters at a location other than the end of the file using fwrite. The two options I've come up with is using file_get_contents and heavily using fseek/fwrite to extend the file.
Delete - Unfortunately, trying to write NULL using fwrite is not the same thing as a 'deleting' a character. As with inserting data, the options again are file_get_contents and fseek/fwrite.
Update - Updating data within a file is a combination of the insert/delete problems. If the new value is shorter than the old value, then I'd have to delete the additional characters. If the new value is longer than the old value, I'd have to insert the additional characters. If they are the same length, then simply using fwrite will be fine.
Hopefully, there is something I'm not aware of which can resolve this problem cleanly. Each of the options I found use either file_get_contents (which I don't care for since the entire file must be read into memory) or heavily use fseek/fwrite to change the file's length (which seems convoluted to me).
Does anyone have an idea I haven't thought of?
Thanks!
You could always use fseek() and fwrite() to shuffle the file in fixed-size 'chunks' rather than using file_get_contents(). The logic is fairly straightforward, but I suspect it would be cumbersome and slow if implemented directly in PHP rather than as a C library.
That's it. Pretty much every language will do it the same way. The recommended way is to use a temporary file, and transfer the original file piece by piece, then atomically move the temp file over the original.
However, there are programs that do such things for you, and in a much more optimized way - primarily database engines.

Categories