"TYPO3 4.0.1: typo3_src-4.0.1/t3lib/class.t3lib_htmlmail.php Source File", "datetime" => "Sat Dec 2 19:22:18 2006", "date" => "2 Dec 2006", "doxygenversion" => "1.4.6", "projectname" => "TYPO3 4.0.1", "projectnumber" => "4.0.1" ); get_header($doxygen_vars); ?>

class.t3lib_htmlmail.php

00001 <?php
00002 /***************************************************************
00003 *  Copyright notice
00004 *
00005 *  (c) 1999-2006 Kasper Skaarhoj (kasperYYYY@typo3.com)
00006 *  All rights reserved
00007 *
00008 *  This script is part of the TYPO3 project. The TYPO3 project is
00009 *  free software; you can redistribute it and/or modify
00010 *  it under the terms of the GNU General Public License as published by
00011 *  the Free Software Foundation; either version 2 of the License, or
00012 *  (at your option) any later version.
00013 *
00014 *  The GNU General Public License can be found at
00015 *  http://www.gnu.org/copyleft/gpl.html.
00016 *  A copy is found in the textfile GPL.txt and important notices to the license
00017 *  from the author is found in LICENSE.txt distributed with these scripts.
00018 *
00019 *
00020 *  This script is distributed in the hope that it will be useful,
00021 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00022 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00023 *  GNU General Public License for more details.
00024 *
00025 *  This copyright notice MUST APPEAR in all copies of the script!
00026 ***************************************************************/
00193 class t3lib_htmlmail {
00194                 // Headerinfo:
00195         var $recipient = "recipient@whatever.com";
00196         var $recipient_copy = "";               // This recipient (or list of...) will also receive the mail. Regard it as a copy.
00197         var $subject = "This is the subject";
00198         var $from_email = "sender@php-mailer.com";
00199         var $from_name = "Mr. Sender";
00200         var $replyto_email = "reply@mailer.com";
00201         var $replyto_name = "Mr. Reply";
00202         var $organisation = "Your Company";
00203         var $priority = 3;   // 1 = highest, 5 = lowest, 3 = normal
00204         var $mailer = "PHP mailer";     // X-mailer
00205         var $alt_base64=0;
00206         var $alt_8bit=0;
00207         var $jumperURL_prefix ="";              // This is a prefix that will be added to all links in the mail. Example: 'http://www.mydomain.com/jump?userid=###FIELD_uid###&url='. if used, anything after url= is urlencoded.
00208         var $jumperURL_useId=0;                 // If set, then the array-key of the urls are inserted instead of the url itself. Smart in order to reduce link-length
00209         var $mediaList="";                              // If set, this is a list of the media-files (index-keys to the array) that should be represented in the html-mail
00210         var $http_password="";
00211         var $http_username="";
00212         var $postfix_version1=false;
00213 
00214         // Internal
00215 
00216 /*              This is how the $theParts-array is normally looking
00217         var $theParts = Array(
00218                 "plain" => Array (
00219                         "content"=> ""
00220                 ),
00221                 "html" => Array (
00222                         "content"=> "",
00223                         "path" => "",
00224                         "media" => Array(),
00225                         "hrefs" => Array()
00226                 ),
00227                 "attach" => Array ()
00228         );
00229 */
00230         var $theParts = Array();
00231 
00232         var $messageid = "";
00233         var $returnPath = "";
00234         var $Xid = "";
00235         var $dontEncodeHeader = false;          // If set, the header will not be encoded
00236 
00237         var $headers = "";
00238         var $message = "";
00239         var $part=0;
00240         var $image_fullpath_list = "";
00241         var $href_fullpath_list = "";
00242 
00243         var $plain_text_header = '';
00244         var $html_text_header = '';
00245         var $charset = '';
00246         var $defaultCharset = 'iso-8859-1';
00247 
00248 
00249 
00250 
00251 
00252 
00253 
00254 
00261         function t3lib_htmlmail () {
00262                 $this->forceReturnPath = $GLOBALS['TYPO3_CONF_VARS']['SYS']['forceReturnPath'];
00263         }
00264 
00268         function start ()       {
00269                 global $TYPO3_CONF_VARS;
00270 
00271                         // Sets the message id
00272                 $host = t3lib_div::getHostname();
00273                 if (!$host || $host == '127.0.0.1' || $host == 'localhost' || $host == 'localhost.localdomain') {
00274                         $host = ($TYPO3_CONF_VARS['SYS']['sitename'] ? preg_replace('/[^A-Za-z0-9_\-]/', '_', $TYPO3_CONF_VARS['SYS']['sitename']) : 'localhost') . '.TYPO3';
00275                 }
00276                 $this->messageid = md5(microtime()) . '@' . $host;
00277 
00278                         // Default line break for Unix systems.
00279                 $this->linebreak = chr(10);
00280                         // Line break for Windows. This is needed because PHP on Windows systems send mails via SMTP instead of using sendmail, and thus the linebreak needs to be \r\n.
00281                 if (TYPO3_OS=='WIN')    {
00282                         $this->linebreak = chr(13).chr(10);
00283                 }
00284 
00285                 if (!$this->charset) {
00286                         if (is_object($GLOBALS['TSFE']) && $GLOBALS['TSFE']->renderCharset) {
00287                                 $this->charset = $GLOBALS['TSFE']->renderCharset;
00288                         } elseif (is_object($GLOBALS['LANG']) && $GLOBALS['LANG']->charSet) {
00289                                 $this->charset = $GLOBALS['LANG']->charSet;
00290                         } elseif ($GLOBALS['TYPO3_CONF_VARS']['BE']['forceCharset']) {
00291                                 $this->charset = $GLOBALS['TYPO3_CONF_VARS']['BE']['forceCharset'];
00292                         } else {
00293                                 $this->charset = $this->defaultCharset;
00294                         }
00295                 }
00296 
00297                         // Use quoted-printable headers by default
00298                 $this->useQuotedPrintable();
00299         }
00300 
00306         function useQuotedPrintable()   {
00307                 $this->plain_text_header = 'Content-Type: text/plain; charset='.$this->charset.$this->linebreak.'Content-Transfer-Encoding: quoted-printable';
00308                 $this->html_text_header = 'Content-Type: text/html; charset='.$this->charset.$this->linebreak.'Content-Transfer-Encoding: quoted-printable';
00309         }
00310 
00316         function useBase64()    {
00317                 $this->plain_text_header = 'Content-Type: text/plain; charset='.$this->charset.$this->linebreak.'Content-Transfer-Encoding: base64';
00318                 $this->html_text_header = 'Content-Type: text/html; charset='.$this->charset.$this->linebreak.'Content-Transfer-Encoding: base64';
00319                 $this->alt_base64=1;
00320         }
00321 
00327         function use8Bit()      {
00328                 $this->plain_text_header = 'Content-Type: text/plain; charset='.$this->charset.$this->linebreak.'Content-Transfer-Encoding: 8bit';
00329                 $this->html_text_header = 'Content-Type: text/html; charset='.$this->charset.$this->linebreak.'Content-Transfer-Encoding: 8bit';
00330                 $this->alt_8bit=1;
00331         }
00332 
00339         function encodeMsg($content)    {
00340                 return $this->alt_base64 ? $this->makeBase64($content) : ($this->alt_8bit ? $content : t3lib_div::quoted_printable($content));
00341         }
00342 
00349         function addPlain ($content)    {
00350                         // Adds plain-text and qp-encodes it
00351                 $content=$this->substHTTPurlsInPlainText($content);
00352                 $this->setPlain($this->encodeMsg($content));
00353         }
00354 
00361         function addAttachment($file)   {
00362                         // Adds an attachment to the mail
00363                 $theArr = $this->getExtendedURL($file);         // We fetch the content and the mime-type
00364                 if ($theArr)    {
00365                         if (!$theArr["content_type"]){$theArr["content_type"]="application/octet-stream";}
00366                         $temp = $this->split_fileref($file);
00367                         $theArr["filename"]= (($temp["file"])?$temp["file"]:(strpos(" ".$theArr["content_type"],"htm")?"index.html":"unknown"));
00368                         $this->theParts["attach"][]=$theArr;
00369                         return true;
00370                 } else { return false;}
00371         }
00372 
00379         function addHTML ($file)        {
00380                         // Adds HTML and media, encodes it from a URL or file
00381                 $status = $this->fetchHTML($file);
00382 //              debug(md5($status));
00383                 if (!$status)   {return false;}
00384                 if ($this->extractFramesInfo()) {
00385                         return "Document was a frameset. Stopped";
00386                 }
00387                 $this->extractMediaLinks();
00388                 $this->extractHyperLinks();
00389                 $this->fetchHTMLMedia();
00390                 $this->substMediaNamesInHTML(0);        // 0 = relative
00391                 $this->substHREFsInHTML();
00392                 $this->setHTML($this->encodeMsg($this->theParts["html"]["content"]));
00393         }
00394 
00402         function extractHtmlInit($html,$url)    {
00403                 $this->theParts["html"]["content"]=$html;
00404                 $this->theParts["html"]["path"]=$url;
00405         }
00406 
00413         function send($recipient)       {
00414                         // This function sends the mail to one $recipient
00415                 if ($recipient) {$this->recipient = $recipient;}
00416                 $this->setHeaders();
00417                 $this->setContent();
00418                 $this->sendTheMail();
00419         }
00420 
00421 
00422 
00423 
00424 
00425 
00426 
00427 
00428 
00429 
00430 
00431 
00432 
00433         /*****************************************
00434          *
00435          * Main functions
00436          *
00437          *****************************************/
00438 
00442         function setHeaders()   {
00443                         // Clears the header-string and sets the headers based on object-vars.
00444                 $this->headers = "";
00445                         // Message_id
00446                 $this->add_header("Message-ID: <".$this->messageid.">");
00447                         // Return path
00448                 if ($this->returnPath)  {
00449                         $this->add_header("Return-Path: ".$this->returnPath);
00450                         $this->add_header("Errors-To: ".$this->returnPath);
00451                 }
00452                         // X-id
00453                 if ($this->Xid) {
00454                         $this->add_header("X-Typo3MID: ".$this->Xid);
00455                 }
00456 
00457                         // From
00458                 if ($this->from_email)  {
00459                         if ($this->from_name)   {
00460                                 $this->add_header('From: '.$this->from_name.' <'.$this->from_email.'>');
00461                         } else {
00462                                 $this->add_header('From: '.$this->from_email);
00463                         }
00464                 }
00465                         // Reply
00466                 if ($this->replyto_email)       {
00467                         if ($this->replyto_name)        {
00468                                 $this->add_header('Reply-To: '.$this->replyto_name.' <'.$this->replyto_email.'>');
00469                         } else {
00470                                 $this->add_header('Reply-To: '.$this->replyto_email);
00471                         }
00472                 }
00473                         // Organisation
00474                 if ($this->organisation)        {
00475                         $this->add_header('Organisation: '.$this->organisation);
00476                 }
00477                         // mailer
00478                 if ($this->mailer)      {
00479                         $this->add_header("X-Mailer: $this->mailer");
00480                 }
00481                         // priority
00482                 if ($this->priority)    {
00483                         $this->add_header("X-Priority: $this->priority");
00484                 }
00485                 $this->add_header("Mime-Version: 1.0");
00486 
00487                 if (!$this->dontEncodeHeader)   {
00488                         $enc = $this->alt_base64 ? 'base64' : 'quoted_printable';       // Header must be ASCII, therefore only base64 or quoted_printable are allowed!
00489                                 // Quote recipient and subject
00490                         $this->recipient = t3lib_div::encodeHeader($this->recipient,$enc,$this->charset);
00491                         $this->subject = t3lib_div::encodeHeader($this->subject,$enc,$this->charset);
00492                 }
00493         }
00494 
00501         function setRecipient ($recip)  {
00502                 // Sets the recipient(s). If you supply a string, you set one recipient. If you supply an array, every value is added as a recipient.
00503                 if (is_array($recip))   {
00504                         $this->recipient = "";
00505                         while (list($key,) = each($recip)) {
00506                                 $this->recipient .= $recip[$key].",";
00507                         }
00508                         $this->recipient = ereg_replace(",$","",$this->recipient);
00509                 } else {
00510                         $this->recipient = $recip;
00511                 }
00512         }
00513 
00519         function getHTMLContentType()   {
00520                 return count($this->theParts["html"]["media"]) ? 'multipart/related;' : 'multipart/alternative;';
00521         }
00522 
00528         function setContent()   {
00529                         // Begins building the message-body
00530                 $this->message = "";
00531                 $boundary = $this->getBoundary();
00532                 // Setting up headers
00533                 if (count($this->theParts["attach"]))   {
00534                         $this->add_header('Content-Type: multipart/mixed;');
00535                         $this->add_header(' boundary="'.$boundary.'"');
00536                         $this->add_message("This is a multi-part message in MIME format.\n");
00537                         $this->constructMixed($boundary);       // Generate (plain/HTML) / attachments
00538                 } elseif ($this->theParts["html"]["content"]) {
00539                         $this->add_header('Content-Type: '.$this->getHTMLContentType());
00540                         $this->add_header(' boundary="'.$boundary.'"');
00541                         $this->add_message("This is a multi-part message in MIME format.\n");
00542                         $this->constructHTML($boundary);                // Generate plain/HTML mail
00543                 } else {
00544                         $this->add_header($this->plain_text_header);
00545                         $this->add_message($this->getContent("plain")); // Generate plain only
00546                 }
00547         }
00548 
00555         function constructMixed ($boundary)     {
00556                         // Here (plain/HTML) is combined with the attachments
00557                 $this->add_message("--".$boundary);
00558                         // (plain/HTML) is added
00559                 if ($this->theParts["html"]["content"]) {
00560                                 // HTML and plain
00561                         $newBoundary = $this->getBoundary();
00562                         $this->add_message("Content-Type: ".$this->getHTMLContentType());
00563                         $this->add_message(' boundary="'.$newBoundary.'"');
00564                         $this->add_message('');
00565                         $this->constructHTML($newBoundary);
00566                 } else {        // Purely plain
00567                         $this->add_message($this->plain_text_header);
00568                         $this->add_message('');
00569                         $this->add_message($this->getContent("plain"));
00570                 }
00571                         // attachments are added
00572                 if (is_array($this->theParts["attach"]))        {
00573                         reset($this->theParts["attach"]);
00574                         while(list(,$media)=each($this->theParts["attach"]))    {
00575                                 $this->add_message("--".$boundary);
00576                                 $this->add_message("Content-Type: ".$media["content_type"]);
00577                                 $this->add_message(' name="'.$media["filename"].'"');
00578                                 $this->add_message("Content-Transfer-Encoding: base64");
00579                                 $this->add_message("Content-Disposition: attachment;");
00580                                 $this->add_message(' filename="'.$media["filename"].'"');
00581                                 $this->add_message('');
00582                                 $this->add_message($this->makeBase64($media["content"]));
00583                         }
00584                 }
00585                 $this->add_message("--".$boundary."--\n");
00586         }
00587 
00594         function constructHTML ($boundary)      {
00595                 if (count($this->theParts["html"]["media"]))    {       // If media, then we know, the multipart/related content-type has been set before this function call...
00596                         $this->add_message("--".$boundary);
00597                                 // HTML has media
00598                         $newBoundary = $this->getBoundary();
00599                         $this->add_message("Content-Type: multipart/alternative;");
00600                         $this->add_message(' boundary="'.$newBoundary.'"');
00601                         $this->add_message('Content-Transfer-Encoding: 7bit');
00602                         $this->add_message('');
00603 
00604                         $this->constructAlternative($newBoundary);      // Adding the plaintext/html mix
00605 
00606                         $this->constructHTML_media($boundary);
00607                 } else {
00608                         $this->constructAlternative($boundary); // Adding the plaintext/html mix, and if no media, then use $boundary instead of $newBoundary
00609                 }
00610         }
00611 
00618         function constructAlternative($boundary)        {
00619                         // Here plain is combined with HTML
00620                 $this->add_message("--".$boundary);
00621                         // plain is added
00622                 $this->add_message($this->plain_text_header);
00623                 $this->add_message('');
00624                 $this->add_message($this->getContent("plain"));
00625                 $this->add_message("--".$boundary);
00626                         // html is added
00627                 $this->add_message($this->html_text_header);
00628                 $this->add_message('');
00629                 $this->add_message($this->getContent("html"));
00630                 $this->add_message("--".$boundary."--\n");
00631         }
00632 
00639         function constructHTML_media ($boundary)        {
00640 /*                      // Constructs the HTML-part of message if the HTML contains media
00641                 $this->add_message("--".$boundary);
00642                         // htmlcode is added
00643                 $this->add_message($this->html_text_header);
00644                 $this->add_message('');
00645                 $this->add_message($this->getContent("html"));
00646 
00647                 OLD stuf...
00648 
00649                 */
00650                         // media is added
00651                 if (is_array($this->theParts["html"]["media"])) {
00652                         reset($this->theParts["html"]["media"]);
00653                         while(list($key,$media)=each($this->theParts["html"]["media"])) {
00654                                 if (!$this->mediaList || t3lib_div::inList($this->mediaList,$key))      {
00655                                         $this->add_message("--".$boundary);
00656                                         $this->add_message("Content-Type: ".$media["ctype"]);
00657                                         $this->add_message("Content-ID: <part".$key.".".$this->messageid.">");
00658                                         $this->add_message("Content-Transfer-Encoding: base64");
00659                                         $this->add_message('');
00660                                         $this->add_message($this->makeBase64($media["content"]));
00661                                 }
00662                         }
00663                 }
00664                 $this->add_message("--".$boundary."--\n");
00665         }
00666 
00692         function sendTheMail () {
00693 #debug(array($this->recipient,$this->subject,$this->message,$this->headers));
00694                         // Sends the mail, requires the recipient, message and headers to be set.
00695                 if (trim($this->recipient) && trim($this->message))     {       //  && trim($this->headers)
00696                         $returnPath = (strlen($this->returnPath)>0)?"-f".$this->returnPath:'';
00697                                 //On windows the -f flag is not used (specific for Sendmail and Postfix), but instead the php.ini parameter sendmail_from is used.
00698                         if($this->returnPath) {
00699                                 ini_set(sendmail_from, $this->returnPath);
00700                         }
00701                                 //If safe mode is on, the fifth parameter to mail is not allowed, so the fix wont work on unix with safe_mode=On
00702                         if(!ini_get('safe_mode') && $this->forceReturnPath) {
00703                                 mail($this->recipient,
00704                                           $this->subject,
00705                                           $this->message,
00706                                           $this->headers,
00707                                           $returnPath);
00708                         } else {
00709                                 mail($this->recipient,
00710                                           $this->subject,
00711                                           $this->message,
00712                                           $this->headers);
00713                         }
00714                                 // Sending copy:
00715                         if ($this->recipient_copy)      {
00716                                 if(!ini_get('safe_mode') && $this->forceReturnPath) {
00717                                         mail(   $this->recipient_copy,
00718                                                                 $this->subject,
00719                                                                 $this->message,
00720                                                                 $this->headers,
00721                                                                 $returnPath);
00722                                 } else {
00723                                         mail(   $this->recipient_copy,
00724                                                                 $this->subject,
00725                                                                 $this->message,
00726                                                                 $this->headers  );
00727                                 }
00728                         }
00729                                 // Auto response
00730                         if ($this->auto_respond_msg)    {
00731                                 $theParts = explode('/',$this->auto_respond_msg,2);
00732                                 $theParts[1] = str_replace("/",chr(10),$theParts[1]);
00733                                 if(!ini_get('safe_mode') && $this->forceReturnPath) {
00734                                         mail(   $this->from_email,
00735                                                                 $theParts[0],
00736                                                                 $theParts[1],
00737                                                                 "From: ".$this->recipient,
00738                                                                 $returnPath);
00739                                 } else {
00740                                         mail(   $this->from_email,
00741                                                                 $theParts[0],
00742                                                                 $theParts[1],
00743                                                                 "From: ".$this->recipient);
00744                                 }
00745                         }
00746                         if($this->returnPath) {
00747                                 ini_restore(sendmail_from);
00748                         }
00749                         return true;
00750                 } else {return false;}
00751         }
00752 
00758         function getBoundary()  {
00759                         // Returns boundaries
00760                 $this->part++;
00761                 return  "----------".uniqid("part_".$this->part."_");
00762         }
00763 
00770         function setPlain ($content)    {
00771                         // Sets the plain-text part. No processing done.
00772                 $this->theParts["plain"]["content"] = $content;
00773         }
00774 
00781         function setHtml ($content)     {
00782                         // Sets the HTML-part. No processing done.
00783                 $this->theParts["html"]["content"] = $content;
00784         }
00785 
00792         function add_header($header)    {
00793                 if (!$this->dontEncodeHeader && !stristr($header,'Content-Type') && !stristr($header,'Content-Transfer-Encoding'))      {
00794                                 // Mail headers must be ASCII, therefore we convert the whole header to either base64 or quoted_printable
00795                         $parts = explode(': ',$header,2);       // Field tags must not be encoded
00796                         if (count($parts)==2)   {
00797                                 $enc = $this->alt_base64 ? 'base64' : 'quoted_printable';
00798                                 $parts[1] = t3lib_div::encodeHeader($parts[1],$enc,$this->charset);
00799                                 $header = implode(': ',$parts);
00800                         }
00801                 }
00802 
00803                         // Adds a header to the mail. Use this AFTER the setHeaders()-function
00804                 $this->headers.=$header."\n";
00805         }
00806 
00813         function add_message($string)   {
00814                         // Adds a line of text to the mail-body. Is normally use internally
00815                 $this->message.=$string."\n";
00816         }
00817 
00824         function getContent($type)      {
00825                 return $this->theParts[$type]["content"];
00826         }
00827 
00833         function preview()      {
00834                 echo nl2br(HTMLSpecialChars($this->headers));
00835                 echo "<BR>";
00836                 echo nl2br(HTMLSpecialChars($this->message));
00837         }
00838 
00839 
00840 
00841 
00842 
00843 
00844 
00845 
00846 
00847 
00848 
00849 
00850 
00851         /****************************************************
00852          *
00853          * Functions for acquiring attachments, HTML, analyzing and so on  **
00854          *
00855          ***************************************************/
00856 
00861         function fetchHTML($file)       {
00862                         // Fetches the HTML-content from either url og local serverfile
00863                 $this->theParts["html"]["content"] = $this->getURL($file);      // Fetches the content of the page
00864                 if ($this->theParts["html"]["content"]) {
00865                         $addr = $this->extParseUrl($file);
00866                         $path = ($addr['scheme']) ? $addr['scheme'].'://'.$addr['host'].(($addr['port'])?':'.$addr['port']:'').(($addr['filepath'])?$addr['filepath']:'/') : $addr['filepath'];
00867                         $this->theParts["html"]["path"] = $path;
00868                         return true;
00869                 } else {
00870                         return false;
00871                 }
00872         }
00873 
00879         function fetchHTMLMedia()       {
00880                         // Fetches the mediafiles which are found by extractMediaLinks()
00881                 if (is_array($this->theParts["html"]["media"])) {
00882                         reset ($this->theParts["html"]["media"]);
00883                         if (count($this->theParts["html"]["media"]) > 0)        {
00884                                 while (list($key,$media) = each ($this->theParts["html"]["media"]))     {
00885                                         $picdata = $this->getExtendedURL($this->theParts["html"]["media"][$key]["absRef"]);             // We fetch the content and the mime-type
00886                                         if (is_array($picdata)) {
00887                                                 $this->theParts["html"]["media"][$key]["content"] = $picdata["content"];
00888                                                 $this->theParts["html"]["media"][$key]["ctype"] = $picdata["content_type"];
00889                                         }
00890                                 }
00891                         }
00892                 }
00893         }
00894 
00900         function extractMediaLinks()    {
00901                         // extracts all media-links from $this->theParts["html"]["content"]
00902                 $html_code = $this->theParts["html"]["content"];
00903                 $attribRegex = $this->tag_regex(Array("img","table","td","tr","body","iframe","script","input","embed"));
00904                 $codepieces = split($attribRegex, $html_code);  // Splits the document by the beginning of the above tags
00905                 $len=strlen($codepieces[0]);
00906                 $pieces = count($codepieces);
00907                 $reg = array();
00908                 for($i=1; $i < $pieces; $i++)   {
00909                         $tag = strtolower(strtok(substr($html_code,$len+1,10)," "));
00910                         $len+=strlen($tag)+strlen($codepieces[$i])+2;
00911                         $dummy = eregi("[^>]*", $codepieces[$i], $reg);
00912                         $attributes = $this->get_tag_attributes($reg[0]);       // Fetches the attributes for the tag
00913                         $imageData=array();
00914                         $imageData["ref"]=($attributes["src"]) ? $attributes["src"] : $attributes["background"];        // Finds the src or background attribute
00915                         if ($imageData["ref"])  {
00916                                 $imageData["quotes"]=(substr($codepieces[$i],strpos($codepieces[$i], $imageData["ref"])-1,1)=='"')?'"':'';              // Finds out if the value had quotes around it
00917                                 $imageData["subst_str"] = $imageData["quotes"].$imageData["ref"].$imageData["quotes"];  // subst_str is the string to look for, when substituting lateron
00918                                 if ($imageData["ref"] && !strstr($this->image_fullpath_list,"|".$imageData["subst_str"]."|"))   {
00919                                         $this->image_fullpath_list.="|".$imageData["subst_str"]."|";
00920                                         $imageData["absRef"] = $this->absRef($imageData["ref"]);
00921                                         $imageData["tag"]=$tag;
00922                                         $imageData["use_jumpurl"]=$attributes["dmailerping"]?1:0;
00923                                         $this->theParts["html"]["media"][]=$imageData;
00924                                 }
00925                         }
00926                 }
00927                         // Extracts stylesheets
00928                 $attribRegex = $this->tag_regex(Array("link"));
00929                 $codepieces = split($attribRegex, $html_code);  // Splits the document by the beginning of the above tags
00930                 $pieces = count($codepieces);
00931                 for($i=1; $i < $pieces; $i++)   {
00932                         $dummy = eregi("[^>]*", $codepieces[$i], $reg);
00933                         $attributes = $this->get_tag_attributes($reg[0]);       // Fetches the attributes for the tag
00934                         $imageData=array();
00935                         if (strtolower($attributes["rel"])=="stylesheet" && $attributes["href"])        {
00936                                 $imageData["ref"]=$attributes["href"];  // Finds the src or background attribute
00937                                 $imageData["quotes"]=(substr($codepieces[$i],strpos($codepieces[$i], $imageData["ref"])-1,1)=='"')?'"':'';              // Finds out if the value had quotes around it
00938                                 $imageData["subst_str"] = $imageData["quotes"].$imageData["ref"].$imageData["quotes"];  // subst_str is the string to look for, when substituting lateron
00939                                 if ($imageData["ref"] && !strstr($this->image_fullpath_list,"|".$imageData["subst_str"]."|"))   {
00940                                         $this->image_fullpath_list.="|".$imageData["subst_str"]."|";
00941                                         $imageData["absRef"] = $this->absRef($imageData["ref"]);
00942                                         $this->theParts["html"]["media"][]=$imageData;
00943                                 }
00944                         }
00945                 }
00946                         // fixes javascript rollovers
00947                 $codepieces = split(quotemeta(".src"), $html_code);
00948                 $pieces = count($codepieces);
00949                 $expr = "^[^".quotemeta("\"").quotemeta("'")."]*";
00950                 for($i=1; $i < $pieces; $i++)   {
00951                         $temp = $codepieces[$i];
00952                         $temp = trim(ereg_replace("=","",trim($temp)));
00953                         ereg ($expr,substr($temp,1,strlen($temp)),$reg);
00954                         $imageData["ref"] = $reg[0];
00955                         $imageData["quotes"] = substr($temp,0,1);
00956                         $imageData["subst_str"] = $imageData["quotes"].$imageData["ref"].$imageData["quotes"];  // subst_str is the string to look for, when substituting lateron
00957                         $theInfo = $this->split_fileref($imageData["ref"]);
00958                         switch ($theInfo["fileext"])    {
00959                                 case "gif":
00960                                 case "jpeg":
00961                                 case "jpg":
00962                                         if ($imageData["ref"] && !strstr($this->image_fullpath_list,"|".$imageData["subst_str"]."|"))   {
00963                                                 $this->image_fullpath_list.="|".$imageData["subst_str"]."|";
00964                                                 $imageData["absRef"] = $this->absRef($imageData["ref"]);
00965                                                 $this->theParts["html"]["media"][]=$imageData;
00966                                         }
00967                                 break;
00968                         }
00969                 }
00970         }
00971 
00977         function extractHyperLinks()    {
00978                         // extracts all hyper-links from $this->theParts["html"]["content"]
00979                 $html_code = $this->theParts["html"]["content"];
00980                 $attribRegex = $this->tag_regex(Array("a","form","area"));
00981                 $codepieces = split($attribRegex, $html_code);  // Splits the document by the beginning of the above tags
00982                 $len=strlen($codepieces[0]);
00983                 $pieces = count($codepieces);
00984                 for($i=1; $i < $pieces; $i++)   {
00985                         $tag = strtolower(strtok(substr($html_code,$len+1,10)," "));
00986                         $len+=strlen($tag)+strlen($codepieces[$i])+2;
00987 
00988                         $dummy = eregi("[^>]*", $codepieces[$i], $reg);
00989                         $attributes = $this->get_tag_attributes($reg[0]);       // Fetches the attributes for the tag
00990                         $hrefData="";
00991                         if ($attributes["href"]) {$hrefData["ref"]=$attributes["href"];} else {$hrefData["ref"]=$attributes["action"];}
00992                         if ($hrefData["ref"])   {
00993                                 $hrefData["quotes"]=(substr($codepieces[$i],strpos($codepieces[$i], $hrefData["ref"])-1,1)=='"')?'"':'';                // Finds out if the value had quotes around it
00994                                 $hrefData["subst_str"] = $hrefData["quotes"].$hrefData["ref"].$hrefData["quotes"];      // subst_str is the string to look for, when substituting lateron
00995                                 if ($hrefData["ref"] && substr(trim($hrefData["ref"]),0,1)!="#" && !strstr($this->href_fullpath_list,"|".$hrefData["subst_str"]."|"))   {
00996                                         $this->href_fullpath_list.="|".$hrefData["subst_str"]."|";
00997                                         $hrefData["absRef"] = $this->absRef($hrefData["ref"]);
00998                                         $hrefData["tag"]=$tag;
00999                                         $this->theParts["html"]["hrefs"][]=$hrefData;
01000                                 }
01001                         }
01002                 }
01003                         // Extracts TYPO3 specific links made by the openPic() JS function
01004                 $codepieces = explode("onClick=\"openPic('", $html_code);
01005                 $pieces = count($codepieces);
01006                 for($i=1; $i < $pieces; $i++)   {
01007                         $showpic_linkArr = explode("'",$codepieces[$i]);
01008                         $hrefData["ref"]=$showpic_linkArr[0];
01009                         if ($hrefData["ref"])   {
01010                                 $hrefData["quotes"]="'";                // Finds out if the value had quotes around it
01011                                 $hrefData["subst_str"] = $hrefData["quotes"].$hrefData["ref"].$hrefData["quotes"];      // subst_str is the string to look for, when substituting lateron
01012                                 if ($hrefData["ref"] && !strstr($this->href_fullpath_list,"|".$hrefData["subst_str"]."|"))      {
01013                                         $this->href_fullpath_list.="|".$hrefData["subst_str"]."|";
01014                                         $hrefData["absRef"] = $this->absRef($hrefData["ref"]);
01015                                         $this->theParts["html"]["hrefs"][]=$hrefData;
01016                                 }
01017                         }
01018                 }
01019         }
01020 
01026         function extractFramesInfo()    {
01027                         // extracts all media-links from $this->theParts["html"]["content"]
01028                 $html_code = $this->theParts["html"]["content"];
01029                 if (strpos(" ".$html_code,"<frame "))   {
01030                         $attribRegex = $this->tag_regex("frame");
01031                         $codepieces = split($attribRegex, $html_code, 1000000 );        // Splits the document by the beginning of the above tags
01032                         $pieces = count($codepieces);
01033                         for($i=1; $i < $pieces; $i++)   {
01034                                 $dummy = eregi("[^>]*", $codepieces[$i], $reg);
01035                                 $attributes = $this->get_tag_attributes($reg[0]);       // Fetches the attributes for the tag
01036                                 $frame="";
01037                                 $frame["src"]=$attributes["src"];
01038                                 $frame["name"]=$attributes["name"];
01039                                 $frame["absRef"] = $this->absRef($frame["src"]);
01040                                 $theInfo[] = $frame;
01041                         }
01042                         return $theInfo;
01043                 }
01044         }
01045 
01052         function substMediaNamesInHTML($absolute)       {
01053                         // This substitutes the media-references in $this->theParts["html"]["content"]
01054                         // If $absolute is true, then the refs are substituted with http:// ref's indstead of Content-ID's (cid).
01055                 if (is_array($this->theParts["html"]["media"])) {
01056                         reset ($this->theParts["html"]["media"]);
01057                         while (list($key,$val) = each ($this->theParts["html"]["media"]))       {
01058                                 if ($val["use_jumpurl"] && $this->jumperURL_prefix)     {
01059                                         $theSubstVal = $this->jumperURL_prefix.t3lib_div::rawUrlEncodeFP($val['absRef']);
01060                                 } else {
01061                                         $theSubstVal = ($absolute) ? $val["absRef"] : "cid:part".$key.".".$this->messageid;
01062                                 }
01063                                 $this->theParts["html"]["content"] = str_replace(
01064                                                 $val["subst_str"],
01065                                                 $val["quotes"].$theSubstVal.$val["quotes"],
01066                                                 $this->theParts["html"]["content"]      );
01067                         }
01068                 }
01069                 if (!$absolute) {
01070                         $this->fixRollOvers();
01071                 }
01072         }
01073 
01079         function substHREFsInHTML()     {
01080                         // This substitutes the hrefs in $this->theParts["html"]["content"]
01081                 if (is_array($this->theParts["html"]["hrefs"])) {
01082                         reset ($this->theParts["html"]["hrefs"]);
01083                         while (list($key,$val) = each ($this->theParts["html"]["hrefs"]))       {
01084                                 if ($this->jumperURL_prefix && $val["tag"]!="form")     {       // Form elements cannot use jumpurl!
01085                                         if ($this->jumperURL_useId)     {
01086                                                 $theSubstVal = $this->jumperURL_prefix.$key;
01087                                         } else {
01088                                                 $theSubstVal = $this->jumperURL_prefix.t3lib_div::rawUrlEncodeFP($val['absRef']);
01089                                         }
01090                                 } else {
01091                                         $theSubstVal = $val["absRef"];
01092                                 }
01093                                 $this->theParts["html"]["content"] = str_replace(
01094                                                 $val["subst_str"],
01095                                                 $val["quotes"].$theSubstVal.$val["quotes"],
01096                                                 $this->theParts["html"]["content"]      );
01097                         }
01098                 }
01099         }
01100 
01107         function substHTTPurlsInPlainText($content)     {
01108                         // This substitutes the http:// urls in plain text with links
01109                 if ($this->jumperURL_prefix)    {
01110                         $textpieces = explode("http://", $content);
01111                         $pieces = count($textpieces);
01112                         $textstr = $textpieces[0];
01113                         for($i=1; $i<$pieces; $i++)     {
01114                                 $len=strcspn($textpieces[$i],chr(32).chr(9).chr(13).chr(10));
01115                                 if (trim(substr($textstr,-1))=="" && $len)      {
01116                                         $lastChar=substr($textpieces[$i],$len-1,1);
01117                                         if (!ereg("[A-Za-z0-9\/#]",$lastChar)) {$len--;}                // Included "\/" 3/12
01118 
01119                                         $parts[0]="http://".substr($textpieces[$i],0,$len);
01120                                         $parts[1]=substr($textpieces[$i],$len);
01121 
01122                                         if ($this->jumperURL_useId)     {
01123                                                 $this->theParts["plain"]["link_ids"][$i]=$parts[0];
01124                                                 $parts[0] = $this->jumperURL_prefix."-".$i;
01125                                         } else {
01126                                                 $parts[0] = $this->jumperURL_prefix.t3lib_div::rawUrlEncodeFP($parts[0]);
01127                                         }
01128                                         $textstr.=$parts[0].$parts[1];
01129                                 } else {
01130                                         $textstr.='http://'.$textpieces[$i];
01131                                 }
01132                         }
01133                         $content = $textstr;
01134                 }
01135                 return $content;
01136         }
01137 
01143         function fixRollOvers() {
01144                         // JavaScript rollOvers cannot support graphics inside of mail. If these exists we must let them refer to the absolute url. By the way: Roll-overs seems to work only on some mail-readers and so far I've seen it work on Netscape 4 message-center (but not 4.5!!)
01145                 $theNewContent = "";
01146                 $theSplit = explode(".src",$this->theParts["html"]["content"]);
01147                 if (count($theSplit)>1) {
01148                         while(list($key,$part)=each($theSplit)) {
01149                                 $sub = substr($part,0,200);
01150                                 if (ereg("cid:part[^ \"']*",$sub,$reg)) {
01151                                         $thePos = strpos($part,$reg[0]);        // The position of the string
01152                                         ereg("cid:part([^\.]*).*",$sub,$reg2);          // Finds the id of the media...
01153                                         $theSubStr = $this->theParts["html"]["media"][intval($reg2[1])]["absRef"];
01154                                         if ($thePos && $theSubStr)      {               // ... and substitutes the javaScript rollover image with this instead
01155                                                 if (!strpos(" ".$theSubStr,"http://")) {$theSubStr = "http://";}                // If the path is NOT and url, the reference is set to nothing
01156                                                 $part = substr($part,0,$thePos).$theSubStr.substr($part,$thePos+strlen($reg[0]),strlen($part));
01157                                         }
01158                                 }
01159                                 $theNewContent.= $part.((($key+1)!=count($theSplit))? ".src" : ""  );
01160                         }
01161                         $this->theParts["html"]["content"]=$theNewContent;
01162                 }
01163         }
01164 
01165 
01166 
01167 
01168 
01169 
01170 
01171 
01172 
01173 
01174 
01175 
01176 
01177 
01178 
01179 
01180         /*******************************************
01181          *
01182          * File and URL-functions
01183          *
01184          *******************************************/
01185 
01190         function makeBase64($inputstr)  {
01191                         // Returns base64-encoded content, which is broken every 76 character
01192                 return chunk_split(base64_encode($inputstr));
01193         }
01194 
01201         function getExtendedURL($url)   {
01202                         // reads the URL or file and determines the Content-type by either guessing or opening a connection to the host
01203                 $res["content"] = $this->getURL($url);
01204                 if (!$res["content"])   {return false;}
01205                 $pathInfo = parse_url($url);
01206                 $fileInfo = $this->split_fileref($pathInfo["path"]);
01207                 if ($fileInfo["fileext"] == "gif")      {$res["content_type"] = "image/gif";}
01208                 if ($fileInfo["fileext"] == "jpg" || $fileInfo["fileext"] == "jpeg")    {$res["content_type"] = "image/jpeg";}
01209                 if ($fileInfo['fileext'] == 'png') {$res['content_type'] = 'image/png';}
01210                 if ($fileInfo["fileext"] == "html" || $fileInfo["fileext"] == "htm")    {$res["content_type"] = "text/html";}
01211                 if ($fileInfo['fileext'] == 'css') {$res['content_type'] = 'text/css';}
01212                 if ($fileInfo["fileext"] == "swf")      {$res["content_type"] = "application/x-shockwave-flash";}
01213                 if (!$res["content_type"])      {$res["content_type"] = $this->getMimeType($url);}
01214                 return $res;
01215         }
01216 
01223         function addUserPass($url)      {
01224                 $user=$this->http_username;
01225                 $pass=$this->http_password;
01226                 $matches = array();
01227                 if ($user && $pass && preg_match('/^(https?:\/\/)/', $url, $matches)) {
01228                         $url = $matches[1].$user.':'.$pass.'@'.substr($url,strlen($matches[1]));
01229                 }
01230                 return $url;
01231         }
01232 
01239         function getURL($url)   {
01240                 $url = $this->addUserPass($url);
01241                         // reads a url or file
01242                 return t3lib_div::getURL($url);
01243         }
01244 
01251         function getStrippedURL($url)   {
01252                         // reads a url or file and strips the HTML-tags AND removes all empty lines. This is used to read plain-text out of a HTML-page
01253                 if($fd = fopen($url,"rb"))      {
01254                         $content = "";
01255                         while (!feof($fd))      {
01256                                 $line = fgetss($fd, 5000);
01257                                 if (trim($line))        {
01258                                         $content.=trim($line)."\n";
01259                                 }
01260                         }
01261                         fclose( $fd );
01262                         return $content;
01263                 }
01264         }
01265 
01272         function getMimeType($url) {
01273                 $mimeType = '';
01274                 $headers = trim(t3lib_div::getURL($url, 2));
01275                 if ($headers) {
01276                         $matches = array();
01277                         if (preg_match('/(Content-Type:[\s]*)([a-zA-Z_0-9\/\-\.\+]*)([\s]|$)/', $headers, $matches)) {
01278                                 $mimeType = trim($matches[2]);
01279                         }
01280                 }
01281                 return $mimeType;
01282         }
01283 
01290         function absRef($ref)   {
01291                         // Returns the absolute address of a link. This is based on $this->theParts["html"]["path"] being the root-address
01292                 $ref = trim($ref);
01293                 $urlINFO = parse_url($ref);
01294                 if ($urlINFO["scheme"]) {
01295                         return $ref;
01296                 } elseif (eregi("^/",$ref)){
01297                         $addr = parse_url($this->theParts["html"]["path"]);
01298                         return  $addr['scheme'].'://'.$addr['host'].($addr['port']?':'.$addr['port']:'').$ref;
01299                 } else {
01300                         return $this->theParts["html"]["path"].$ref;    // If the reference is relative, the path is added, in order for us to fetch the content
01301                 }
01302         }
01303 
01310         function split_fileref($fileref)        {
01311                         // Returns an array with path, filename, filebody, fileext.
01312                 if (    ereg("(.*/)(.*)$",$fileref,$reg)        )       {
01313                         $info["path"] = $reg[1];
01314                         $info["file"] = $reg[2];
01315                 } else {
01316                         $info["path"] = "";
01317                         $info["file"] = $fileref;
01318                 }
01319                 $reg="";
01320                 if (    ereg("(.*)\.([^\.]*$)",$info["file"],$reg)      )       {
01321                         $info["filebody"] = $reg[1];
01322                         $info["fileext"] = strtolower($reg[2]);
01323                         $info["realFileext"] = $reg[2];
01324                 } else {
01325                         $info["filebody"] = $info["file"];
01326                         $info["fileext"] = "";
01327                 }
01328                 return $info;
01329         }
01330 
01337         function extParseUrl($path)     {
01338                         // Returns an array with file or url-information
01339                 $res = parse_url($path);
01340                 ereg("(.*/)([^/]*)$",$res["path"],$reg);
01341                 $res["filepath"]=$reg[1];
01342                 $res["filename"]=$reg[2];
01343                 return $res;
01344         }
01345 
01352         function tag_regex($tagArray)   {
01353                 if (!is_array($tagArray))       {
01354                         $tagArray=Array($tagArray);
01355                 }
01356                 $theRegex = "";
01357                 $c=count($tagArray);
01358                 while(list(,$tag)=each($tagArray))      {
01359                         $c--;
01360                         $theRegex.="<".sql_regcase($tag)."[[:space:]]".(($c)?"|":"");
01361                 }
01362                 return $theRegex;
01363         }
01364 
01374         function get_tag_attributes($tag)       {
01375                 $attributes = Array();
01376                 $tag = ltrim(eregi_replace ("^<[^ ]*","",trim($tag)));
01377                 $tagLen = strlen($tag);
01378                 $safetyCounter = 100;
01379                         // Find attribute
01380                 while ($tag)    {
01381                         $value = "";
01382                         $reg = split("[[:space:]=>]",$tag,2);
01383                         $attrib = $reg[0];
01384 
01385                         $tag = ltrim(substr($tag,strlen($attrib),$tagLen));
01386                         if (substr($tag,0,1)=="=")      {
01387                                 $tag = ltrim(substr($tag,1,$tagLen));
01388                                 if (substr($tag,0,1)=='"')      {       // Quotes around the value
01389                                         $reg = explode('"',substr($tag,1,$tagLen),2);
01390                                         $tag = ltrim($reg[1]);
01391                                         $value = $reg[0];
01392                                 } else {        // No qoutes around value
01393                                         ereg("^([^[:space:]>]*)(.*)",$tag,$reg);
01394                                         $value = trim($reg[1]);
01395                                         $tag = ltrim($reg[2]);
01396                                         if (substr($tag,0,1)==">")      {
01397                                                 $tag ="";
01398                                         }
01399                                 }
01400                         }
01401                         $attributes[strtolower($attrib)]=$value;
01402                         $safetyCounter--;
01403                         if ($safetyCounter<0)   {break;}
01404                 }
01405                 return $attributes;
01406         }
01407 
01416         function quoted_printable($string)      {
01417                 return t3lib_div::quoted_printable($string, 76);
01418         }
01419 
01427         function convertName($name)     {
01428                 return $name;
01429         }
01430 }
01431 
01432 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_htmlmail.php'])  {
01433         include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_htmlmail.php']);
01434 }
01435 ?>