Who wants to touch my PHP?

Functional HTML form poops data to this thing, which then supposedly creates a file and then either sits on it or shoots it to someone else.

Except that it hates me and won’t do diddly squat. After hours of dicking around I’ve grabbed all the bugs I can find, but now my weak and burn-y eyes are failing me.

As far as I can tell, I’m screwing up with creating the file, and am pretty much unable to think further. Since I’ve been making functionally random changes to it at this point, I figured it was time to call for halp from people who aren’t crazy. Halp!

Yes there is a mail exchanger on the box, I use it for another script that IS working. Yes the HTML form is posting fine. Yes it calls up the right script (I echo’d swear words at myself a few times to check). No none of the variables are misspelled (although those aren’t technically the HTML variables I’m using, call me paranoid. Yes it has correct permissions.

If someone figures out what blindingly obvious thing I have done wrong, I will send you something I didn’t cook so that you won’t die. Possibly it will be a PM with a picture of a spider.

<!DOCTYPE html>
<html>
    <title></title>
<body>
<?php

function handleMail($path, $fileName, $quarter){
    $from_mail = 'redact';
    $from_name = 'redact';
    $replyto = $from_mail;
    $mailto = 'redact';

    $message = 'nerp';
    $subject = $quarter. 'derg';

    $file = $path.$filename;
    $file_size = filesize($file);
    $handle = fopen($file, "r");
    $content = fread($handle, $file_size);
    fclose($handle);
    $content = chunk_split(base64_encode($content));
    $uid = md5(uniqid(time()));
    $name = basename($file);
    $header = "From: ".$from_name." <".$from_mail.">
";
    $header .= "Reply-To: ".$replyto."
";
    $header .= "BCC: " . $from_mail;
    $header .= "MIME-Version: 1.0
";
    $header .= "Content-Type: multipart/mixed; boundary=\"".$uid."\"

";
    $header .= "This is a multi-part message in MIME format.
";
    $header .= "--".$uid."
";
    $header .= "Content-type:text/plain; charset=iso-8859-1
";
    $header .= "Content-Transfer-Encoding: 7bit

";
    $header .= $message."

";
    $header .= "--".$uid."
";
    $header .= "Content-Type: application/octet-stream; name=\"".$filename."\"
"; // use different content types here
    $header .= "Content-Transfer-Encoding: base64
";
    $header .= "Content-Disposition: attachment; filename=\"".$filename."\"

";
    $header .= $content."

";
    $header .= "--".$uid."--";
    if (mail($mailto, $subject, "", $header)) {
        echo "mail send ... OK"; // or use booleans here
    } else {
        echo "mail send ... ERROR!";
    }
}
        
//main

$toFile[0] = $_REQUEST('a');
$toFile[1] = $_REQUEST('b');
$toFile[2] = $_REQUEST('c');
$toFile[3] = $_REQUEST('d');
$toFile[4] = $_REQUEST('e');
$toFile[5] = $_REQUEST('f');
$sendNow = $_REQUEST('g');

$curDate = getdate();
$day = $curDate[mday];
$month = $curDate[mon];
$year = $curDate[year];
$quarter = $year;


if($isnull($toFile[3]) == true) {
    $toFile[3] = $day . "." . $month .  "." . $year; 
}

for($i = 0; $i < 6; $i++) {
    if ($i== 0){
        $fileContent = PHP_EOL . $toFile[i] . ',';
    }
    
    $fileContent .= $toFile[i] . ', ';
}

$fileName = $month . 'm' . $year . 'y' . '.txt';
$path = './'.$fileName;

$file=fopen($fileName,'a') or exit("Unable to open file!");

file_put_contents($file, $fileContent, FILE_APPEND);

if ($day > 29) {
    switch ($month) {
        case 3:
            $quarter .= ' Q1';
            handleMail($path, $fileName, $quarter);
            break;
        case 6: 
            $quarter .= ' Q2';
           handleMail($path, $fileName, $quarter);
            break;
        case 9: 
            $quarter .= ' Q3';
            handleMail($path, $fileName, $quarter);
            break;
        case 12: 
            $quarter .= ' Q4';
            handleMail($path, $fileName, $quarter);
            break;
    }
}
//debug

if ($sendNow ==1){
    $quarter = 'DEBUG';
    handleMail($path, $fileName, $quarter);
    echo "sent DEBUG message";
}
else if ($day > 29) {
    echo "message sent";
}
else {
    echo "info saved";
}

?>
               
</body>
</html>

I think you need square brackets when indexing $_REQUEST. Is the $isnull meant to be is_null? file_put_contents doesn’t need the file to be opened first, just give it the filename as the first parameter. Are you sure you have write permission to the directory, based on what user the web server runs as?

After fixing those up, it at least creates a file and dumps some stuff in it on my system.

file_put_contents takes a file name (string), not a file handle

Swapping from string to file handle was one of the semi random changes. Also goddamn netbeans IDE, yes the square brackets would be right. Why doesn’t it catch stuff like that?

is it working now?

It does, but I’m waiting on the guy who runs the box to do something funky with the permissions to let me write stuff.

Right now all it does is make a sad face (note to self: learn ASCII art, make sad face, echo that ish on errors). Well, ok, it runs on 0777 but even I know that that’s a bad thing. I don’t know why exactly, but I know it is double plus ungood.

Thanks folks. You guys were a big help. I’ll be sure to bring all PHP related angar here.

… why would my (corrected and heavily modified) script be filling a .txt with:

Array, Array, Array, Array, Array, Array, 

That’s a direct copy paste. I have no idea what the heyo is happening here, but it sure as hell shouldn’t be.

Any ideas?

You’re outputing a variable that is an array? Probably helpful to post your new code, otherwise its quite hard to say anything more helpful.

You could try running your script with

error_reporting(E_ALL);

at the top. All the warnings may lead you in the right direction.

Mmm, I tried error reporting but I made the brackets switch error so it was a no dice. I’ll give it a shot tomorrow and let you know.

PHP has so many fun and interesting ways to screw up! Seems like you need a community to help until you’ve hit the fifty script mark.

Thanks.

That can happen if you try to ‘echo’ an array variable without indexing it. If that’s what you actually want to do, use print_r instead.

I.e.,


$foo[0] = "bar";
$foo[1] = "baz";
echo $foo;       // prints 'Array'
print_r($foo);   // prints array properly

I’m using a for loop to put it into the file, since that’s what I’m used to doing when outputting data from arrays. Also I want to add commas without putting them into the array, because I’m planning to send an email to boss about stuff once it’s been databases. Wasnt even aware you could just dump out the array unindexed like that.

Can that also happen if data isn’t getting into the array? I’ve printed commas and string lits to the file no problem, so I’m thinking that that’s where the problem is coming in. Gonna comment out the file stuff and see if it works with echo to check that. No reason it shouldn’t; I did the exact same stuff with an email script and pretty much just ripped the form for this one.

Side note, I guess it might be smarter to return a string with the data in it, comma separated, and then print that to the file. Adds another point of failure, but reduces the complexity of outputting to the file. I kinda like the additional separation, and I especially like that it won’t rely on this current implementation, making it easier to steal next time I need a file related script.

No, if you were trying to access an index of the array that didnt exist because the array is empty, PHP would display nothing or if you had warnings turned it would output a message saying the index didnt exist. If its displaying ‘Array’, as Fugitive has said it means you’re its outputting an array variable without an index.

Well that sounds like science to me.

$handle = fopen($path, "a");

for($i = 0; $i < 6; $i++) {
    if ($i== 0){
        $toFile[i] = PHP_EOL . $toFile . ', ';
        fwrite($handle, $toFile[i]);
    }   
    else {
        $toFile[i] = $toFile . ', ';
        fwrite($handle, $toFile[i]);
	
    } 
}

That’s what I’m currently using to push data to the file. It seems like it should work, but it sure don’t. I’m going to try pushing the data I need to a string and seeing if that solves the problem.

edit: Ok, so I echo’d a bunch of stuff to test things out.

Array ( [0] => s [1] => ff [2] => [3] => s [4] => s [5] => agaga [sendNow] => ) Array , , contract info saved

The first segment is a print_r from inside the function that gets the input from the html form. That is indeed the input I entered, so it works. The next array is an echo on $toFile[0]. Is this the wrong way to access an array in PHP? Because it prints the word Array here. The hey is going on?

Anyway, next attempt is using $toFileString = implode(’,’, $toFile); and seeing if that works.

You probably need to use ‘$i’ as the index, not just ‘i’.

Oh for fucks sake. Yep, that would be it. Goddamn IDE.

Array
(
    [0] => Array
        (
            [0] => a
            [1] => s
            [2] => s
            [3] => f
            [4] => 
            [5] => g
            [sendNow] => 
        )

)
$toFile[] = askQuestions();
print '<pre>';
print_r($toFile);
print '</pre>';

Apparently the issue is that my array is being returned from my function and put inside another array, rather than just getting plugged into the array. I’m guessing there’s a secret here that I am missing on how to properly return an array without having it turn into a multidimensional hellfest.

edit: And here is where C++ fucked me. You do it by not including the square brackets when returning >.<

edit2: Tested and functional. Thanks guys, I learned one HELL of a lot of stuff from this experience.

edit3:

For those who are curious, here is the (mostly) finished and entirely functional script.



<!DOCTYPE html>
<html>
    <title></title>
<body>
    

<?php
function askQuestions() {
    echo "<form action='contractsave.php' method='post' >

         <input type='text' name='a'> a<br/>
         <input type='text' name='b'>b<br/>
         <input type='text' name='c'>c<br/>
         <input type='text' name='d'>d<br/>
         <input type='text' name='e'>e<br/>
         <input type='text' name='f'>f<br/>
         <input type='radio' name = 'sendNow' value=1>Send Now<br/>
         <input type='radio' name = 'sendNow' value=0>Wait<br/><br/>
         <input type='submit' />
     </form> ";
    
    $toFile[0] = $_REQUEST["a"];
    $toFile[1] = $_REQUEST["b"];
    $toFile[2] = $_REQUEST["c"];
    $toFile[3] = $_REQUEST["d"];
    $toFile[4] = $_REQUEST["e"];
    $toFile[5] = $_REQUEST["f"];
    $toFile['sendNow'] = $_REQUEST["sendNow"];
    
    return($toFile);
}
function handleMail($path, $fileName, $quarter){
    $from_mail = 'q';
    $from_name = 'f';
    $replyto = 'g';
    $mailto = 'r';

    $message = 'f';
    $subject = $quarter. 'a';

    $file = $path.$filename;
    $file_size = filesize($file);
    $handle = fopen($file, "r");
    $content = fread($handle, $file_size);
    fclose($handle);
    $content = chunk_split(base64_encode($content));
    $uid = md5(uniqid(time()));
    $name = basename($file);
    $header = "From: ".$from_name." <".$from_mail.">
";
    $header .= "Reply-To: ".$replyto."
";
    $header .= "BCC: " . $from_mail;
    $header .= "MIME-Version: 1.0
";
    $header .= "Content-Type: multipart/mixed; boundary=\"".$uid."\"

";
    $header .= "This is a multi-part message in MIME format.
";
    $header .= "--".$uid."
";
    $header .= "Content-type:text/plain; charset=iso-8859-1
";
    $header .= "Content-Transfer-Encoding: 7bit

";
    $header .= $message."

";
    $header .= "--".$uid."
";
    $header .= "Content-Type: application/octet-stream; name=\"".$filename."\"
"; // use different content types here
    $header .= "Content-Transfer-Encoding: base64
";
    $header .= "Content-Disposition: attachment; filename=\"".$filename."\"

";
    $header .= $content."

";
    $header .= "--".$uid."--";
    if (mail($mailto, $subject, "", $header)) {
        echo "mail send ... OK"; // or use booleans here
    } else {
        echo "mail send ... ERROR!";
    }
}
//main

$curDate = getdate();
$day = $curDate[mday];
$month = $curDate[mon];
$year = $curDate[year];
$quarter = $year;

$dateNow = $day . '/' . $month . '/' . $year;
$fileName = $month . 'm' . $year . 'y' . '.txt';
$path = './'.$fileName;

$toFile = askQuestions();
$sendNow = $toFile['sendNow'];

if(empty($toFile[0])) {
    $toFile[0] = $dateNow;
}

$toFile = array_slice($toFile, 0, 6);
$toFile[6] = $dateNow;
$toFileString = PHP_EOL;
$toFileString .= implode(',', $toFile);

$handle = fopen($path, "a+");

$fileCheck = fread($handle, filesize($path));
$fileHeaders = 'Date Recorded, Date Issued, Date Live, Customer Name, DC/CE, Contract Company, Contract Amount,' . PHP_EOL;

if (!strstr($fileCheck, $fileHeaders, false)){
    $fileHeaders .= $fileCheck;
    fwrite($handle, $fileHeaders);
}

fwrite($handle, $toFileString);
fclose($handle);

if ($day > 29) {
    switch ($month) {
        case 3:
            $quarter .= ' Q1';
            handleMail($path, $fileName, $quarter);
            break;
        case 6: 
            $quarter .= ' Q2';
           handleMail($path, $fileName, $quarter);
            break;
        case 9: 
            $quarter .= ' Q3';
            handleMail($path, $fileName, $quarter);
            break;
        case 12: 
            $quarter .= ' Q4';
            handleMail($path, $fileName, $quarter);
            break;
    }
}
//debug

if ($sendNow ==1){
    $quarter = 'DEBUG';
    handleMail($path, $fileName, $quarter);
    echo "sent DEBUG message";
}
else if ($day > 29) {
    echo "message sent";
}
else {
    echo "contract info saved";
}

?>      
               
</body>
</html>

Although apparently thunderbird has no idea what the sam hell the attachment is. I guess I screwed up that part somehow. Fuuuuuck it.

edit4: Added in something to check the file for headers (it’s a .csv, no headers no logic to it), and add em in if they’re not there. Kinda felt like I should add that in too since I’ve already posted so goddamn much.

If the function already returns an array, you only need to do:


$toFile = askQuestions();

EDIT: ah, it seems you have figured it out. Bleh, sorry.

Well, hey, I did figure that out but the “why is my email script sending an attachment of unknown type when the file is saved as a .txt” question is still open.

I made the mistake of letting my boss see it, and now he wants something similar for a different purpose >.<

So, yay, the googles continue.

Trying changing the Content-Type to plain/text in the mailer function. You’ve got it set to application/octet-stream at the moment which basically means unknown data. Thunderbird cares about that rather than the file extension.

Yeah I cribbed that from someone else’s script, I have no idea what it does or did. I should also learn to read, apparently, because so many issues I’ve had are typos. No idea I was so reliant on the IDE cuddling me, and I very much miss it.

It’s like trying to type without spell check: painful and mostly pointless.

Thanks again guys!