Updated Situation:
I have managed to create a registration form that outputs the data to a new CSV file for use into a separate database. However the code that sends the attachment doesn't work, but the system stores the file into a separate folder (I must stress this is while I am testing).
My question is, can I both create the CSV file and send it via email? If so, what do I need to do?
I am also aware that there are security risks: One suggestion has been to store the CSV files outside to root directory. is this foolproof and if not, could anyone make any recommendations?
My code is:
<?php
$_POST['password'] = md5($_POST['password']);
$headers=array_keys($_POST);
$file = "csv/" . $_POST['username'].date('Ymdhis').".csv"; //filename
$file = fopen($file, 'a');
fputcsv($file, $headers);
fputcsv($file, $_POST);
fclose($file);
require_once('email/PHPMailerAutoload.php');
$m = new PHPMailer;
$m->isSMTP();
$m->SMTPAuth = true;
$m->SMTPDebug = 0;
$m->Host = 'mymail.com';
$m->Username = 'me#mymail.com';
$m->Password = 'mypass';
$m->SMTPSecure = 'SSL';
$m->Port = 26;
$m->From = 'me#mymail.com';
$m->FromName = 'My name';
$m->addReplyTo('me#mymail.com', 'Reply Address');
$m->AddAddress('me#mymail.com', 'My name');
$m->isHTML(true);
$m->addAttachment('csv/data.csv', 'data.csv');
$m->Subject = 'New feed ';
$m->Body = '<p>This is an email just sent from our website</p><p><strong>Please import into your database.</strong></p>';
$m->AltBody = 'This is the body. Please import into the database';
if($m->send()) {
echo '<h1>Thank you</h1> <p>We have received your Registration and will send you confirmation details shortly.</p>';
} else {
echo $m->ErrorInfo;
}
I also have a checkbox field that needs to be written with the commas separating the values, for example 1,2,3. How can I write this?
Any assistance/advice will as always be gratefully received.
Many thanks in advance.
$_POST['id']="101"; //example data
$_POST['username']="kraysak"; //example data
$_POST['password']="grumpycat"; //example data
$_POST['usergroup']="admin"; //example data
$_POST['lastaccess']="14-10-2014 00:01"; //example data,
$_POST['password'] = md5($_POST['password']);
$headers=array_keys($_POST);
$file = $_POST['username'].date('Ymdhis').".csv"; //filename
$file = fopen($file, 'a');
fputcsv($file, $headers ); //write headers (key of the $_POST array (id,username,password,etc)
fputcsv($file, $_POST );
fclose($file);
this create a file named kraysak20141014010253.csv with the next information:
id,username,password,usergroup,lastaccess
101,kraysak,5557981401e83c1963412f19c7487965,amdin,"14-10-2014 00:01"
is hard for me to explain, (my english isn't good enought) but fputcsv funtion write the content of an array in the file, and $_POST is an array... so, you dont need to create new variables, you only need to use md5() function in one variable.
fputcsv consists of two parameters; location and content. So;
fputcsv(location, content);
or
$fileNameVariable = 'blah';
$fileName = $fileNameVariable . date('Ymdhis') . '.csv';
$fp = fopen('/exampleDirectoryName/' . $fileName, 'w');
$headers = array ('info1', 'info2', 'info3');
fputcsv($fp, $headers);
You can adapt this exmaple for your situation pretty easily.
Try:
$csvname=md5(rand());
$fp = fopen("csv/$csvname.csv", "w");
$savearray = [ $name, $email, $password, $usergroup, $lastsid, $fname, $lname, $lastaccess, $company, $phone, $addone, $addtwo, $city, $stateprov, $country, $postalcode, $rescom, $addbook, $subscriptions, $affilid, $affilcommpct, $affilsalestodate, $affilcommearned, $affilcommowed, $affilcommpaid, $whlsalepct, $show_currency, $loyaltypoints ];
fputcsv($fp, $savearray);
fclose($fp);
Use array() on $savearray instead of [] for older php versions.
Related
So for an assignment, I have to create a form where users can post ride shares so other people can see and join their ride. I'm doing this by writing the form to a file data.txt, and reading the file to display all the rides on a board. My only problem is when I get the contents of data.txt, it's all combined together. I need to be able to display each ride separately. How would I go about doing this?
Here is my code so far:
The writing:
if (isset($_POST['name'])
&& isset($_POST['email'])
&& isset($_POST['date'])
&& isset($_POST['destination'])
&& isset($_POST['msg'])) {
$name = $_POST['name'];
$email = $_POST['email'];
$date = $_POST['date'];
$destination = $_POST['destination'];
$msg = $_POST['msg'];
//TODO the file write here VV, use 'a' instead of 'w' too ADD to the file instead of REWRITING IT.
$arr = [$name,$email,$date,$destination,$msg];
$write = json_encode($arr);
$file = fopen('data.txt', 'a');
fwrite($file, $write);
fclose($file);
}
And the reading:
$path = 'data.txt';
$handle = fopen($path, 'r');
$contents = fread($handle, filesize($path));
echo $contents;
fclose($handle);
$newarr = [json_decode($contents)];
foreach($newarr as $stuff)
{
echo $stuff[0];
}
And the output is something like:
["Simon Long","example#gmail.com","2109-01-01T01:01","canada","this is a message"] Simon Long
Let's say there are multiple postings in there, it would just print them all together. I need a way to separate postings so I can display them nicely on the board.
Use a multidimensional array.
$arr = [
"Simon Long","example#gmail.com","2109-01-01T01:01","canada","this is a message",
"John Doe","john#gmail.com","2109-01-01T01:01","canada","this is a message",
"Jane Doe","jane#gmail.com","2109-01-01T01:01","canada","this is a message"
];
Then you when you add to it just append to the final array and replace the whole file.
$contents = file_get_contents($path);
$decoded = json_decode($contents);
$decoded[] = [$name,$email,$date,$destination,$msg];
file_put_contents($path, json_encode($decoded)); //replace the entire file.
Also just as a side note. isset accepts multiple arguments so you don't need to use it as you are. You can do this:
if (isset($_POST['name'], $_POST['email'], $_POST['date'], $_POST['destination'] ...)
It's also a good idea to sanitise any input from the user.
$name = filter_input(INPUT_POST, 'name', FILTER_SANITIZE_STRING);
I want to import a .csv file with headers such as name, email etc. as part of mail merge functionality in our web app (we are using Symfony 3.4). I have so far successfully managed to persist the .csv file to the database using Doctrine when I know what the headers on the .csv are going to be. I also need to be able to give the user the option of changing the header of the columns in case the headers are different or auto-matching on import doesn't work.
Is the best option here to persist the information to the database and then move the data using Doctrine, or is there some way to give the user the option to match columns before persisting? I am relatively new to both Symfony and Doctrine so I can't see the solution.
Here is the code from the controller:
public function usersListUploadAction(Request $request) {
// grab uploaded .csv file
$file = $_FILES["file"]["tmp_name"];
$fileimplode = implode("/", $file);
// convert .csv if made on mac
if (!ini_get("auto_detect_line_endings")) {
ini_set("auto_detect_line_endings", '1');
}
// create associative array from .csv
$reader = Reader::createFromPath($fileimplode);
$addedUsers = $reader->fetchAssoc();
$em = $this->getDoctrine()->getManager();
foreach($addedUsers as $row) {
// check for existing users
$emailAddress = $row["Email Address"];
$user = $this->get('manager_user.repository')->findByEmailAddressWithoutParents($emailAddress);
if ($user === []) {
// create new user
$userTypeId = 1;
$role = $request->get('roles', []);
$firstname = $row["First Name"];
$surname = $row["Last Name"];
$email = $row["Email Address"];
$username = (strtolower($row["First Name"].".".$row["Last Name"]));
$phone = null;
$userBuilder = $this->get('manager_user.manager')->newUser(
$userTypeId,
$username,
$phone,
$email,
$role,
$password = null,
$organisation = null,
$emailResetPasswordLink = 0,
$firstname,
$surname,
$name = null,
$roles = []
);
$user = $userBuilder;
// add email to contact_methods
$cmType = $this->get('manager_user_contact_method_type.repository')->find(ContactMethodTypeInterface::EMAIL);
$cmEmail = $this->get('manager_user_contact_method.builder')->createNew($cmType, $row["Email Address"], $user, 1);
$em->persist($userBuilder);
$em->persist($cmEmail);
}
$em->flush();
}
// return to user list page with list updated from .csv users
$listId = $request->get('listId');
$list = $this->get('manager.email.list_repository')->find($listId);
$status = 1;
//loop over the added users
foreach($addedUsers as $row) {
$userNameLower = (strtolower($row["First Name"].".".$row["Last Name"]));
$userId = strval($this->get('manager_user.repository')->getUserIdByUserName($userNameLower));
$user = $this->get('manager_user.repository')->find($userId);
if(!$user->isInList($list)) { //this user is not in the list already so add it
$dateSubscribed = new \DateTime();
$emailCampaignListUser = new EmailCampaignListUser($user, $list, $dateSubscribed, $status);
$em->persist($emailCampaignListUser);
}
}
$em->flush();
return $this->redirectToRoute('manager_email_campaign_lists_users_upload_check', array('listId' => 1));
}
I provide you an example (not full).
AS i ve commented you can process like this.
First step, the user can match expected fields with csv's header fields
Import data using the mapping previously made.
For the first step, you can choose the frontend solution you want, like Drag&Drop.
In my opinion you've to define your keys
//this is your code
//Here we define that "firstname" is your key for the first name
$fields = ["firstname","lastname"];
Second part of the first step is getting CSV header, using fgetcsv on the first line (header line)
if (($handle = fopen("yourcsv.csv", "r")) !== FALSE) {
//Here you get all csv headers
$header = fgetcsv($handle, 1000, ",");
fclose($handle);
}
At this point after you (or the user) do the mapping, you can store the mapping in database if this is a real need or simply use POST to get the mapping at the second step.
Second Step we parse the csv file skipping the first line and use the mapping previously done to get data correctly.
//Your mapping is stored in $mapping by example
//it contains "fieldname" => "csv index" example "firstname" => 3
if (($handle = fopen("test.csv", "r")) !== FALSE) {
//skip header line here
fgetcsv($handle, 1000, ",");
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
//$data contain each user data
$userBuilder = $this->get('manager_user.manager')->newUser(
$data[$mapping['firstname']],
$data[$mapping['lastname']],
//etc...
);
}
fclose($handle);
}
Hope this helps and clear.
`
$file = fopen("test.txt", "r");
$members = array();
var_dump($members);
$mail->addAddress ($members);
enter code here
//I would like to assigned $members which has email address in file and assigned to $mail->addAddress
?>`
$output = sprintf("%s email.\n",$row['email']);**strong text**
$mail->addAddress ($row['email']);
Title of this question explains the workflow i am trying to achieve.
So i have made email piping to script.php in my c-panel. It works, even though it always returns message: "Mail delivery failed: local delivery failed" to the sender email. But that's not an issue her, i guess :)
I have tested piping with a test script:
#!/usr/bin/php -q
<?php
$fd = fopen("php://stdin", "r");
$email = "";
while (!feof($fd)) {
$email .= fread($fd, 1024);
}
fclose($fd);
$filename = rand(7, 100000).'email'.time();
$fdw = fopen("/home/user/public_html/project/emails/" . $filename, "w+");
fwrite($fdw, $email);
fclose($fdw);
?>
As a result i get .txt file which contains all the email content.
Lets go further: Now i use this script to capture previously created file, parse it (get all the html table cell values, which is in email body region) and then connect to drupal and finally create node containing html table cell value information:
#!/usr/bin/php -q
<?php
$email = file_get_contents("emails/80358email1406727227.txt");
$parsed = getTextBetweenTags('td', $email);
$trimmed_array=array_map('trim',$parsed);
function getTextBetweenTags($tag, $html, $strict=0)
{
//a new dom object
$dom = new domDocument;
//load the html into the object
if($strict==1)
{
$dom->loadXML($html);
}
else
{
$dom->loadHTML($html);
}
// discard white space
$dom->preserveWhiteSpace = false;
// the tag by its tag name
$content = $dom->getElementsByTagname($tag);
// the array to return
$out = array();
foreach ($content as $item)
{
// add node value to the out array
$out[] = $item->nodeValue
}
// return the results
return $out;
}
//connect to drupal
define( 'DRUPAL_ROOT', $_SERVER['DOCUMENT_ROOT'] );
$base_url = 'http://' . $_SERVER['HTTP_HOST'];
require_once DRUPAL_ROOT . '/includes/bootstrap.inc';
drupal_bootstrap( DRUPAL_BOOTSTRAP_FULL );
//create new node
$node = new stdClass();
$node->type = "Task";
node_object_prepare($node);
$node->title = $trimmed_array[0];
$node->language = 'en';
$node->status = 1;
$node->uid = 1; // UID of the author of the node; or use $node->name
$node->field_num['und'][0]['value'] =$trimmed_array[1];
$node->field_status['und'][0]['tid'] = 1 ;
...
node_save($node);
I manually execute the code above, it works, it takes .txt file, parses it, saves table cell values in array, connects to drupal, and creates a new node of type "task", but the problem starts when i change
line
$email = file_get_contents("emails/80358email1406727227.txt");
to line
$email = file_get_contents("php://stdin");
so when i send email, it gets piped to script, and it doesnt create a new node.
Im stuck here, any thoughts?
Why script can do the job when opening a .txt file, but does nothing when reads from stdin?
I tried and looked for a solution, but cannot find any definitive.
Basically, I have a txt file that lists usernames and passwords. I want to be able to change the password of a certain user.
Contents of users.txt file:
user1,pass1
user2,pass2
user3,pass3
I've tried the following php code:
// $username = look for this user (no help required)
// $userpwd = new password to be set
$myFile = "./users.txt";
$fh = fopen($myFile,'r+');
while(!feof($fh)) {
$users = explode(',',fgets($fh));
if ($users[0] == $username) {
$users[1]=$userpwd;
fwrite($fh,"$users[0],$users[1]");
}
}
fclose($fh);
This should works! :)
$file = "./users.txt";
$fh = fopen($file,'r+');
// string to put username and passwords
$users = '';
while(!feof($fh)) {
$user = explode(',',fgets($fh));
// take-off old "\r\n"
$username = trim($user[0]);
$password = trim($user[1]);
// check for empty indexes
if (!empty($username) AND !empty($password)) {
if ($username == 'mahdi') {
$password = 'okay';
}
$users .= $username . ',' . $password;
$users .= "\r\n";
}
}
// using file_put_contents() instead of fwrite()
file_put_contents('./users.txt', $users);
fclose($fh);
I think when you get that file use file_get_contents after that use preg_replace for the particular user name
I have done this in the past some thing like here
$str = "";
$reorder_file = FILE_PATH;
$filecheck = isFileExists($reorder_file);
if($filecheck != "")
{
$reorder_file = $filecheck;
}
else
{
errorLog("$reorder_file :".FILE_NOT_FOUND);
$error = true;
$reorder_file = "";
}
if($reorder_file!= "")
{
$wishlistbuttonhtml="YOUR PASSWORD WHICH YOU WANT TO REPLACE"
$somecontent = $wishlistbuttonhtml;
$Handle = fopen($reorder_file, 'c+');
$bodytag = file_get_contents($reorder_file);
$str=$bodytag;
$pattern = '/(YOUR_REGEX_WILL_GO_HERE_FOR_REPLACING_PWD)/i';
$replacement = $somecontent;
$content = preg_replace($pattern, $replacement, $str,-1, $count);
fwrite($Handle, $content);
fclose($Handle);
}
Hope this helps....
The proper way of doing this is to use a database instead. Databases can do random access easily, doing it with text files less so.
If you can't switch to a database for whatever reason, and you don't expect to have more than about a thousand users for your system, then it would be far simpler to just read the whole file in, convert it to a PHP data structure, make the changes you need to make, convert it back into text and overwrite the original file.
In this case, that would mean file() to load the text file into an array with each element being a username and password as a string, explode all elements on the array at the comma to get the username and password separately, make the changes you need to make, then write the modified data to disc.
You might also find fgetcsv() useful for reading the data. If you SplFileObject and have a recent version of PHP then fputcsv() may also be available to write the data back out.
However, just using a database is a far better solution. Right tool for the job.
$fn = fopen("test.txt","r") or die("fail to open file");
$fp = fopen('output.txt', 'w') or die('fail to open output file');
while($row = fgets($fn))
{
$num = explode("++", $row);
$name = $num[1];
$sex = $num[2];
$blood = $num[3];
$city = $num[4];
fwrite($fp, "Name: $name\n");
fwrite($fp, "Sex: $sex\n");
fwrite($fp, "Blood: $blood\n");
fwrite($fp, "City: $city\n");
}
fclose($fn);
fclose($fp);
If you're on a *nix system you could use sed; I find it neater than playing with file handles etc:
exec("sed -i '/^$username,.\+\$/$username,$userpwd/g' ./users.txt 2>&1", $output, $return);
If not I'd agree with GordonM and parse the file into a PHP data structure, manipulate it, then put it back:
$data = file_get_contents('./users.txt');
$users = array_map(function($line) {
return explode(',', $line);
}, explode("\n", $data));
foreach ( $users as $i => $user ) {
if ( $user[0] == $username ) {
$user[1] = $userpwd;
$users[$i] = $user;
}
}
file_put_contents('./users.txt', implode("\n", array_map(function($line) {
return implode(',', $line);
}, $users)));
There are, of course, an infinite number of ways of doing that!