PHP Script doesn't create XML file - php

I am having some trouble with a PHP script. I am trying to do two things:
Create an XML file in /usr/local/ezreplay/data/XML/ directory and add contents to it using inputs passed to it from a HTML form;
Upload a PCAP file which is included in the submitted HTML form.
Here is my PHP (apologies it is a little long but I believe all of it is relevant here):
<?php
// Check if the 'expirydate' input is set
if (isset($_POST['expirydate'])) {
// Convert the input string to a timestamp using 'strtotime'
$timestamp = strtotime($_POST['expirydate']);
// Format the timestamp as a 'mm/dd/yyyy' string using 'date'
$expirydate = date('m/d/Y', $timestamp);
}
// Check if all required POST variables are set
if ( isset($_POST['destinationip']) && isset($_POST['destinationport']) && isset($expirydate) && isset($_POST['multiplier']) && isset($_POST['pcap']) ) {
// Set the path for the XML file
$path = '/usr/local/ezreplay/data/XML/' . trim($_POST['destinationip']) . ':' . trim($_POST['destinationport']) . ':' . $expirydate . ':' . trim($_POST['multiplier']) . ':' . trim($_POST['pcap']) . '.xml';
// Initialize the contents of the XML file
$contents = "";
// Open the XML file in append mode
if ( $fh = fopen($path,"a+") ) {
// Add the opening 'config' tag to the XML file
$contents .= '<config>';
// If the 'destinationip' and 'destinationport' POST variables are not empty, add a 'destination' tag to the XML file
if ( trim( $_POST['destinationip'] ) != "" && trim( $_POST['destinationport'] ) != "" ) {
$contents .= "\n" . '<destination>' . $_POST['destinationip'] . ':' . $_POST['destinationport'] . '</destination>';
}
// If the 'multiplier' POST variable is not empty, add a 'multiplier' tag to the XML file
if ( trim( $_POST['multiplier'] ) != "" ) {
$contents .= "\n" . '<multiplier>' . $_POST['multiplier'] . '</multiplier>';
}
// If the 'pcap' POST variable is not empty, add a 'pcap' tag to the XML file
if ( trim( $_POST['pcap'] ) != "" ) {
$contents .= "\n" . '<pcap>/usr/local/ezreplay/data/PCAP/' . $_POST['pcap'] . '</pcap>';
// Add default tags to XML config file to ensure the pcap does not fail and loops continuously until expiration date hits
$contents .= "\n" . '<loop>0</loop>';
$contents .= "\n" . '<nofail>true</nofail>';
}
// Add the closing 'config' tag to the XML file
$contents .= "\n" . '</config>';
// Write the contents to the file
if ( fwrite( $fh, $contents ) ) {
// Success
} else {
echo "The XML config could not be created";
}
// Close the file
fclose($fh);
}
}
// Set the target directory and file name
$target_dir = "/usr/local/ezreplay/data/PCAP/";
$basename = basename($_FILES["pcap"]["name"]);
$target_file = $target_dir . $basename;
// Check if the file has a pcap extension
$allowedExtensions = array('pcap');
$basenameWithoutExt = null;
foreach ($allowedExtensions as $allowedExtension) {
if (preg_match('#\\.' . $allowedExtension . '$#',$basename)) {
$basenameWithoutExt = substr($basename,0,-1 - strlen($allowedExtension));
break;
}
}
// Accept only .pcap files
if (is_null($basenameWithoutExt)) {
echo "Sorry, only .pcap files are allowed. Please try creating your Packet Replay again using a .pcap file.";
exit;
}
// Check if the file already exists
if (file_exists($target_file)) {
echo "The Packet Replay could not be started, the PCAP is already running.";
exit;
}
// Try to upload the file
if (move_uploaded_file($_FILES["pcap"]["tmp_name"], $target_file)) {
// Success
} else {
echo "Sorry, there was an error uploading your file.";
exit;
}
// Start the Packet Replay
$command = '/usr/local/ezreplay/bin/startreplay.sh ' . $path;
system($command);
echo "The Packet Replay has been started.";
?>
Now the file upload is working and I can see the final echo message being returned in my browser however the XML file is never created. I have changed the directory ownership to the apache user and even chmod 777 to eliminate any permissions issues but it still doesn't create the file.
Any ideas why this is not working? The PHP and apache error logs don't show any issues and as I mentioned the script seems to be working to a degree as the file upload takes place perfectly.
Thanks!

I think the file is not being created due to "/" in the filename. As mentioned at Allowed characters in filename

I managed to fix this with the following edits.
<?php
// Set the target directory and file name
$target_dir = "/usr/local/ezreplay/data/PCAP/";
$basename = basename($_FILES["pcap"]["name"]);
$target_file = $target_dir . $basename;
// Check if the file has a pcap extension
$allowedExtensions = array('pcap');
$basenameWithoutExt = null;
foreach ($allowedExtensions as $allowedExtension) {
if (preg_match('#\\.' . $allowedExtension . '$#',$basename)) {
$basenameWithoutExt = substr($basename,0,-1 - strlen($allowedExtension));
break;
}
}
// Accept only .pcap files
if (is_null($basenameWithoutExt)) {
echo "Sorry, only .pcap files are allowed. Please try creating your Packet Replay again using a .pcap file.";
exit;
}
// Check if the file already exists
if (file_exists($target_file)) {
echo "The Packet Replay could not be started, the PCAP is already running.";
exit;
}
// Try to upload the file
if (move_uploaded_file($_FILES["pcap"]["tmp_name"], $target_file)) {
//Success
} else {
echo "Sorry, there was an error uploading your file.";
exit;
}
// Check if the 'expirydate' input is set
if (isset($_POST['expirydate'])) {
// Convert the input string to a timestamp using 'strtotime'
$timestamp = strtotime($_POST['expirydate']);
// Format the timestamp as a 'mm-dd-yyyy' string using 'date'
$expirydate = date('m-d-Y', $timestamp);
}
// Check if 'destinationip', 'destinationport', 'multiplier' and 'pcap' required POST variables are set
if (isset($_POST['destinationip']) && isset($_POST['destinationport']) && isset($_POST['multiplier'])) {
// Set the filename and path for the XML file
$file = '/usr/local/ezreplay/data/XML/' . trim($_POST['destinationip']) . ':' . trim($_POST['destinationport']) . ':' . trim($_POST['multiplier']) . ':' . $expirydate . ':' . $_FILES["pcap"]["name"] . '.xml';
// Initialize the contents of the XML file
$contents = "";
// Add the opening 'config' tag to the XML file
$contents .= '<config>';
// If the 'destinationip' and 'destinationport' POST variables are not empty, add a 'destination' tag to the XML file
if (trim($_POST['destinationip']) != "" && trim($_POST['destinationport']) != "") {
$contents .= "\n" . '<destination>' . $_POST['destinationip'] . ':' . $_POST['destinationport'] . '</destination>';
}
// If the 'multiplier' POST variable is not empty, add a 'multiplier' tag to the XML file
if (trim($_POST['multiplier']) != "") {
$contents .= "\n" . '<multiplier>' . $_POST['multiplier'] . '</multiplier>';
}
// If the 'pcap' POST variable is not empty, add a 'pcap' tag to the XML file
if (trim($_FILES["pcap"]["name"]) != "") {
$contents .= "\n" . '<pcap>/usr/local/ezreplay/data/PCAP/' . $_FILES["pcap"]["name"] . '</pcap>';
}
// Add default tags to XML config file to ensure the pcap does not fail and loops continuously until expiration date hits
$contents .= "\n" . '<loop>0</loop>';
$contents .= "\n" . '<nofail>true</nofail>';
// Add the closing 'config' tag to the XML file
$contents .= "\n" . '</config>';
// Write the contents to the file
if (file_put_contents($file, $contents)) {
// Success
} else {
echo "The XML config could not be created";
}
}
// Start the Packet Replay
$command = '/usr/local/ezreplay/bin/startreplay.sh ' . $path;
system($command);
echo "The Packet Replay has been started.";
?>

Related

How do I create a new log file if my current log file is larger than 50mb in php?

I have a project where I have to make a new log file if the current log file is larger than 50mb. I know that we have to test for the size of the file.
I am starting out with this $log variable:
$log =
"Branch: ".$branchDir . PHP_EOL.
"Phase: ". $phaseDir . PHP_EOL.
"Total number of results files deleted: ". count($folderCounter). PHP_EOL.
"File names: " . $filePathToDelete . PHP_EOL.
"Starting CustomerID directory name: " . $CustIDvalue . PHP_EOL;
// $log = 'this is a test' . $branch . PHP_EOL;
$dt = time();
$mysql_datetime = strftime("%Y-%m-%d %H:%M:%S", $dt);
$mysql_datetimes = preg_replace('/\s+/', '', $mysql_datetime);
$logFileName = "ResultsFileDeletion" . $mysql_datetimes . ".txt";
if (unlink($filePathToDelete)) {
//this echo string will be moved to a log file
echo "first unlink: {$filePathToDelete} was deleted <br>";
$myFile =
file_put_contents("c:\\sites\\EtonBio/sequencing/logs/{$logFileName}",
$log, FILE_APPEND);
echo 'my file: ' . $myFile . '<br>';
}
I found this code snippet:
$size = filesize($_FILES['foto']['tmp_name']);
I believe my if statement would look something like this:
if($size < 52428800) {
*creates another log file
}
I want to format the $size variable correctly and I am also not sure how to make a new log file.
$size = filesize($_FILES['foto']['tmp_name']); only works if you are uploading the file.
If you want to check a file already in you server ou can simply do
$size = filesize("path/to/file");
Also, there is a ' in your $log declaration that shouldn't be there

Losing variable value when trying to copy file using mailReader.php

I'm using the mailReader script found here: https://github.com/stuporglue/mailreader
I am trying to copy the file(s) after upload to another folder.
The file(s) upload correctly to the folder where the script resides.
When I try to run a copy command, the filename variable is empty.
Here is the portion of the code I am working with: The last three lines are what I added.
private function saveFile($filename,$contents,$mimeType = 'unknown'){
$filename = preg_replace('/[^a-zA-Z0-9_-]/','_',$filename);
$unlocked_and_unique = FALSE;
while(!$unlocked_and_unique){
// Find unique
$name = time() . "_" . $filename;
$name = substr_replace($name,".pdf",-4); // added 1-19-2016
while(file_exists($this->save_directory . $name)) {
$name = time() . "_" . $filename;
$name = substr_replace($name,".pdf",-4);
}
// Attempt to lock
$outfile = fopen($this->save_directory.$name,'w');
if(flock($outfile,LOCK_EX)){
$unlocked_and_unique = TRUE;
}else{
flock($outfile,LOCK_UN);
fclose($outfile);
}
}
fwrite($outfile,$contents);
fclose($outfile);
if (copy($this->save_directory.$name, "/attachments/" . TRANS_ID . "/". $name)) {
unlink( $this->save_directory.$name );
}
I receive confirmation by email that the file(s) are uploaded, then another email with the error message.
Warning: copy(/attachments/W7652222-546/1453406138_residential-print_from_td.pdf): failed to open stream: No such file or directory in /home/myhost/public_html/mailreader/mailReader.php on line 224
224 being the line number of my added code.
The source filename is missing from in front of /attachments...
Anyone have any thoughts?
$name is defined in the while loop and may not be accessible on the upper scopes my suggestion is to change your code to this:
private function saveFile($filename,$contents,$mimeType = 'unknown'){
$filename = preg_replace('/[^a-zA-Z0-9_-]/','_',$filename);
$unlocked_and_unique = FALSE;
$name = '';
while(!$unlocked_and_unique){
// Find unique
$name = time() . "_" . $filename;
$name = substr_replace($name,".pdf",-4); // added 1-19-2016
while(file_exists($this->save_directory . $name)) {
$name = time() . "_" . $filename;
$name = substr_replace($name,".pdf",-4);
}
// Attempt to lock
$outfile = fopen($this->save_directory.$name,'w');
if(flock($outfile,LOCK_EX)){
$unlocked_and_unique = TRUE;
}else{
flock($outfile,LOCK_UN);
fclose($outfile);
}
}
fwrite($outfile,$contents);
fclose($outfile);
if (copy($this->save_directory.$name, "/attachments/" . TRANS_ID . "/". $name)) {
unlink( $this->save_directory.$name );
}
I hope this solves your problem
I ended up defining a constant of email_id in the private function saveToDb, then running a script after everything else is finished to query the table using the email_id and looping through the records moving the files.

If a URL get clicked a file name has to be changed, how do i do that?

I have this snippet in a HTML file. But I want that a file name gets changed if its opened from 1unread.txt to 1read.txt so it will get in the list of read.
<h2>Unread</h2>
<?php
foreach (glob("*1unread.txt") as $filename) {
echo "<a href='$filename'>Download {$filename}</a><br>" . "\n" ;
}
?>
<h2>Read</h2>
<?php
foreach (glob("*1read.txt") as $filename) {
echo "<a href='$filename'>Download {$filename}</a><br>" . "\n" ;
}
?>
If have read on php.net that I can change a file name with this:
bool rename ( string $oldname , string $newname [, resource $context ] )
but how do I make this happen when the download linked is used? And what does the variable $context do? I am kinda new to PHP so don't expect much from me to understand :P
Thanks anyway
download.php:
<?php
//Only offer file to download which are having "unread" or "read" in their filename.
if(!strstr($_GET['file'], 'unread') || !strstr($_GET['file'], 'read']))
die('Invalid file.');
//Make sure the file exists.
if(!file_exists($_GET['file']))
die('File not found.');
echo file_get_contents($_GET['file']);
if(strstr($_GET['file'], 'unread')) {
//rename 1unread.txt to 1read.txt
$newFileName = str_replace('unread', 'read', $_GET['file']);
rename($_GET['file'], $newFileName);
echo sprintf("RENAMED '%s' TO '%s'!", $_GET['file'], $newFileName); //Debug
} else {
//rename 1read.txt to 1unread.txt
$newFileName = str_replace('read', 'unread', $_GET['file']);
rename($_GET['file'], $newFileName);
echo sprintf("RENAMED '%s' TO '%s'!", $_GET['file'], $newFileName); //Debug
}
?>
Replace the download button with this:
echo "<a href='download.php?file=$filename'>Download {$filename}</a><br>" . "\n" ;

PHP class ImapMailbox not downloading attachments

Running Apache 2.2 with PHP 5.3 on Windows 8. Trying to get the PHP class ImapMailbox to download attachments, but each time I getMail(), the attachments value is empty on every email that has attachments.
All the rest of the email info is downloaded correctly.
I've looked through the class code but can't identify where the problem might be.
Here is my current code:
$mailbox = new ImapMailbox('{testsite.com:110/pop3/novalidate-cert}INBOX', 'testemail#testsite.com', 'MyPaSs', ATTACH_DIR, 'utf-8');
$mails = array();
foreach($mailbox->searchMailbox('SUBJECT "test attach" SINCE "' . date('m/d/Y', strtotime('-1 week')) . '"') as $mailId) {
$mail = $mailbox->getMail($mailId);
$mails[] = $mail;
}
After dumping the $data var in getMail(), it appears there are attachments in winmail.dat format. The code cannot get to these because no attachmentId value is being assigned due to an empty 'ifid' value. Decoding the winmail.dat attachments can be done, but only if they are detected and written to file.
Any ideas how create a workaround in the ImapMailbox code for this?
Here is what I wrote that fixes this problem.
At the beginning of initMailPart() method, add the following:
static $altAttachmentId = 0;
At the end of the IF block for if($this->attachmentsDir) { add the following where the closing } bracket is:
} elseif (!empty($params['fileName']) || !empty($params['filename']) || !empty($params['name'])) { // Process attachments that are not inline.
// Check if need to decode TNEF (Winmail.dat) file.
if ($partStructure->ifsubtype && $partStructure->subtype == 'MS-TNEF') {
require_once 'path_to_your/tnef_decoder.php';
$Tnef = new tnef_decoder;
$un_tnef = $Tnef->decompress($data);
$attached_files = array();
foreach ($un_tnef as $f) {
if (!empty($f['name']) && !empty($f['stream'])) {
$attachment = new IncomingMailAttachment();
$attachment->id = $altAttachmentId;
$attachment->name = $f['name'];
$attachment->filePath = $this->attachmentsDir . DIRECTORY_SEPARATOR . preg_replace('~[\\\\/]~', '', $f['name']);
$mail->addAttachment($attachment);
if (file_exists($attachment->filePath) && md5($f['stream']) != md5_file($attachment->filePath)) {
$attachment->filePath = $this->attachmentsDir . DIRECTORY_SEPARATOR . preg_replace('~[\\\\/]~', '', $mail->id . '_' . $altAttachmentId . '_' . $f['name']);
}
file_put_contents($attachment->filePath, $f['stream']);
$altAttachmentId++;
}
}
} else {
if (!empty($params['filename'])) {
$fileName = $params['filename']; // Account for random camel-case mistake on element.
} elseif (!empty($params['fileName'])) {
$fileName = $params['fileName'];
} else {
$fileName = $params['name'];
}
$attachment = new IncomingMailAttachment();
$attachment->id = $altAttachmentId;
$attachment->name = $fileName;
$attachment->filePath = $this->attachmentsDir . DIRECTORY_SEPARATOR . preg_replace('~[\\\\/]~', '', $mail->id . '_' . $altAttachmentId . '_' . $fileName);
$mail->addAttachment($attachment);
file_put_contents($attachment->filePath, $data);
$altAttachmentId++;
}
}
Note that you must include the tnef_decoder.php file found in the Roundcube Webmail package for the TNEF decoding to work. I got inspiration for the TNEF solution here.
This modification will process all TNEF encoded files in a Winmail.dat file and any other attachment that is not attached inline. Watch your memory usage on large files.
It also won't overwrite existing files that are the same name if they are not exactly the same.

PHP Delete File script

I have a basic PHP script that displays the file contents of a directory. Here is the script:
<?php
$Dept = "deptTemplate";
if(isset($_REQUEST['dir'])) {
$current_dir = $_REQUEST['dir'];
} else {
$current_dir = 'docs';
}
if ($handle = opendir($current_dir)) {
while (false !== ($file_or_dir = readdir($handle))) {
if(in_array($file_or_dir, array('.', '..'))) continue;
$path = $current_dir.'/'.$file_or_dir;
if(is_file($path)) {
echo '`'.$file_or_dir.' - [Delete button/link]<br/>`';
} else {
echo '``'.$file_or_dir."\n`` - [Delete button/link]`<br/>`";
}
}
closedir($handle);
}
?>
I am trying to create a delete link/button that displays next to each file and when clicked, the corresponding file will be deleted. Would you know how to do this?
Use the built-in unlink($filepath) function.
Sure, you'd have to use unlink() and rmdir(), and you'd need a recursive directory removal function because rmdir() doesn't work on directories with files in them. You'd also want to make sure that the deletion script is really secure to stop people from just deleting everything.
Something like this for the recursive function:
function Remove_Dir($dir)
{
$error = array();
if(is_dir($dir))
{
$files = scandir($dir); //scandir() returns an array of all files/directories in the directory
foreach($files as $file)
{
$fullpath = $dir . "/" . $file;
if($file == '..' || $file == '.')
{
continue; //Skip if ".." or "."
}
elseif(is_dir($fullpath))
{
Remove_Dir($fullpath); //recursively remove nested directories if directory
}
elseif(is_file($fullpath))
{
unlink($fullpath); //Delete file otherwise
}
else
{
$error[] = 'Error on ' . $fullpath . '. Not Directory or File.' //Should be impossible error, because everything in a directory should be a file or directory, or . or .., and thus should be covered.
}
}
$files = scandir($dir); //Check directory again
if(count($files) > 2) //if $files contains more than . and ..
{
Remove_Dir($dir);
}
else
{
rmdir($dir); //Remove directory once all files/directories are removed from within it.
}
if(count($error) != 0)
{return $error;}
else
{return true;}
}
}
Then you just need to pass the file or directory to be deleted through GET or something to the script, probably require urlencode() or something for that, make sure that it's an authorized user with permissions to delete trying to delete the stuff, and unlink() if it's a file, and Remove_Dir() if it's a directory.
You should have to prepend the full path to the directory or file to the directory/file in the script before removing the directory/file.
Some things you'll want for security is firstly making sure that the deletion is taking place in the place it's supposed to, so someone can't do ?dir=/ or something and attempt to delete the entire filesystem from root, which can probably be circumvented by prepending the appropriate path onto the input with something like $dir = '/home/user/public_html/directories/' . $_GET['dir'];, of course then they can potentially delete everything in that path, which means that you need to make sure that the user is authorized to do so.
Need to keep periodic backups of files just in case.
Something like this? Not tested...
<?php
echo '`'.$file_or_dir.' - [Delete button/link]<br/>`';
?>
<?php
if ($_GET['del'] == 1 && isset($_GET['file_or_dir']){
unlink ("path/".$_GET['file_or_dir']);
}
?>
I've worked it out:
I added this delete link on the end of each listed file in the original script:
- < a href="delete.php?file='.$file_or_dir.'&dir=' . $dir . '"> Delete< /a>< br/>';
This link takes me to the download script page, which looked like this:
<?php
ob_start();
$file = $_GET["file"];
$getDir = $_GET["dir"];
$dir = 'docs/' . $getDir . '';
$isFile = ($dir == "") ? 'docs/' . $file . '' : '' . $dir . '/' . $file . '';
if (is_file($isFile)){
if ($dir == "")
unlink('docs/' . $file . '');
else
unlink('' . $dir . '/' . $file . '');
echo '' . $file . ' deleted';
echo ' from ' . $dir . '';
}
else{
rmdir('' . $dir . '/' . $file . '');
echo '' . $dir . '/' . $file . ' deleted';}
header("Location: indexer.php?p=" . $getDir . "");
ob_flush();
?>
It all works brilliantly now, thank you all for your help and suggestions :)

Categories