TYPO3 CMS  TYPO3_6-2
DataSubmissionController.php
Go to the documentation of this file.
1 <?php
3 
18 
25 
26  protected $reserved_names = 'recipient,recipient_copy,auto_respond_msg,auto_respond_checksum,redirect,subject,attachment,from_email,from_name,replyto_email,replyto_name,organisation,priority,html_enabled,quoted_printable,submit_x,submit_y';
27 
28  // Collection of suspicious header data, used for logging
29  protected $dirtyHeaders = array();
30 
31  protected $characterSet;
32 
33  protected $subject;
34 
35  protected $fromName;
36 
37  protected $replyToName;
38 
39  protected $organisation;
40 
41  protected $fromAddress;
42 
43  protected $replyToAddress;
44 
45  protected $priority;
46 
48 
49  protected $encoding = 'quoted-printable';
50 
54  protected $mailMessage;
55 
56  protected $recipient;
57 
58  protected $plainContent = '';
59 
63  protected $temporaryFiles = array();
64 
88  public function start($valueList, $base64 = FALSE) {
89  $this->mailMessage = Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Mail\\MailMessage');
90  if ($GLOBALS['TSFE']->config['config']['formMailCharset']) {
91  // Respect formMailCharset if it was set
92  $this->characterSet = $GLOBALS['TSFE']->csConvObj->parse_charset($GLOBALS['TSFE']->config['config']['formMailCharset']);
93  } elseif ($GLOBALS['TSFE']->metaCharset != $GLOBALS['TSFE']->renderCharset) {
94  // Use metaCharset for mail if different from renderCharset
95  $this->characterSet = $GLOBALS['TSFE']->metaCharset;
96  } else {
97  // Otherwise use renderCharset as default
98  $this->characterSet = $GLOBALS['TSFE']->renderCharset;
99  }
100  if ($base64 || $valueList['use_base64']) {
101  $this->encoding = 'base64';
102  }
103  if (isset($valueList['recipient'])) {
104  // Convert form data from renderCharset to mail charset
105  $this->subject = $valueList['subject'] ? $valueList['subject'] : 'Formmail on ' . Utility\GeneralUtility::getIndpEnv('HTTP_HOST');
106  $this->subject = $this->sanitizeHeaderString($this->subject);
107  $this->fromName = $valueList['from_name'] ? $valueList['from_name'] : ($valueList['name'] ? $valueList['name'] : '');
108  $this->fromName = $this->sanitizeHeaderString($this->fromName);
109  $this->replyToName = $valueList['replyto_name'] ? $valueList['replyto_name'] : $this->fromName;
110  $this->replyToName = $this->sanitizeHeaderString($this->replyToName);
111  $this->organisation = $valueList['organisation'] ? $valueList['organisation'] : '';
112  $this->organisation = $this->sanitizeHeaderString($this->organisation);
113  $this->fromAddress = $valueList['from_email'] ? $valueList['from_email'] : ($valueList['email'] ? $valueList['email'] : '');
114  if (!Utility\GeneralUtility::validEmail($this->fromAddress)) {
115  $this->fromAddress = Utility\MailUtility::getSystemFromAddress();
116  $this->fromName = Utility\MailUtility::getSystemFromName();
117  }
118  $this->replyToAddress = $valueList['replyto_email'] ? $valueList['replyto_email'] : $this->fromAddress;
119  $this->priority = $valueList['priority'] ? Utility\MathUtility::forceIntegerInRange($valueList['priority'], 1, 5) : 3;
120  // Auto responder
121  $this->autoRespondMessage = trim($valueList['auto_respond_msg']) && $this->fromAddress ? trim($valueList['auto_respond_msg']) : '';
122  if ($this->autoRespondMessage !== '') {
123  // Check if the value of the auto responder message has been modified with evil intentions
124  $autoRespondChecksum = $valueList['auto_respond_checksum'];
125  $correctHmacChecksum = Utility\GeneralUtility::hmac($this->autoRespondMessage, 'content_form');
126  if ($autoRespondChecksum !== $correctHmacChecksum) {
127  Utility\GeneralUtility::sysLog('Possible misuse of DataSubmissionController auto respond method. Subject: ' . $valueList['subject'], 'Core', Utility\GeneralUtility::SYSLOG_SEVERITY_ERROR);
128  return;
129  } else {
130  $this->autoRespondMessage = $this->sanitizeHeaderString($this->autoRespondMessage);
131  }
132  }
133  $plainTextContent = '';
134  $htmlContent = '<table border="0" cellpadding="2" cellspacing="2">';
135  // Runs through $V and generates the mail
136  if (is_array($valueList)) {
137  foreach ($valueList as $key => $val) {
138  if (!Utility\GeneralUtility::inList($this->reserved_names, $key)) {
139  $space = strlen($val) > 60 ? LF : '';
140  $val = is_array($val) ? implode($val, LF) : $val;
141  // Convert form data from renderCharset to mail charset (HTML may use entities)
142  $plainTextValue = $val;
143  $HtmlValue = htmlspecialchars($val);
144  $plainTextContent .= strtoupper($key) . ': ' . $space . $plainTextValue . LF . $space;
145  $htmlContent .= '<tr><td bgcolor="#eeeeee"><font face="Verdana" size="1"><strong>' . strtoupper($key) . '</strong></font></td><td bgcolor="#eeeeee"><font face="Verdana" size="1">' . nl2br($HtmlValue) . '&nbsp;</font></td></tr>';
146  }
147  }
148  }
149  $htmlContent .= '</table>';
150  $this->plainContent = $plainTextContent;
151  if ($valueList['html_enabled']) {
152  $this->mailMessage->setBody($htmlContent, 'text/html', $this->characterSet);
153  $this->mailMessage->addPart($plainTextContent, 'text/plain', $this->characterSet);
154  } else {
155  $this->mailMessage->setBody($plainTextContent, 'text/plain', $this->characterSet);
156  }
157  for ($a = 0; $a < 10; $a++) {
158  $variableName = 'attachment' . ($a ?: '');
159  if (!isset($_FILES[$variableName])) {
160  continue;
161  }
162 
163  if ($_FILES[$variableName]['error'] !== UPLOAD_ERR_OK) {
164  Utility\GeneralUtility::sysLog(
165  'Error in uploaded file in DataSubmissionController: temporary file "' .
166  $_FILES[$variableName]['tmp_name'] . '" ("' . $_FILES[$variableName]['name'] . '") Error code: ' .
167  $_FILES[$variableName]['error'],
168  'Core',
170  );
171  continue;
172  }
173 
174  if (!is_uploaded_file($_FILES[$variableName]['tmp_name'])) {
175  Utility\GeneralUtility::sysLog(
176  'Possible abuse of DataSubmissionController: temporary file "' . $_FILES[$variableName]['tmp_name'] .
177  '" ("' . $_FILES[$variableName]['name'] . '") was not an uploaded file.',
178  'Core',
180  );
181  continue;
182  }
183 
184  $theFile = Utility\GeneralUtility::upload_to_tempfile($_FILES[$variableName]['tmp_name']);
185  $theName = $_FILES[$variableName]['name'];
186  if ($theFile && file_exists($theFile)) {
187  if (filesize($theFile) < $GLOBALS['TYPO3_CONF_VARS']['FE']['formmailMaxAttachmentSize']) {
188  $this->mailMessage->attach(\Swift_Attachment::fromPath($theFile)->setFilename($theName));
189  }
190  }
191  $this->temporaryFiles[] = $theFile;
192  }
193  $from = $this->fromName ? array($this->fromAddress => $this->fromName) : array($this->fromAddress);
194  $this->recipient = $this->parseAddresses($valueList['recipient']);
195  $this->mailMessage->setSubject($this->subject)->setFrom($from)->setTo($this->recipient)->setPriority($this->priority);
196  $replyTo = $this->replyToName ? array($this->replyToAddress => $this->replyToName) : array($this->replyToAddress);
197  $this->mailMessage->setReplyTo($replyTo);
198  $this->mailMessage->getHeaders()->addTextHeader('Organization', $this->organisation);
199  if ($valueList['recipient_copy']) {
200  $this->mailMessage->setCc($this->parseAddresses($valueList['recipient_copy']));
201  }
202  $this->mailMessage->setCharset($this->characterSet);
203  // Ignore target encoding. This is handled automatically by Swift Mailer and overriding the defaults
204  // is not worth the trouble
205  // Log dirty header lines
206  if ($this->dirtyHeaders) {
207  Utility\GeneralUtility::sysLog('Possible misuse of DataSubmissionController: see TYPO3 devLog', 'Core', Utility\GeneralUtility::SYSLOG_SEVERITY_ERROR);
208  if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['enable_DLOG']) {
209  Utility\GeneralUtility::devLog('DataSubmissionController: ' . Utility\GeneralUtility::arrayToLogString($this->dirtyHeaders, '', 200), 'Core', 3);
210  }
211  }
212  }
213  }
214 
221  protected function sanitizeHeaderString($string) {
222  $pattern = '/[\\r\\n\\f\\e]/';
223  if (preg_match($pattern, $string) > 0) {
224  $this->dirtyHeaders[] = $string;
225  $string = '';
226  }
227  return $string;
228  }
229 
241  protected function parseAddresses($rawAddresses = '') {
243  $addressParser = Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Mail\\Rfc822AddressesParser', $rawAddresses);
244  $addresses = $addressParser->parseAddressList();
245  $addressList = array();
246  foreach ($addresses as $address) {
247  if ($address->personal) {
248  // Item with name found ( name <email@example.org> )
249  $addressList[$address->mailbox . '@' . $address->host] = $address->personal;
250  } else {
251  // Item without name found ( email@example.org )
252  $addressList[] = $address->mailbox . '@' . $address->host;
253  }
254  }
255  return $addressList;
256  }
257 
263  public function sendTheMail() {
264  // Sending the mail requires the recipient and message to be set.
265  if (!$this->mailMessage->getTo() || !trim($this->mailMessage->getBody())) {
266  return FALSE;
267  }
268  $this->mailMessage->send();
269  // Auto response
270  if ($this->autoRespondMessage) {
271  $theParts = explode('/', $this->autoRespondMessage, 2);
272  $theParts[0] = str_replace('###SUBJECT###', $this->subject, $theParts[0]);
273  $theParts[1] = str_replace(
274  array('/', '###MESSAGE###'),
275  array(LF, $this->plainContent),
276  $theParts[1]
277  );
279  $autoRespondMail = Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Mail\\MailMessage');
280  $autoRespondMail->setTo($this->fromAddress)->setSubject($theParts[0])->setFrom($this->recipient)->setBody($theParts[1]);
281  $autoRespondMail->send();
282  }
283  return $this->mailMessage->isSent();
284  }
285 
289  public function __destruct() {
290  foreach ($this->temporaryFiles as $file) {
291  if (Utility\GeneralUtility::isAllowedAbsPath($file) && Utility\GeneralUtility::isFirstPartOfStr($file, PATH_site . 'typo3temp/upload_temp_')) {
292  Utility\GeneralUtility::unlink_tempfile($file);
293  }
294  }
295  }
296 
297 }
static isFirstPartOfStr($str, $partStr)
static arrayToLogString(array $arr, $valueList=array(), $valueLength=20)
if(!defined('TYPO3_MODE')) $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_userauth.php']['logoff_pre_processing'][]