PageRenderTime 53ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 1ms

/public_html/lists/admin/lib.php

https://github.com/samtuke/phplist
PHP | 1593 lines | 1278 code | 151 blank | 164 comment | 271 complexity | ab0cf8e8692af8cd4452f82387977519 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. require_once dirname(__FILE__)."/accesscheck.php";
  3. # library used for plugging into the webbler, instead of "connect"
  4. # depricated and should be removed
  5. include_once dirname(__FILE__).'/class.phplistmailer.php';
  6. $domain = getConfig("domain");
  7. $website = getConfig("website");
  8. if (!$GLOBALS["message_envelope"]) {
  9. # why not try set it to "person in charge of this system". Will help get rid of a lot of bounces to nobody@server :-)
  10. $admin = getConfig('admin_address');
  11. if (!empty($admin)) {
  12. $GLOBALS["message_envelope"] = $admin;
  13. }
  14. }
  15. $GLOBALS['homepage'] = 'home';
  16. if (defined("IN_WEBBLER") && is_object($GLOBALS["config"]["plugins"]["phplist"])) {
  17. $GLOBALS["tables"] = $GLOBALS["config"]["plugins"]["phplist"]->tables;
  18. }
  19. /* this should probably move to init.php */
  20. $GLOBALS['bounceruleactions'] = array(
  21. 'deleteuser' => $GLOBALS['I18N']->get('delete subscriber'),
  22. 'unconfirmuser' => $GLOBALS['I18N']->get('unconfirm subscriber'),
  23. 'blacklistuser' => $GLOBALS['I18N']->get('blacklist subscriber'),
  24. 'blacklistemail' => $GLOBALS['I18N']->get('blacklist email address'),
  25. 'deleteuserandbounce' => $GLOBALS['I18N']->get('delete subscriber and bounce'),
  26. 'unconfirmuseranddeletebounce' => $GLOBALS['I18N']->get('unconfirm subscriber and delete bounce'),
  27. 'blacklistuseranddeletebounce' => $GLOBALS['I18N']->get('blacklist subscriber and delete bounce'),
  28. 'blacklistemailanddeletebounce' => $GLOBALS['I18N']->get('blacklist email address and delete bounce'),
  29. 'deletebounce' => $GLOBALS['I18N']->get('delete bounce'),
  30. );
  31. if( !isset($GLOBALS["developer_email"]) ) {
  32. ini_set('error_append_string','phpList version '.VERSION);
  33. ini_set('error_prepend_string','<p class="error">Sorry a software error occurred:<br/>
  34. Please <a href="http://mantis.phplist.com">report a bug</a> when reporting the bug, please include URL and the entire content of this page.<br/>');
  35. }
  36. function listName($id) {
  37. global $tables;
  38. $req = Sql_Fetch_Row_Query(sprintf('select name from %s where id = %d',$tables["list"],$id));
  39. return $req[0] ? stripslashes($req[0]) : $GLOBALS['I18N']->get('Unnamed List');
  40. }
  41. function setMessageData($msgid,$name,$value) {
  42. if ($name == 'PHPSESSID') return;
  43. if ($name == session_name()) return;
  44. if ($name == 'targetlist' && is_array($value)) {
  45. Sql_query(sprintf('delete from %s where messageid = %d',$GLOBALS['tables']["listmessage"],$msgid));
  46. if ( !empty($value["all"]) || !empty($value["allactive"])) {
  47. $res = Sql_query('select * from '. $GLOBALS['tables']['list']. ' '.$GLOBALS['subselect']);
  48. while ($row = Sql_Fetch_Array($res)) {
  49. $listid = $row["id"];
  50. if ($row["active"] || !empty($value["all"])) {
  51. $result = Sql_query("insert ignore into ".$GLOBALS['tables']["listmessage"]." (messageid,listid,entered) values($msgid,$listid,current_timestamp)");
  52. }
  53. }
  54. } else {
  55. foreach($value as $listid => $val) {
  56. $query
  57. = ' insert into ' . $GLOBALS['tables']["listmessage"]
  58. . ' (messageid,listid,entered)'
  59. . ' values'
  60. . ' (?, ?, current_timestamp)';
  61. $result = Sql_Query_Params($query, array($msgid, $listid));
  62. }
  63. }
  64. }
  65. if (is_array($value) || is_object($value)) {
  66. $value = 'SER:'.serialize($value);
  67. }
  68. Sql_Replace($GLOBALS['tables']['messagedata'], array('id' => $msgid, 'name' => $name, 'data' => $value), array('name', 'id'));
  69. # print "<br/>setting $name for $msgid to $value";
  70. # exit;
  71. }
  72. function loadMessageData($msgid) {
  73. $default = array(
  74. 'from' => getConfig('message_from_address'),
  75. ## can add some more from below
  76. 'google_track' => getConfig('always_add_googletracking'),
  77. );
  78. if (empty($default['from'])) {
  79. $default['from'] = getConfig('admin_address');
  80. }
  81. if (!isset($GLOBALS['MD']) || !is_array($GLOBALS['MD'])) {
  82. $GLOBALS['MD'] = array();
  83. }
  84. if (isset($GLOBALS['MD'][$msgid])) return $GLOBALS['MD'][$msgid];
  85. ## when loading an old message that hasn't got data stored in message data, load it from the message table
  86. $prevMsgData = Sql_Fetch_Assoc_Query(sprintf('select * from %s where id = %d',
  87. $GLOBALS['tables']['message'],$msgid));
  88. $finishSending = time() + DEFAULT_MESSAGEAGE;
  89. $messagedata = array(
  90. 'template' => getConfig("defaultmessagetemplate"),
  91. 'sendformat' => 'HTML',
  92. 'message' => '',
  93. 'forwardmessage' => '',
  94. 'textmessage' => '',
  95. 'rsstemplate' => '',
  96. 'embargo' => array('year' => date('Y'),'month' => date('m'),'day' => date('d'),'hour' => date('H'),'minute' => date('i')),
  97. 'repeatinterval' => 0,
  98. 'repeatuntil' => array('year' => date('Y'),'month' => date('m'),'day' => date('d'),'hour' => date('H'),'minute' => date('i')),
  99. 'requeueinterval' => 0,
  100. 'requeueuntil' => array('year' => date('Y'),'month' => date('m'),'day' => date('d'),'hour' => date('H'),'minute' => date('i')),
  101. 'finishsending' => array('year' => date('Y',$finishSending),'month' => date('m',$finishSending),'day' => date('d',$finishSending),'hour' => date('H',$finishSending),'minute' => date('i',$finishSending)),
  102. 'fromfield' => '',
  103. 'subject' => '',
  104. 'forwardsubject' => '',
  105. 'footer' => getConfig("messagefooter"),
  106. 'forwardfooter' => getConfig("forwardfooter"),
  107. 'status' => '',
  108. 'tofield' => '',
  109. 'replyto' => '',
  110. 'targetlist' => '',
  111. 'criteria_match' => '',
  112. 'sendurl' => '',
  113. 'sendmethod' => 'inputhere', ## make a config
  114. 'testtarget' => '',
  115. 'notify_start' => getConfig("notifystart_default"),
  116. 'notify_end' => getConfig("notifyend_default"),
  117. 'google_track' => $default['google_track'] == 'true' || $default['google_track'] === true || $default['google_track'] == '1',
  118. 'excludelist' => array(),
  119. );
  120. if (is_array($prevMsgData)) {
  121. foreach ($prevMsgData as $key => $val) {
  122. $messagedata[$key] = $val;
  123. }
  124. }
  125. $msgdata_req = Sql_Query(sprintf('select * from %s where id = %d',
  126. $GLOBALS['tables']['messagedata'],$msgid));
  127. while ($row = Sql_Fetch_Assoc($msgdata_req)) {
  128. if (strpos($row['data'],'SER:') === 0) {
  129. $data = stripSlashesArray(unserialize(substr($row['data'], 4)));
  130. } else {
  131. $data = stripslashes($row['data']);
  132. }
  133. if (!in_array($row['name'],array('astext','ashtml','astextandhtml','aspdf','astextandpdf'))) { ## don't overwrite counters in the message table from the data table
  134. $messagedata[stripslashes($row['name'])] = $data;
  135. }
  136. }
  137. foreach (array('embargo','repeatuntil','requeueuntil') as $datefield) {
  138. if (!is_array($messagedata[$datefield])) {
  139. $messagedata[$datefield] = array('year' => date('Y'),'month' => date('m'),'day' => date('d'),'hour' => date('H'),'minute' => date('i'));
  140. }
  141. }
  142. // Load lists that were targetted with message...
  143. $result = Sql_Query(sprintf('select list.name,list.id
  144. from '.$GLOBALS['tables']['listmessage'].' listmessage,'.$GLOBALS['tables']['list'].' list
  145. where listmessage.messageid = %d and listmessage.listid = list.id',$msgid));
  146. while ($lst = Sql_fetch_array($result)) {
  147. $messagedata["targetlist"][$lst["id"]] = 1;
  148. }
  149. ## backwards, check that the content has a url and use it to fill the sendurl
  150. if (empty($messagedata['sendurl'])) {
  151. ## can't do "ungreedy matching, in case the URL has placeholders, but this can potentially
  152. ## throw problems
  153. if (preg_match('/\[URL:(.*)\]/i',$messagedata['message'],$regs)) {
  154. $messagedata['sendurl'] = $regs[1];
  155. }
  156. }
  157. if (empty($messagedata['sendurl']) && !empty($messagedata['message'])) {
  158. # if there's a message and no url, make sure to show the editor, and not the URL input
  159. $messagedata['sendmethod'] = 'inputhere';
  160. }
  161. ### parse the from field into it's components - email and name
  162. if (preg_match("/([^ ]+@[^ ]+)/",$messagedata["fromfield"],$regs)) {
  163. # if there is an email in the from, rewrite it as "name <email>"
  164. $messagedata["fromname"] = str_replace($regs[0],"",$messagedata["fromfield"]);
  165. $messagedata["fromemail"] = $regs[0];
  166. # if the email has < and > take them out here
  167. $messagedata["fromemail"] = str_replace("<","",$messagedata["fromemail"]);
  168. $messagedata["fromemail"] = str_replace(">","",$messagedata["fromemail"]);
  169. # make sure there are no quotes around the name
  170. $messagedata["fromname"] = str_replace('"',"",ltrim(rtrim($messagedata["fromname"])));
  171. } elseif (strpos($messagedata["fromfield"]," ")) {
  172. # if there is a space, we need to add the email
  173. $messagedata["fromname"] = $messagedata["fromfield"];
  174. # $cached[$messageid]["fromemail"] = "listmaster@$domain";
  175. $messagedata["fromemail"] = $default['from'];
  176. } else {
  177. $messagedata["fromemail"] = $default['from'];
  178. $messagedata["fromname"] = $messagedata["fromfield"] ;
  179. }
  180. $messagedata["fromname"] = trim($messagedata["fromname"]);
  181. # erase double spacing
  182. while (strpos($messagedata["fromname"]," ")) {
  183. $messagedata["fromname"] = str_replace(" "," ",$messagedata["fromname"]);
  184. }
  185. ## if the name ends up being empty, copy the email
  186. if (empty($messagedata["fromname"])) {
  187. $messagedata["fromname"] = $messagedata["fromemail"];
  188. }
  189. if (!empty($messagedata['targetlist']['unselect'])) {
  190. unset($messagedata['targetlist']['unselect']);
  191. }
  192. if (!empty($messagedata['excludelist']['unselect'])) {
  193. unset($messagedata['excludelist']['unselect']);
  194. }
  195. $GLOBALS['MD'][$msgid] = $messagedata;
  196. # var_dump($messagedata);
  197. return $messagedata;
  198. }
  199. #Send email with a random encrypted token.
  200. function sendAdminPasswordToken ($adminId){
  201. #Retrieve the admin login name.
  202. $SQLquery = sprintf('select loginname,email from %s where id=%d;', $GLOBALS['tables']['admin'], $adminId);
  203. $row = Sql_Fetch_Row_Query($SQLquery);
  204. $adminName = $row[0];
  205. $email = $row[1];
  206. #Check if the token is not present in the database yet.
  207. while(1){
  208. #Randomize the token to be encrypted and insert it into the db.
  209. $date = date("U"); $random = rand(1, $date);
  210. $key = md5($date ^ $random);
  211. $SQLquery = sprintf("select * from %s where key_value = '%s'", $GLOBALS['tables']['admin_password_request'], $key);
  212. $row = Sql_Fetch_Row_Query($SQLquery);
  213. //echo "<script text='javascript'>alert('".($row[0]=='')."');</script>";
  214. if($row[0]=='') break;
  215. }
  216. $query = sprintf("insert into %s(date, admin, key_value) values (now(), %d, '%s');", $GLOBALS['tables']['admin_password_request'], $adminId, $key);
  217. Sql_Query($query);
  218. $urlroot = getConfig('website').$GLOBALS['adminpages'];
  219. #Build the email body to be sent, and finally send it.
  220. $emailBody = $GLOBALS['I18N']->get('Hello').' '.$adminName."\n\n";
  221. $emailBody.= $GLOBALS['I18N']->get('You have requested a new password for phpList.')."\n\n";
  222. $emailBody.= $GLOBALS['I18N']->get('To enter a new one, please visit the following link:')."\n\n";
  223. $emailBody.= sprintf('http://%s/?page=login&token=%s',$urlroot, $key)."\n\n";
  224. $emailBody.= $GLOBALS['I18N']->get('You have 24 hours left to change your password. After that, your token won\'t be valid.');
  225. if (sendMail ($email, $GLOBALS['I18N']->get('New password'), "\n\n".$emailBody,"","",true)) {
  226. return $GLOBALS['I18N']->get('A password change token has been sent to the corresponding email address.');
  227. } else {
  228. return $GLOBALS['I18N']->get('Error sending password change token');
  229. }
  230. }
  231. function getTopSmtpServer($domain) {
  232. $mx = getmxrr($domain, $mxhosts,$weight);
  233. $thgiew = array_flip($weight);
  234. ksort($thgiew);
  235. return $mxhosts[array_shift($thgiew)];
  236. }
  237. function sendMail ($to,$subject,$message,$header = "",$parameters = "",$skipblacklistcheck = 0) {
  238. if (TEST)
  239. return 1;
  240. # do a quick check on mail injection attempt, @@@ needs more work
  241. if (preg_match("/\n/",$to)) {
  242. logEvent("Error: invalid recipient, containing newlines, email blocked");
  243. return 0;
  244. }
  245. if (preg_match("/\n/",$subject)) {
  246. logEvent("Error: invalid subject, containing newlines, email blocked");
  247. return 0;
  248. }
  249. if (!$to) {
  250. logEvent("Error: empty To: in message with subject $subject to send");
  251. return 0;
  252. } elseif (!$subject) {
  253. logEvent("Error: empty Subject: in message to send to $to");
  254. return 0;
  255. }
  256. if (!$skipblacklistcheck && isBlackListed($to)) {
  257. logEvent("Error, $to is blacklisted, not sending");
  258. Sql_Query(sprintf('update %s set blacklisted = 1 where email = "%s"',$GLOBALS["tables"]["user"],$to));
  259. addUserHistory($to,"Marked Blacklisted","Found user in blacklist while trying to send an email, marked black listed");
  260. return 0;
  261. }
  262. return sendMailPhpMailer($to,$subject,$message);
  263. }
  264. function constructSystemMail($message,$subject = '') {
  265. $hasHTML = strip_tags($message) != $message;
  266. $htmlcontent = '';
  267. if ($hasHTML) {
  268. $message = stripslashes($message);
  269. $textmessage = HTML2Text($message);
  270. $htmlmessage = $message;
  271. } else {
  272. $textmessage = $message;
  273. $htmlmessage = $message;
  274. # $htmlmessage = str_replace("\n\n","\n",$htmlmessage);
  275. $htmlmessage = nl2br($htmlmessage);
  276. ## make links clickable:
  277. preg_match_all('~https?://[^\s<]+~i',$htmlmessage,$matches);
  278. for ($i=0; $i<sizeof($matches[0]);$i++) {
  279. $match = $matches[0][$i];
  280. $htmlmessage = str_replace($match,'<a href="'.$match.'">'.$match.'</a>',$htmlmessage);
  281. }
  282. }
  283. ## add li-s around the lists
  284. if (preg_match('/<ul>\s+(\*.*)<\/ul>/imsxU',$htmlmessage,$listsmatch)) {
  285. $lists = $listsmatch[1];
  286. $listsHTML = '';
  287. preg_match_all('/\*([^\*]+)/',$lists,$matches);
  288. for ($i=0;$i<sizeof($matches[0]);$i++) {
  289. $listsHTML .= '<li>'.$matches[1][$i].'</li>';
  290. }
  291. $htmlmessage = str_replace($listsmatch[0],'<ul>'.$listsHTML.'</ul>',$htmlmessage);
  292. }
  293. $htmltemplate = '';
  294. $templateid = getConfig('systemmessagetemplate');
  295. if (!empty($templateid)) {
  296. $req = Sql_Fetch_Row_Query(sprintf('select template from %s where id = %d',
  297. $GLOBALS["tables"]["template"],$templateid));
  298. $htmltemplate = stripslashes($req[0]);
  299. }
  300. if (strpos($htmltemplate,'[CONTENT]')) {
  301. $htmlcontent = str_replace('[CONTENT]',$htmlmessage,$htmltemplate);
  302. $htmlcontent = str_replace('[SUBJECT]',$subject,$htmlcontent);
  303. $htmlcontent = str_replace('[FOOTER]','',$htmlcontent);
  304. if (!EMAILTEXTCREDITS) {
  305. $phpListPowered = preg_replace('/src=".*power-phplist.png"/','src="powerphplist.png"',$GLOBALS['PoweredByImage']);
  306. } else {
  307. $phpListPowered = $GLOBALS['PoweredByText'];
  308. }
  309. if (strpos($htmlcontent,'[SIGNATURE]')) {
  310. $htmlcontent = str_replace('[SIGNATURE]',$phpListPowered,$htmlcontent);
  311. } elseif (strpos($htmlcontent,'</body>')) {
  312. $htmlcontent = str_replace('</body>',$phpListPowered.'</body>',$htmlcontent);
  313. } else {
  314. $htmlcontent .= $phpListPowered;
  315. }
  316. }
  317. return array($htmlcontent,$textmessage);
  318. }
  319. function sendMailPhpMailer ($to,$subject,$message) {
  320. # global function to capture sending emails, to avoid trouble with
  321. # older (and newer!) php versions
  322. $fromemail = getConfig("message_from_address");
  323. $fromname = getConfig("message_from_name");
  324. $message_replyto_address = getConfig("message_replyto_address");
  325. if ($message_replyto_address)
  326. $reply_to = $message_replyto_address;
  327. else
  328. $reply_to = $from_address;
  329. $destinationemail = '';
  330. # print "Sending $to from $fromemail<br/>";
  331. if (DEVVERSION) {
  332. $message = "To: $to\n".$message;
  333. if ($GLOBALS["developer_email"]) {
  334. $destinationemail = $GLOBALS["developer_email"];
  335. } else {
  336. print "Error: Running DEV version, but developer_email not set";
  337. }
  338. } else {
  339. $destinationemail = $to;
  340. }
  341. list($htmlmessage,$textmessage) = constructSystemMail($message,$subject);
  342. $mail = new PHPlistMailer('systemmessage',$destinationemail,false);
  343. if (!empty($htmlmessage)) {
  344. $mail->add_html($htmlmessage,$textmessage,getConfig('systemmessagetemplate'));
  345. ## In the above phpMailer strips all tags, which removes the links which are wrapped in < and > by HTML2text
  346. ## so add it again
  347. $mail->add_text($textmessage);
  348. }
  349. $mail->add_text($textmessage);
  350. # 0008549: message envelope not passed to php mailer,
  351. $mail->Sender = $GLOBALS["message_envelope"];
  352. ## always add the List-Unsubscribe header
  353. $removeurl = getConfig("unsubscribeurl");
  354. $sep = strpos($removeurl,'?') === false ? '?':'&';
  355. $mail->addCustomHeader("List-Unsubscribe: <".$removeurl.$sep.'email='.$to."&jo=1>");
  356. return $mail->compatSend("", $destinationemail, $fromname, $fromemail, $subject);
  357. }
  358. function sendMailDirect($destinationemail, $subject, $message) {
  359. $GLOBALS['smtpError'] = '';
  360. ## try to deliver directly, so that any error (eg user not found) can be sent back to the
  361. ## subscriber, so they can fix it
  362. unset($GLOBALS["developer_email"]);
  363. list($htmlmessage,$textmessage) = constructSystemMail($message,$subject);
  364. $mail = new PHPlistMailer('systemmessage',$destinationemail,false,true);
  365. list($dummy,$domain) = explode('@',$destinationemail);
  366. #print_r ($mxhosts);exit;
  367. $smtpServer = getTopSmtpServer($domain);
  368. $fromemail = getConfig("message_from_address");
  369. $fromname = getConfig("message_from_name");
  370. $mail->Host = $smtpServer;
  371. $mail->Helo = getConfig("website");
  372. $mail->Port = 25;
  373. $mail->Mailer = "smtp";
  374. if (!empty($htmlmessage)) {
  375. $mail->add_html($htmlmessage,$textmessage,getConfig('systemmessagetemplate'));
  376. $mail->add_text($textmessage);
  377. }
  378. $mail->add_text($textmessage);
  379. try {
  380. $mail->Send('',$destinationemail, $fromname, $fromemail, $subject);
  381. } catch (Exception $e) {
  382. $GLOBALS['smtpError'] = $e->getMessage();
  383. return false;
  384. }
  385. return true;
  386. }
  387. function sendAdminCopy($subject,$message,$lists = array()) {
  388. $sendcopy = getConfig("send_admin_copies");
  389. if ($sendcopy) {
  390. $lists = cleanArray($lists);
  391. $mails = array();
  392. if (sizeof($lists) && SEND_LISTADMIN_COPY) {
  393. $mailsreq = Sql_Query(sprintf('select email from %s admin, %s list where admin.id = list.owner and list.id in (%s)',
  394. $GLOBALS['tables']['admin'],$GLOBALS['tables']['list'],join(',',$lists)));
  395. while ($row = Sql_Fetch_Array($mailsreq)) {
  396. array_push($mails,$row['email']);
  397. }
  398. }
  399. ## hmm, do we want to be exclusive? Either listadmin or main ones
  400. ## could do all instead
  401. if (!sizeof($mails)) {
  402. $admin_mail = getConfig("admin_address");
  403. if ($c = getConfig("admin_addresses")) {
  404. $mails = explode(",", $c);
  405. }
  406. array_push($mails,$admin_mail);
  407. }
  408. $sent = array();
  409. foreach ($mails as $admin_mail) {
  410. $admin_mail = trim($admin_mail);
  411. if ( !isset($sent[$admin_mail]) && !empty($admin_mail) ) {
  412. sendMail($admin_mail,$subject,$message,system_messageheaders($admin_mail));
  413. logEvent(s('Sending admin copy to').' '.$admin_mail);
  414. $sent[$admin_mail] = 1;
  415. }
  416. }
  417. }
  418. }
  419. function safeImageName($name) {
  420. $name = "image".str_replace(".","DOT",$name);
  421. $name = str_replace("(","BRO",$name);
  422. $name = str_replace(")","BRC",$name);
  423. $name = str_replace(" ","SPC",$name);
  424. $name = str_replace("-","DASH",$name);
  425. $name = str_replace("_","US",$name);
  426. $name = str_replace("/","SLASH",$name);
  427. $name = str_replace(':','COLON',$name);
  428. return $name;
  429. }
  430. function clean2 ($value) {
  431. $value = trim($value);
  432. $value = preg_replace("/\r/","",$value);
  433. $value = preg_replace("/\n/","",$value);
  434. $value = str_replace('"',"&quot;",$value);
  435. $value = str_replace("'","&rsquo;",$value);
  436. $value = str_replace("`","&lsquo;",$value);
  437. $value = stripslashes($value);
  438. return $value;
  439. }
  440. function cleanEmail ($value) {
  441. $value = trim($value);
  442. $value = preg_replace("/\r/","",$value);
  443. $value = preg_replace("/\n/","",$value);
  444. $value = preg_replace('/"/',"&quot;",$value);
  445. $value = preg_replace('/^mailto:/i','',$value);
  446. $value = str_replace('(','',$value);
  447. $value = str_replace(')','',$value);
  448. $value = preg_replace('/\.$/','',$value);
  449. ## these are allowed in emails
  450. // $value = preg_replace("/'/","&rsquo;",$value);
  451. $value = preg_replace("/`/","&lsquo;",$value);
  452. $value = stripslashes($value);
  453. return $value;
  454. }
  455. if (TEST && REGISTER)
  456. $pixel = '<img src="http://powered.phplist.com/images/pixel.gif" width="1" height="1" />';
  457. function timeDiff($time1,$time2) {
  458. if (!$time1 || !$time2) {
  459. return $GLOBALS['I18N']->get('Unknown');
  460. }
  461. $t1 = strtotime($time1);
  462. $t2 = strtotime($time2);
  463. if ($t1 < $t2) {
  464. $diff = $t2 - $t1;
  465. } else {
  466. $diff = $t1 - $t2;
  467. }
  468. if ($diff == 0)
  469. return $GLOBALS['I18N']->get('very little time');
  470. return secs2time($diff);
  471. }
  472. function previewTemplate($id,$adminid = 0,$text = "", $footer = "") {
  473. global $tables;
  474. if (defined("IN_WEBBLER")) {
  475. $more = '&amp;pi='.$_GET["pi"];
  476. } else {
  477. $more = '';
  478. }
  479. $poweredImageId = 0;
  480. # make sure the 0 template has the powered by image
  481. $query
  482. = ' select id'
  483. . ' from %s'
  484. . ' where filename = ?'
  485. . ' and template = 0';
  486. $query = sprintf($query, $GLOBALS['tables']['templateimage']);
  487. $rs = Sql_Query_Params($query, array('powerphplist.png'));
  488. if (!Sql_Num_Rows($rs)) {
  489. $query
  490. = ' insert into %s'
  491. . ' (template, mimetype, filename, data, width, height)'
  492. . ' values (0, ?, ?, ?, ?, ?)';
  493. $query = sprintf($query, $GLOBALS["tables"]["templateimage"]);
  494. Sql_Query_Params($query, array('image/png', 'powerphplist.png', $GLOBALS['newpoweredimage'], 70, 30));
  495. $poweredImageId = Sql_Insert_Id();
  496. } else {
  497. $row = Sql_Fetch_Row($rs);
  498. $poweredImageId = $row[0];
  499. }
  500. $tmpl = Sql_Fetch_Row_Query(sprintf('select template from %s where id = %d',$tables["template"],$id));
  501. $template = stripslashes($tmpl[0]);
  502. $img_req = Sql_Query(sprintf('select id,filename from %s where template = %d order by filename desc',$tables["templateimage"],$id));
  503. while ($img = Sql_Fetch_Array($img_req)) {
  504. $template = preg_replace("#".preg_quote($img["filename"])."#","?page=image&amp;id=".$img["id"].$more,$template);
  505. }
  506. if ($adminid) {
  507. $att_req = Sql_Query("select name,value from {$tables["adminattribute"]},{$tables["admin_attribute"]} where {$tables["adminattribute"]}.id = {$tables["admin_attribute"]}.adminattributeid and {$tables["admin_attribute"]}.adminid = $adminid");
  508. while ($att = Sql_Fetch_Array($att_req)) {
  509. $template = preg_replace("#\[LISTOWNER.".strtoupper(preg_quote($att["name"]))."\]#",$att["value"],$template);
  510. }
  511. }
  512. if (empty($footer)) {
  513. $footer = getConfig('messagefooter');
  514. }
  515. if ($footer) {
  516. $template = str_ireplace("[FOOTER]",$footer,$template);
  517. }
  518. $template = preg_replace("#\[CONTENT\]#",$text,$template);
  519. $fromemail = getConfig('campaignfrom_default');
  520. if (empty($fromemail)) {
  521. $fromemail = 'user@server.com';
  522. }
  523. $template = str_ireplace("[FROMEMAIL]",$fromemail,$template);
  524. $template = str_ireplace("[EMAIL]",'recipient@destination.com',$template);
  525. $template = str_ireplace("[SUBJECT]",s('This is the Newsletter Subject'),$template);
  526. $template = str_ireplace("[UNSUBSCRIBE]",sprintf('<a href="%s">%s</a>',getConfig("unsubscribeurl"),$GLOBALS["strThisLink"]),$template);
  527. #0013076: Blacklisting posibility for unknown users
  528. $template = str_ireplace("[BLACKLIST]",sprintf('<a href="%s">%s</a>',getConfig("blacklisturl"),$GLOBALS["strThisLink"]),$template);
  529. $template = str_ireplace("[PREFERENCES]",sprintf('<a href="%s">%s</a>',getConfig("preferencesurl"),$GLOBALS["strThisLink"]),$template);
  530. if (!EMAILTEXTCREDITS) {
  531. $template = str_ireplace("[SIGNATURE]",'<img src="?page=image&amp;id='.$poweredImageId.'" width="70" height="30" />',$template);
  532. } else {
  533. $template = str_ireplace("[SIGNATURE]",$GLOBALS["PoweredByText"],$template);
  534. }
  535. $template = preg_replace("/\[[A-Z\. ]+\]/","",$template);
  536. $template = str_ireplace('<form','< form',$template);
  537. $template = str_ireplace('</form','< /form',$template);
  538. return $template;
  539. }
  540. function parseMessage($content,$template,$adminid = 0) {
  541. global $tables;
  542. $tmpl = Sql_Fetch_Row_Query("select template from {$tables["template"]} where id = $template");
  543. $template = $tmpl[0];
  544. $template = preg_replace("#\[CONTENT\]#",$content,$template);
  545. $att_req = Sql_Query("select name,value from {$tables["adminattribute"]},{$tables["admin_attribute"]} where {$tables["adminattribute"]}.id = {$tables["admin_attribute"]}.adminattributeid and {$tables["admin_attribute"]}.adminid = $adminid");
  546. while ($att = Sql_Fetch_Array($att_req)) {
  547. $template = preg_replace("#\[LISTOWNER.".strtoupper(preg_quote($att["name"]))."\]#",$att["value"],$template);
  548. }
  549. return $template;
  550. }
  551. function listOwner($listid = 0) {
  552. global $tables;
  553. $req = Sql_Fetch_Row_Query("select owner from {$tables["list"]} where id = $listid");
  554. return $req[0];
  555. }
  556. function listUsedInSubscribePage($listid = 0) {
  557. if (empty($listid)) return false;
  558. $used = false;
  559. $req = Sql_Query(sprintf('select data from %s where name = "lists"',$GLOBALS['tables']['subscribepage_data']));
  560. while ($row = Sql_Fetch_Assoc($req)) {
  561. $lists = explode(',',$row['data']);
  562. $used = $used || in_array($listid,$lists);
  563. if ($used) return true;
  564. }
  565. return $used;
  566. }
  567. function system_messageHeaders($useremail = "") {
  568. $from_address = getConfig("message_from_address");
  569. $from_name = getConfig("message_from_name");
  570. if ($from_name)
  571. $additional_headers = "From: \"$from_name\" <$from_address>\n";
  572. else
  573. $additional_headers = "From: $from_address\n";
  574. $message_replyto_address = getConfig("message_replyto_address");
  575. if ($message_replyto_address)
  576. $additional_headers .= "Reply-To: $message_replyto_address\n";
  577. else
  578. $additional_headers .= "Reply-To: $from_address\n";
  579. $v = VERSION;
  580. $additional_headers .= "X-Mailer: phplist version $v (www.phplist.com)\n";
  581. $additional_headers .= "X-MessageID: systemmessage\n";
  582. if ($useremail)
  583. $additional_headers .= "X-User: ".$useremail."\n";
  584. return $additional_headers;
  585. }
  586. function logEvent($msg) {
  587. $logged = false;
  588. foreach ($GLOBALS['plugins'] as $pluginname => $plugin) {
  589. $logged = $logged || $plugin->logEvent($msg);
  590. }
  591. if ($logged) return;
  592. global $tables;
  593. if (isset($GLOBALS['page'])) {
  594. $p = $GLOBALS['page'];
  595. } elseif (isset($_GET['page'])) {
  596. $p = $_GET['page'];
  597. } elseif (isset($_GET['p'])) {
  598. $p = $_GET['p'];
  599. } else {
  600. $p = 'unknown page';
  601. }
  602. if (!Sql_Table_Exists($tables["eventlog"])) {
  603. return;
  604. }
  605. $query
  606. = ' insert into %s'
  607. . ' (entered,page,entry)'
  608. . ' values'
  609. . ' (current_timestamp, ?, ?)';
  610. $query = sprintf($query, $tables["eventlog"]);
  611. Sql_Query_Params($query, array($p, $msg));
  612. }
  613. ### process locking stuff
  614. function getPageLock($force = 0) {
  615. global $tables;
  616. $thispage = $GLOBALS["page"];
  617. if ($thispage == 'pageaction') {
  618. $thispage = $_GET['action'];
  619. }
  620. # cl_output('getting pagelock '.$thispage);
  621. # ob_end_flush();
  622. if ($GLOBALS["commandline"] && $thispage == 'processqueue') {
  623. if (is_object($GLOBALS['MC'])) {
  624. ## multi-send requires a valid memcached setup
  625. $max = MAX_SENDPROCESSES;
  626. } else {
  627. $max = 1;
  628. }
  629. } else {
  630. $max = 1;
  631. }
  632. ## allow killing other processes
  633. if ($force) {
  634. Sql_Query_Params("delete from ".$tables['sendprocess']." where page = ?",array($thispage));
  635. }
  636. $query
  637. = ' select current_timestamp - modified as age, id'
  638. . ' from ' . $tables['sendprocess']
  639. . ' where page = ?'
  640. . ' and alive > 0'
  641. . ' order by age desc';
  642. $running_req = Sql_Query_Params($query, array($thispage));
  643. $running_res = Sql_Fetch_Assoc($running_req);
  644. $count = Sql_Num_Rows($running_req);
  645. if (VERBOSE) {
  646. cl_output($count. ' out of '.$max.' active processes');
  647. }
  648. $waited = 0;
  649. # while ($running_res['age'] && $count >= $max) { # a process is already running
  650. while ($count >= $max) { # don't check age, as it may be 0
  651. # cl_output('running process: '.$running_res['age'].' '.$max);
  652. if ($running_res['age'] > 600) {# some sql queries can take quite a while
  653. #cl_output($running_res['id'].' is old '.$running_res['age']);
  654. # process has been inactive for too long, kill it
  655. Sql_query("update {$tables["sendprocess"]} set alive = 0 where id = ".$running_res['id']);
  656. } elseif ((int)$count >= (int)$max) {
  657. # cl_output (sprintf($GLOBALS['I18N']->get('A process for this page is already running and it was still alive %s seconds ago'),$running_res['age']));
  658. output (sprintf($GLOBALS['I18N']->get('A process for this page is already running and it was still alive %s seconds ago'),$running_res['age']),0);
  659. sleep(1); # to log the messages in the correct order
  660. if ($GLOBALS["commandline"]) {
  661. cl_output($GLOBALS['I18N']->get('Running commandline, quitting. We\'ll find out what to do in the next run.'));
  662. exit;
  663. }
  664. output ($GLOBALS['I18N']->get('Sleeping for 20 seconds, aborting will quit'),0);
  665. flush();
  666. $abort = ignore_user_abort(0);
  667. sleep(20);
  668. }
  669. $waited++;
  670. if ($waited > 10) {
  671. # we have waited 10 cycles, abort and quit script
  672. output($GLOBALS['I18N']->get('We have been waiting too long, I guess the other process is still going ok'),0);
  673. return false;
  674. }
  675. $query
  676. = ' select current_timestamp - modified as age, id'
  677. . ' from ' . $tables['sendprocess']
  678. . ' where page = ?'
  679. . ' and alive > 0'
  680. . ' order by age desc';
  681. $running_req = Sql_Query_Params($query, array($thispage));
  682. $running_res = Sql_Fetch_Assoc($running_req);
  683. $count = Sql_Num_Rows($running_req);
  684. }
  685. $query
  686. = ' insert into ' . $tables['sendprocess']
  687. . ' (started, page, alive, ipaddress)'
  688. . ' values'
  689. . ' (current_timestamp, ?, 1, ?)';
  690. if (!empty($GLOBALS['commandline'])) {
  691. $processIdentifier = SENDPROCESS_SERVERNAME.':'.getmypid();
  692. } else {
  693. $processIdentifier = $_SERVER['REMOTE_ADDR'];
  694. }
  695. $res = Sql_Query_Params($query, array($thispage, $processIdentifier));
  696. $send_process_id = Sql_Insert_Id($tables['sendprocess'], 'id');
  697. $abort = ignore_user_abort(1);
  698. # cl_output('Got pagelock '.$send_process_id );
  699. return $send_process_id;
  700. }
  701. function keepLock($processid) {
  702. global $tables;
  703. $thispage = $GLOBALS["page"];
  704. Sql_query("Update ".$tables["sendprocess"]." set alive = alive + 1 where id = $processid");
  705. }
  706. function checkLock($processid) {
  707. global $tables;
  708. $thispage = $GLOBALS["page"];
  709. $res = Sql_query("select alive from {$tables['sendprocess']} where id = $processid");
  710. $row = Sql_Fetch_Row($res);
  711. return $row[0];
  712. }
  713. // function addAbsoluteResources() moved to commonlib/maillib.php
  714. function getPageCache($url,$lastmodified = 0) {
  715. $req = Sql_Fetch_Row_Query(sprintf('select content from %s where url = "%s" and lastmodified >= %d',$GLOBALS["tables"]["urlcache"],$url,$lastmodified));
  716. return $req[0];
  717. }
  718. function getPageCacheLastModified($url) {
  719. $req = Sql_Fetch_Row_Query(sprintf('select lastmodified from %s where url = "%s"',$GLOBALS["tables"]["urlcache"],$url));
  720. return $req[0];
  721. }
  722. function setPageCache($url,$lastmodified = 0,$content) {
  723. # if (isset($GLOBALS['developer_email'])) return;
  724. Sql_Query(sprintf('delete from %s where url = "%s"',$GLOBALS["tables"]["urlcache"],$url));
  725. Sql_Query(sprintf('insert into %s (url,lastmodified,added,content)
  726. values("%s",%d,current_timestamp,"%s")',$GLOBALS["tables"]["urlcache"],$url,$lastmodified,addslashes($content)));
  727. }
  728. function clearPageCache () {
  729. Sql_Query('delete from ' . $GLOBALS['tables']['urlcache']);
  730. unset($GLOBALS['urlcache']);
  731. }
  732. function removeJavascript($content) {
  733. $content = preg_replace('/<script[^>]*>(.*?)<\/script\s*>/mis','',$content);
  734. return $content;
  735. }
  736. function stripComments($content) {
  737. $content = preg_replace('/<!--(.*?)-->/mis','',$content);
  738. return $content;
  739. }
  740. function compressContent($content) {
  741. ## this needs loads more testing across systems to be sure
  742. return $content;
  743. $content = preg_replace("/\n/",' ',$content);
  744. $content = preg_replace("/\r/",'',$content);
  745. $content = removeJavascript($content);
  746. $content = stripComments($content);
  747. ## find some clean way to remove double spacing
  748. $content = preg_replace("/\t/"," ",$content);
  749. while (preg_match("/ /",$content)) {
  750. $content = preg_replace("/ /"," ",$content);
  751. }
  752. return $content;
  753. }
  754. function encryptPass($pass) {
  755. if (empty($pass)) return '';
  756. if (function_exists('hash')) {
  757. if(!in_array(ENCRYPTION_ALGO, hash_algos(), true)) {
  758. ## fallback, not that secure, but better than none at all
  759. $algo = 'md5';
  760. } else {
  761. $algo = ENCRYPTION_ALGO;
  762. }
  763. return hash($algo,$pass);
  764. } else {
  765. return md5($pass);
  766. }
  767. }
  768. /* do not use @@@
  769. # try to pull remote styles into the email, but that's a nightmare, because
  770. # it needs to be made absolute again
  771. # kind of works, but not really nicely.
  772. function includeStyles($text) {
  773. $styles = fetchStyles($text);
  774. $text = stripStyles($text);
  775. $text = preg_replace('#</head>#','<style type="text/css">'.$styles.'</style></head>',$text);
  776. return $text;
  777. }
  778. function stripStyles($text) {
  779. $tags = array('src\s*=\s*','href\s*=\s*','action\s*=\s*',
  780. 'background\s*=\s*','@import\s+','@import\s+url\(');
  781. foreach ($tags as $tag) {
  782. preg_match_all('/<link.*('.$tag.')"([^"|\#]*)".*>/Uim', $text, $foundtags);
  783. for ($i=0; $i< count($foundtags[0]); $i++) {
  784. $pat = $foundtags[0][$i];
  785. $match = $foundtags[2][$i];
  786. $tagmatch = $foundtags[1][$i];
  787. if (preg_match("#[http|https]:#i",$match) && preg_match("#\.css$#i",$match)) {
  788. $text = str_replace($foundtags[0][$i],'',$text);
  789. }
  790. }
  791. }
  792. return $text;
  793. }
  794. function fetchStyles($text) {
  795. $styles = '';
  796. $url = '';
  797. $tags = array('src\s*=\s*','href\s*=\s*','action\s*=\s*',
  798. 'background\s*=\s*','@import\s+','@import\s+url\(');
  799. foreach ($tags as $tag) {
  800. preg_match_all('/<link.*('.$tag.')"([^"|\#]*)"/Uim', $text, $foundtags);
  801. for ($i=0; $i< count($foundtags[0]); $i++) {
  802. $match = $foundtags[2][$i];
  803. $url = $match;
  804. $tagmatch = $foundtags[1][$i];
  805. if (preg_match("#[http|https]:#i",$match) && preg_match("#\.css$#i",$match)) {
  806. $styles .= fetchUrl($match);
  807. }
  808. }
  809. }
  810. return addAbsoluteResources($styles,$url);
  811. }
  812. */
  813. /* verify that a redirection is to ourselves */
  814. function isValidRedirect($url) {
  815. ## we might want to add some more checks here
  816. return strpos($url,$_SERVER['HTTP_HOST']);
  817. }
  818. /* check the url_append config and expand the url with it
  819. */
  820. function expandURL($url) {
  821. $url_append = getConfig('remoteurl_append');
  822. $url_append = strip_tags($url_append);
  823. $url_append = preg_replace('/\W/','',$url_append);
  824. if ($url_append) {
  825. if (strpos($url,'?')) {
  826. $url = $url.$url_append;
  827. } else {
  828. $url = $url.'?'.$url_append;
  829. }
  830. }
  831. return $url;
  832. }
  833. function testUrl($url) {
  834. if (VERBOSE) logEvent('Checking '.$url);
  835. $code = 500;
  836. if ($GLOBALS['has_curl']) {
  837. if (VERBOSE) logEvent('Checking curl ');
  838. $curl = curl_init();
  839. curl_setopt($curl, CURLOPT_URL, $url);
  840. curl_setopt($curl, CURLOPT_TIMEOUT, 10);
  841. curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
  842. curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
  843. curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
  844. curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
  845. curl_setopt($curl, CURLOPT_HEADER, 0);
  846. curl_setopt($curl, CURLOPT_DNS_USE_GLOBAL_CACHE, true);
  847. curl_setopt($curl, CURLOPT_USERAGENT,'phplist v'.VERSION.' (http://www.phplist.com)');
  848. $raw_result = curl_exec($curl);
  849. $code = curl_getinfo($curl,CURLINFO_HTTP_CODE);
  850. } elseif ($GLOBALS['has_pear_http_request']) {
  851. if (VERBOSE) logEvent('Checking PEAR ');
  852. @require_once "HTTP/Request.php";
  853. $headreq = new HTTP_Request($url,$request_parameters);
  854. $headreq->addHeader('User-Agent', 'phplist v'.VERSION.' (http://www.phplist.com)');
  855. if (!PEAR::isError($headreq->sendRequest(false))) {
  856. $code = $headreq->getResponseCode();
  857. }
  858. }
  859. if (VERBOSE) logEvent('Checking '.$url.' => '.$code);
  860. return $code;
  861. }
  862. function fetchUrl($url,$userdata = array()) {
  863. $content = '';
  864. ## fix the Editor replacing & with &amp;
  865. $url = str_ireplace('&amp;','&',$url);
  866. # logEvent("Fetching $url");
  867. if (sizeof($userdata)) {
  868. foreach ($userdata as $key => $val) {
  869. if ($key != 'password') {
  870. $url = utf8_encode(str_ireplace("[$key]",urlencode($val),utf8_decode($url)));
  871. }
  872. }
  873. }
  874. if (!isset($GLOBALS['urlcache'])) {
  875. $GLOBALS['urlcache'] = array();
  876. }
  877. $url = expandUrl($url);
  878. # print "<h1>Fetching ".$url."</h1>";
  879. # keep in memory cache in case we send a page to many emails
  880. if (isset($GLOBALS['urlcache'][$url]) && is_array($GLOBALS['urlcache'][$url])
  881. && (time() - $GLOBALS['urlcache'][$url]['fetched'] < REMOTE_URL_REFETCH_TIMEOUT)) {
  882. # logEvent($url . " is cached in memory");
  883. if (VERBOSE && function_exists('output')) {
  884. output('From memory cache: '.$url);
  885. }
  886. return $GLOBALS['urlcache'][$url]['content'];
  887. }
  888. $dbcache_lastmodified = getPageCacheLastModified($url);
  889. $timeout = time() - $dbcache_lastmodified;
  890. if ($timeout < REMOTE_URL_REFETCH_TIMEOUT) {
  891. # logEvent($url.' was cached in database');
  892. if (VERBOSE && function_exists('output')) {
  893. output('From database cache: '.$url);
  894. }
  895. return getPageCache($url);
  896. } else {
  897. # logEvent($url.' is not cached in database '.$timeout.' '. $dbcache_lastmodified." ".time());
  898. }
  899. $request_parameters = array(
  900. 'timeout' => 600,
  901. 'allowRedirects' => 1,
  902. 'method' => 'HEAD',
  903. );
  904. $remote_charset = 'UTF-8';
  905. ## relying on the last modified header doesn't work for many pages
  906. ## use current time instead
  907. ## see http://mantis.phplist.com/view.php?id=7684
  908. # $lastmodified = strtotime($header["last-modified"]);
  909. $lastmodified = time();
  910. $cache = getPageCache($url,$lastmodified);
  911. if (!$cache) {
  912. ## @#TODO, make it work with Request2
  913. if (function_exists('curl_init')) {
  914. $content = fetchUrlCurl($url,$request_parameters);
  915. } elseif (0 && $GLOBALS['has_pear_http_request'] == 2) {
  916. @require_once "HTTP/Request2.php";
  917. } elseif ($GLOBALS['has_pear_http_request']) {
  918. @require_once "HTTP/Request.php";
  919. $content = fetchUrlPear($url,$request_parameters);
  920. } else {
  921. return false;
  922. }
  923. } else {
  924. if (VERBOSE) logEvent($url.' was cached in database');
  925. $content = $cache;
  926. }
  927. if (!empty($content)) {
  928. $content = addAbsoluteResources($content,$url);
  929. logEvent('Fetching '.$url.' success');
  930. setPageCache($url,$lastmodified,$content);
  931. $GLOBALS['urlcache'][$url] = array(
  932. 'fetched' => time(),
  933. 'content' => $content,
  934. );
  935. }
  936. return $content;
  937. }
  938. function fetchUrlCurl($url,$request_parameters) {
  939. if (VERBOSE) logEvent($url.' fetching with curl ');
  940. $curl = curl_init();
  941. curl_setopt($curl, CURLOPT_URL, $url);
  942. curl_setopt($curl, CURLOPT_TIMEOUT, $request_parameters['timeout']);
  943. curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
  944. curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
  945. curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
  946. curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
  947. curl_setopt($curl, CURLOPT_HEADER, 0);
  948. curl_setopt($curl, CURLOPT_DNS_USE_GLOBAL_CACHE, true);
  949. curl_setopt($curl, CURLOPT_USERAGENT,'phplist v'.VERSION.'c (http://www.phplist.com)');
  950. $raw_result = curl_exec($curl);
  951. $status = curl_getinfo($curl,CURLINFO_HTTP_CODE);
  952. curl_close($curl);
  953. if (VERBOSE) logEvent('fetched '.$url.' status '.$status);
  954. # var_dump($status); exit;
  955. return $raw_result;
  956. }
  957. function fetchUrlPear($url,$request_parameters) {
  958. if (VERBOSE) logEvent($url.' fetching with PEAR');
  959. if (0 && $GLOBALS['has_pear_http_request'] == 2) {
  960. $headreq = new HTTP_Request2($url,$request_parameters);
  961. $headreq->setHeader('User-Agent', 'phplist v'.VERSION.'p (http://www.phplist.com)');
  962. } else {
  963. $headreq = new HTTP_Request($url,$request_parameters);
  964. $headreq->addHeader('User-Agent', 'phplist v'.VERSION.'p (http://www.phplist.com)');
  965. }
  966. if (!PEAR::isError($headreq->sendRequest(false))) {
  967. $code = $headreq->getResponseCode();
  968. if ($code != 200) {
  969. logEvent('Fetching '.$url.' failed, error code '.$code);
  970. return 0;
  971. }
  972. $header = $headreq->getResponseHeader();
  973. if (preg_match('/charset=(.*)/i',$header['content-type'],$regs)) {
  974. $remote_charset = strtoupper($regs[1]);
  975. }
  976. $request_parameters['method'] = 'GET';
  977. if (0 && $GLOBALS['has_pear_http_request'] == 2) {
  978. $req = new HTTP_Request2($url,$request_parameters);
  979. $req->setHeader('User-Agent', 'phplist v'.VERSION.'p (http://www.phplist.com)');
  980. } else {
  981. $req = new HTTP_Request($url,$request_parameters);
  982. $req->addHeader('User-Agent', 'phplist v'.VERSION.'p (http://www.phplist.com)');
  983. }
  984. logEvent('Fetching '.$url);
  985. if (VERBOSE && function_exists('output')) {
  986. output('Fetching remote: '.$url);
  987. }
  988. if (!PEAR::isError($req->sendRequest(true))) {
  989. $content = $req->getResponseBody();
  990. if ($remote_charset != 'UTF-8' && function_exists('iconv')) {
  991. $content = iconv($remote_charset,'UTF-8//TRANSLIT',$content);
  992. }
  993. } else {
  994. logEvent('Fetching '.$url.' failed on GET '.$req->getResponseCode());
  995. return 0;
  996. }
  997. } else {
  998. logEvent('Fetching '.$url.' failed on HEAD');
  999. return 0;
  1000. }
  1001. return $content;
  1002. }
  1003. function releaseLock($processid) {
  1004. global $tables;
  1005. if (!$processid) return;
  1006. Sql_query("delete from {$tables["sendprocess"]} where id = $processid");
  1007. }
  1008. function parseQueryString($str) {
  1009. if (empty($str)) return array();
  1010. $op = array();
  1011. $pairs = explode("&", $str);
  1012. foreach ($pairs as $pair) {
  1013. if (strpos($pair,'=') !== false) {
  1014. list($k, $v) = array_map("urldecode", explode("=", $pair));
  1015. $op[$k] = $v;
  1016. } else {
  1017. $op[$pair] = '';
  1018. }
  1019. }
  1020. return $op;
  1021. }
  1022. function cleanUrl($url,$disallowed_params = array('PHPSESSID')) {
  1023. $parsed = @parse_url($url);
  1024. $params = array();
  1025. if (empty($parsed['query'])) {
  1026. $parsed['query'] = '';
  1027. }
  1028. # hmm parse_str should take the delimiters as a parameter
  1029. if (strpos($parsed['query'],'&amp;')) {
  1030. $pairs = explode('&amp;',$parsed['query']);
  1031. foreach ($pairs as $pair) {
  1032. if (strpos($pair,'=') !== false) {
  1033. list($key,$val) = explode('=',$pair);
  1034. $params[$key] = $val;
  1035. } else {
  1036. $params[$pair] = '';
  1037. }
  1038. }
  1039. } else {
  1040. ## parse_str turns . into _ which is wrong
  1041. # parse_str($parsed['query'],$params);
  1042. $params= parseQueryString($parsed['query']);
  1043. }
  1044. $uri = !empty($parsed['scheme']) ? $parsed['scheme'].':'.((strtolower($parsed['scheme']) == 'mailto') ? '':'//'): '';
  1045. $uri .= !empty($parsed['user']) ? $parsed['user'].(!empty($parsed['pass'])? ':'.$parsed['pass']:'').'@':'';
  1046. $uri .= !empty($parsed['host']) ? $parsed['host'] : '';
  1047. $uri .= !empty($parsed['port']) ? ':'.$parsed['port'] : '';
  1048. $uri .= !empty($parsed['path']) ? $parsed['path'] : '';
  1049. # $uri .= $parsed['query'] ? '?'.$parsed['query'] : '';
  1050. $query = '';
  1051. foreach ($params as $key => $val) {
  1052. if (!in_array($key,$disallowed_params)) {
  1053. //0008980: Link Conversion for Click Tracking. no = will be added if key is empty.
  1054. $query .= $key . ( $val != "" ? '=' . $val . '&' : '&' );
  1055. }
  1056. }
  1057. $query = substr($query,0,-1);
  1058. $uri .= $query ? '?'.$query : '';
  1059. # if (!empty($params['p'])) {
  1060. # $uri .= '?p='.$params['p'];
  1061. # }
  1062. $uri .= !empty($parsed['fragment']) ? '#'.$parsed['fragment'] : '';
  1063. return $uri;
  1064. }
  1065. function adminName($id = 0) {
  1066. if (!$id) {
  1067. $id = $_SESSION["logindetails"]["id"];
  1068. }
  1069. if (is_object($GLOBALS["admin_auth"])) {
  1070. return $GLOBALS["admin_auth"]->adminName($id);
  1071. }
  1072. $query
  1073. = ' select loginname'
  1074. . ' from ' . $GLOBALS['tables']['admin']
  1075. . ' where id = ?';
  1076. $rs = Sql_Query_Params($query, array($id));
  1077. $req = Sql_Fetch_Row($rs);
  1078. return $req[0] ? $req[0] : "Nobody";
  1079. }
  1080. if (!function_exists("dbg")) {
  1081. function xdbg($msg,$logfile = "") {
  1082. if (!$logfile) return;
  1083. $fp = @fopen($logfile,"a");
  1084. $line = "[".date("d M Y, H:i:s")."] ".getenv("REQUEST_URI").'('.$config["stats"]["number_of_queries"].") $msg \n";
  1085. @fwrite($fp,$line);
  1086. @fclose($fp);
  1087. }
  1088. }
  1089. function addSubscriberStatistics($item = '',$amount,$list = 0) {
  1090. switch (STATS_INTERVAL) {
  1091. case 'monthly':
  1092. # mark everything as the first day of the month
  1093. $time = mktime(0,0,0,date('m'),1,date('Y'));
  1094. break;
  1095. case 'weekly':
  1096. # mark everything for the first sunday of the week
  1097. $time = mktime(0,0,0,date('m'),date('d') - date('w'),date('Y'));
  1098. break;
  1099. case 'daily':
  1100. $time = mktime(0,0,0,date('m'),date('d'),date('Y'));
  1101. break;
  1102. }
  1103. $query
  1104. = ' update ' . $GLOBALS['tables']['userstats']
  1105. . ' set value = value + ?'
  1106. . ' where unixdate = ?'
  1107. . ' and item = ?'
  1108. . ' and listid = ?';
  1109. Sql_Query_Params($query, array($amount, $time, $item, $list));
  1110. $done = Sql_Affected_Rows();
  1111. if (!$done) {
  1112. $query
  1113. = ' insert into ' . $GLOBALS['tables']['userstats']
  1114. . ' (value, unixdate, item, listid)'
  1115. . ' values'
  1116. . ' (?, ?, ?, ?)';
  1117. Sql_Query_Params($query, array($amount, $time, $item, $list));
  1118. }
  1119. }
  1120. function deleteMessage($id = 0) {
  1121. if( !$GLOBALS["require_login"] || $_SESSION["logindetails"]['superuser'] ){
  1122. $ownerselect_and = '';
  1123. $ownerselect_where = '';
  1124. } else {
  1125. $ownerselect_where = ' WHERE owner = ' . $_SESSION["logindetails"]['id'];
  1126. $ownerselect_and = ' and owner = ' . $_SESSION["logindetails"]['id'];
  1127. }
  1128. # delete the message in delete
  1129. $result = Sql_query("select id from ".$GLOBALS['tables']["message"]." where id = $id $ownerselect_and");
  1130. while ($row = Sql_Fetch_Row($result)) {
  1131. $result = Sql_query("delete from ".$GLOBALS['tables']["message"]." where id = $row[0]");
  1132. $suc6 = Sql_Affected_Rows();
  1133. $result = Sql_query("delete from ".$GLOBALS['tables']["usermessage"]." where messageid = $row[0]");
  1134. $result = Sql_query("delete from ".$GLOBALS['tables']["listmessage"]." where messageid = $row[0]");
  1135. return $suc6;
  1136. }
  1137. }
  1138. function deleteBounce($id = 0) {
  1139. if (!$id) return;
  1140. $id = sprintf('%d',$id);
  1141. Sql_query(sprintf('delete from %s where id = %d',$GLOBALS['tables']['bounce'],$id));
  1142. Sql_query(sprintf('delete from %s where bounce = %d',$GLOBALS['tables']['user_message_bounce'],$id));
  1143. Sql_query(sprintf('delete from %s where bounce = %d',$GLOBALS['tables']['bounceregex_bounce'],$id));
  1144. }
  1145. function reverse_htmlentities($mixed)
  1146. {
  1147. $htmltable = get_html_translation_table(HTML_ENTITIES);
  1148. foreach($htmltable as $key => $value)
  1149. {
  1150. $mixed = str_replace(addslashes($value),$key,$mixed);
  1151. }
  1152. return $mixed;
  1153. }
  1154. function loadBounceRules($all = 0) {
  1155. if ($all) {
  1156. $status = '';
  1157. } else {
  1158. $status = ' where status = "active"';
  1159. }
  1160. $result = array();
  1161. $req = Sql_Query(sprintf('select * from %s %s order by listorder',$GLOBALS['tables']['bounceregex'],$status));
  1162. while ($row = Sql_Fetch_Array($req)) {
  1163. if ($row['regex'] && $row['action']) {
  1164. $result[$row['regex']] = array(
  1165. 'action' => $row['action'],
  1166. 'id' => $row['id']
  1167. );
  1168. }
  1169. }
  1170. return $result;
  1171. }
  1172. function matchedBounceRule($text,$activeonly = 0) {
  1173. if ($activeonly) {
  1174. $status = ' where status = "active"';
  1175. } else {
  1176. $status = '';
  1177. }
  1178. $req = Sql_Query(sprintf('select * from %s %s order by listorder',$GLOBALS['tables']['bounceregex'],$status));
  1179. while ($row = Sql_Fetch_Array($req)) {
  1180. $pattern = str_replace(' ','\s+',$row['regex']);
  1181. # print "Trying to match ".$pattern;
  1182. #print ' with '.$text;
  1183. # print '<br/>';
  1184. if (@preg_match('/'.preg_quote($pattern).'/iUm',$text)) {
  1185. return $row['id'];
  1186. } elseif (@preg_match('/'.$pattern.'/iUm',$text)) {
  1187. return $row['id'];
  1188. }
  1189. }
  1190. return '';
  1191. }
  1192. function matchBounceRules($text,$rules = array()) {
  1193. if (!sizeof($rules)) {
  1194. $rules = loadBounceRules();
  1195. }
  1196. foreach ($rules as $pattern => $rule) {
  1197. $pattern = str_replace(' ','\s+',$pattern);
  1198. if (@preg_match('/'.preg_quote($pattern).'/iUm',$text)) {
  1199. return $rule;
  1200. } elseif (@preg_match('/'.$pattern.'/iUm',$text)) {
  1201. return $rule;
  1202. } else {
  1203. # print "Trying to match $pattern failed<br/>";
  1204. }
  1205. }
  1206. return '';
  1207. }
  1208. function flushBrowser() {
  1209. ## push some more output to the browser, so it displays things sooner
  1210. for ($i=0;$i<10000; $i++) {
  1211. print ' '."\n";
  1212. }
  1213. flush();
  1214. }
  1215. function flushClickTrackCache() {
  1216. if (!isset($GLOBALS['cached']['linktracksent'])) return;
  1217. foreach ($GLOBALS['cached']['linktracksent'] as $mid => $numsent) {
  1218. foreach ($numsent as $fwdid => $fwdtotal) {
  1219. if (VERBOSE)
  1220. output("Flushing clicktrack stats for $mid: $fwdid => $fwdtotal");
  1221. Sql_Query(sprintf('update %s set total = %d where messageid = %d and forwardid = %d',
  1222. $GLOBALS['tables']['linktrack_ml'],$fwdtotal,$mid,$fwdid));
  1223. }
  1224. }
  1225. }
  1226. function resetMessageStatistics($messageid = 0) {
  1227. ## remove the record of the links in the message, actual clicks of links, and the users sent to
  1228. Sql_Query(sprintf('delete from %s where messageid = %d',$GLOBALS['tables']['linktrack_ml'],$messageid));
  1229. Sql_Query(sprintf('delete from %s where messageid = %d',$GLOBALS['tables']['linktrack_uml_click'],$messageid));
  1230. Sql_Query(sprintf('delete from %s where messageid = %d',$GLOBALS['tables']['usermessage'],$messageid));
  1231. }
  1232. if (!function_exists('formatbytes')) {
  1233. function formatBytes ($value) {
  1234. $gb = 1024 * 1024 * 1024;
  1235. $mb = 1024 * 1024;
  1236. $kb = 1024;
  1237. $gbs = $value / $gb;
  1238. if ($gbs > 1)
  1239. return sprintf('%2.2fGb',$gbs);
  1240. $mbs = $value / $mb;
  1241. if ($mbs > 1)
  1242. return sprintf('%2.2fMb',$mbs);
  1243. $kbs = $value / $kb;
  1244. if ($kbs > 1)
  1245. return sprintf('%dKb',$kbs);
  1246. else
  1247. return sprintf('%dBytes',$value);
  1248. }
  1249. }
  1250. function strip_newlines( $str, $placeholder = '' ) {
  1251. $str = str_replace(chr(13) . chr(10), $placeholder , $str);
  1252. $str = str_replace(chr(10), $placeholder , $str

Large files files are truncated, but you can click here to view the full file