PageRenderTime 56ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 1ms

/phplist/admin/lib.php

https://github.com/radicaldesigns/amp
PHP | 813 lines | 703 code | 66 blank | 44 comment | 188 complexity | 73fc8b5da94537cfd648e2a029bfab88 MD5 | raw file
Possible License(s): LGPL-2.1, GPL-2.0, BSD-3-Clause, LGPL-2.0, CC-BY-SA-3.0, AGPL-1.0
  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. #error_reporting(63);
  6. # set some defaults if they are not specified
  7. if (!defined("REGISTER")) define("REGISTER",1);
  8. if (!defined("USE_PDF")) define("USE_PDF",0);
  9. if (!defined("VERBOSE")) define("VERBOSE",0);
  10. if (!defined("ENABLE_RSS")) define("ENABLE_RSS",0);
  11. if (!defined("ALLOW_ATTACHMENTS")) define("ALLOW_ATTACHMENTS",0);
  12. if (!defined("EMAILTEXTCREDITS")) define("EMAILTEXTCREDITS",0);
  13. if (!defined("PAGETEXTCREDITS")) define("PAGETEXTCREDITS",0);
  14. if (!defined("USEFCK")) define("USEFCK",0);
  15. if (!defined("ASKFORPASSWORD")) define("ASKFORPASSWORD",0);
  16. if (!defined("UNSUBSCRIBE_REQUIRES_PASSWORD")) define("UNSUBSCRIBE_REQUIRES_PASSWORD",0);
  17. if (!defined("UNSUBSCRIBE_JUMPOFF")) define("UNSUBSCRIBE_JUMPOFF",0);
  18. if (!defined("ENCRYPTPASSWORD")) define("ENCRYPTPASSWORD",0);
  19. if (!defined("PHPMAILER")) define("PHPMAILER",0);
  20. if (!defined("MANUALLY_PROCESS_QUEUE")) define("MANUALLY_PROCESS_QUEUE",1);
  21. if (!defined("CHECK_SESSIONIP")) define("CHECK_SESSIONIP",1);
  22. if (!defined("FILESYSTEM_ATTACHMENTS")) define("FILESYSTEM_ATTACHMENTS",0);
  23. if (!defined("MIMETYPES_FILE")) define("MIMETYPES_FILE","/etc/mime.types");
  24. if (!defined("DEFAULT_MIMETYPE")) define("DEFAULT_MIMETYPE","application/octet-stream");
  25. if (!defined("USE_REPETITION")) define("USE_REPETITION",0);
  26. if (!defined("USE_EDITMESSAGE")) define("USE_EDITMESSAGE",0);
  27. if (!defined("FCKIMAGES_DIR")) define("FCKIMAGES_DIR","uploadimages");
  28. if (!defined("USE_MANUAL_TEXT_PART")) define("USE_MANUAL_TEXT_PART",0);
  29. if (!defined("ALLOW_NON_LIST_SUBSCRIBE")) define("ALLOW_NON_LIST_SUBSCRIBE",0);
  30. if (!defined("MAILQUEUE_BATCH_SIZE")) define("MAILQUEUE_BATCH_SIZE",0);
  31. if (!defined("MAILQUEUE_BATCH_PERIOD")) define("MAILQUEUE_BATCH_PERIOD",3600);
  32. if (!defined('MAILQUEUE_THROTTLE')) define('MAILQUEUE_THROTTLE',0);
  33. if (!defined('MAILQUEUE_AUTOTHROTTLE')) define('MAILQUEUE_AUTOTHROTTLE',0);
  34. if (!defined("NAME")) define("NAME",'PHPlist');
  35. if (!defined("USE_OUTLOOK_OPTIMIZED_HTML")) define("USE_OUTLOOK_OPTIMIZED_HTML",0);
  36. if (!defined("EXPORT_EXCEL")) define("EXPORT_EXCEL",0);
  37. if (!defined("USE_PREPARE")) define("USE_PREPARE",0);
  38. if (!defined("HTMLEMAIL_ENCODING")) define("HTMLEMAIL_ENCODING","quoted-printable");
  39. if (!defined('TEXTEMAIL_ENCODING')) define('TEXTEMAIL_ENCODING','7bit');
  40. if (!defined("USE_LIST_EXCLUDE")) define("USE_LIST_EXCLUDE",0);
  41. if (!defined("WARN_SAVECHANGES")) define("WARN_SAVECHANGES",1);
  42. if (!defined("STACKED_ATTRIBUTE_SELECTION")) define("STACKED_ATTRIBUTE_SELECTION",0);
  43. if (!defined("REMOTE_URL_REFETCH_TIMEOUT")) define('REMOTE_URL_REFETCH_TIMEOUT',3600);
  44. if (!defined('CLICKTRACK')) define('CLICKTRACK',0);
  45. if (!defined('CLICKTRACK_SHOWDETAIL')) define('CLICKTRACK_SHOWDETAIL',0);
  46. if (!defined('USETINYMCEMESG')) define('USETINYMCEMESG',0);
  47. if (!defined('USETINYMCETEMPL')) define('USETINYMCETEMPL',0);
  48. if (!defined('TINYMCEPATH')) define('TINYMCEPATH','');
  49. if (!defined('STATS_INTERVAL')) define('STATS_INTERVAL','monthly');
  50. if (!defined('USE_DOMAIN_THROTTLE')) define('USE_DOMAIN_THROTTLE',0);
  51. if (!defined('DOMAIN_BATCH_SIZE')) define('DOMAIN_BATCH_SIZE',1);
  52. if (!defined('DOMAIN_BATCH_PERIOD')) define('DOMAIN_BATCH_PERIOD',120);
  53. if (!defined('DOMAIN_AUTO_THROTTLE')) define('DOMAIN_AUTO_THROTTLE',0);
  54. if (!defined('LANGUAGE_SWITCH')) define('LANGUAGE_SWITCH',1);
  55. if (!defined('USE_ADVANCED_BOUNCEHANDLING')) define('USE_ADVANCED_BOUNCEHANDLING',0);
  56. if (!defined('DATE_START_YEAR')) define('DATE_START_YEAR',1900);
  57. if (!defined('DATE_END_YEAR')) define('DATE_END_YEAR',0);
  58. if (!defined('ALLOW_IMPORT')) define('ALLOW_IMPORT',1);
  59. if (!defined('EMPTY_VALUE_PREFIX')) define('EMPTY_VALUE_PREFIX','--');
  60. if (!defined('USE_ADMIN_DETAILS_FOR_MESSAGES')) define('USE_ADMIN_DETAILS_FOR_MESSAGES',1);
  61. if (!isset($GLOBALS["export_mimetype"])) $GLOBALS["export_mimetype"] = 'application/csv';
  62. if (!isset($GLOBALS["admin_auth_module"])) $GLOBALS["admin_auth_module"] = 'phplist_auth.inc';
  63. if (!isset($GLOBALS["require_login"])) $GLOBALS["require_login"] = 0;
  64. if (!defined("WORKAROUND_OUTLOOK_BUG") && defined("USE_CARRIAGE_RETURNS")) {
  65. define("WORKAROUND_OUTLOOK_BUG",USE_CARRIAGE_RETURNS);
  66. }
  67. if (!isset($GLOBALS["blacklist_gracetime"])) $GLOBALS["blacklist_gracetime"] = 5;
  68. if (!isset($GLOBALS["message_envelope"])) $GLOBALS["message_envelope"] = '';
  69. $domain = getConfig("domain");
  70. $website = getConfig("website");
  71. if (defined("IN_WEBBLER") && is_object($GLOBALS["config"]["plugins"]["phplist"])) {
  72. $GLOBALS["tables"] = $GLOBALS["config"]["plugins"]["phplist"]->tables;
  73. $GLOBALS["table_prefix"] = $GLOBALS["config"]["plugins"]["phplist"]->table_prefix;
  74. }
  75. $usephpmailer = 0;
  76. if (PHPMAILER && is_file(dirname(__FILE__).'/phpmailer/class.phpmailer.php')) {
  77. include_once dirname(__FILE__) . '/class.phplistmailer.php';
  78. $usephpmailer = 1;
  79. }
  80. $GLOBALS['bounceruleactions'] = array(
  81. 'deleteuser' => $GLOBALS['I18N']->get('delete user'),
  82. 'unconfirmuser' => $GLOBALS['I18N']->get('unconfirm user'),
  83. 'blacklistuser' => $GLOBALS['I18N']->get('blacklist user'),
  84. 'deleteuserandbounce' => $GLOBALS['I18N']->get('delete user and bounce'),
  85. 'unconfirmuseranddeletebounce' => $GLOBALS['I18N']->get('unconfirm user and delete bounce'),
  86. 'blacklistuseranddeletebounce' => $GLOBALS['I18N']->get('blacklist user and delete bounce'),
  87. 'deletebounce' => $GLOBALS['I18N']->get('delete bounce'),
  88. );
  89. # check whether Pear HTTP/Request is available
  90. @include_once "HTTP/Request.php";
  91. $GLOBALS['has_pear_http_request'] = class_exists('HTTP_Request');
  92. ini_set('error_append_string','<font style=\"{font-variant: small-caps;font-size: 12px}\">phplist</font> version '.VERSION);
  93. ini_set('error_prepend_string','<P><font color=red style=\"{font-size: 12px}\">Sorry a software error occurred:</font><br/>
  94. Please <a href=http://mantis.tincan.co.uk>report a bug</a> when reporting the bug, please include URL and the entire content of this page.<br/>');
  95. function listName($id) {
  96. global $tables;
  97. $req = Sql_Fetch_Row_Query(sprintf('select name from %s where id = %d',$tables["list"],$id));
  98. return $req[0] ? $req[0] : $GLOBALS['I18N']->get('Unnamed List');
  99. }
  100. function setMessageData($msgid,$name,$value) {
  101. Sql_Query(sprintf('replace into %s set id = %d,name = "%s", data = "%s"',
  102. $GLOBALS['tables']['messagedata'],$msgid,addslashes($name),$value));
  103. # print "setting $name for $msgid to $value";
  104. # exit;
  105. }
  106. function loadMessageData($msgid) {
  107. $messagedata = array();
  108. $msgdata_req = Sql_Query(sprintf('select * from %s where id = %d',
  109. $GLOBALS['tables']['messagedata'],$msgid));
  110. while ($row = Sql_Fetch_Array($msgdata_req)) {
  111. $messagedata[$row['name']] = $row['data'];
  112. }
  113. return $messagedata;
  114. }
  115. function HTMLselect ($name, $table, $column, $value) {
  116. $res = "<!--$value--><select name=$name>\n";
  117. $result = Sql_Query("SELECT id,$column FROM $table");
  118. while($row = Sql_Fetch_Array($result)) {
  119. $res .= "<option value=".$row["id"] ;
  120. if ($row["$column"] == $value)
  121. $res .= " selected";
  122. if ($row["id"] == $value)
  123. $res .= " selected";
  124. $res .= ">" . $row[$column] . "\n";
  125. }
  126. $res .= "</select>\n";
  127. return $res;
  128. }
  129. function sendMail ($to,$subject,$message,$header = "",$parameters = "",$skipblacklistcheck = 0) {
  130. if (TEST)
  131. return 1;
  132. # do a quick check on mail injection attempt, @@@ needs more work
  133. if (preg_match("/\n/",$to)) {
  134. logEvent("Error: invalid recipient, containing newlines, email blocked");
  135. return 0;
  136. }
  137. if (preg_match("/\n/",$subject)) {
  138. logEvent("Error: invalid subject, containing newlines, email blocked");
  139. return 0;
  140. }
  141. if (!$to) {
  142. logEvent("Error: empty To: in message with subject $subject to send");
  143. return 0;
  144. } elseif (!$subject) {
  145. logEvent("Error: empty Subject: in message to send to $to");
  146. return 0;
  147. }
  148. if (!$skipblacklistcheck && isBlackListed($to)) {
  149. logEvent("Error, $to is blacklisted, not sending");
  150. Sql_Query(sprintf('update %s set blacklisted = 1 where email = "%s"',$GLOBALS["tables"]["user"],$to));
  151. addUserHistory($to,"Marked Blacklisted","Found user in blacklist while trying to send an email, marked black listed");
  152. return 0;
  153. }
  154. if ($GLOBALS['usephpmailer']) {
  155. return sendMailPhpMailer($to,$subject,$message);
  156. } else {
  157. return sendMailOriginal($to,$subject,$message,$header,$parameters);
  158. }
  159. return 0;
  160. }
  161. function sendMailOriginal ($to,$subject,$message,$header = "",$parameters = "") {
  162. # global function to capture sending emails, to avoid trouble with
  163. # older (and newer!) php versions
  164. $v = phpversion();
  165. $v = preg_replace("/\-.*$/","",$v);
  166. if ($GLOBALS["message_envelope"]) {
  167. $header = rtrim($header);
  168. if ($header)
  169. $header .= "\n";
  170. $header .= "Errors-To: ".$GLOBALS["message_envelope"];
  171. if (!$parameters || !ereg("-f".$GLOBALS["message_envelope"],$parameters)) {
  172. $parameters = '-f'.$GLOBALS["message_envelope"];
  173. }
  174. }
  175. // Use the system email encoding method
  176. if (TEXTEMAIL_ENCODING) {
  177. // only add if the required header is not already present
  178. if (!strpos(strtolower($header), 'content-transfer-encoding')) {
  179. $header = rtrim($header);
  180. if ($header)
  181. $header .= "\n";
  182. $header .= "Content-Transfer-Encoding: " . TEXTEMAIL_ENCODING;
  183. }
  184. }
  185. if (WORKAROUND_OUTLOOK_BUG) {
  186. $header = rtrim($header);
  187. if ($header)
  188. $header .= "\n";
  189. $header .= "X-Outlookbug-fixed: Yes";
  190. $message = preg_replace("/\r?\n/", "\r\n", $message);
  191. }
  192. # version 4.2.3 (and presumably up) does not allow the fifth parameter in safe mode
  193. # make sure not to send out loads of test emails to ppl when developing
  194. if (!ereg("dev",VERSION)) {
  195. if ($v > "4.0.5" && !ini_get("safe_mode")) {
  196. if (mail($to,$subject,$message,$header,$parameters))
  197. return 1;
  198. else
  199. return mail($to,$subject,$message,$header);
  200. }
  201. else
  202. return mail($to,$subject,$message,$header);
  203. } else {
  204. # send mails to one place when running a test version
  205. $message = "To: $to\n".$message;
  206. if ($GLOBALS["developer_email"]) {
  207. # fake occasional failure
  208. if (mt_rand(0,50) == 1) {
  209. return 0;
  210. } else {
  211. if(@mail($GLOBALS["developer_email"],$subject,$message,$header,$parameters)) {
  212. return 1;
  213. } else {
  214. return mail($GLOBALS["developer_email"],$subject,$message,$header);
  215. }
  216. }
  217. } else {
  218. print "Error: Running CVS version, but developer_email not set";
  219. }
  220. }
  221. }
  222. function sendMailPhpMailer ($to,$subject,$message) {
  223. # global function to capture sending emails, to avoid trouble with
  224. # older (and newer!) php versions
  225. $fromemail = getConfig("message_from_address");
  226. $fromname = getConfig("message_from_name");
  227. $message_replyto_address = getConfig("message_replyto_address");
  228. if ($message_replyto_address)
  229. $reply_to = $message_replyto_address;
  230. else
  231. $reply_to = $from_address;
  232. $destinationemail = '';
  233. if (!ereg("dev",VERSION)) {
  234. $mail = new PHPlistMailer('systemmessage',$to);
  235. $destinationemail = $to;
  236. $mail->add_text($message);
  237. } else {
  238. # send mails to one place when running a test version
  239. $message = "To: $to\n".$message;
  240. if ($GLOBALS["developer_email"]) {
  241. # fake occasional failure
  242. if (mt_rand(0,50) == 1) {
  243. return 0;
  244. } else {
  245. $mail = new PHPlistMailer('systemmessage',$GLOBALS["developer_email"]);
  246. $mail->add_text($message);
  247. $destinationemail = $GLOBALS["developer_email"];
  248. }
  249. } else {
  250. print "Error: Running CVS version, but developer_email not set";
  251. }
  252. }
  253. $mail->build_message(
  254. array(
  255. "html_charset" => getConfig("html_charset"),
  256. "html_encoding" => HTMLEMAIL_ENCODING,
  257. "text_charset" => getConfig("text_charset"),
  258. "text_encoding" => TEXTEMAIL_ENCODING)
  259. );
  260. return $mail->send("", $destinationemail, $fromname, $fromemail, $subject);
  261. }
  262. function sendAdminCopy($subject,$message) {
  263. $sendcopy = getConfig("send_admin_copies");
  264. if ($sendcopy == "true") {
  265. $admin_mail = getConfig("admin_address");
  266. $mails = explode(",",getConfig("admin_addresses"));
  267. array_push($mails,$admin_mail);
  268. $sent = array();
  269. foreach ($mails as $admin_mail) {
  270. $admin_mail = trim($admin_mail);
  271. if (!$sent[$admin_mail] && $admin_mail) {
  272. sendMail($admin_mail,$subject,$message,system_messageheaders($admin_mail));
  273. $sent[$admin_mail] = 1;
  274. }
  275. }
  276. }
  277. }
  278. function safeImageName($name) {
  279. $name = "image".ereg_replace("\.","DOT",$name);
  280. $name = ereg_replace("-","DASH",$name);
  281. $name = ereg_replace("_","US",$name);
  282. $name = ereg_replace("/","SLASH",$name);
  283. return $name;
  284. }
  285. function clean2 ($value) {
  286. $value = trim($value);
  287. $value = ereg_replace("\r","",$value);
  288. $value = ereg_replace("\n","",$value);
  289. $value = ereg_replace('"',"&quot;",$value);
  290. $value = ereg_replace("'","&rsquo;",$value);
  291. $value = ereg_replace("`","&lsquo;",$value);
  292. $value = stripslashes($value);
  293. return $value;
  294. }
  295. if (TEST && REGISTER)
  296. $pixel = '<img src="http://phplist.tincan.co.uk/images/pixel.gif" width=1 height=1>';
  297. function timeDiff($time1,$time2) {
  298. if (!$time1 || !$time2) {
  299. return $GLOBALS['I18N']->get('Unknown');
  300. }
  301. $t1 = strtotime($time1);
  302. $t2 = strtotime($time2);
  303. if ($t1 < $t2) {
  304. $diff = $t2 - $t1;
  305. } else {
  306. $diff = $t1 - $t2;
  307. }
  308. if ($diff == 0)
  309. return $GLOBALS['I18N']->get('very little time');
  310. $hours = (int)($diff / 3600);
  311. $mins = (int)(($diff - ($hours * 3600)) / 60);
  312. $secs = (int)($diff - $hours * 3600 - $mins * 60);
  313. if ($hours)
  314. $res = $hours . " hours";
  315. if ($mins)
  316. $res .= " ".$mins . " mins";
  317. if ($secs)
  318. $res .= " ".$secs . " secs";
  319. return $res;
  320. }
  321. function previewTemplate($id,$adminid = 0,$text = "", $footer = "") {
  322. global $tables;
  323. if (defined("IN_WEBBLER")) {
  324. $more = '&pi='.$_GET["pi"];
  325. }
  326. $tmpl = Sql_Fetch_Row_Query(sprintf('select template from %s where id = %d',$tables["template"],$id));
  327. $template = stripslashes($tmpl[0]);
  328. $img_req = Sql_Query(sprintf('select id,filename from %s where template = %d order by filename desc',$tables["templateimage"],$id));
  329. while ($img = Sql_Fetch_Array($img_req)) {
  330. $template = preg_replace("#".preg_quote($img["filename"])."#","?page=image&id=".$img["id"].$more,$template);
  331. }
  332. if ($adminid) {
  333. $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");
  334. while ($att = Sql_Fetch_Array($att_req)) {
  335. $template = preg_replace("#\[LISTOWNER.".strtoupper(preg_quote($att["name"]))."\]#",$att["value"],$template);
  336. }
  337. }
  338. if ($footer)
  339. $template = eregi_replace("\[FOOTER\]",$footer,$template);
  340. $template = preg_replace("#\[CONTENT\]#",$text,$template);
  341. $template = eregi_replace("\[UNSUBSCRIBE\]",sprintf('<a href="%s">%s</a>',getConfig("unsubscribeurl"),$GLOBALS["strThisLink"]),$template);
  342. $template = eregi_replace("\[PREFERENCES\]",sprintf('<a href="%s">%s</a>',getConfig("preferencesurl"),$GLOBALS["strThisLink"]),$template);
  343. if (!EMAILTEXTCREDITS) {
  344. $template = eregi_replace("\[SIGNATURE\]",$GLOBALS["PoweredByImage"],$template);
  345. } else {
  346. $template = eregi_replace("\[SIGNATURE\]",$GLOBALS["PoweredByText"],$template);
  347. }
  348. $template = ereg_replace("\[[A-Z\. ]+\]","",$template);
  349. $template = ereg_replace('<form','< form',$template);
  350. $template = ereg_replace('</form','< /form',$template);
  351. return $template;
  352. }
  353. function parseMessage($content,$template,$adminid = 0) {
  354. global $tables;
  355. $tmpl = Sql_Fetch_Row_Query("select template from {$tables["template"]} where id = $template");
  356. $template = $tmpl[0];
  357. $template = preg_replace("#\[CONTENT\]#",$content,$template);
  358. $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");
  359. while ($att = Sql_Fetch_Array($att_req)) {
  360. $template = preg_replace("#\[LISTOWNER.".strtoupper(preg_quote($att["name"]))."\]#",$att["value"],$template);
  361. }
  362. return $template;
  363. }
  364. function listOwner($listid = 0) {
  365. global $tables;
  366. $req = Sql_Fetch_Row_Query("select owner from {$tables["list"]} where id = $listid");
  367. return $req[0];
  368. }
  369. function system_messageHeaders($useremail = "") {
  370. $from_address = getConfig("message_from_address");
  371. $from_name = getConfig("message_from_name");
  372. if ($from_name)
  373. $additional_headers = "From: \"$from_name\" <$from_address>\n";
  374. else
  375. $additional_headers = "From: $from_address\n";
  376. $message_replyto_address = getConfig("message_replyto_address");
  377. if ($message_replyto_address)
  378. $additional_headers .= "Reply-To: $message_replyto_address\n";
  379. else
  380. $additional_headers .= "Reply-To: $from_address\n";
  381. $v = VERSION;
  382. $v = ereg_replace("-dev","",$v);
  383. $additional_headers .= "X-Mailer: PHPlist version $v (www.phplist.com)\n";
  384. $additional_headers .= "X-MessageID: systemmessage\n";
  385. if ($useremail)
  386. $additional_headers .= "X-User: ".$useremail."\n";
  387. return $additional_headers;
  388. }
  389. function logEvent($msg) {
  390. global $tables;
  391. if (isset($GLOBALS['page'])) {
  392. $p = $GLOBALS['page'];
  393. } elseif (isset($_GET['page'])) {
  394. $p = $_GET['page'];
  395. } elseif (isset($_GET['p'])) {
  396. $p = $_GET['p'];
  397. } else {
  398. $p = 'unknown page';
  399. }
  400. if (Sql_Table_Exists($tables["eventlog"]))
  401. Sql_Query(sprintf('insert into %s (entered,page,entry) values(now(),"%s","%s")',$tables["eventlog"],
  402. $p,addslashes($msg)));
  403. }
  404. ### process locking stuff
  405. function getPageLock() {
  406. global $tables;
  407. $thispage = $GLOBALS["page"];
  408. $running_req = Sql_query("select now() - modified,id from ".$tables["sendprocess"]." where page = \"$thispage\" and alive order by started desc");
  409. $running_res = Sql_Fetch_row($running_req);
  410. $waited = 0;
  411. while ($running_res[1]) { # a process is already running
  412. if ($running_res[0] > 600) {# some sql queries can take quite a while
  413. # process has been inactive for too long, kill it
  414. Sql_query("update {$tables["sendprocess"]} set alive = 0 where id = $running_res[1]");
  415. } else {
  416. output ($GLOBALS['I18N']->get('A process for this page is already running and it was still alive').' '.$running_res[0].' '.$GLOBALS['I18N']->get('seconds ago'));
  417. sleep(1); # to log the messages in the correct order
  418. if ($GLOBALS["commandline"]) {
  419. output("Running commandline, quitting. We'll find out what to do in the next run.");
  420. exit;
  421. }
  422. output ($GLOBALS['I18N']->get('Sleeping for 20 seconds, aborting will quit'));
  423. flush();
  424. $abort = ignore_user_abort(0);
  425. sleep(20);
  426. }
  427. $waited++;
  428. if ($waited > 10) {
  429. # we have waited 10 cycles, abort and quit script
  430. output($GLOBALS['I18N']->get('We have been waiting too long, I guess the other process is still going ok'));
  431. exit;
  432. }
  433. $running_req = Sql_query("select now() - modified,id from ".$tables["sendprocess"]." where page = \"$thispage\" and alive order by started desc");
  434. $running_res = Sql_Fetch_row($running_req);
  435. }
  436. $res = Sql_query('insert into '.$tables["sendprocess"].' (started,page,alive,ipaddress) values(now(),"'.$thispage.'",1,"'.getenv("REMOTE_ADDR").'")');
  437. $send_process_id = Sql_Insert_Id();
  438. $abort = ignore_user_abort(1);
  439. return $send_process_id;
  440. }
  441. function keepLock($processid) {
  442. global $tables;
  443. $thispage = $GLOBALS["page"];
  444. Sql_query("Update ".$tables["sendprocess"]." set alive = alive + 1 where id = $processid");
  445. }
  446. function checkLock($processid) {
  447. global $tables;
  448. $thispage = $GLOBALS["page"];
  449. $res = Sql_query("select alive from {$tables['sendprocess']} where id = $processid");
  450. $row = Sql_Fetch_Row($res);
  451. return $row[0];
  452. }
  453. function addAbsoluteResources($text,$url) {
  454. $parts = parse_url($url);
  455. $tags = array('src\s*=\s*','href\s*=\s*','action\s*=\s*',
  456. 'background\s*=\s*','@import\s+','@import\s+url\(');
  457. foreach ($tags as $tag) {
  458. # preg_match_all('/'.preg_quote($tag).'"([^"|\#]*)"/Uim', $text, $foundtags);
  459. preg_match_all('/('.$tag.')"([^"|\#]*)"/Uim', $text, $foundtags);
  460. for ($i=0; $i< count($foundtags[0]); $i++) {
  461. $match = $foundtags[2][$i];
  462. $tagmatch = $foundtags[1][$i];
  463. # print "$match<br/>";
  464. if (preg_match("#[http|javascript|https|ftp|mailto]:#i",$match)) {
  465. # scheme exists, leave it alone
  466. } elseif (ereg("^/",$match)) {
  467. # starts with /
  468. $text = preg_replace('#'.preg_quote($foundtags[0][$i]).'#im',$tagmatch.'"'.$parts["scheme"].'://'.$parts["host"].$match.'"',$text,1);
  469. } else {
  470. $path = $parts["path"];
  471. if (!preg_match('#/$#',$path)) {
  472. $pathparts = explode('/',$path);
  473. array_pop($pathparts);
  474. $path = join('/',$pathparts);
  475. $path .= '/';
  476. }
  477. $text = preg_replace('#'.preg_quote($foundtags[0][$i]).'#im',
  478. $tagmatch.'"'.$parts["scheme"].'://'.$parts["host"].$path.$match.'"',$text,1);
  479. }
  480. }
  481. }
  482. # $text = preg_replace('#PHPSESSID=[^\s]+
  483. return $text;
  484. }
  485. function getPageCache($url,$lastmodified = 0) {
  486. $req = Sql_Fetch_Row_Query(sprintf('select content from %s where url = "%s" and lastmodified >= %d',$GLOBALS["tables"]["urlcache"],$url,$lastmodified));
  487. return $req[0];
  488. }
  489. function getPageCacheLastModified($url) {
  490. $req = Sql_Fetch_Row_Query(sprintf('select lastmodified from %s where url = "%s"',$GLOBALS["tables"]["urlcache"],$url));
  491. return $req[0];
  492. }
  493. function setPageCache($url,$lastmodified = 0,$content) {
  494. if (isset($GLOBALS['developer_email'])) return;
  495. Sql_Query(sprintf('delete from %s where url = "%s"',$GLOBALS["tables"]["urlcache"],$url));
  496. Sql_Query(sprintf('insert into %s (url,lastmodified,added,content)
  497. values("%s",%d,now(),"%s")',$GLOBALS["tables"]["urlcache"],$url,$lastmodified,addslashes($content)));
  498. }
  499. function fetchUrl($url,$userdata = array()) {
  500. require_once "HTTP/Request.php";
  501. # logEvent("Fetching $url");
  502. if (sizeof($userdata)) {
  503. foreach ($userdata as $key => $val) {
  504. $url = eregi_replace("\[$key\]",urlencode($val),$url);
  505. }
  506. }
  507. if (!isset($GLOBALS['urlcache'])) {
  508. $GLOBALS['urlcache'] = array();
  509. }
  510. # keep in memory cache in case we send a page to many emails
  511. if (isset($GLOBALS['urlcache'][$url]) && is_array($GLOBALS['urlcache'][$url])
  512. && (time() - $GLOBALS['urlcache'][$url]['fetched'] < REMOTE_URL_REFETCH_TIMEOUT)) {
  513. # logEvent($url . " is cached in memory");
  514. return $GLOBALS['urlcache'][$url]['content'];
  515. }
  516. $dbcache_lastmodified = getPageCacheLastModified($url);
  517. $timeout = time() - $dbcache_lastmodified;
  518. if (time() - $dbcache_lastmodified < REMOTE_URL_REFETCH_TIMEOUT) {
  519. # logEvent($url.' is cached in database');
  520. return getPageCache($url);
  521. } else {
  522. # logEvent($url.' is not cached in database '.$timeout.' '. $dbcache_lastmodified." ".time());
  523. }
  524. # add a small timeout, although the biggest timeout will exist in doing the DNS lookup,
  525. # so it won't make too much of a difference
  526. $request_parameters = array(
  527. 'timeout' => 10,
  528. 'allowRedirects' => 1,
  529. 'method' => 'HEAD',
  530. );
  531. $headreq = new HTTP_Request($url,$request_parameters);
  532. $headreq->addHeader('User-Agent', 'phplist v'.VERSION.' (http://www.phplist.com)');
  533. if (!PEAR::isError($headreq->sendRequest(false))) {
  534. $code = $headreq->getResponseCode();
  535. if ($code != 200) {
  536. logEvent('Fetching '.$url.' failed, error code '.$code);
  537. return 0;
  538. }
  539. $header = $headreq->getResponseHeader();
  540. $lastmodified = strtotime($header["last-modified"]);
  541. $cache = getPageCache($url,$lastmodified);
  542. if (!$cache) {
  543. $request_parameters['method'] = 'GET';
  544. $req = new HTTP_Request($url,$request_parameters);
  545. $req->addHeader('User-Agent', 'phplist v'.VERSION.' (http://www.phplist.com)');
  546. logEvent('Fetching '.$url);
  547. if (!PEAR::isError($req->sendRequest(true))) {
  548. $content = $req->getResponseBody();
  549. $content = addAbsoluteResources($content,$url);
  550. logEvent('Fetching '.$url.' success');
  551. setPageCache($url,$lastmodified,$content);
  552. } else {
  553. logEvent('Fetching '.$url.' failed');
  554. return 0;
  555. }
  556. } else {
  557. logEvent($url.' was cached in database');
  558. $content = $cache;
  559. }
  560. } else {
  561. logEvent('Fetching '.$url.' failed');
  562. return 0;
  563. }
  564. $GLOBALS['urlcache'][$url] = array(
  565. 'fetched' => time(),
  566. 'content' => $content,
  567. );
  568. return $content;
  569. }
  570. function releaseLock($processid) {
  571. global $tables;
  572. if (!$processid) return;
  573. Sql_query("delete from {$tables["sendprocess"]} where id = $processid");
  574. }
  575. function cleanUrl($url,$disallowed_params = array('PHPSESSID')) {
  576. $parsed = parse_url($url);
  577. $params = array();
  578. # hmm parse_str should take the delimiters as a parameter
  579. if (strpos($parsed['query'],'&amp;')) {
  580. $pairs = explode('&amp;',$parsed['query']);
  581. foreach ($pairs as $pair) {
  582. list($key,$val) = explode('=',$pair);
  583. $params[$key] = $val;
  584. }
  585. } else {
  586. parse_str($parsed['query'],$params);
  587. }
  588. $uri = $parsed['scheme'] ? $parsed['scheme'].':'.((strtolower($parsed['scheme']) == 'mailto') ? '':'//'): '';
  589. $uri .= $parsed['user'] ? $parsed['user'].($parsed['pass']? ':'.$parsed['pass']:'').'@':'';
  590. $uri .= $parsed['host'] ? $parsed['host'] : '';
  591. $uri .= $parsed['port'] ? ':'.$parsed['port'] : '';
  592. $uri .= $parsed['path'] ? $parsed['path'] : '';
  593. # $uri .= $parsed['query'] ? '?'.$parsed['query'] : '';
  594. $query = '';
  595. foreach ($params as $key => $val) {
  596. if (!in_array($key,$disallowed_params)) {
  597. $query .= $key.'='.$val.'&';
  598. }
  599. }
  600. $query = substr($query,0,-1);
  601. $uri .= $query ? '?'.$query : '';
  602. # if (!empty($params['p'])) {
  603. # $uri .= '?p='.$params['p'];
  604. # }
  605. $uri .= $parsed['fragment'] ? '#'.$parsed['fragment'] : '';
  606. return $uri;
  607. }
  608. function adminName($id) {
  609. if (!$id) {
  610. $id = $_SESSION["logindetails"]["id"];
  611. }
  612. if (is_object($GLOBALS["admin_auth"])) {
  613. return $GLOBALS["admin_auth"]->adminName($id);
  614. }
  615. $req = Sql_Fetch_Row_Query(sprintf('select loginname from %s where id = %d',$GLOBALS["tables"]["admin"],$id));
  616. return $req[0] ? $req[0] : "<font color=red>Nobody</font>";
  617. }
  618. if (!function_exists("dbg")) {
  619. function dbg($msg,$logfile = "") {
  620. if (!$logfile) return;
  621. $fp = @fopen($logfile,"a");
  622. $line = "[".date("d M Y, H:i:s")."] ".getenv("REQUEST_URI").'('.$config["stats"]["number_of_queries"].") $msg \n";
  623. @fwrite($fp,$line);
  624. @fclose($fp);
  625. }
  626. }
  627. function addSubscriberStatistics($item = '',$amount,$list = 0) {
  628. switch (STATS_INTERVAL) {
  629. case 'monthly':
  630. # mark everything as the first day of the month
  631. $time = mktime(0,0,0,date('m'),1,date('Y'));
  632. break;
  633. case 'weekly':
  634. # mark everything for the first sunday of the week
  635. $time = mktime(0,0,0,date('m'),date('d') - date('w'),date('Y'));
  636. break;
  637. case 'daily':
  638. $time = mktime(0,0,0,date('m'),date('d'),date('Y'));
  639. break;
  640. }
  641. Sql_Query(sprintf('update %s set value = value + %d where unixdate = %d and item = "%s" and listid = %d',
  642. $GLOBALS['tables']['userstats'],$amount,$time,$item,$list));
  643. $done = Sql_Affected_Rows();
  644. if (!$done) {
  645. Sql_Query(sprintf('insert into %s set value = %d,unixdate = %d,item = "%s",listid = %d',
  646. $GLOBALS['tables']['userstats'],$amount,$time,$item,$list));
  647. }
  648. }
  649. function deleteBounce($id = 0) {
  650. if (!$id) return;
  651. $id = sprintf('%d',$id);
  652. Sql_query(sprintf('delete from %s where id = %d',$GLOBALS['tables']['bounce'],$id));
  653. Sql_query(sprintf('delete from %s where bounce = %d',$GLOBALS['tables']['user_message_bounce'],$id));
  654. Sql_query(sprintf('delete from %s where bounce = %d',$GLOBALS['tables']['bounceregex_bounce'],$id));
  655. }
  656. function reverse_htmlentities($mixed)
  657. {
  658. $htmltable = get_html_translation_table(HTML_ENTITIES);
  659. foreach($htmltable as $key => $value)
  660. {
  661. $mixed = ereg_replace(addslashes($value),$key,$mixed);
  662. }
  663. return $mixed;
  664. }
  665. function loadBounceRules($all = 0) {
  666. if ($all) {
  667. $status = '';
  668. } else {
  669. $status = ' where status = "active"';
  670. }
  671. $result = array();
  672. $req = Sql_Query(sprintf('select * from %s %s order by listorder',$GLOBALS['tables']['bounceregex'],$status));
  673. while ($row = Sql_Fetch_Array($req)) {
  674. if ($row['regex'] && $row['action']) {
  675. $result[$row['regex']] = array(
  676. 'action' => $row['action'],
  677. 'id' => $row['id']
  678. );
  679. }
  680. }
  681. return $result;
  682. }
  683. function matchedBounceRule($text,$activeonly = 0) {
  684. if ($activeonly) {
  685. $status = ' where status = "active"';
  686. } else {
  687. $status = '';
  688. }
  689. $req = Sql_Query(sprintf('select * from %s %s order by listorder',$GLOBALS['tables']['bounceregex'],$status));
  690. while ($row = Sql_Fetch_Array($req)) {
  691. $pattern = str_replace(' ','\s+',$row['regex']);
  692. # print "Trying to match ".$pattern;
  693. #print ' with '.$text;
  694. # print '<br/>';
  695. if (@preg_match('/'.preg_quote($pattern).'/iUm',$text)) {
  696. return $row['id'];
  697. } elseif (@preg_match('/'.$pattern.'/iUm',$text)) {
  698. return $row['id'];
  699. }
  700. }
  701. return '';
  702. }
  703. function matchBounceRules($text,$rules = array()) {
  704. if (!sizeof($rules)) {
  705. $rules = loadBounceRules();
  706. }
  707. foreach ($rules as $pattern => $rule) {
  708. $pattern = str_replace(' ','\s+',$pattern);
  709. if (@preg_match('/'.preg_quote($pattern).'/iUm',$text)) {
  710. return $rule;
  711. } elseif (@preg_match('/'.$pattern.'/iUm',$text)) {
  712. return $rule;
  713. } else {
  714. # print "Trying to match $pattern failed<br/>";
  715. }
  716. }
  717. return '';
  718. }
  719. function validateRssFrequency($freq = '') {
  720. if (!$freq) return '';
  721. if (in_array($freq,array_keys($GLOBALS['rssfrequencies']))) {
  722. return $freq;
  723. }
  724. return '';
  725. }
  726. class timer {
  727. var $start;
  728. function timer() {
  729. $now = gettimeofday();
  730. $this->start = $now["sec"] * 1000000 + $now["usec"];
  731. }
  732. function elapsed($seconds = 0) {
  733. $now = gettimeofday();
  734. $end = $now["sec"] * 1000000 + $now["usec"];
  735. $elapsed = $end - $this->start;
  736. if ($seconds) {
  737. return $elapsed / 1000000;
  738. } else {
  739. return $elapsed;
  740. }
  741. }
  742. }
  743. ?>