check if safe_mode is enabled (putenv is not allowed then) and
[squirrelmail.git] / functions / smtp.php
index fae9ea73445687e2dc1c713a269acd52e03466c0..dae83a2a6f22fdf9516ebcec33721d531cd80ae9 100644 (file)
@@ -7,6 +7,18 @@
 
    $smtp_php = true;
 
+   // This should most probably go to some initialization...
+   if (ereg("^([^@%/]+)[@%/](.+)$", $username, $usernamedata)) {
+      $popuser = $usernamedata[1];
+      $domain  = $usernamedata[2];
+         unset($usernamedata);
+   } else {
+      $popuser = $username;
+   }
+   // We need domain for smtp
+   if (!$domain)
+      $domain = getenv("HOSTNAME");
+
    // Returns true only if this message is multipart
    function isMultipart () {
       global $attachments;
@@ -38,7 +50,7 @@
                $filetype = "application/octet-stream";
             
             $header = "--".mimeBoundary()."\r\n";
-            $header .= "Content-Type: $filetype\r\n";
+            $header .= "Content-Type: $filetype;name=\"$remotename\"\r\n";
             $header .= "Content-Disposition: attachment; filename=\"$remotename\"\r\n";
             $header .= "Content-Transfer-Encoding: base64\r\n\r\n";
             fputs ($fp, $header);
 
    // Return a nice MIME-boundary
    function mimeBoundary () {
-      global $version, $REMOTE_ADDR, $SERVER_NAME, $REMOTE_PORT;
-
       static $mimeBoundaryString;
 
       if ($mimeBoundaryString == "") {
-         $temp = "SquirrelMail".$version.$REMOTE_ADDR.$SERVER_NAME.
-            $REMOTE_PORT;
-         $mimeBoundaryString = "=-_+".substr(md5($temp),1,20);
+         $mimeBoundaryString = GenerateRandomString(70, '\'()+,-./:=?_', 7);
       }
 
       return $mimeBoundaryString;
 
    /* Time offset for correct timezone */
    function timezone () {
+      global $invert_time;
+      
       $diff_second = date("Z");
+      if ($invert_time)
+          $diff_second = - $diff_second;
       if ($diff_second > 0)
          $sign = "+";
       else
    /* Print all the needed RFC822 headers */
    function write822Header ($fp, $t, $c, $b, $subject, $more_headers) {
       global $REMOTE_ADDR, $SERVER_NAME, $REMOTE_PORT;
-      global $data_dir, $username, $domain, $version, $useSendmail;
+      global $data_dir, $username, $popuser, $domain, $version, $useSendmail;
       global $default_charset, $HTTP_VIA, $HTTP_X_FORWARDED_FOR;
       global $REMOTE_HOST;
 
          $reply_to = getPref($data_dir, $username, "reply_to");
          $from = getPref($data_dir, $username, "full_name");
          $from_addr = getPref($data_dir, $username, "email_address");
-         
+
          if ($from_addr == "")
-            $from_addr = "$username@$domain";
+            $from_addr = $popuser."@".$domain;
          
          $to_list = getLineOfAddrs($to);
          $cc_list = getLineOfAddrs($cc);
          $bcc_list = getLineOfAddrs($bcc);
-         
+
          /* Encoding 8-bit characters and making from line */
-         $subject = encodeHeader($subject);
+         $subject = sqStripSlashes(encodeHeader($subject));
          if ($from == "")
             $from = "<$from_addr>";
          else
             $body .= "Content-Type: text/plain\r\n";
 
          $body .= "Content-Transfer-Encoding: 8bit\r\n\r\n";
-         $body .= stripslashes($passedBody) . "\r\n";
+         $body .= sqStripSlashes($passedBody) . "\r\n\r\n";
          fputs ($fp, $body);
 
          $attachmentlength = attachFiles($fp);
          $postbody .= "\r\n--".mimeBoundary()."--\r\n\r\n";
          fputs ($fp, $postbody);
       } else {
-         $body = stripslashes($passedBody) . "\r\n";
+         $body = sqStripSlashes($passedBody) . "\r\n";
          fputs ($fp, $body);
          $postbody = "\r\n";
          fputs ($fp, $postbody);
 
    // Send mail using the sendmail command
    function sendSendmail($t, $c, $b, $subject, $body, $more_headers) {
-      global $sendmail_path, $username, $domain;
+      global $sendmail_path, $popuser, $username, $domain;
+
+      // Build envelope sender address. Make sure it doesn't contain 
+      // spaces or other "weird" chars that would allow a user to
+      // exploit the shell/pipe it is used in.
+      $envelopefrom = "$popuser@$domain";
+      $envelopefrom = ereg_replace("[[:blank:]]","", $envelopefrom);
+      $envelopefrom = ereg_replace("[[:space:]]","", $envelopefrom);
+      $envelopefrom = ereg_replace("[[:cntrl:]]","", $envelopefrom);
 
       // open pipe to sendmail
-      $fp = popen (escapeshellcmd("$sendmail_path -t -f$username@$domain"), "w");
+      $fp = popen (escapeshellcmd("$sendmail_path -t -f$envelopefrom"), "w");
       
       $headerlength = write822Header ($fp, $t, $c, $b, $subject, $more_headers);
       $bodylength = writeBody($fp, $body);
    }
 
    function sendSMTP($t, $c, $b, $subject, $body, $more_headers) {
-      global $username, $domain, $version, $smtpServerAddress, $smtpPort,
+      global $username, $popuser, $domain, $version, $smtpServerAddress, $smtpPort,
          $data_dir, $color;
 
       $to = parseAddrs($t);
       $bcc = parseAddrs($b);
       $from_addr = getPref($data_dir, $username, "email_address");
 
-      if ($from_addr == "")
-         $from_addr = "$username@$domain";
+      if (!$from_addr)
+         $from_addr = "$popuser@$domain";
 
       $smtpConnection = fsockopen($smtpServerAddress, $smtpPort, $errorNumber, $errorString);
       if (!$smtpConnection) {
          sqimap_mailbox_select ($imap_stream, $mailbox);
          sqimap_messages_flag ($imap_stream, $reply_id, $reply_id, "Answered");
 
-        // Insert In-Reply-To and References headers if the 
-        // message-id of the message we reply to is set (longer than "<>")
-        // The References header should really be the old Referenced header
-        // with the message ID appended, but it can be only the message ID too.
-        $hdr = sqimap_get_small_header ($imap_stream, $reply_id, false);
-        if(strlen($hdr->message_id) > 2) {
-           $more_headers["In-Reply-To"] = $hdr->message_id;
-           $more_headers["References"]  = $hdr->message_id;
-        }
+         // Insert In-Reply-To and References headers if the 
+         // message-id of the message we reply to is set (longer than "<>")
+         // The References header should really be the old Referenced header
+         // with the message ID appended, but it can be only the message ID too.
+         $hdr = sqimap_get_small_header ($imap_stream, $reply_id, false);
+         if(strlen($hdr->message_id) > 2) {
+            $more_headers["In-Reply-To"] = $hdr->message_id;
+            $more_headers["References"]  = $hdr->message_id;
+         }
       }
-      
-      if ($useSendmail==true) {  
+
+      // In order to remove the problem of users not able to create
+         // messages with "." on a blank line, RFC821 has made provision
+         // in section 4.5.2 (Transparency).
+         $body = ereg_replace("\n\.", "\n\.\.", $body);
+         $body = ereg_replace("^\.", "\.\.", $body);
+
+      // this is to catch all plain \n instances and
+      // replace them with \r\n.  
+      $body = ereg_replace("\r\n", "\n", $body);
+      $body = ereg_replace("\n", "\r\n", $body);
+
+      if ($useSendmail) {
          $length = sendSendmail($t, $c, $b, $subject, $body, $more_headers);
       } else {
          $length = sendSMTP($t, $c, $b, $subject, $body, $more_headers);
       if (sqimap_mailbox_exists ($imap_stream, $sent_folder)) {
          sqimap_append ($imap_stream, $sent_folder, $length);
          write822Header ($imap_stream, $t, $c, $b, $subject, $more_headers);
-         writeBody ($imap_stream, $body); 
+         writeBody ($imap_stream, $body);
          sqimap_append_done ($imap_stream);
-      }   
-      sqimap_logout($imap_stream); 
+      }
+      sqimap_logout($imap_stream);
       // Delete the files uploaded for attaching (if any).
       deleteAttachments();
    }
+
 ?>