<?php
/***************************************************************************
- * Copyright (C) 2003-2006 Polytechnique.org *
+ * Copyright (C) 2003-2010 Polytechnique.org *
* http://opensource.polytechnique.org/ *
* *
* This program is free software; you can redistribute it and/or modify *
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
***************************************************************************/
-// {{{ requires + defines
+require_once("massmailer.inc.php");
-require_once("xorg.misc.inc.php");
-
-define('FEMME', 1);
-define('HOMME', 0);
-
-// }}}
-// {{{ class MassMailer
-
-abstract class MassMailer
-{
- private $_tpl;
- private $_css;
- private $_prefix;
-
- public $_id;
- public $_shortname;
- public $_title;
- public $_title_mail;
-
- public $_head;
-
- function __construct($tpl, $css, $prefix)
- {
- $this->_tpl = $tpl;
- $this->_css = $css;
- $this->_prefix = $prefix;
- }
-
- public function id()
- {
- return is_null($this->_shortname) ? $this->_id : $this->_shortname;
- }
-
- public function title($mail = false)
- {
- return $mail ? $this->_title_mail : $this->_title;
- }
-
- public function head($prenom = null, $nom = null, $sexe = null, $type = 'text')
- {
- if (is_null($prenom)) {
- return $this->_head;
- } else {
- $head = $this->_head;
- $head = str_replace('<cher>', $sexe ? 'Chère' : 'Cher', $head);
- $head = str_replace('<prenom>', $prenom, $head);
- $head = str_replace('<nom>', $nom, $head);
- if ($type == 'text') {
- $head = enriched_to_text($head, false, true, 2, 64);
- } else {
- $head = enriched_to_text($head, true);
- }
- return $head;
- }
- }
-
- public function css(&$page = null)
- {
- if (!is_null($page)) {
- $page->addCssLink($this->_css);
- return true;
- } else {
- $css = file_get_contents(dirname(__FILE__) . '/../htdocs/css/' . $this->_css);
- return preg_replace('@/\*.*?\*/@s', '', $css);
- }
- }
-
- public function toText(&$page, $prenom, $nom, $sexe)
- {
- $this->css($page);
- $page->assign('is_mail', false);
- $page->assign('html_version', false);
- $page->assign('prenom', $prenom);
- $page->assign('nom', $nom);
- $page->assign('sexe', $sexe);
- $this->assignData($page);
- }
-
- public function toHtml(&$page, $prenom, $nom, $sexe)
- {
- $this->css($page);
- $page->assign('prefix', $this->_prefix . '/' . $this->id());
- $page->assign('is_mail', false);
- $page->assign('html_version', true);
- $page->assign('prenom', $prenom);
- $page->assign('nom', $nom);
- $page->assign('sexe', $sexe);
- $this->assignData($page);
- }
-
- public function sendTo($prenom, $nom, $login, $sexe, $html)
- {
- global $globals;
-
- $mailer = new PlMailer($this->_tpl);
- $this->assignData($mailer);
- $mailer->assign('is_mail', true);
- $mailer->assign('prenom', $prenom);
- $mailer->assign('nom', $nom);
- $mailer->assign('sexe', $sexe);
- $mailer->assign('prefix', null);
- $mailer->addTo("\"$prenom $nom\" <$login@{$globals->mail->domain}>");
- $mailer->send($html);
- }
-
- public function sendToAll()
- {
- $this->setSent();
- $query = "SELECT u.user_id, a.alias,
- u.prenom, IF(u.nom_usage='', u.nom, u.nom_usage),
- FIND_IN_SET('femme', u.flags),
- q.core_mail_fmt AS pref
- FROM {$this->subscriptionTable()} AS ni
- INNER JOIN auth_user_md5 AS u USING(user_id)
- INNER JOIN auth_user_quick AS q ON(q.user_id = u.user_id)
- INNER JOIN aliases AS a ON(u.user_id=a.id AND FIND_IN_SET('bestalias',a.flags))
- LEFT JOIN emails AS e ON(e.uid=u.user_id AND e.flags='active')
- WHERE ({$this->subscriptionWhere()}) AND e.email IS NOT NULL
- GROUP BY u.user_id
- LIMIT 60";
- while (true) {
- $res = XDB::iterRow($query);
- if (!$res->total()) {
- exit;
- }
- $sent = array();
- while (list($uid, $bestalias, $prenom, $nom, $sexe, $fmt) = $res->next()) {
- $sent[] = "user_id='$uid'";
- $this->sendTo($prenom, $nom, $bestalias, $sexe, $fmt=='html');
- }
- XDB::execute("UPDATE {$this->subscriptionTable()}
- SET {$this->subscriptionUpdate()}
- WHERE " . implode(' OR ', $sent));
- sleep(60);
- }
- }
-
- abstract protected function assignData(&$smarty);
- abstract protected function setSent();
- abstract static public function subscribe($uid = -1);
- abstract static public function unsubscribe($uid = -1);
- abstract static public function subscriptionState($uid = -1);
-
- abstract protected function subscriptionTable();
- abstract protected function subscriptionWhere();
- abstract protected function subscriptionUpdate();
-}
-
-// }}}
// {{{ class NewsLetter
class NewsLetter extends MassMailer
{
public $_date;
- public $_cats = Array();
- public $_arts = Array();
+ public $_cats = array();
+ public $_arts = array();
function __construct($id = null)
{
- parent::__construct('newsletter/nl.tpl', 'nl.css', 'nl/show');
+ parent::__construct('newsletter/nl.mail.tpl', 'nl.css', 'nl/show', 'newsletter', 'newsletter_ins');
if (isset($id)) {
if ($id == 'last') {
$res = XDB::query("SELECT MAX(id) FROM newsletter WHERE bits!='new'");
} else {
$res = XDB::query("SELECT * FROM newsletter WHERE bits='new'");
if (!$res->numRows()) {
- Newsletter::create();
+ NewsLetter::create();
}
- $res = XDB::query("SELECT * FROM newsletter WHERE bits='new'");
+ $res = XDB::query("SELECT * FROM newsletter WHERE bits='new' ORDER BY id DESC LIMIT 1");
+ }
+ if ($res->numRows() != 1) {
+ throw new MailNotFound();
}
$nl = $res->fetchOneAssoc();
- $this->_id = $nl['id'];
- $this->_shortname = $nl['short_name'];
- $this->_date = $nl['date'];
- $this->_title = $nl['titre'];
+ $this->_id = $nl['id'];
+ $this->_shortname = $nl['short_name'];
+ $this->_date = $nl['date'];
+ $this->_title = $nl['titre'];
$this->_title_mail = $nl['titre_mail'];
- $this->_head = $nl['head'];
+ $this->_head = $nl['head'];
$res = XDB::iterRow("SELECT cid,titre FROM newsletter_cat ORDER BY pos");
while (list($cid, $title) = $res->next()) {
$this->_cats[$cid] = $title;
}
-
+
$res = XDB::iterRow(
"SELECT a.title,a.body,a.append,a.aid,a.cid,a.pos
FROM newsletter_art AS a
XDB::execute('UPDATE newsletter SET date={?},titre={?},titre_mail={?},head={?},short_name={?} WHERE id={?}',
$this->_date, $this->_title, $this->_title_mail, $this->_head, $this->_shortname,$this->_id);
}
-
+
public function getArt($aid)
{
foreach ($this->_arts as $key=>$artlist) {
public function saveArticle(&$a)
{
- if ($a->_aid>=0) {
- XDB::execute('REPLACE INTO newsletter_art (id,aid,cid,pos,title,body,append)
- VALUES ({?},{?},{?},{?},{?},{?},{?})',
+ $a->_cid = ($a->_cid == 0) ? null : $a->_cid;
+ if ($a->_aid >= 0) {
+ XDB::execute('REPLACE INTO newsletter_art (id, aid, cid, pos, title, body, append)
+ VALUES ({?}, {?}, {?}, {?}, {?}, {?}, {?})',
$this->_id, $a->_aid, $a->_cid, $a->_pos,
$a->_title, $a->_body, $a->_append);
- $this->_arts['a'.$a->_aid] = $a;
+ $this->_arts['a' . $a->_aid] = $a;
} else {
XDB::execute('INSERT INTO newsletter_art
- SELECT {?},MAX(aid)+1,{?},'.($a->_pos ? intval($a->_pos) : 'MAX(pos)+1').',{?},{?},{?}
+ SELECT {?}, MAX(aid)+1, {?}, '
+ . ($a->_pos ? intval($a->_pos) : 'MAX(pos)+1')
+ . ', {?}, {?}, {?}
FROM newsletter_art AS a
- WHERE a.id={?}',
+ WHERE a.id = {?}',
$this->_id, $a->_cid, $a->_title, $a->_body, $a->_append, $this->_id);
- $this->_arts['a'.$a->_aid] = $a;
+ $this->_arts['a' . $a->_aid] = $a;
}
}
-
+
public function delArticle($aid)
{
XDB::execute('DELETE FROM newsletter_art WHERE id={?} AND aid={?}', $this->_id, $aid);
protected function setSent()
{
- XDB::execute("UPDATE newsletter SET bits='sent' WHERE id={?}", $this->_id);
- }
-
- protected function subscriptionTable()
- {
- return 'newsletter_ins';
- }
-
- protected function subscriptionWhere()
- {
- return 'ni.last<' . $this->_id;
+ XDB::execute("UPDATE newsletter SET bits='sent' WHERE id={?}", $this->_id);
}
- protected function subscriptionUpdate()
+ static public function subscriptionState($uid = null)
{
- return 'last=' . $this->_id;
+ $user = is_null($uid) ? S::v('uid') : $uid;
+ $res = XDB::query("SELECT 1
+ FROM newsletter_ins
+ WHERE uid={?}", $user);
+ return $res->fetchOneCell();
}
- static public function subscriptionState($uid = -1)
+ static public function unsubscribe($uid = null)
{
- $user = ($uid == -1) ? S::v('uid') : $uid;
- $res = XDB::query('SELECT 1 FROM newsletter_ins WHERE user_id={?}', $user);
- return $res->fetchOneCell();
+ $user = is_null($uid) ? S::v('uid') : $uid;
+ XDB::execute("DELETE FROM newsletter_ins
+ WHERE uid={?}", $user);
}
- static public function unsubscribe($uid = -1)
+ static public function subscribe($uid = null)
{
- $user = ($uid == -1) ? S::v('uid') : $uid;
- XDB::execute('DELETE FROM newsletter_ins WHERE user_id={?}', $user);
+ $user = is_null($uid) ? S::v('uid') : $uid;
+ XDB::execute("REPLACE INTO newsletter_ins (uid,last)
+ VALUES ({?}, NULL)", $user);
}
- static public function subscribe($uid = -1)
+ protected function subscriptionWhere()
{
- $user = ($uid == -1) ? S::v('uid') : $uid;
- XDB::execute('REPLACE INTO newsletter_ins (user_id,last) VALUES ({?}, 0)', $user);
+ return '1';
}
static public function create()
class NLArticle
{
// {{{ properties
-
+
var $_aid;
var $_cid;
var $_pos;
// }}}
// {{{ constructor
-
+
function __construct($title='', $body='', $append='', $aid=-1, $cid=0, $pos=0)
{
$this->_body = $body;
// }}}
// {{{ function body()
-
+
public function body()
{ return trim($this->_body); }
-
+
// }}}
// {{{ function append()
-
+
public function append()
{ return trim($this->_append); }
// }}}
// {{{ function toText()
- public function toText()
+ public function toText($hash = null, $login = null)
{
$title = '*'.$this->title().'*';
- $body = enriched_to_text($this->_body,false,true);
- $app = enriched_to_text($this->_append,false,false,4);
- return trim("$title\n\n$body\n\n$app")."\n";
+ $body = MiniWiki::WikiToText($this->_body, true);
+ $app = MiniWiki::WikiToText($this->_append,false,4);
+ $text = trim("$title\n\n$body\n\n$app")."\n";
+ if (!is_null($hash) && !is_null($login)) {
+ $text = str_replace('%HASH%', "$hash/$login", $text);
+ } else {
+ $text = str_replace('%HASH%', '', $text);
+ }
+ return $text;
}
// }}}
// {{{ function toHtml()
- public function toHtml()
+ public function toHtml($hash = null, $login = null)
{
- $title = "<h2 class='xorg_nl'><a id='art{$this->_aid}'></a>".htmlentities($this->title()).'</h2>';
- $body = enriched_to_text($this->_body,true);
- $app = enriched_to_text($this->_append,true);
-
+ $title = "<h2 class='xorg_nl'><a id='art{$this->_aid}'></a>".pl_entities($this->title()).'</h2>';
+ $body = MiniWiki::WikiToHTML($this->_body);
+ $app = MiniWiki::WikiToHTML($this->_append);
+
$art = "$title\n";
$art .= "<div class='art'>\n$body\n";
if ($app) {
$art .= "<div class='app'>$app</div>";
}
$art .= "</div>\n";
-
+ if (!is_null($hash) && !is_null($login)) {
+ $art = str_replace('%HASH%', "$hash/$login", $art);
+ } else {
+ $art = str_replace('%HASH%', '', $art);
+ }
+
return $art;
}
public function check()
{
- $text = enriched_to_text($this->_body);
+ $text = MiniWiki::WikiToText($this->_body);
$arr = explode("\n",wordwrap($text,68));
$c = 0;
foreach ($arr as $line) {
}
// }}}
-}
+ // {{{ function parseUrlsFromArticle()
-// }}}
-// {{{ Functions
+ private function parseUrlsFromArticle()
+ {
+ $email_regex = '([a-z0-9.\-+_\$]+@([\-.+_]?[a-z0-9])+)';
+ $url_regex = '((https?|ftp)://[a-zA-Z0-9._%#+/?=&~-]+)';
+ $regex = '{' . $email_regex . '|' . $url_regex . '}i';
+
+ $matches = array();
+ $body_matches = array();
+ if (preg_match_all($regex, $this->body(), $body_matches)) {
+ $matches = array_merge($matches, $body_matches[0]);
+ }
-function justify($text,$n)
-{
- $arr = explode("\n",wordwrap($text,$n));
- $arr = array_map('trim',$arr);
- $res = '';
- foreach ($arr as $key => $line) {
- $nxl = isset($arr[$key+1]) ? trim($arr[$key+1]) : '';
- $nxl_split = preg_split('! +!',$nxl);
- $nxw_len = count($nxl_split) ? strlen($nxl_split[0]) : 0;
- $line = trim($line);
-
- if (strlen($line)+1+$nxw_len < $n) {
- $res .= "$line\n";
- continue;
- }
-
- if (preg_match('![.:;]$!',$line)) {
- $res .= "$line\n";
- continue;
- }
+ $append_matches = array();
+ if (preg_match_all($regex, $this->append(), $append_matches)) {
+ $matches = array_merge($matches, $append_matches[0]);
+ }
- $tmp = preg_split('! +!',trim($line));
- $words = count($tmp);
- if ($words <= 1) {
- $res .= "$line\n";
- continue;
+ return $matches;
}
- $len = array_sum(array_map('strlen',$tmp));
- $empty = $n - $len;
- $sw = floatval($empty) / floatval($words-1);
-
- $cur = 0;
- $l = '';
- foreach ($tmp as $word) {
- $l .= $word;
- $cur += $sw + strlen($word);
- $l = str_pad($l,intval($cur+0.5));
- }
- $res .= trim($l)."\n";
- }
- return trim($res);
-}
+ // }}}
+ // {{{ function getLinkIps()
-function enriched_to_text($input,$html=false,$just=false,$indent=0,$width=68)
-{
- $text = trim($input);
- if ($html) {
- $text = htmlspecialchars($text);
- $text = str_replace('[b]','<strong>', $text);
- $text = str_replace('[/b]','</strong>', $text);
- $text = str_replace('[i]','<em>', $text);
- $text = str_replace('[/i]','</em>', $text);
- $text = str_replace('[u]','<span style="text-decoration: underline">', $text);
- $text = str_replace('[/u]','</span>', $text);
- require_once('url_catcher.inc.php');
- $text = url_catcher($text);
- return nl2br($text);
- } else {
- $text = preg_replace('!\[\/?b\]!','*',$text);
- $text = preg_replace('!\[\/?u\]!','_',$text);
- $text = preg_replace('!\[\/?i\]!','/',$text);
- $text = preg_replace('!(((https?|ftp)://|www\.)[^\r\n\t ]*)!','[\1]', $text);
- $text = preg_replace('!(([a-zA-Z0-9\-_+.]*@[a-zA-Z0-9\-_+.]*)(?:\?[^\r\n\t ]*)?)!','[mailto:\1]', $text);
- $text = $just ? justify($text,$width-$indent) : wordwrap($text,$width-$indent);
- if($indent) {
- $ind = str_pad('',$indent);
- $text = $ind.str_replace("\n","\n$ind",$text);
+ public function getLinkIps(&$blacklist_host_resolution_count)
+ {
+ $matches = $this->parseUrlsFromArticle();
+ $article_ips = array();
+
+ if (!empty($matches)) {
+ global $globals;
+
+ foreach ($matches as $match) {
+ $host = parse_url($match, PHP_URL_HOST);
+ if ($host == '') {
+ list(, $host) = explode('@', $match);
+ }
+
+ if ($blacklist_host_resolution_count >= $globals->mail->blacklist_host_resolution_limit) {
+ break;
+ }
+
+ if (!preg_match('/^(' . str_replace(' ', '|', $globals->mail->domain_whitelist) . ')$/i', $host)) {
+ $article_ips = array_merge($article_ips, array(gethostbyname($host) => $host));
+ ++$blacklist_host_resolution_count;
+ }
+ }
}
- return $text;
+
+ return $article_ips;
}
+
+ // }}}
}
// }}}
-// vim:set et sw=4 sts=4 sws=4:
+// vim:set et sw=4 sts=4 sws=4 enc=utf-8:
?>