feature 2965: apply new template on pwg_mail()
TODO : review other mail functions, configuration GUI git-svn-id: http://piwigo.org/svn/trunk@25344 68402e56-0260-453c-a942-63ccdbb3a9ee
This commit is contained in:
parent
4c0899f889
commit
7a26038e66
10 changed files with 969 additions and 348 deletions
|
@ -229,42 +229,6 @@ $conf['users_page'] = 20;
|
|||
// image level permissions available in the admin interface
|
||||
$conf['available_permission_levels'] = array(0,1,2,4,8);
|
||||
|
||||
// mail_options: only set it true if you have a send mail warning with
|
||||
// "options" parameter missing on mail() function execution.
|
||||
$conf['mail_options'] = false;
|
||||
|
||||
// send_bcc_mail_webmaster: send bcc mail to webmaster. Set true for debug
|
||||
// or test.
|
||||
$conf['send_bcc_mail_webmaster'] = false;
|
||||
|
||||
// default_email_format:
|
||||
// Define the default email format use to send email
|
||||
// Value could be text/plain or text/html
|
||||
$conf['default_email_format'] = 'text/html';
|
||||
|
||||
// alternative_email_format:
|
||||
// Define the alternative email format use to send email
|
||||
// Value could be text/plain or text/html
|
||||
$conf['alternative_email_format'] = 'text/plain';
|
||||
|
||||
// define the name of sender mail:
|
||||
// If value is empty, gallery title is used
|
||||
$conf['mail_sender_name'] = '';
|
||||
|
||||
// smtp configuration
|
||||
// (work if fsockopen function is allowed for smtp port)
|
||||
// smtp_host: smtp server host
|
||||
// if null, regular mail function is used
|
||||
// format: hoststring[:port]
|
||||
// exemple: smtp.pwg.net:21
|
||||
// smtp_user/smtp_password: user & password for smtp identication
|
||||
$conf['smtp_host'] = '';
|
||||
$conf['smtp_user'] = '';
|
||||
$conf['smtp_password'] = '';
|
||||
|
||||
// 'ssl' or 'tls'
|
||||
$conf['smtp_secure'] = null;
|
||||
|
||||
// check_upgrade_feed: check if there are database upgrade required. Set to
|
||||
// true, a message will strongly encourage you to upgrade your database if
|
||||
// needed.
|
||||
|
@ -306,6 +270,39 @@ $conf['ext_imagick_dir'] = '';
|
|||
// are array(5,10,20,50,'all') but you can set any other numeric value.
|
||||
$conf['comments_page_nb_comments'] = 10;
|
||||
|
||||
// +-----------------------------------------------------------------------+
|
||||
// | email |
|
||||
// +-----------------------------------------------------------------------+
|
||||
|
||||
// send_bcc_mail_webmaster: send bcc mail to webmaster. Set true for debug
|
||||
// or test.
|
||||
$conf['send_bcc_mail_webmaster'] = false;
|
||||
|
||||
// define the name of sender mail: if value is empty, gallery title is used
|
||||
$conf['mail_sender_name'] = '';
|
||||
|
||||
// define the email of sender mail: if valie is empty, webmaster email is used
|
||||
$conf['mail_sender_email'] = '';
|
||||
|
||||
// set true to allow text/html emails
|
||||
$conf['allow_html_email'] = true;
|
||||
|
||||
// 'clear' or 'dark'
|
||||
$conf['mail_theme'] = 'clear';
|
||||
|
||||
// smtp configuration (work if fsockopen function is allowed for smtp port)
|
||||
// smtp_host: smtp server host
|
||||
// if null, regular mail function is used
|
||||
// format: hoststring[:port]
|
||||
// exemple: smtp.pwg.net:21
|
||||
// smtp_user/smtp_password: user & password for smtp identication
|
||||
$conf['smtp_host'] = '';
|
||||
$conf['smtp_user'] = '';
|
||||
$conf['smtp_password'] = '';
|
||||
|
||||
// 'ssl' or 'tls'
|
||||
$conf['smtp_secure'] = null;
|
||||
|
||||
// +-----------------------------------------------------------------------+
|
||||
// | metadata |
|
||||
// +-----------------------------------------------------------------------+
|
||||
|
|
404
include/emogrifier.class.php
Normal file
404
include/emogrifier.class.php
Normal file
|
@ -0,0 +1,404 @@
|
|||
<?php
|
||||
/*
|
||||
UPDATES
|
||||
|
||||
2008-08-10 Fixed CSS comment stripping regex to add PCRE_DOTALL (changed from '/\/\*.*\*\//U' to '/\/\*.*\*\//sU')
|
||||
2008-08-18 Added lines instructing DOMDocument to attempt to normalize HTML before processing
|
||||
2008-10-20 Fixed bug with bad variable name... Thanks Thomas!
|
||||
2008-03-02 Added licensing terms under the MIT License
|
||||
Only remove unprocessable HTML tags if they exist in the array
|
||||
2009-06-03 Normalize existing CSS (style) attributes in the HTML before we process the CSS.
|
||||
Made it so that the display:none stripper doesn't require a trailing semi-colon.
|
||||
2009-08-13 Added support for subset class values (e.g. "p.class1.class2").
|
||||
Added better protection for bad css attributes.
|
||||
Fixed support for HTML entities.
|
||||
2009-08-17 Fixed CSS selector processing so that selectors are processed by precedence/specificity, and not just in order.
|
||||
2009-10-29 Fixed so that selectors appearing later in the CSS will have precedence over identical selectors appearing earlier.
|
||||
2009-11-04 Explicitly declared static functions static to get rid of E_STRICT notices.
|
||||
2010-05-18 Fixed bug where full url filenames with protocols wouldn't get split improperly when we explode on ':'... Thanks Mark!
|
||||
Added two new attribute selectors
|
||||
2010-06-16 Added static caching for less processing overhead in situations where multiple emogrification takes place
|
||||
2010-07-26 Fixed bug where '0' values were getting discarded because of php's empty() function... Thanks Scott!
|
||||
2010-09-03 Added checks to invisible node removal to ensure that we don't try to remove non-existent child nodes of parents that have already been deleted
|
||||
2011-04-08 Fixed errors in CSS->XPath conversion for adjacent sibling selectors and id/class combinations... Thanks Bob V.!
|
||||
2011-06-08 Fixed an error where CSS @media types weren't being parsed correctly... Thanks Will W.!
|
||||
2011-08-03 Fixed an error where an empty selector at the beginning of the CSS would cause a parse error on the next selector... Thanks Alexei T.!
|
||||
2011-10-13 Fully fixed a bug introduced in 2011-06-08 where selectors at the beginning of the CSS would be parsed incorrectly... Thanks Thomas A.!
|
||||
2011-10-26 Added an option to allow you to output emogrified code without extended characters being turned into HTML entities.
|
||||
Moved static references to class attributes so they can be manipulated.
|
||||
Added the ability to clear out the (formerly) static cache when CSS is reloaded.
|
||||
2011-12-22 Fixed a bug that was overwriting existing inline styles from the original HTML... Thanks Sagi L.!
|
||||
2012-01-31 Fixed a bug that was introduced with the 2011-12-22 revision... Thanks Sagi L. and M. Bąkowski!
|
||||
Added extraction of <style> blocks within the HTML due to popular demand.
|
||||
Added several new pseudo-selectors (first-child, last-child, nth-child, and nth-of-type).
|
||||
2012-02-07 Fixed some recent code introductions to use class constants rather than global constants.
|
||||
Fixed some recent code introductions to make it cleaner to read.
|
||||
2012-05-01 Made removal of invisible nodes operate in a case-insensitive manner... Thanks Juha P.!
|
||||
2013-10-10 Add preserveStyleTag option
|
||||
*/
|
||||
|
||||
define('CACHE_CSS', 0);
|
||||
define('CACHE_SELECTOR', 1);
|
||||
define('CACHE_XPATH', 2);
|
||||
|
||||
class Emogrifier {
|
||||
|
||||
// for calculating nth-of-type and nth-child selectors
|
||||
const INDEX = 0;
|
||||
const MULTIPLIER = 1;
|
||||
|
||||
private $html = '';
|
||||
private $css = '';
|
||||
private $unprocessableHTMLTags = array('wbr');
|
||||
private $caches = array();
|
||||
|
||||
// this attribute applies to the case where you want to preserve your original text encoding.
|
||||
// by default, emogrifier translates your text into HTML entities for two reasons:
|
||||
// 1. because of client incompatibilities, it is better practice to send out HTML entities rather than unicode over email
|
||||
// 2. it translates any illegal XML characters that DOMDocument cannot work with
|
||||
// if you would like to preserve your original encoding, set this attribute to true.
|
||||
public $preserveEncoding = false;
|
||||
|
||||
// by default, emogrifier removes <style> tags, set preserveStyleTag to true to keep them
|
||||
public $preserveStyleTag = false;
|
||||
|
||||
public function __construct($html = '', $css = '') {
|
||||
$this->html = $html;
|
||||
$this->css = $css;
|
||||
$this->clearCache();
|
||||
}
|
||||
|
||||
public function setHTML($html = '') { $this->html = $html; }
|
||||
public function setCSS($css = '') {
|
||||
$this->css = $css;
|
||||
$this->clearCache(CACHE_CSS);
|
||||
}
|
||||
|
||||
public function clearCache($key = null) {
|
||||
if (!is_null($key)) {
|
||||
if (isset($this->caches[$key])) $this->caches[$key] = array();
|
||||
} else {
|
||||
$this->caches = array(
|
||||
CACHE_CSS => array(),
|
||||
CACHE_SELECTOR => array(),
|
||||
CACHE_XPATH => array(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// there are some HTML tags that DOMDocument cannot process, and will throw an error if it encounters them.
|
||||
// in particular, DOMDocument will complain if you try to use HTML5 tags in an XHTML document.
|
||||
// these functions allow you to add/remove them if necessary.
|
||||
// it only strips them from the code (does not remove actual nodes).
|
||||
public function addUnprocessableHTMLTag($tag) { $this->unprocessableHTMLTags[] = $tag; }
|
||||
public function removeUnprocessableHTMLTag($tag) {
|
||||
if (($key = array_search($tag,$this->unprocessableHTMLTags)) !== false)
|
||||
unset($this->unprocessableHTMLTags[$key]);
|
||||
}
|
||||
|
||||
// applies the CSS you submit to the html you submit. places the css inline
|
||||
public function emogrify() {
|
||||
$body = $this->html;
|
||||
|
||||
// remove any unprocessable HTML tags (tags that DOMDocument cannot parse; this includes wbr and many new HTML5 tags)
|
||||
if (count($this->unprocessableHTMLTags)) {
|
||||
$unprocessableHTMLTags = implode('|',$this->unprocessableHTMLTags);
|
||||
$body = preg_replace("/<\/?($unprocessableHTMLTags)[^>]*>/i",'',$body);
|
||||
}
|
||||
|
||||
$encoding = mb_detect_encoding($body);
|
||||
$body = mb_convert_encoding($body, 'HTML-ENTITIES', $encoding);
|
||||
|
||||
$xmldoc = new DOMDocument;
|
||||
$xmldoc->encoding = $encoding;
|
||||
$xmldoc->strictErrorChecking = false;
|
||||
$xmldoc->formatOutput = true;
|
||||
$xmldoc->loadHTML($body);
|
||||
$xmldoc->normalizeDocument();
|
||||
|
||||
$xpath = new DOMXPath($xmldoc);
|
||||
|
||||
// before be begin processing the CSS file, parse the document and normalize all existing CSS attributes (changes 'DISPLAY: none' to 'display: none');
|
||||
// we wouldn't have to do this if DOMXPath supported XPath 2.0.
|
||||
// also store a reference of nodes with existing inline styles so we don't overwrite them
|
||||
$vistedNodes = $vistedNodeRef = array();
|
||||
$nodes = @$xpath->query('//*[@style]');
|
||||
foreach ($nodes as $node) {
|
||||
$normalizedOrigStyle = preg_replace('/[A-z\-]+(?=\:)/Se',"strtolower('\\0')", $node->getAttribute('style'));
|
||||
|
||||
// in order to not overwrite existing style attributes in the HTML, we have to save the original HTML styles
|
||||
$nodeKey = md5($node->getNodePath());
|
||||
if (!isset($vistedNodeRef[$nodeKey])) {
|
||||
$vistedNodeRef[$nodeKey] = $this->cssStyleDefinitionToArray($normalizedOrigStyle);
|
||||
$vistedNodes[$nodeKey] = $node;
|
||||
}
|
||||
|
||||
$node->setAttribute('style', $normalizedOrigStyle);
|
||||
}
|
||||
|
||||
// grab any existing style blocks from the html and append them to the existing CSS
|
||||
// (these blocks should be appended so as to have precedence over conflicting styles in the existing CSS)
|
||||
$css = $this->css;
|
||||
$nodes = @$xpath->query('//style');
|
||||
foreach ($nodes as $node) {
|
||||
// append the css
|
||||
$css .= "\n\n{$node->nodeValue}";
|
||||
// remove the <style> node
|
||||
if (!$this->preserveStyleTag) {
|
||||
$node->parentNode->removeChild($node);
|
||||
}
|
||||
}
|
||||
|
||||
// filter the CSS
|
||||
$search = array(
|
||||
'/\/\*.*\*\//sU', // get rid of css comment code
|
||||
'/^\s*@import\s[^;]+;/misU', // strip out any import directives
|
||||
'/^\s*@media\s[^{]+{\s*}/misU', // strip any empty media enclosures
|
||||
'/^\s*@media\s+((aural|braille|embossed|handheld|print|projection|speech|tty|tv)\s*,*\s*)+{.*}\s*}/misU', // strip out all media types that are not 'screen' or 'all' (these don't apply to email)
|
||||
'/^\s*@media\s[^{]+{(.*})\s*}/misU', // get rid of remaining media type enclosures
|
||||
);
|
||||
|
||||
$replace = array(
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
'\\1',
|
||||
);
|
||||
|
||||
$css = preg_replace($search, $replace, $css);
|
||||
|
||||
$csskey = md5($css);
|
||||
if (!isset($this->caches[CACHE_CSS][$csskey])) {
|
||||
|
||||
// process the CSS file for selectors and definitions
|
||||
preg_match_all('/(^|[^{}])\s*([^{]+){([^}]*)}/mis', $css, $matches, PREG_SET_ORDER);
|
||||
|
||||
$all_selectors = array();
|
||||
foreach ($matches as $key => $selectorString) {
|
||||
// if there is a blank definition, skip
|
||||
if (!strlen(trim($selectorString[3]))) continue;
|
||||
|
||||
// else split by commas and duplicate attributes so we can sort by selector precedence
|
||||
$selectors = explode(',',$selectorString[2]);
|
||||
foreach ($selectors as $selector) {
|
||||
|
||||
// don't process pseudo-elements and behavioral (dynamic) pseudo-classes; ONLY allow structural pseudo-classes
|
||||
if (strpos($selector, ':') !== false && !preg_match('/:\S+\-(child|type)\(/i', $selector)) continue;
|
||||
|
||||
$all_selectors[] = array('selector' => trim($selector),
|
||||
'attributes' => trim($selectorString[3]),
|
||||
'line' => $key, // keep track of where it appears in the file, since order is important
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// now sort the selectors by precedence
|
||||
usort($all_selectors, array($this,'sortBySelectorPrecedence'));
|
||||
|
||||
$this->caches[CACHE_CSS][$csskey] = $all_selectors;
|
||||
}
|
||||
|
||||
foreach ($this->caches[CACHE_CSS][$csskey] as $value) {
|
||||
|
||||
// query the body for the xpath selector
|
||||
$nodes = $xpath->query($this->translateCSStoXpath(trim($value['selector'])));
|
||||
|
||||
foreach($nodes as $node) {
|
||||
// if it has a style attribute, get it, process it, and append (overwrite) new stuff
|
||||
if ($node->hasAttribute('style')) {
|
||||
// break it up into an associative array
|
||||
$oldStyleArr = $this->cssStyleDefinitionToArray($node->getAttribute('style'));
|
||||
$newStyleArr = $this->cssStyleDefinitionToArray($value['attributes']);
|
||||
|
||||
// new styles overwrite the old styles (not technically accurate, but close enough)
|
||||
$combinedArr = array_merge($oldStyleArr,$newStyleArr);
|
||||
$style = '';
|
||||
foreach ($combinedArr as $k => $v) $style .= (strtolower($k) . ':' . $v . ';');
|
||||
} else {
|
||||
// otherwise create a new style
|
||||
$style = trim($value['attributes']);
|
||||
}
|
||||
$node->setAttribute('style', $style);
|
||||
}
|
||||
}
|
||||
|
||||
// now iterate through the nodes that contained inline styles in the original HTML
|
||||
foreach ($vistedNodeRef as $nodeKey => $origStyleArr) {
|
||||
$node = $vistedNodes[$nodeKey];
|
||||
$currStyleArr = $this->cssStyleDefinitionToArray($node->getAttribute('style'));
|
||||
|
||||
$combinedArr = array_merge($currStyleArr, $origStyleArr);
|
||||
$style = '';
|
||||
foreach ($combinedArr as $k => $v) $style .= (strtolower($k) . ':' . $v . ';');
|
||||
|
||||
$node->setAttribute('style', $style);
|
||||
}
|
||||
|
||||
// This removes styles from your email that contain display:none.
|
||||
// We need to look for display:none, but we need to do a case-insensitive search. Since DOMDocument only supports XPath 1.0,
|
||||
// lower-case() isn't available to us. We've thus far only set attributes to lowercase, not attribute values. Consequently, we need
|
||||
// to translate() the letters that would be in 'NONE' ("NOE") to lowercase.
|
||||
$nodes = $xpath->query('//*[contains(translate(translate(@style," ",""),"NOE","noe"),"display:none")]');
|
||||
// The checks on parentNode and is_callable below ensure that if we've deleted the parent node,
|
||||
// we don't try to call removeChild on a nonexistent child node
|
||||
if ($nodes->length > 0)
|
||||
foreach ($nodes as $node)
|
||||
if ($node->parentNode && is_callable(array($node->parentNode,'removeChild')))
|
||||
$node->parentNode->removeChild($node);
|
||||
|
||||
if ($this->preserveEncoding) {
|
||||
return mb_convert_encoding($xmldoc->saveHTML(), $encoding, 'HTML-ENTITIES');
|
||||
} else {
|
||||
return $xmldoc->saveHTML();
|
||||
}
|
||||
}
|
||||
|
||||
private function sortBySelectorPrecedence($a, $b) {
|
||||
$precedenceA = $this->getCSSSelectorPrecedence($a['selector']);
|
||||
$precedenceB = $this->getCSSSelectorPrecedence($b['selector']);
|
||||
|
||||
// we want these sorted ascendingly so selectors with lesser precedence get processed first and
|
||||
// selectors with greater precedence get sorted last
|
||||
return ($precedenceA == $precedenceB) ? ($a['line'] < $b['line'] ? -1 : 1) : ($precedenceA < $precedenceB ? -1 : 1);
|
||||
}
|
||||
|
||||
private function getCSSSelectorPrecedence($selector) {
|
||||
$selectorkey = md5($selector);
|
||||
if (!isset($this->caches[CACHE_SELECTOR][$selectorkey])) {
|
||||
$precedence = 0;
|
||||
$value = 100;
|
||||
$search = array('\#','\.',''); // ids: worth 100, classes: worth 10, elements: worth 1
|
||||
|
||||
foreach ($search as $s) {
|
||||
if (trim($selector == '')) break;
|
||||
$num = 0;
|
||||
$selector = preg_replace('/'.$s.'\w+/','',$selector,-1,$num);
|
||||
$precedence += ($value * $num);
|
||||
$value /= 10;
|
||||
}
|
||||
$this->caches[CACHE_SELECTOR][$selectorkey] = $precedence;
|
||||
}
|
||||
|
||||
return $this->caches[CACHE_SELECTOR][$selectorkey];
|
||||
}
|
||||
|
||||
// right now we support all CSS 1 selectors and most CSS2/3 selectors.
|
||||
// http://plasmasturm.org/log/444/
|
||||
private function translateCSStoXpath($css_selector) {
|
||||
|
||||
$css_selector = trim($css_selector);
|
||||
$xpathkey = md5($css_selector);
|
||||
if (!isset($this->caches[CACHE_XPATH][$xpathkey])) {
|
||||
// returns an Xpath selector
|
||||
$search = array(
|
||||
'/\s+>\s+/', // Matches any element that is a child of parent.
|
||||
'/\s+\+\s+/', // Matches any element that is an adjacent sibling.
|
||||
'/\s+/', // Matches any element that is a descendant of an parent element element.
|
||||
'/([^\/]+):first-child/i', // first-child pseudo-selector
|
||||
'/([^\/]+):last-child/i', // last-child pseudo-selector
|
||||
'/(\w)\[(\w+)\]/', // Matches element with attribute
|
||||
'/(\w)\[(\w+)\=[\'"]?(\w+)[\'"]?\]/', // Matches element with EXACT attribute
|
||||
'/(\w+)?\#([\w\-]+)/e', // Matches id attributes
|
||||
'/(\w+|[\*\]])?((\.[\w\-]+)+)/e', // Matches class attributes
|
||||
|
||||
);
|
||||
$replace = array(
|
||||
'/',
|
||||
'/following-sibling::*[1]/self::',
|
||||
'//',
|
||||
'*[1]/self::\\1',
|
||||
'*[last()]/self::\\1',
|
||||
'\\1[@\\2]',
|
||||
'\\1[@\\2="\\3"]',
|
||||
"(strlen('\\1') ? '\\1' : '*').'[@id=\"\\2\"]'",
|
||||
"(strlen('\\1') ? '\\1' : '*').'[contains(concat(\" \",@class,\" \"),concat(\" \",\"'.implode('\",\" \"))][contains(concat(\" \",@class,\" \"),concat(\" \",\"',explode('.',substr('\\2',1))).'\",\" \"))]'",
|
||||
);
|
||||
|
||||
$css_selector = '//'.preg_replace($search, $replace, $css_selector);
|
||||
|
||||
// advanced selectors are going to require a bit more advanced emogrification
|
||||
// if we required PHP 5.3 we could do this with closures
|
||||
$css_selector = preg_replace_callback('/([^\/]+):nth-child\(\s*(odd|even|[+\-]?\d|[+\-]?\d?n(\s*[+\-]\s*\d)?)\s*\)/i', array($this, 'translateNthChild'), $css_selector);
|
||||
$css_selector = preg_replace_callback('/([^\/]+):nth-of-type\(\s*(odd|even|[+\-]?\d|[+\-]?\d?n(\s*[+\-]\s*\d)?)\s*\)/i', array($this, 'translateNthOfType'), $css_selector);
|
||||
|
||||
$this->caches[CACHE_SELECTOR][$xpathkey] = $css_selector;
|
||||
}
|
||||
return $this->caches[CACHE_SELECTOR][$xpathkey];
|
||||
}
|
||||
|
||||
private function translateNthChild($match) {
|
||||
|
||||
$result = $this->parseNth($match);
|
||||
|
||||
if (isset($result[self::MULTIPLIER])) {
|
||||
if ($result[self::MULTIPLIER] < 0) {
|
||||
$result[self::MULTIPLIER] = abs($result[self::MULTIPLIER]);
|
||||
return sprintf("*[(last() - position()) mod %u = %u]/self::%s", $result[self::MULTIPLIER], $result[self::INDEX], $match[1]);
|
||||
} else {
|
||||
return sprintf("*[position() mod %u = %u]/self::%s", $result[self::MULTIPLIER], $result[self::INDEX], $match[1]);
|
||||
}
|
||||
} else {
|
||||
return sprintf("*[%u]/self::%s", $result[self::INDEX], $match[1]);
|
||||
}
|
||||
}
|
||||
|
||||
private function translateNthOfType($match) {
|
||||
|
||||
$result = $this->parseNth($match);
|
||||
|
||||
if (isset($result[self::MULTIPLIER])) {
|
||||
if ($result[self::MULTIPLIER] < 0) {
|
||||
$result[self::MULTIPLIER] = abs($result[self::MULTIPLIER]);
|
||||
return sprintf("%s[(last() - position()) mod %u = %u]", $match[1], $result[self::MULTIPLIER], $result[self::INDEX]);
|
||||
} else {
|
||||
return sprintf("%s[position() mod %u = %u]", $match[1], $result[self::MULTIPLIER], $result[self::INDEX]);
|
||||
}
|
||||
} else {
|
||||
return sprintf("%s[%u]", $match[1], $result[self::INDEX]);
|
||||
}
|
||||
}
|
||||
|
||||
private function parseNth($match) {
|
||||
|
||||
if (in_array(strtolower($match[2]), array('even','odd'))) {
|
||||
$index = strtolower($match[2]) == 'even' ? 0 : 1;
|
||||
return array(self::MULTIPLIER => 2, self::INDEX => $index);
|
||||
// if there is a multiplier
|
||||
} else if (stripos($match[2], 'n') === false) {
|
||||
$index = intval(str_replace(' ', '', $match[2]));
|
||||
return array(self::INDEX => $index);
|
||||
} else {
|
||||
|
||||
if (isset($match[3])) {
|
||||
$multiple_term = str_replace($match[3], '', $match[2]);
|
||||
$index = intval(str_replace(' ', '', $match[3]));
|
||||
} else {
|
||||
$multiple_term = $match[2];
|
||||
$index = 0;
|
||||
}
|
||||
|
||||
$multiplier = str_ireplace('n', '', $multiple_term);
|
||||
|
||||
if (!strlen($multiplier)) $multiplier = 1;
|
||||
elseif ($multiplier == 0) return array(self::INDEX => $index);
|
||||
else $multiplier = intval($multiplier);
|
||||
|
||||
while ($index < 0) $index += abs($multiplier);
|
||||
|
||||
return array(self::MULTIPLIER => $multiplier, self::INDEX => $index);
|
||||
}
|
||||
}
|
||||
|
||||
private function cssStyleDefinitionToArray($style) {
|
||||
$definitions = explode(';',$style);
|
||||
$retArr = array();
|
||||
foreach ($definitions as $def) {
|
||||
if (empty($def) || strpos($def, ':') === false) continue;
|
||||
list($key,$value) = explode(':',$def,2);
|
||||
if (empty($key) || strlen(trim($value)) === 0) continue;
|
||||
$retArr[trim($key)] = trim($value);
|
||||
}
|
||||
return $retArr;
|
||||
}
|
||||
}
|
|
@ -21,13 +21,8 @@
|
|||
// | USA. |
|
||||
// +-----------------------------------------------------------------------+
|
||||
|
||||
// +-----------------------------------------------------------------------+
|
||||
// | functions |
|
||||
// +-----------------------------------------------------------------------+
|
||||
|
||||
/*
|
||||
* Returns the name of the mail sender :
|
||||
*
|
||||
/**
|
||||
* Returns the name of the mail sender
|
||||
* @return string
|
||||
*/
|
||||
function get_mail_sender_name()
|
||||
|
@ -37,20 +32,29 @@ function get_mail_sender_name()
|
|||
return (empty($conf['mail_sender_name']) ? $conf['gallery_title'] : $conf['mail_sender_name']);
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* Returns the email of the mail sender
|
||||
* @since 2.6
|
||||
* @return string
|
||||
*/
|
||||
function get_mail_sender_email()
|
||||
{
|
||||
global $conf;
|
||||
|
||||
return (empty($conf['mail_sender_email']) ? get_webmaster_mail_address() : $conf['mail_sender_email']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of mail configuration parameters :
|
||||
*
|
||||
* - mail_options
|
||||
* - send_bcc_mail_webmaster
|
||||
* - default_email_format
|
||||
* - alternative_email_format
|
||||
* - allow_html_email
|
||||
* - use_smtp
|
||||
* - smtp_host
|
||||
* - smtp_user
|
||||
* - smtp_password
|
||||
* - boundary_key
|
||||
* - smtp_secure
|
||||
* - email_webmaster
|
||||
* - formated_email_webmaster
|
||||
* - name_webmaster
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
|
@ -59,35 +63,28 @@ function get_mail_configuration()
|
|||
global $conf;
|
||||
|
||||
$conf_mail = array(
|
||||
'mail_options' => $conf['mail_options'],
|
||||
'send_bcc_mail_webmaster' => $conf['send_bcc_mail_webmaster'],
|
||||
'default_email_format' => $conf['default_email_format'],
|
||||
'alternative_email_format' => $conf['alternative_email_format'],
|
||||
'allow_html_email' => $conf['allow_html_email'],
|
||||
'mail_theme' => $conf['mail_theme'],
|
||||
'use_smtp' => !empty($conf['smtp_host']),
|
||||
'smtp_host' => $conf['smtp_host'],
|
||||
'smtp_user' => $conf['smtp_user'],
|
||||
'smtp_password' => $conf['smtp_password'],
|
||||
'smtp_secure' => $conf['smtp_secure'],
|
||||
'email_webmaster' => get_mail_sender_email(),
|
||||
'name_webmaster' => get_mail_sender_name(),
|
||||
);
|
||||
|
||||
// we have webmaster id among user list, what's his email address ?
|
||||
$conf_mail['email_webmaster'] = get_webmaster_mail_address();
|
||||
|
||||
// name of the webmaster is the title of the gallery
|
||||
$conf_mail['formated_email_webmaster'] = format_email(get_mail_sender_name(), $conf_mail['email_webmaster']);
|
||||
|
||||
return $conf_mail;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an email address with an associated real name
|
||||
*
|
||||
* @param string name
|
||||
* @param string email
|
||||
*/
|
||||
function format_email($name, $email)
|
||||
{
|
||||
// Spring cleaning
|
||||
$cvt_email = trim(preg_replace('#[\n\r]+#s', '', $email));
|
||||
$cvt_name = trim(preg_replace('#[\n\r]+#s', '', $name));
|
||||
|
||||
|
@ -106,15 +103,46 @@ function format_email($name, $email)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the mail and the name from a formatted address
|
||||
* @since 2.6
|
||||
* @param string|array $input
|
||||
* @return array
|
||||
*/
|
||||
function unformat_email($input)
|
||||
{
|
||||
if (is_array($input))
|
||||
{
|
||||
return $input;
|
||||
}
|
||||
|
||||
if (preg_match('/(.*)<(.*)>.*/', $input, $matches))
|
||||
{
|
||||
return array(
|
||||
'email' => trim($matches[2]),
|
||||
'name' => trim($matches[1]),
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
return array(
|
||||
'email' => trim($input),
|
||||
'name' => '',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns an email address list with minimal email string
|
||||
*
|
||||
* @param string with email list (email separated by comma)
|
||||
* @param string $email_list - comma separated
|
||||
* @return string
|
||||
*/
|
||||
function get_strict_email_list($email_list)
|
||||
{
|
||||
$result = array();
|
||||
$list = explode(',', $email_list);
|
||||
|
||||
foreach ($list as $email)
|
||||
{
|
||||
if (strpos($email, '<') !== false)
|
||||
|
@ -130,37 +158,19 @@ function get_strict_email_list($email_list)
|
|||
|
||||
/**
|
||||
* Return an new mail template
|
||||
*
|
||||
* @param string email_format: mail format, text/html or text/plain
|
||||
* @param string theme: theme to use [default get_default_theme()]
|
||||
* @param string $email_format - text/html or text/plain
|
||||
* @return Template
|
||||
*/
|
||||
function & get_mail_template($email_format, $theme='')
|
||||
function &get_mail_template($email_format)
|
||||
{
|
||||
if (empty($theme))
|
||||
{
|
||||
$theme = get_default_theme();
|
||||
}
|
||||
|
||||
$mail_template = new Template(PHPWG_ROOT_PATH.'themes', $theme, 'template/mail/'.$email_format);
|
||||
|
||||
return $mail_template;
|
||||
$template = new Template(PHPWG_ROOT_PATH.'themes', 'default', 'template/mail/'.$email_format);
|
||||
return $template;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return string email format (text/html or text/plain)
|
||||
*
|
||||
* @param string format
|
||||
*/
|
||||
function get_str_email_format($is_html)
|
||||
{
|
||||
return ($is_html ? 'text/html' : 'text/plain');
|
||||
}
|
||||
|
||||
/*
|
||||
* Switch language to param language
|
||||
* Switch language to specified language
|
||||
* All entries are push on language stack
|
||||
*
|
||||
* @param string language
|
||||
* @param string $language
|
||||
*/
|
||||
function switch_lang_to($language)
|
||||
{
|
||||
|
@ -197,6 +207,7 @@ function switch_lang_to($language)
|
|||
// Translations are in admin file too
|
||||
load_language('admin.lang', '', array('language'=>$language) );
|
||||
|
||||
// Reload all plugins files (see load_language declaration)
|
||||
if (!empty($language_files))
|
||||
{
|
||||
foreach ($language_files as $dirname => $files)
|
||||
|
@ -219,10 +230,8 @@ function switch_lang_to($language)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* Switch back language pushed with switch_lang_to function
|
||||
*
|
||||
* @param: none
|
||||
*/
|
||||
function switch_lang_back()
|
||||
{
|
||||
|
@ -456,12 +465,11 @@ WHERE
|
|||
return $return;
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* sends an email, using Piwigo specific informations
|
||||
*
|
||||
* @param:
|
||||
* - to: receiver(s) of the mail (list separated by comma).
|
||||
* - args: function params of mail function:
|
||||
* @param string|string[] $to
|
||||
* @param array $args
|
||||
* o from: sender [default value webmaster email]
|
||||
* o Cc: array of carbon copy receivers of the mail. [default value empty]
|
||||
* o Bcc: array of blind carbon copy receivers of the mail. [default value empty]
|
||||
|
@ -469,9 +477,11 @@ WHERE
|
|||
* o content: content of mail [default value '']
|
||||
* o content_format: format of mail content [default value 'text/plain']
|
||||
* o email_format: global mail format [default value $conf_mail['default_email_format']]
|
||||
* o theme: template to use [default get_default_theme()]
|
||||
* o theme: theme to use [default value $conf_mail['mail_theme']]
|
||||
* o mail_title: main title of the mail [default value $conf['gallery_title']]
|
||||
* o mail_subtitle: subtitle of the mail [default value subject]
|
||||
*
|
||||
* @return boolean (Ok or not)
|
||||
* @return boolean
|
||||
*/
|
||||
function pwg_mail($to, $args = array())
|
||||
{
|
||||
|
@ -491,9 +501,11 @@ function pwg_mail($to, $args = array())
|
|||
|
||||
$mail = new PHPMailer;
|
||||
|
||||
foreach (explode(',', get_strict_email_list($to)) as $recipient)
|
||||
$recipients = !is_array($to) ? explode(',', $to) : $to;
|
||||
foreach ($recipients as $recipient)
|
||||
{
|
||||
$mail->addAddress($recipient);
|
||||
$recipient = unformat_email($recipient);
|
||||
$mail->addAddress($recipient['email'], $recipient['name']);
|
||||
}
|
||||
|
||||
$mail->WordWrap = 76;
|
||||
|
@ -504,86 +516,97 @@ function pwg_mail($to, $args = array())
|
|||
|
||||
if (empty($args['from']))
|
||||
{
|
||||
$mail->From = get_webmaster_mail_address();
|
||||
$mail->FromName = get_mail_sender_name();
|
||||
|
||||
$mail->addReplyTo(get_webmaster_mail_address(), get_mail_sender_name());
|
||||
$from = array(
|
||||
'email' => $conf_mail['email_webmaster'],
|
||||
'name' => $conf_mail['name_webmaster'],
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
$mail->From = $args['from'];
|
||||
$mail->addReplyTo($args['from']);
|
||||
$from = unformat_email($args['from']);
|
||||
}
|
||||
$mail->setFrom($from['email'], $from['name']);
|
||||
$mail->addReplyTo($from['email'], $from['name']);
|
||||
|
||||
// Subject
|
||||
if (empty($args['subject']))
|
||||
{
|
||||
$args['subject'] = 'Piwigo';
|
||||
}
|
||||
|
||||
$args['subject'] = trim(preg_replace('#[\n\r]+#s', '', $args['subject']));
|
||||
|
||||
$mail->Subject = $args['subject'];
|
||||
|
||||
// Cc
|
||||
if (!empty($args['Cc']))
|
||||
{
|
||||
$mail->addCC($args['Cc']);
|
||||
foreach ($args['Cc'] as $cc)
|
||||
{
|
||||
$cc = unformat_email($cc);
|
||||
$mail->addCC($cc['email'], $cc['name']);
|
||||
}
|
||||
}
|
||||
|
||||
// Bcc
|
||||
if ($conf_mail['send_bcc_mail_webmaster'])
|
||||
{
|
||||
$args['Bcc'][] = get_webmaster_mail_address();;
|
||||
$args['Bcc'][] = get_webmaster_mail_address();
|
||||
}
|
||||
|
||||
if (!empty($args['Bcc']))
|
||||
{
|
||||
foreach ($args['Bcc'] as $bcc)
|
||||
{
|
||||
$mail->addBCC($bcc);
|
||||
$bcc = unformat_email($bcc);
|
||||
$mail->addBCC($bcc['email'], $bcc['name']);
|
||||
}
|
||||
}
|
||||
|
||||
// theme
|
||||
if (empty($args['theme']) or !in_array($args['theme'], array('clear','dark')))
|
||||
{
|
||||
$args['theme'] = $conf_mail['mail_theme'];
|
||||
}
|
||||
|
||||
// content
|
||||
if (empty($args['email_format']))
|
||||
{
|
||||
$args['email_format'] = $conf_mail['default_email_format'];
|
||||
}
|
||||
|
||||
if (!isset($args['content']))
|
||||
{
|
||||
$args['content'] = '';
|
||||
}
|
||||
if (!isset($args['mail_title']))
|
||||
{
|
||||
$args['mail_title'] = $conf['gallery_title'];
|
||||
}
|
||||
if (!isset($args['mail_subtitle']))
|
||||
{
|
||||
$args['mail_subtitle'] = $args['subject'];
|
||||
}
|
||||
|
||||
// content type
|
||||
if (empty($args['content_format']))
|
||||
{
|
||||
$args['content_format'] = 'text/plain';
|
||||
}
|
||||
|
||||
if (empty($args['theme']))
|
||||
$content_type_list = array();
|
||||
if ($conf_mail['allow_html_email'] and @$args['email_format'] != 'text/plain')
|
||||
{
|
||||
$args['theme'] = get_default_theme();
|
||||
}
|
||||
|
||||
$content_type_list[] = $args['email_format'];
|
||||
if (!empty($conf_mail['alternative_email_format']))
|
||||
{
|
||||
$content_type_list[] = $conf_mail['alternative_email_format'];
|
||||
$content_type_list[] = 'text/html';
|
||||
}
|
||||
$content_type_list[] = 'text/plain';
|
||||
|
||||
$contents = array();
|
||||
|
||||
foreach (array_unique($content_type_list) as $content_type)
|
||||
foreach ($content_type_list as $content_type)
|
||||
{
|
||||
// key compose of indexes witch allow ti cache mail data
|
||||
$cache_key = $content_type.'-'.$lang_info['code'].'-'.$args['theme'];
|
||||
// key compose of indexes witch allow to cache mail data
|
||||
$cache_key = $content_type.'-'.$lang_info['code'];
|
||||
$cache_key.= '-'.crc32(@$args['mail_title'] . @$args['mail_subtitle']);
|
||||
|
||||
if (!isset($conf_mail[$cache_key]))
|
||||
{
|
||||
// instanciate a new Template
|
||||
if (!isset($conf_mail[$cache_key]['theme']))
|
||||
{
|
||||
$conf_mail[$cache_key]['theme'] = get_mail_template($content_type, $args['theme']);
|
||||
$conf_mail[$cache_key]['theme'] = get_mail_template($content_type);
|
||||
trigger_action('before_parse_mail_template', $cache_key, $content_type);
|
||||
}
|
||||
|
||||
$conf_mail[$cache_key]['theme']->set_filename('mail_header', 'header.tpl');
|
||||
|
@ -594,9 +617,11 @@ function pwg_mail($to, $args = array())
|
|||
'GALLERY_URL' => get_gallery_home_url(),
|
||||
'GALLERY_TITLE' => isset($page['gallery_title']) ? $page['gallery_title'] : $conf['gallery_title'],
|
||||
'VERSION' => $conf['show_version'] ? PHPWG_VERSION : '',
|
||||
'PHPWG_URL' => PHPWG_URL,
|
||||
'TITLE_MAIL' => urlencode(l10n('A comment on your site')),
|
||||
'MAIL' => get_webmaster_mail_address()
|
||||
'PHPWG_URL' => defined('PHPWG_URL') ? PHPWG_URL : '',
|
||||
'CONTENT_ENCODING' => get_pwg_charset(),
|
||||
'CONTACT_MAIL' => $conf_mail['email_webmaster'],
|
||||
'MAIL_TITLE' => $args['mail_title'],
|
||||
'MAIL_SUBTITLE' => $args['mail_subtitle'],
|
||||
)
|
||||
);
|
||||
|
||||
|
@ -608,18 +633,14 @@ function pwg_mail($to, $args = array())
|
|||
$conf_mail[$cache_key]['theme']->assign_var_from_handle('GLOBAL_MAIL_CSS', 'css');
|
||||
}
|
||||
|
||||
$file = PHPWG_ROOT_PATH.'themes/'.$args['theme'].'/mail-css.tpl';
|
||||
if (is_file($file))
|
||||
if ($conf_mail[$cache_key]['theme']->smarty->template_exists('mail-css-'. $args['theme'] .'.tpl'))
|
||||
{
|
||||
$conf_mail[$cache_key]['theme']->set_filename('css', realpath($file));
|
||||
$conf_mail[$cache_key]['theme']->set_filename('css', 'mail-css-'. $args['theme'] .'.tpl');
|
||||
$conf_mail[$cache_key]['theme']->assign_var_from_handle('MAIL_CSS', 'css');
|
||||
}
|
||||
}
|
||||
|
||||
// what are displayed on the header of each mail ?
|
||||
$conf_mail[$cache_key]['header'] = $conf_mail[$cache_key]['theme']->parse('mail_header', true);
|
||||
|
||||
// what are displayed on the footer of each mail ?
|
||||
$conf_mail[$cache_key]['footer'] = $conf_mail[$cache_key]['theme']->parse('mail_footer', true);
|
||||
}
|
||||
|
||||
|
@ -627,16 +648,21 @@ function pwg_mail($to, $args = array())
|
|||
$contents[$content_type] = $conf_mail[$cache_key]['header'];
|
||||
|
||||
// Content
|
||||
if (($args['content_format'] == 'text/plain') and ($content_type == 'text/html'))
|
||||
if ($args['content_format'] == 'text/plain' and $content_type == 'text/html')
|
||||
{
|
||||
$contents[$content_type].= '<p>'.
|
||||
// convert plain text to html
|
||||
$contents[$content_type].=
|
||||
'<p>'.
|
||||
nl2br(
|
||||
preg_replace("/(http:\/\/)([^\s,]*)/i",
|
||||
"<a href='$1$2' class='thumblnk'>$1$2</a>",
|
||||
htmlspecialchars($args['content']))).
|
||||
preg_replace(
|
||||
'/(https?:\/\/([-\w\.]+[-\w])+(:\d+)?(\/([\w\/_\.\#-]*(\?\S+)?[^\.\s])?)?)/i',
|
||||
'<a href="$1">$1</a>',
|
||||
htmlspecialchars($args['content'])
|
||||
)
|
||||
).
|
||||
'</p>';
|
||||
}
|
||||
else if (($args['content_format'] == 'text/html') and ($content_type == 'text/plain'))
|
||||
else if ($args['content_format'] == 'text/html' and $content_type == 'text/plain')
|
||||
{
|
||||
// convert html text to plain text
|
||||
$contents[$content_type].= strip_tags($args['content']);
|
||||
|
@ -653,10 +679,11 @@ function pwg_mail($to, $args = array())
|
|||
// Undo Compute root_path in order have complete path
|
||||
unset_make_full_url();
|
||||
|
||||
// Send content to PHPMailer
|
||||
if (isset($contents['text/html']))
|
||||
{
|
||||
$mail->isHTML(true); // Set email format to HTML
|
||||
$mail->Body = $contents['text/html'];
|
||||
$mail->isHTML(true);
|
||||
$mail->Body = move_css_to_body($contents['text/html']);
|
||||
|
||||
if (isset($contents['text/plain']))
|
||||
{
|
||||
|
@ -703,93 +730,34 @@ function pwg_mail($to, $args = array())
|
|||
}
|
||||
}
|
||||
|
||||
$ret = true;
|
||||
$pre_result = trigger_event('before_send_mail', true, $to, $args, $mail);
|
||||
|
||||
if ($pre_result)
|
||||
{
|
||||
$ret = $mail->send();
|
||||
if(!$ret)
|
||||
if (!$ret and is_admin())
|
||||
{
|
||||
trigger_error('Mailer Error: ' . $mail->ErrorInfo, E_USER_WARNING);
|
||||
}
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/* DEPRECATED
|
||||
* pwg sendmail
|
||||
*
|
||||
* @param:
|
||||
* - result of other sendmail
|
||||
* - to: Receiver or receiver(s) of the mail.
|
||||
* - subject [default value 'Piwigo']
|
||||
* - content: content of mail
|
||||
* - headers: headers of mail
|
||||
*
|
||||
* @return boolean (Ok or not)
|
||||
/**
|
||||
* @deprecated 2.6
|
||||
*/
|
||||
function pwg_send_mail($result, $to, $subject, $contents, $headers)
|
||||
function pwg_send_mail($result, $to, $subject, $content, $headers)
|
||||
{
|
||||
trigger_error('pwg_send_mail function is deprecated', E_USER_NOTICE);
|
||||
|
||||
if (!$result)
|
||||
{
|
||||
include_once(PHPWG_ROOT_PATH.'include/class.phpmailer.php');
|
||||
|
||||
global $conf_mail;
|
||||
|
||||
if ($conf_mail['use_smtp'])
|
||||
{
|
||||
include_once( PHPWG_ROOT_PATH.'include/class_smtp_mail.inc.php' );
|
||||
$smtp_mail = new smtp_mail(
|
||||
$conf_mail['smtp_host'], $conf_mail['smtp_user'], $conf_mail['smtp_password'],
|
||||
$conf_mail['email_webmaster']);
|
||||
return $smtp_mail->mail($to, $subject, $content, $headers);
|
||||
}
|
||||
else
|
||||
{
|
||||
$mail = new PHPMailer;
|
||||
|
||||
$mail->From = 'plg@pigolabs.com';
|
||||
$mail->FromName = 'Pierrick en local';
|
||||
foreach (explode(',', $to) as $recipient)
|
||||
{
|
||||
$mail->addAddress($recipient); // Add a recipient
|
||||
}
|
||||
// $mail->addReplyTo('plg@piwigo.org', 'Pierrick de Piwigo.org');
|
||||
// $mail->addCC('cc@example.com');
|
||||
// $mail->addBCC('bcc@example.com');
|
||||
|
||||
$mail->WordWrap = 76; // Set word wrap to 50 characters
|
||||
|
||||
if (isset($contents['text/html']))
|
||||
{
|
||||
$mail->isHTML(true); // Set email format to HTML
|
||||
$mail->Body = $contents['text/html'];
|
||||
|
||||
if (isset($contents['text/plain']))
|
||||
{
|
||||
$mail->AltBody = $contents['text/plain'];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$mail->isHTML(false);
|
||||
$mail->Body = $contents['text/plain'];
|
||||
}
|
||||
|
||||
$mail->CharSet = 'UTF-8';
|
||||
$mail->Subject = $subject;
|
||||
|
||||
if(!$mail->send()) {
|
||||
echo 'Message could not be sent.';
|
||||
echo 'Mailer Error: ' . $mail->ErrorInfo;
|
||||
exit;
|
||||
}
|
||||
|
||||
// if ($conf_mail['mail_options'])
|
||||
// {
|
||||
// $options = '-f '.$conf_mail['email_webmaster'];
|
||||
// return mail($to, $subject, $content, $headers, $options);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// return mail($to, $subject, $content, $headers);
|
||||
// }
|
||||
}
|
||||
return pwg_mail($to, array(
|
||||
'content' => $content,
|
||||
'subject' => $subject,
|
||||
));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -797,68 +765,44 @@ function pwg_send_mail($result, $to, $subject, $contents, $headers)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated 2.6
|
||||
*/
|
||||
function move_ccs_rules_to_body($content)
|
||||
{
|
||||
return $content;
|
||||
// We search all css rules in style tags
|
||||
preg_match('#<style>(.*?)</style>#s', $content, $matches);
|
||||
trigger_error('move_ccs_rules_to_body function is deprecated, use move_css_to_body', E_USER_NOTICE);
|
||||
|
||||
if (!empty($matches[1]))
|
||||
{
|
||||
preg_match_all('#([^\n]*?)\{(.*?)\}#s', $matches[1], $matches);
|
||||
|
||||
$selectors = array();
|
||||
$unknow_selectors = '';
|
||||
|
||||
foreach ($matches[1] as $key => $value)
|
||||
{
|
||||
$selects = explode(',', $value);
|
||||
$style = trim($matches[2][$key], ' ;');
|
||||
|
||||
foreach($selects as $select)
|
||||
{
|
||||
$select = trim($select);
|
||||
$selectors[$select][] = $style;
|
||||
}
|
||||
return move_css_to_body($content);
|
||||
}
|
||||
|
||||
foreach ($selectors as $selector => $style)
|
||||
/**
|
||||
* Moves CSS rules contained in the <style> tag to inline CSS
|
||||
* (for compatibility with Gmail and such clients)
|
||||
* @since 2.6
|
||||
* @param string $content
|
||||
* @return string
|
||||
*/
|
||||
function move_css_to_body($content)
|
||||
{
|
||||
if (!preg_match('/^(#|\.|)([A-Za-z0-9_-]*)$/', $selector, $matches))
|
||||
{
|
||||
$unknow_selectors .= $selector.' {'.implode(";\n", $style).";}\n";
|
||||
}
|
||||
else switch ($matches[1])
|
||||
{
|
||||
case '#':
|
||||
$content = preg_replace('|id="'.$matches[2].'"|', 'id="'.$matches[2].'" style="'.implode(";\n", $style).";\"\n", $content);
|
||||
break;
|
||||
case '.':
|
||||
$content = preg_replace('|class="'.$matches[2].'"|', 'class="'.$matches[2].'" style="'.implode(";\n", $style).";\"\n", $content);
|
||||
break;
|
||||
default:
|
||||
$content = preg_replace('#<'.$matches[2].'( |>)#', '<'.$matches[2].' style="'.implode(";\n", $style).";\"\n$1", $content);
|
||||
break;
|
||||
}
|
||||
include_once(PHPWG_ROOT_PATH.'include/emogrifier.class.php');
|
||||
|
||||
$e = new Emogrifier($content);
|
||||
$e->preserveStyleTag = true;
|
||||
return $e->emogrify();
|
||||
}
|
||||
|
||||
// Keep unknow tags in page head
|
||||
if (!empty($unknow_selectors))
|
||||
{
|
||||
$content = preg_replace('#<style>.*?</style>#s', "<style type=\"text/css\">\n$unknow_selectors</style>", $content);
|
||||
}
|
||||
else
|
||||
{
|
||||
$content = preg_replace('#<style>.*?</style>#s', '', $content);
|
||||
}
|
||||
}
|
||||
return $content;
|
||||
}
|
||||
|
||||
/*Testing block*/
|
||||
function pwg_send_mail_test($result, $to, $subject, $content, $headers, $args)
|
||||
/**
|
||||
* Saves a copy of the mail if _data/tmp
|
||||
* @param boolean $result
|
||||
* @param string $to
|
||||
* @param array $args
|
||||
* @param PHPMailer $mail
|
||||
* @return boolean $result
|
||||
*/
|
||||
function pwg_send_mail_test($result, $to, $args, $mail)
|
||||
{
|
||||
global $conf, $user, $lang_info;
|
||||
|
||||
$dir = PHPWG_ROOT_PATH.$conf['data_location'].'tmp';
|
||||
if (mkgetdir($dir, MKGETDIR_DEFAULT&~MKGETDIR_DIE_ON_ERROR))
|
||||
{
|
||||
|
@ -871,21 +815,23 @@ function pwg_send_mail_test($result, $to, $subject, $content, $headers, $args)
|
|||
{
|
||||
$filename .= '.html';
|
||||
}
|
||||
|
||||
$file = fopen($filename, 'w+');
|
||||
fwrite($file, $to ."\n");
|
||||
fwrite($file, $subject ."\n");
|
||||
fwrite($file, $headers);
|
||||
fwrite($file, $content);
|
||||
fwrite($file, implode(', ', $to) ."\n");
|
||||
fwrite($file, $mail->Subject ."\n");
|
||||
fwrite($file, $mail->createHeader() ."\n");
|
||||
fwrite($file, $mail->createBody());
|
||||
fclose($file);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
if ($conf['debug_mail'])
|
||||
add_event_handler('send_mail', 'pwg_send_mail_test', EVENT_HANDLER_PRIORITY_NEUTRAL+10, 6);
|
||||
{
|
||||
add_event_handler('before_send_mail', 'pwg_send_mail_test', EVENT_HANDLER_PRIORITY_NEUTRAL+10, 4);
|
||||
}
|
||||
|
||||
|
||||
add_event_handler('send_mail', 'pwg_send_mail', EVENT_HANDLER_PRIORITY_NEUTRAL, 5);
|
||||
add_event_handler('send_mail_content', 'move_ccs_rules_to_body');
|
||||
trigger_action('functions_mail_included');
|
||||
|
||||
?>
|
|
@ -1,22 +1,23 @@
|
|||
</div> <!-- content -->
|
||||
<div id="copyright">
|
||||
<hr>
|
||||
{'Sent by'|@translate}
|
||||
<a href="{$GALLERY_URL}">{$GALLERY_TITLE}</a>
|
||||
{* <!-- end $CONTENT --> *}
|
||||
</td></tr>
|
||||
|
||||
{* Please, do not remove this copyright. If you really want to,
|
||||
<tr><td id="footer">
|
||||
{* <!-- begin FOOTER --> *}
|
||||
{* <!-- Please, do not remove this copyright. If you really want to,
|
||||
contact us on http://piwigo.org to find a solution on how
|
||||
to show the origin of the script...*}
|
||||
- {'Powered by'|@translate}
|
||||
<a href="http://piwigo.org" class="Piwigo">
|
||||
<span class="Piwigo">Piwigo</span></a>
|
||||
{$VERSION}
|
||||
to show the origin of the script... --> *}
|
||||
|
||||
- {'Contact'|@translate}
|
||||
<a href="mailto:{$MAIL}?subject={$TITLE_MAIL}">{'Webmaster'|@translate}</a>
|
||||
{'Sent by'|translate} <a href="{$GALLERY_URL}">{$GALLERY_TITLE}</a>
|
||||
- {'Powered by'|translate} <a href="{$PHPWG_URL}" class="Piwigo">Piwigo</a>
|
||||
{if not empty($VERSION)}{$VERSION}{/if}
|
||||
|
||||
</div> <!-- copyright -->
|
||||
</div> <!-- the_page -->
|
||||
- {'Contact'|translate}
|
||||
<a href="mailto:{$CONTACT_MAIL}?subject={'A comment on your site'|translate|escape:url}">{'Webmaster'|@translate}</a>
|
||||
{* <!-- end FOOTER --> *}
|
||||
</td></tr>
|
||||
</table>
|
||||
|
||||
</td></tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
|
@ -1,11 +1,103 @@
|
|||
/* Global mail css */
|
||||
{strip}
|
||||
/* page */
|
||||
body {
|
||||
font-family:"Verdana", "Helvetica", "Optima", sans-serif;
|
||||
font-size:12px;
|
||||
margin:0px;
|
||||
padding:0px;
|
||||
}
|
||||
|
||||
body {ldelim} font-family: Univers, Helvetica, Optima; font-size:12px; margin:0px; padding:0px; }
|
||||
#the_page {ldelim} margin:0px; padding:0px; text-align:left;}
|
||||
#content {ldelim} margin:0px; padding:30px 0px 0px 30px; width:732px;}
|
||||
hr {ldelim} width:632px; margin-left:0;}
|
||||
#copyright {ldelim} font-size:10px; margin:0px; padding:48px 0px 32px 62px;}
|
||||
.PWG {ldelim} font-family:verdana, sans-serif !important; font-size:0.9em; font-weight:normal; letter-spacing:0px;}
|
||||
h2 {ldelim} padding:7px 15px; width:617px; font-weight:bold;}
|
||||
img {ldelim} margin:16px; border:16px solid #aaa; -moz-border-radius: 4px; border-radius: 4px 4px; }
|
||||
img:hover {ldelim} padding: 15px; border: 1px solid yellow; -moz-border-radius: 4px; border-radius: 4px 4px; }
|
||||
html, body, #bodyTable {
|
||||
width:100%;
|
||||
height:100%;
|
||||
}
|
||||
|
||||
/* main block */
|
||||
#header {
|
||||
padding:20px;
|
||||
}
|
||||
#header #title {
|
||||
font-size:26px;
|
||||
font-weight:bold;
|
||||
}
|
||||
#header #subtitle {
|
||||
font-size:20px;
|
||||
}
|
||||
#content {
|
||||
padding:0 20px 20px 20px;
|
||||
}
|
||||
#footer {
|
||||
font-size:10px;
|
||||
padding:5px;
|
||||
}
|
||||
#topSpacer {
|
||||
margin-bottom:20px;
|
||||
}
|
||||
|
||||
/* images */
|
||||
img {
|
||||
border:none;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5 {
|
||||
margin:0.5em 0 0.25em 0;
|
||||
}
|
||||
h1 { font-size:26px; }
|
||||
h2 { font-size:20px; }
|
||||
h3 { font-size:16px; }
|
||||
h4 { font-size:12px; }
|
||||
h5 { font-size:10px; }
|
||||
|
||||
/* paragraphs */
|
||||
p {
|
||||
margin:0.25em 0 0.5em 0;
|
||||
}
|
||||
blockquote {
|
||||
margin-left:10px;
|
||||
padding-left:10px;
|
||||
font-family:"Times",serif;
|
||||
font-size:14px;
|
||||
}
|
||||
|
||||
/* list */
|
||||
ul, ol {
|
||||
margin:0.5em 0 0.25em 30px;
|
||||
padding:0;
|
||||
}
|
||||
dl {
|
||||
margin:0.5em 0 0.25em 10px;
|
||||
}
|
||||
dt {
|
||||
margin:0.25em 0 0 0;
|
||||
font-weight:bold;
|
||||
}
|
||||
dd {
|
||||
margin:0 0 0.25em 10px;
|
||||
}
|
||||
|
||||
/* tables */
|
||||
#content table {
|
||||
width:100%;
|
||||
border-spacing:0;
|
||||
border-collapse:collapse;
|
||||
}
|
||||
#content table td {
|
||||
padding:2px 3px;
|
||||
}
|
||||
#content table th {
|
||||
font-weight:bold;
|
||||
text-align:center;
|
||||
padding:4px 0;
|
||||
}
|
||||
#content table tfoot td {
|
||||
font-size:0.8em;
|
||||
}
|
||||
|
||||
/* line */
|
||||
hr {
|
||||
border-width:0 0 1px 0;
|
||||
border-color:#ddd;
|
||||
border-style:solid;
|
||||
margin:1em;
|
||||
}
|
||||
{/strip}
|
|
@ -1,13 +1,29 @@
|
|||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html lang="{$lang_info.code}" dir="{$lang_info.direction}">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset={$CONTENT_ENCODING}"/>
|
||||
<title>Piwigo Mail</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset={$CONTENT_ENCODING}">
|
||||
<style><!-- /* Mini style for mails */
|
||||
|
||||
<style type="text/css">
|
||||
{if isset($GLOBAL_MAIL_CSS)}{$GLOBAL_MAIL_CSS}{/if}
|
||||
{if isset($MAIL_CSS)}{$MAIL_CSS}{/if}
|
||||
--></style>
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="the_page">
|
||||
<div id="content" class="content">
|
||||
<table id="bodyTable" cellspacing="0" cellpadding="10" border="0">
|
||||
<tr><td align="center" valign="top">
|
||||
|
||||
<table id="contentTable" cellspacing="0" cellpadding="0" border="0">
|
||||
<tr><td id="header">
|
||||
{* <!-- begin HEADER --> *}
|
||||
<div id="title">{$MAIL_TITLE}</div>
|
||||
{if not empty($MAIL_SUBTITLE)}<div id="subtitle">{$MAIL_SUBTITLE}</div>{/if}
|
||||
{* <!-- end HEADER --> *}
|
||||
</td></tr>
|
||||
|
||||
<tr><td id="content">
|
||||
{* <!-- use an invisible div with a bottom margin to force the browser
|
||||
to merge the margin with the element bellow (typically h1/h2/...) --> *}
|
||||
<div id="topSpacer"></div>
|
||||
{* <!-- begin CONTENT --> *}
|
73
themes/default/template/mail/text/html/mail-css-clear.tpl
Normal file
73
themes/default/template/mail/text/html/mail-css-clear.tpl
Normal file
|
@ -0,0 +1,73 @@
|
|||
{strip}
|
||||
/* page */
|
||||
body {
|
||||
color:#111;
|
||||
}
|
||||
|
||||
html, body, #bodyTable {
|
||||
background:#fff;
|
||||
}
|
||||
#contentTable {
|
||||
width:600px;
|
||||
}
|
||||
|
||||
/* main block */
|
||||
#header {
|
||||
background:#eee;
|
||||
background:radial-gradient(ellipse at center, #fefefe, #e5e5e5);
|
||||
border-top:4px solid #f70;
|
||||
text-align:center;
|
||||
text-shadow:1px 1px 0px #fff;
|
||||
}
|
||||
#header #subtitle {
|
||||
color:#e06900;
|
||||
}
|
||||
#content {
|
||||
background:#fefefe;
|
||||
border-width:1px;
|
||||
border-style:solid;
|
||||
border-color:#ddd #eee;
|
||||
box-shadow:inset 0 0 20px #eee;
|
||||
}
|
||||
#footer {
|
||||
background:#eee;
|
||||
border-bottom:2px solid #f70;
|
||||
}
|
||||
|
||||
/* links */
|
||||
a {
|
||||
color:#f70;
|
||||
text-decoration:none;
|
||||
}
|
||||
a:hover {
|
||||
text-decoration:underline;
|
||||
}
|
||||
|
||||
/* images */
|
||||
img.photo {
|
||||
border:10px solid #ddd;
|
||||
}
|
||||
img.photo:hover {
|
||||
border-color:#eee;
|
||||
}
|
||||
|
||||
/* paragraphs */
|
||||
blockquote {
|
||||
border-left:2px solid #aaa;
|
||||
border-radius:2px;
|
||||
}
|
||||
|
||||
/* tables */
|
||||
#content table td {
|
||||
border-bottom:1px solid #efefef;
|
||||
}
|
||||
#content table th {
|
||||
background:#aaa;
|
||||
color:#fff;
|
||||
border-right:1px solid #ddd;
|
||||
}
|
||||
#content table tfoot td {
|
||||
background:#eee;
|
||||
border-right:1px solid #fff;
|
||||
}
|
||||
{/strip}
|
87
themes/default/template/mail/text/html/mail-css-dark.tpl
Normal file
87
themes/default/template/mail/text/html/mail-css-dark.tpl
Normal file
|
@ -0,0 +1,87 @@
|
|||
{strip}
|
||||
/* page */
|
||||
body {
|
||||
color:#fff;
|
||||
}
|
||||
|
||||
html, body, #bodyTable {
|
||||
background:#111;
|
||||
}
|
||||
#contentTable {
|
||||
width:600px;
|
||||
}
|
||||
|
||||
/* main block */
|
||||
#header {
|
||||
background:#444;
|
||||
background:radial-gradient(ellipse at center, #555, #333);
|
||||
border:1px solid #000;
|
||||
border-top:4px solid #f70;
|
||||
text-align:center;
|
||||
text-shadow:1px 1px 0px #000;
|
||||
}
|
||||
#header #title {
|
||||
color:#eee;
|
||||
}
|
||||
#header #subtitle {
|
||||
color:#e06900;
|
||||
}
|
||||
#content {
|
||||
background:#111;
|
||||
border-width:1px;
|
||||
border-style:solid;
|
||||
border-color:#666 #000;
|
||||
box-shadow:inset 0 0 20px #333;
|
||||
}
|
||||
#footer {
|
||||
background:#333;
|
||||
border:1px solid #000;
|
||||
border-bottom:2px solid #f70;
|
||||
}
|
||||
|
||||
/* links */
|
||||
a {
|
||||
color:#f70;
|
||||
text-decoration:none;
|
||||
}
|
||||
a:hover {
|
||||
text-decoration:underline;
|
||||
}
|
||||
|
||||
/* images */
|
||||
img.photo {
|
||||
border:10px solid #666;
|
||||
}
|
||||
img.photo:hover {
|
||||
border-color:#999;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5 {
|
||||
color:#bbb;
|
||||
}
|
||||
|
||||
/* paragraphs */
|
||||
blockquote {
|
||||
border-left:2px solid #aaa;
|
||||
border-radius:2px;
|
||||
}
|
||||
|
||||
/* tables */
|
||||
#content table td {
|
||||
border-bottom:1px solid #999;
|
||||
}
|
||||
#content table th {
|
||||
background:#666;
|
||||
border-right:1px solid #aaa;
|
||||
}
|
||||
#content table tfoot td {
|
||||
background:#444;
|
||||
color:#aaa;
|
||||
border-right:1px solid #aaa;
|
||||
}
|
||||
|
||||
/* line */
|
||||
hr {
|
||||
border-color:#555;
|
||||
}
|
||||
{/strip}
|
|
@ -1,5 +1,7 @@
|
|||
{literal}
|
||||
|
||||
--
|
||||
{/literal}
|
||||
----
|
||||
{'Sent by'|@translate} "{$GALLERY_TITLE}" {$GALLERY_URL}
|
||||
{'Contact'|@translate} {$MAIL}
|
||||
{'Powered by'|@translate} Piwigo {$VERSION}
|
||||
{'Powered by'|@translate} "Piwigo{if not empty($VERSION)} {$VERSION}{/if}" {$PHPWG_URL}
|
||||
{'Contact'|@translate}: {$CONTACT_MAIL}
|
|
@ -1,3 +1,6 @@
|
|||
{$MAIL_TITLE}
|
||||
{if not empty($MAIL_SUBTITLE)}{$MAIL_SUBTITLE}
|
||||
{/if}
|
||||
----
|
||||
{literal}
|
||||
|
||||
{/literal}{*note that there must be an empty line to separate the mime headers*}
|
||||
{/literal}
|
Loading…
Reference in a new issue