| 1 |
<?php
|
| 2 |
// $Id: listhandler.module,v 1.87 2009/10/25 16:15:02 philipnet Exp $
|
| 3 |
|
| 4 |
/**
|
| 5 |
* @file
|
| 6 |
* Listhandler main module.
|
| 7 |
*/
|
| 8 |
|
| 9 |
/**
|
| 10 |
* To do:
|
| 11 |
* Does attachment handling screw up druapl_html_to_text or vise-versa?
|
| 12 |
* listhandler_update_5000 needs testing with the new db_drop_index code
|
| 13 |
* 5.x to 6.x migration needs testing
|
| 14 |
* Descriptions for database schema
|
| 15 |
* Check attachment handling after admin screen UI improvement.
|
| 16 |
*/
|
| 17 |
|
| 18 |
/**
|
| 19 |
* Implementation of hook_help().
|
| 20 |
*/
|
| 21 |
function listhandler_help($path, $arg) {
|
| 22 |
$output = '';
|
| 23 |
switch ($path) {
|
| 24 |
case 'admin/help#listhandler':
|
| 25 |
$output = '<p>'. t('The listhandler module allows you to connect mailing lists to forums and vice versa. It works in conjunction with the mailhandler module. Mailhandler receives an email and then asks listhandler if the received email is part of a list. If the email is from a mailing list associated with a forum on your site, then listhandler adds the recieved email to the forum.') .'</p>';
|
| 26 |
$output .= '<p>'. t('Listhandler administration allows you to set the email address of the list administrator. The email address is used as the From: field to check the address of messages sent by anonymous users. You can also enable and disable the listhandler for a list.') .'</p>';
|
| 27 |
$output .= t('<p>You can:</p>
|
| 28 |
<ul>
|
| 29 |
<li>administer listhandler <a href="!admin-listhandler">administer >> listhandler</a>.</li>
|
| 30 |
<li>administer mailhandler <a href="!admin-mailhandler">administer >> mailhandler</a> to create a mailbox which list handler can work with.</li>
|
| 31 |
<li>administer forum <a href="!admin-forum">administer >> forum</a>.</li>
|
| 32 |
', array('!admin-listhandler' => url('admin/content/listhandler'), '!admin-mailhandler' =>
|
| 33 |
url('admin/content/mailhandler'), '!admin-forum' => url('admin/content/forum'))) .'</ul>';
|
| 34 |
$output .= '<p>'. t('For more information please read the configuration and customization handbook <a href="!listhandler">Listhandler page</a>.', array('!listhandler' => 'http://www.drupal.org/handbook/modules/listhandler/')) .'</p>';
|
| 35 |
return $output;
|
| 36 |
case 'admin/build/modules#description':
|
| 37 |
$output = t('Connect your mailing lists to your drupal site and your drupal site to your mailing lists.');
|
| 38 |
break;
|
| 39 |
case 'admin/content/listhandler':
|
| 40 |
$output = t("First go to the <a href='!url'>mailhandler configuration screen</a> and add some mailboxes. A mailbox becomes recognised as a mailing list if the 'Second E-mail address' is set.", array('!url' => url('admin/content/mailhandler')));
|
| 41 |
break;
|
| 42 |
}
|
| 43 |
return $output;
|
| 44 |
}
|
| 45 |
|
| 46 |
/**
|
| 47 |
* Implementation of hook_perm().
|
| 48 |
* Permissions for this module
|
| 49 |
*/
|
| 50 |
function listhandler_perm() {
|
| 51 |
return array('administer listhandler');
|
| 52 |
}
|
| 53 |
|
| 54 |
/**
|
| 55 |
* Implementation of hook_menu().
|
| 56 |
*/
|
| 57 |
function listhandler_menu() {
|
| 58 |
$items = array();
|
| 59 |
$items['admin/content/listhandler'] = array(
|
| 60 |
'title' => 'Listhandler',
|
| 61 |
'description' => 'Manage mailing-lists subscriptions.',
|
| 62 |
'page callback' => 'drupal_get_form',
|
| 63 |
'page arguments' => array('listhandler_admin_settings'),
|
| 64 |
'access callback' => 'user_access',
|
| 65 |
'access arguments' => array('administer listhandler')
|
| 66 |
);
|
| 67 |
|
| 68 |
return $items;
|
| 69 |
}
|
| 70 |
|
| 71 |
/**
|
| 72 |
* Implementation of hook_theme().
|
| 73 |
*/
|
| 74 |
function listhandler_theme() {
|
| 75 |
return array(
|
| 76 |
'listhandler_admin_settings' => array(
|
| 77 |
'arguments' => array('form' => NULL)
|
| 78 |
)
|
| 79 |
);
|
| 80 |
}
|
| 81 |
|
| 82 |
/**
|
| 83 |
* Configuration options for this module
|
| 84 |
*/
|
| 85 |
function listhandler_admin_settings() {
|
| 86 |
// This is the first chance we get to identify any new Mailhandler mailboxes.
|
| 87 |
// We need to check for:
|
| 88 |
// * new mailboxes
|
| 89 |
// * removed mailboxes
|
| 90 |
|
| 91 |
|
| 92 |
|
| 93 |
$form = array();
|
| 94 |
$form['listhandler_from'] = array(
|
| 95 |
'#type' => 'textfield',
|
| 96 |
'#title' => t("'Anonymous user' email address"),
|
| 97 |
'#default_value' => variable_get('listhandler_from', ''),
|
| 98 |
'#size' => 50,
|
| 99 |
'#maxlength' => 100,
|
| 100 |
'#description' => t('Used as the From address of messages sent by anonymous users; this is usually the mailing list administrator. However, if it is not then please ensure this email address can post to the list otherwise a bounce message will be generated'));
|
| 101 |
$form['listhandler_strip_title'] = array(
|
| 102 |
'#type' => 'textfield',
|
| 103 |
'#title' => t('Strip title'),
|
| 104 |
'#default_value' => variable_get('listhandler_strip_title', 'Re: , AW:,[my list]'),
|
| 105 |
'#size' => 50,
|
| 106 |
'#maxlength' => 1024,
|
| 107 |
'#description' => t("A comma delimited sequence of strings that should be stripped from the titles of topics and comments posted to the forums. You can use it to remove certain tags like 'Re: ' or '[My Mailinglist]'."));
|
| 108 |
$form['listhandler_attachments_as_link'] = array(
|
| 109 |
'#type' => 'radios',
|
| 110 |
'#title' => t('Attachment handling'),
|
| 111 |
'#options' => array(0 => t('Links at the bottom of emails'), 1 => t('Attachments in emails')),
|
| 112 |
'#default_value' => variable_get('listhandler_attachments_as_link', 0),
|
| 113 |
'#description' => t('Send attachments as links or MIME attachments. It only affects mails generated by forum posts.'));
|
| 114 |
$form['listhandler_accountstatus'] = array(
|
| 115 |
'#type' => 'radios',
|
| 116 |
'#title' => t('Account status'),
|
| 117 |
'#default_value' => variable_get('listhandler_accountstatus', 0),
|
| 118 |
'#options' => array(0 => t('blocked'), 1 => t('active')),
|
| 119 |
'#description' => t('The status of accounts created by Listhandler.'));
|
| 120 |
$form['listhandler_htmltotext'] = array(
|
| 121 |
'#type' => 'radios',
|
| 122 |
'#title' => t('HTML to text converter'),
|
| 123 |
'#default_value' => variable_get('listhandler_htmltotext', 0),
|
| 124 |
'#options' => array(0 => t('Fancy'), 1 => t('Standard')),
|
| 125 |
'#description' => t('If forums posts will be made using a WYSIWYG editor (i.e. TinyMCE) then the Fancy converter offers a more accurate convertion.'));
|
| 126 |
$form['listhandler_alwaysnewthread'] = array(
|
| 127 |
'#type' => 'radios',
|
| 128 |
'#title' => t('Email Replies'),
|
| 129 |
'#default_value' => variable_get('listhandler_alwaysnewthread', 0),
|
| 130 |
'#options' => array(0 => t('Replies as comments to original thread'), 1 => t('Replies as new threads')),
|
| 131 |
'#description' => t('Whether incoming email replies will be treated as comments or new threads.'));
|
| 132 |
|
| 133 |
$form['listhandler_list'] = array(
|
| 134 |
'#tree' => TRUE,
|
| 135 |
);
|
| 136 |
|
| 137 |
$form['listhandler_prefix'] = array(
|
| 138 |
'#tree' => TRUE,
|
| 139 |
);
|
| 140 |
|
| 141 |
$result = db_query("
|
| 142 |
SELECT {mailhandler}.mid AS mid, {listhandler_prefix}.prefix AS prefix, {mailhandler}.mailto AS mailto FROM {mailhandler}
|
| 143 |
LEFT OUTER JOIN {listhandler_prefix}
|
| 144 |
ON {mailhandler}.mid = {listhandler_prefix}.mid
|
| 145 |
ORDER BY mailto");
|
| 146 |
|
| 147 |
while ($mailbox = db_fetch_object($result)) {
|
| 148 |
$form['listhandler_list'][$mailbox->mid] = array(
|
| 149 |
'#value' => '<div><a href="mailto:'. $mailbox->mailto .'">'. $mailbox->mailto .'</a></div>');
|
| 150 |
$form['listhandler_prefix'][$mailbox->mid] = array(
|
| 151 |
'#type' => 'textfield',
|
| 152 |
'#default_value' => $mailbox->prefix,
|
| 153 |
'#size' => 50,
|
| 154 |
'#maxlength' => 100);
|
| 155 |
}
|
| 156 |
|
| 157 |
$form=system_settings_form($form);
|
| 158 |
|
| 159 |
$form['#submit'][] = 'listhandler_admin_settings_submit';
|
| 160 |
$form['#theme'] = 'listhandler_admin_settings';
|
| 161 |
return $form;
|
| 162 |
}
|
| 163 |
|
| 164 |
/**
|
| 165 |
* Theme call to render the tabular form of mailing lists and prefixes
|
| 166 |
*/
|
| 167 |
function theme_listhandler_admin_settings($form) {
|
| 168 |
$output = '';
|
| 169 |
$output .= drupal_render($form['listhandler_from']);
|
| 170 |
$output .= drupal_render($form['listhandler_strip_title']);
|
| 171 |
$output .= drupal_render($form['listhandler_accountstatus']);
|
| 172 |
$output .= drupal_render($form['listhandler_attachments_as_link']);
|
| 173 |
$output .= drupal_render($form['listhandler_htmltotext']);
|
| 174 |
$output .= drupal_render($form['listhandler_alwaysnewthread']);
|
| 175 |
if (count($form['listhandler_list'])) {
|
| 176 |
$rows = array();
|
| 177 |
foreach (element_children($form['listhandler_list']) as $mid) {
|
| 178 |
$row = array();
|
| 179 |
$row[] = drupal_render($form['listhandler_list'][$mid]);
|
| 180 |
$row[] = drupal_render($form['listhandler_prefix'][$mid]);
|
| 181 |
$rows[] = $row;
|
| 182 |
}
|
| 183 |
$header = array(t('Mailing list'), t('Prefix'));
|
| 184 |
$output .= theme('table', $header, $rows);
|
| 185 |
$output .= '<div>'. t("The prefix will be prepended to all outgoing mail subjects for the specified list. It is a good idea to put the prefix in the 'strip title' field.") .'</div>';
|
| 186 |
}
|
| 187 |
else {
|
| 188 |
$output .= '<div>'. t("No mailing lists have been defined. Please go to the <a href='!url'>mailhandler configuration screen</a> and add one or more mailboxes. A mailbox becomes recognised as a mailing list if the 'Second E-mail address' is set.", array('!url' => 'admin/content/mailhandler')) .'</div>';
|
| 189 |
}
|
| 190 |
$output .= drupal_render($form);
|
| 191 |
return $output;
|
| 192 |
}
|
| 193 |
|
| 194 |
/**
|
| 195 |
* Writes configuration settings as Drupal variables and entries in
|
| 196 |
* the listhandler and mailhandler tables
|
| 197 |
*/
|
| 198 |
function listhandler_admin_settings_submit($form, &$form_state) {
|
| 199 |
// Drupal can save the standard options, it's just the table it can't:
|
| 200 |
if (isset($form_state['values']['listhandler_prefix'])) {
|
| 201 |
foreach ($form_state['values']['listhandler_prefix'] as $key => $value) {
|
| 202 |
$result = db_query("SELECT {listhandler_prefix}.mid FROM {listhandler_prefix} WHERE mid = %d", $key);
|
| 203 |
if (!db_fetch_array($result)) {
|
| 204 |
db_query("INSERT INTO {listhandler_prefix} (prefix,mid) VALUES ('%s', '%d')", $value, $key);
|
| 205 |
}
|
| 206 |
else {
|
| 207 |
db_query("UPDATE {listhandler_prefix} SET prefix = '%s' WHERE mid = %d", $value, $key);
|
| 208 |
}
|
| 209 |
}
|
| 210 |
}
|
| 211 |
}
|
| 212 |
|
| 213 |
/**
|
| 214 |
* Implementation of hook_nodeapi().
|
| 215 |
*/
|
| 216 |
function listhandler_nodeapi(&$node, $op, $arg = 0) {
|
| 217 |
switch ($op) {
|
| 218 |
case 'update': // what to do with updates?
|
| 219 |
break;
|
| 220 |
case 'insert': // mail new forum topics to mailing list.
|
| 221 |
if ($node->type == 'forum') {
|
| 222 |
if ($node->sentbylisthandler) { // avoid running an infinite loop.
|
| 223 |
// save ids in listhandler table.
|
| 224 |
db_query("INSERT INTO {listhandler} (msgid, nid, cid, pid, uid, mid, tid) VALUES ('%s','%s','%s','%s','%s','%s','%s')", $node->message_id, $node->nid, 0, 0, $node->uid, $node->mid, $node->tid);
|
| 225 |
// call watchdog
|
| 226 |
watchdog('listhandler', "Forum '%s' inserted.", array("%s" => $node->title), WATCHDOG_NOTICE);
|
| 227 |
}
|
| 228 |
else {
|
| 229 |
$node->subject = $node->title;
|
| 230 |
$node->comment = $node->body;
|
| 231 |
listhandler_send_mail((array) $node);
|
| 232 |
}
|
| 233 |
}
|
| 234 |
break;
|
| 235 |
}
|
| 236 |
}
|
| 237 |
|
| 238 |
/**
|
| 239 |
* Called by comment.module after submitting a comment.
|
| 240 |
* Sends comments to specified addresses.
|
| 241 |
*
|
| 242 |
* $type: type of call, here insert is expected.
|
| 243 |
*
|
| 244 |
* $edit: Array containing the comment.
|
| 245 |
* Important fields:
|
| 246 |
* $edit["subject"]: Oh well.
|
| 247 |
* $edit["comment"]: The text
|
| 248 |
* $edit["nid"]: commented node id
|
| 249 |
* $edit["cid"]: comment id
|
| 250 |
* $edit["pid"]: cid of parent
|
| 251 |
* $edit["uid"]: user id
|
| 252 |
* $edit["mid"]: id of mailbox
|
| 253 |
* $edit["tid"]: taxo id of the forum
|
| 254 |
*/
|
| 255 |
function listhandler_comment($edit = array(), $type) {
|
| 256 |
if ($type == "insert") { // only accept calls by the comment insert hook.
|
| 257 |
if ($edit["sentbylisthandler"]) { // avoid running an infinite loop.
|
| 258 |
// save comment ids in listhandler table.
|
| 259 |
db_query("INSERT INTO {listhandler} (msgid, nid, cid, pid, uid, mid, tid) VALUES ('%s','%s','%s','%s','%s','%s','%s')", $edit["message_id"], $edit["nid"], $edit["cid"], $edit["pid"], $edit["uid"], $edit["mid"], $edit["tid"]);
|
| 260 |
// call watchdog
|
| 261 |
watchdog('listhandler', "Comment '%s' inserted.", array("%s" => $edit["subject"]), WATCHDOG_NOTICE);
|
| 262 |
}
|
| 263 |
else {
|
| 264 |
if (filter_access($edit['format']) && $edit['subject'] == truncate_utf8(decode_entities(strip_tags(check_markup($edit['comment'], $edit['format']))), 29, TRUE)) {
|
| 265 |
// subject was autogenerated, get it from parent instead
|
| 266 |
if ($edit['pid']) {
|
| 267 |
$parent = db_fetch_object(db_query('SELECT * FROM {comments} WHERE cid = %d', $edit['pid']));
|
| 268 |
$edit['subject'] = truncate_utf8(decode_entities(check_plain(t('Re: ') . $parent->subject)), 29, TRUE);
|
| 269 |
}
|
| 270 |
// no parent, get node title
|
| 271 |
else {
|
| 272 |
$parent = db_fetch_object(db_query('SELECT title FROM {node} WHERE nid = %d', $edit['nid']));
|
| 273 |
$parent->subject = truncate_utf8(decode_entities(strip_tags(check_markup($parent->title, $edit['format']))), 29, TRUE);
|
| 274 |
$edit['subject'] = t('Re: ') . $parent->subject;
|
| 275 |
}
|
| 276 |
db_query("UPDATE {comments} SET subject = '%s' WHERE cid = %d", $parent->subject, $edit['cid']);
|
| 277 |
}
|
| 278 |
|
| 279 |
listhandler_send_mail($edit);
|
| 280 |
}
|
| 281 |
}
|
| 282 |
}
|
| 283 |
|
| 284 |
/**
|
| 285 |
* Send email to mailing list.
|
| 286 |
* Includes a References/In_reply-To header if possible.
|
| 287 |
*/
|
| 288 |
function listhandler_send_mail($edit) {
|
| 289 |
global $user, $base_url, $language;
|
| 290 |
|
| 291 |
if (!$user->uid) {
|
| 292 |
$edit['name'] = variable_get('anonymous', 'Anonymous');
|
| 293 |
$edit['mail'] = variable_get('listhandler_from', '');
|
| 294 |
}
|
| 295 |
else {
|
| 296 |
$edit["name"] = $user->name;
|
| 297 |
$edit["mail"] = $user->mail;
|
| 298 |
}
|
| 299 |
// Find the list to send to.
|
| 300 |
$mboxen = array();
|
| 301 |
|
| 302 |
// taxo terms of the node.
|
| 303 |
if (count($edit['taxonomy'])) {
|
| 304 |
foreach ($edit['taxonomy'] as $taxoterm) {
|
| 305 |
// Now for the mailbox.
|
| 306 |
switch ($GLOBALS['db_type']) {
|
| 307 |
case 'mysql':
|
| 308 |
case 'mysqli':
|
| 309 |
$result2 = db_query("SELECT * FROM {mailhandler} m WHERE m.commands REGEXP '%s'", 'tid:[[:blank:]]*'. $taxoterm .'[[:>:]]');
|
| 310 |
break;
|
| 311 |
case 'pgsql':
|
| 312 |
$result2 = db_query("SELECT * FROM {mailhandler} m WHERE m.commands ~ '%s'", 'tid:[[:blank:]]*'. $taxoterm .'[[:>:]]');
|
| 313 |
}
|
| 314 |
while ($mbox = db_fetch_object($result2)) {
|
| 315 |
$mboxen[] = array($mbox->mid, $mbox->mailto, $taxoarr->tid);
|
| 316 |
}
|
| 317 |
}
|
| 318 |
}
|
| 319 |
else {
|
| 320 |
$result = db_query("SELECT t.tid FROM {term_node} t WHERE t.nid = %d", $edit["nid"]);
|
| 321 |
while ($taxoarr = db_fetch_object($result)) {
|
| 322 |
// Now for the mailbox.
|
| 323 |
switch ($GLOBALS['db_type']) {
|
| 324 |
case 'mysql':
|
| 325 |
case 'mysqli':
|
| 326 |
$result2 = db_query("SELECT * FROM {mailhandler} m WHERE m.commands REGEXP '%s'", 'tid:[[:blank:]]*'. $taxoarr->tid .'[[:>:]]');
|
| 327 |
break;
|
| 328 |
case 'pgsql':
|
| 329 |
$result2 = db_query("SELECT * FROM {mailhandler} m WHERE m.commands ~ '%s'", 'tid:[[:blank:]]*'. $taxoarr->tid .'[[:>:]]');
|
| 330 |
}
|
| 331 |
while ($mbox = db_fetch_object($result2)) {
|
| 332 |
$mboxen[] = array($mbox->mid, $mbox->mailto, $taxoarr->tid);
|
| 333 |
}
|
| 334 |
}
|
| 335 |
}
|
| 336 |
// Find parent's MsgID if received by listhandler.
|
| 337 |
if ($edit["pid"]) {
|
| 338 |
// We should get only one or no result.
|
| 339 |
$result = db_fetch_object(db_query("SELECT * FROM {listhandler} WHERE cid = %d", $edit['pid']));
|
| 340 |
}
|
| 341 |
else {
|
| 342 |
$result = db_fetch_object(db_query("SELECT * FROM {listhandler} WHERE nid = %d", $edit['nid']));
|
| 343 |
$edit['pid']=0;
|
| 344 |
}
|
| 345 |
$mid=array();
|
| 346 |
if ($result) {// Parent was sent or received by listhandler
|
| 347 |
$mid['References'] = $result->msgid;
|
| 348 |
$mid['In-Reply-To'] = $result->msgid;
|
| 349 |
}
|
| 350 |
//common headers
|
| 351 |
$dir = str_replace("/", ".", substr(strchr(str_replace("http://", "", $base_url), "/"), 1));
|
| 352 |
foreach ($mboxen as $mbox) {
|
| 353 |
$edit["mid"] = $mbox[0];
|
| 354 |
$to = $mbox[1];
|
| 355 |
$edit["tid"] = $mbox[2];
|
| 356 |
|
| 357 |
// The below is required for EZMLM
|
| 358 |
// It sets the Return Path to the Listhandler subscribed email address (rather than the webserver)
|
| 359 |
// so that EZMLM (and everybody else) knows that we sent it
|
| 360 |
$mid['Return-Path'] = $edit['mail'];
|
| 361 |
|
| 362 |
// We add tokens to the MID. Replies to comments sent by listhandler can thus be classified easier.
|
| 363 |
$msgid = "<listhandler=". $edit["mid"] ."&site=". $dir . $_SERVER["SERVER_NAME"] ."&nid=". $edit["nid"] ."&pid=". $edit["pid"] ."&cid=". $edit["cid"] ."&uid=". $user->uid ."&tid=". $edit["tid"] ."&". md5($edit["nid"] . $edit["cid"]) ."@". $dir . strtolower($_SERVER["SERVER_NAME"]) .">";
|
| 364 |
$mid['Message-Id'] = $msgid;
|
| 365 |
|
| 366 |
// Ensure emails are treated as mailing list posts, not junk
|
| 367 |
$mid['Precedence'] = "list";
|
| 368 |
|
| 369 |
if (variable_get('listhandler_htmltotext', 0)) {
|
| 370 |
$subject = decode_entities(strip_tags($edit['subject']));
|
| 371 |
$body = decode_entities(strip_tags($edit['comment'])); }
|
| 372 |
else {
|
| 373 |
$subject = drupal_html_to_text($edit['subject']);
|
| 374 |
$body = drupal_html_to_text($edit['comment']);
|
| 375 |
}
|
| 376 |
|
| 377 |
// Add attachments
|
| 378 |
$fragment = NULL;
|
| 379 |
$lfiles = FALSE;
|
| 380 |
if ($edit['cid']) {
|
| 381 |
$fragment = "comment-" . $edit['cid'];
|
| 382 |
//attachment comments are already created
|
| 383 |
if (function_exists('comment_upload_load_files')) {
|
| 384 |
$lfiles = comment_upload_load_files($edit['cid']);
|
| 385 |
}
|
| 386 |
}
|
| 387 |
else {
|
| 388 |
$lfiles = $edit['files'];
|
| 389 |
}
|
| 390 |
if ($lfiles) {
|
| 391 |
// add $fragment to arguments: needed to build proper URL back
|
| 392 |
// to comments, which can contain attachments too
|
| 393 |
if (variable_get('listhandler_attachments_as_link', 0)) {
|
| 394 |
$body .= _listhandler_mail_links($lfiles, $edit['nid'], $fragment);
|
| 395 |
}
|
| 396 |
else {
|
| 397 |
$body = _listhandler_mail_attachments($body, $lfiles, $mid, $fragment);
|
| 398 |
}
|
| 399 |
}
|
| 400 |
|
| 401 |
// send email
|
| 402 |
$params = array(
|
| 403 |
'body' => $body,
|
| 404 |
'subject' => $subject,
|
| 405 |
'mid' => $mid
|
| 406 |
);
|
| 407 |
$ok = drupal_mail('listhandler', 'mail', $to, $language, $params, $edit["mail"] /* from */);
|
| 408 |
|
| 409 |
// sanitize cid and tid values for SQL mode STRICT_TRANS_TABLES
|
| 410 |
if (!$edit["cid"]) {
|
| 411 |
$edit["cid"]=0;
|
| 412 |
}
|
| 413 |
if (!$edit["tid"]) {
|
| 414 |
$edit["tid"]=0;
|
| 415 |
}
|
| 416 |
|
| 417 |
// save comment ids in listhandler table.
|
| 418 |
// Not strictly needed, the same info is stored in the msgid.
|
| 419 |
db_query("INSERT INTO {listhandler} (msgid, nid, cid, pid, uid, mid, tid) VALUES ('%s','%s','%s','%s','%s','%s','%s')", $msgid, $edit["nid"], $edit["cid"], $edit["pid"], $user->uid, $edit["mid"], $edit["tid"]);
|
| 420 |
|
| 421 |
// Call watchdog
|
| 422 |
if ($ok) {
|
| 423 |
watchdog('listhandler', "'!s' sent to '!a'.", array("!s" => $edit["subject"], "!a" => $to), WATCHDOG_NOTICE);
|
| 424 |
}
|
| 425 |
else {
|
| 426 |
watchdog('listhandler', "Error sending '!s' to '!a'.", array("!s" => $edit["subject"], "!a" => $to), WATCHDOG_WARNING);
|
| 427 |
}
|
| 428 |
}
|
| 429 |
}
|
| 430 |
|
| 431 |
/**
|
| 432 |
* Implements hook_mail.
|
| 433 |
*/
|
| 434 |
function listhandler_mail($key, &$message, $params) {
|
| 435 |
$message['subject'] = $params['subject'];
|
| 436 |
$message['body'][] = $params['body'];
|
| 437 |
$message['headers'] = array_merge($message['headers'], $params['mid']);
|
| 438 |
}
|
| 439 |
|
| 440 |
/**
|
| 441 |
* Called by mailhandler after a new mail has been received.
|
| 442 |
*
|
| 443 |
* Only the first and last argument are used.
|
| 444 |
*
|
| 445 |
* $node: The new node or comment
|
| 446 |
* $stream: The number of the opened imap stream.
|
| 447 |
* $msg_number: The number of the current message in the mailbox.
|
| 448 |
* $mailbox: Array containing info about the mailbox the message is from.
|
| 449 |
* $header: Some, but not all headers (From, To, message_id, ...) of the current message.
|
| 450 |
*/
|
| 451 |
function listhandler_mailhandler($node, $result, $msg_number, $header, $mailbox) {
|
| 452 |
global $base_url;
|
| 453 |
|
| 454 |
if ($node->tid) { // If no tid is assigned, then the mail is not comming through a mailhandler enabled list. Do nothing.
|
| 455 |
$node->cid = 0; // Might have a cid from the msg id. This will confuse comment_post. Updating comments via mail does not make sense anyway. GK
|
| 456 |
// Override value from msgid. Might be crossposted.
|
| 457 |
$node->mid = $mailbox['mid'];
|
| 458 |
// We need to ensure that no messages that have been sent by listhandler on this site (!)
|
| 459 |
// get processed. We would get an infinite loop on a mailing list.
|
| 460 |
$dir = str_replace("/", ".", substr(strchr(str_replace("http://", "", $base_url), "/"), 1));
|
| 461 |
$regex = "<listhandler=[[:print:]]+@". $dir . strtolower($_SERVER["SERVER_NAME"]) .">";
|
| 462 |
if (ereg($regex, $header->message_id)) {
|
| 463 |
// Sent by listhandler on this site. Destroy the node.
|
| 464 |
watchdog('listhandler', "Discarded message '!s' to avoid loop.", array("!s" => $node->title), WATCHDOG_NOTICE);
|
| 465 |
unset($node);
|
| 466 |
return;
|
| 467 |
}
|
| 468 |
else {
|
| 469 |
// Debug
|
| 470 |
//if($node->site != $dir . $_SERVER["SERVER_NAME"]) { // parent (!) not sent by listhandler on this site.
|
| 471 |
if ($node->uid == 0) { // mailhandler did not find the author, create a new account
|
| 472 |
$node = listhandler_create_author($node, $header);
|
| 473 |
}
|
| 474 |
//}
|
| 475 |
// Strip stuff from title
|
| 476 |
$replace = explode(',', variable_get('listhandler_strip_title', ''));
|
| 477 |
//print_r($replace);
|
| 478 |
$replacements = array();
|
| 479 |
//print_r($replacements);
|
| 480 |
foreach ($replace as $v) {
|
| 481 |
$replacements[trim($v)] = '';
|
| 482 |
}
|
| 483 |
//print_r($replacements);
|
| 484 |
unset($replacements['']);
|
| 485 |
//print_r($node->title);
|
| 486 |
if (count($replacements)) {
|
| 487 |
$node->title = trim(strtr($node->title, $replacements));
|
| 488 |
}
|
| 489 |
//print_r($node->title);
|
| 490 |
if (trim($node->title) == '') {
|
| 491 |
$node->title = truncate_utf8(decode_entities(strip_tags(check_markup($node->body, 1))), 29, TRUE);
|
| 492 |
}
|
| 493 |
$node = listhandler_find_parent($node, $header);
|
| 494 |
|
| 495 |
$node->message_id = $header->message_id;
|
| 496 |
$node->sentbylisthandler = TRUE;
|
| 497 |
|
| 498 |
return $node;
|
| 499 |
}
|
| 500 |
}
|
| 501 |
else { // allow other modules to have that node unaltered.
|
| 502 |
return $node;
|
| 503 |
}
|
| 504 |
}
|
| 505 |
|
| 506 |
/**
|
| 507 |
* Create account for unknown authors of a new mailsubmitted node or comment.
|
| 508 |
* Admin is able to choose if it will be
|
| 509 |
* a real account or a blocked one (see conf).
|
| 510 |
* if no account can be created (email or name already taken) the name and address
|
| 511 |
* are prepended to the node body and posted as anonymous.
|
| 512 |
*/
|
| 513 |
function listhandler_create_author($node, $header) {
|
| 514 |
$from = $header->from;
|
| 515 |
$from_address = strtolower(sprintf("%s@%s", $from[0]->mailbox, $from[0]->host));
|
| 516 |
// decode encoded author name
|
| 517 |
$from_name = '';
|
| 518 |
$from_arr = imap_mime_header_decode($header->from[0]->personal);
|
| 519 |
for ($i = 0; $i < count($from_arr); $i++) {
|
| 520 |
if ($from_arr[$i]->charset != 'default') {
|
| 521 |
$from_name .= drupal_convert_to_utf8($from_arr[$i]->text, $from_arr[$i]->charset);
|
| 522 |
}
|
| 523 |
else {
|
| 524 |
$from_name .= $from_arr[$i]->text;
|
| 525 |
}
|
| 526 |
}
|
| 527 |
$from_name = trim($from_name, '"');
|
| 528 |
if ($from_name == '') {
|
| 529 |
$from_name = $from_address;
|
| 530 |
}
|
| 531 |
// check if name is available
|
| 532 |
if (db_result(db_query("SELECT COUNT(name) FROM {users} WHERE LOWER(name) = LOWER('%s')", $from_name)) > 0) {
|
| 533 |
$node->body = t('Message from !n !a', array('!n' => $from_name, '!a' => $from_address)) ."\n\n". $node->body;
|
| 534 |
watchdog('listhandler', "Cannot create account: The name '!s' is already taken.", array("!s" => $from_name), WATCHDOG_WARNING);
|
| 535 |
}
|
| 536 |
// check if address is valid
|
| 537 |
elseif (!valid_email_address($from_address)) {
|
| 538 |
$node->body = t('Message from !n !a', array('!n' => $from_name, '!a' => $from_address)) ."\n\n". $node->body;
|
| 539 |
watchdog('listhandler', "Cannot create account: The email address '!s' is not valid.", array("!s" => $from_address), WATCHDOG_WARNING);
|
| 540 |
}
|
| 541 |
// create account
|
| 542 |
else {
|
| 543 |
$empty_account = new stdClass();
|
| 544 |
$from_user = user_save($empty_account, array('name' => $from_name, 'pass' => user_password(), 'init' => $from_address, 'mail' => $from_address, 'roles' => array(DRUPAL_AUTHENTICATED_RID), 'status' => variable_get('listhandler_accountstatus', 0)), 'account');
|
| 545 |
watchdog('listhandler', 'Created account for !fa, with roles !rid', array('!fa' => $from_address, '!rid' => implode(', ', $from_user->roles)), WATCHDOG_NOTICE);
|
| 546 |
mailhandler_switch_user($from_user->uid);
|
| 547 |
}
|
| 548 |
$node->uid = $from_user->uid;
|
| 549 |
$node->name = $from_user->name;
|
| 550 |
|
| 551 |
return $node;
|
| 552 |
}
|
| 553 |
|
| 554 |
/**
|
| 555 |
* Find the parent of a new mailsubmitted comment. First use some heuristics
|
| 556 |
* and assumptions about Message-ID, References, and In-Reply-To headers.
|
| 557 |
* Then try to find a parent based on Subject line.
|
| 558 |
* If all else fails, start a new forum topic.
|
| 559 |
*/
|
| 560 |
function listhandler_find_parent($node, $header) {
|
| 561 |
// create new thread no matter what?
|
| 562 |
if (variable_get('listhandler_alwaysnewthread', 0)) {
|
| 563 |
return listhandler_new_thread($node);
|
| 564 |
}
|
| 565 |
|
| 566 |
if ($node->threading) {
|
| 567 |
$parent = db_fetch_object(db_query("SELECT * FROM {listhandler} WHERE msgid = '<%s>'", $node->threading));
|
| 568 |
// Debug
|
| 569 |
// watchdog('listhandler', "Parent seek '". $node->threading ."\np.nid:".$parent->nid."\n p.cid".$parent->cid."\nSubject: ".$header->subject."'", array(), WATCHDOG_DEBUG);
|
| 570 |
if ($parent) { // parent (!) seen by listhandler on this site.
|
| 571 |
return listhandler_parent_thread($node, $parent);
|
| 572 |
}
|
| 573 |
}
|
| 574 |
|
| 575 |
// Still no parent.
|
| 576 |
// Now find the most recent matching subject in the current forum
|
| 577 |
$title = trim(substr($node->title, (strrpos($node->title, ':'))));
|
| 578 |
// watchdog ('listhandler', 'Now searching for title "'.$title.'"', array(), WATCHDOG_DEBUG);
|
| 579 |
$parent = db_fetch_object(db_query("SELECT * FROM {listhandler} l INNER JOIN {node} n ON l.nid = n.nid WHERE n.title LIKE '%%%s' AND mid = %d ORDER by n.nid DESC", $title, $node->mid));
|
| 580 |
if ($parent) {
|
| 581 |
return listhandler_parent_thread($node, $parent);
|
| 582 |
}
|
| 583 |
else {
|
| 584 |
// Could be a comment to a comment.
|
| 585 |
// watchdog ('listhandler', 'Could be a comment to a comment', array(), WATCHDOG_DEBUG);
|
| 586 |
$parent = db_fetch_object(db_query("SELECT * FROM {comments} c WHERE c.subject = '%s' ORDER BY cid DESC", $title));
|
| 587 |
if ($parent) {
|
| 588 |
return listhandler_parent_thread($node, $parent);
|
| 589 |
}
|
| 590 |
else {
|
| 591 |
// No parent found so new thread.
|
| 592 |
return listhandler_new_thread($node);
|
| 593 |
}
|
| 594 |
}
|
| 595 |
}
|
| 596 |
|
| 597 |
/**
|
| 598 |
* Convert upload files into links.
|
| 599 |
* Optional argument $fragment is used in supporting comments
|
| 600 |
*/
|
| 601 |
function _listhandler_mail_links($lfiles, $nid, $fragment=NULL) {
|
| 602 |
$body = '';
|
| 603 |
$attachments = '';
|
| 604 |
foreach ($lfiles as $key => $ufile) {
|
| 605 |
$ufile = (object) $ufile;
|
| 606 |
$href = file_create_url((strpos($ufile->fid, 'upload') === FALSE ? $ufile->filepath : file_create_filename($ufile->filename, file_create_path())));
|
| 607 |
$href = str_replace(' ', '%20', $href);
|
| 608 |
$text = $ufile->description ? $ufile->description : $ufile->filename ;
|
| 609 |
$attachments .= "\n\n"." [". $text ."]:\n". $href;
|
| 610 |
}
|
| 611 |
if (!empty($attachments)) {
|
| 612 |
// change set up for call to url() function. Drupal 6 wants it to have
|
| 613 |
// options array as second argument.
|
| 614 |
if ($fragment) {
|
| 615 |
$my_url_options = array('fragment' => $fragment, 'absolute' => TRUE);
|
| 616 |
}
|
| 617 |
else {
|
| 618 |
$my_url_options = array('absolute' => TRUE);
|
| 619 |
}
|
| 620 |
$url = url('node/'. $nid, $my_url_options);
|
| 621 |
|
| 622 |
$body .= "\n\n". t('File attachments') .":";
|
| 623 |
$body .= $attachments;
|
| 624 |
$body .= "\n----------\n". t("Original attachments can be found at:\n!u", array('!u' => $url));
|
| 625 |
}
|
| 626 |
return $body;
|
| 627 |
}
|
| 628 |
|
| 629 |
/**
|
| 630 |
* Convert upload files into mail attachments.
|
| 631 |
*/
|
| 632 |
function _listhandler_mail_attachments($body, $files, &$mid, $fragment=NULL) {
|
| 633 |
$trenner = md5(uniqid(time()));
|
| 634 |
$mid['Content-Type'] = "multipart/mixed; boundary=$trenner";
|
| 635 |
$message = "\n--$trenner\n";
|
| 636 |
$message .= "Content-Type: text/plain; charset=UTF-8; format=flowed;"."\n\n"; // sets the mime type
|
| 637 |
|
| 638 |
$message .= $body ."\n";
|
| 639 |
$message .= "\n\n";
|
| 640 |
foreach ($files as $key => $file) {
|
| 641 |
$file = (object) $file;
|
| 642 |
if ($file->filename) {
|
| 643 |
$file->filepath = str_replace("\\", "\\\\", $file->filepath);
|
| 644 |
$message .= "--". $trenner ."\n";
|
| 645 |
$message .= "Content-Type:". $file->filemime .";\n\tname=\"". $file->filename ."\"\n";
|
| 646 |
$message .= "Content-Transfer-Encoding: base64\n";
|
| 647 |
$message .= "Content-Disposition: attachment;\n\tfilename=\"". $file->filename ."\"\n\n";
|
| 648 |
$filedata = fread(fopen($file->filepath, "rb"), $file->filesize);
|
| 649 |
$message .= chunk_split(base64_encode($filedata));
|
| 650 |
$message .= "\n\n";
|
| 651 |
}
|
| 652 |
}
|
| 653 |
$message .= "--". $trenner ."--";
|
| 654 |
return $message;
|
| 655 |
}
|
| 656 |
|
| 657 |
/**
|
| 658 |
* Sets $node-> attributes to that of the parent thread.
|
| 659 |
*/
|
| 660 |
function listhandler_parent_thread($node, $parent) {
|
| 661 |
// Debug
|
| 662 |
// watchdog('listhandler', "Parent found '". $node->threading ."\np.nid:".$parent->nid."\np.cid".$parent->cid."\nSubject:".$node->title."'", array(), WATCHDOG_DEBUG);
|
| 663 |
$node->pid = $parent->cid;
|
| 664 |
if ($node->cid) unset($node->cid);
|
| 665 |
$node->nid = $parent->nid;
|
| 666 |
$node->type = 'comment';
|
| 667 |
|
| 668 |
// use perms to set publish status for comments
|
| 669 |
$node->status = user_access('post comments without approval') ? 0 : 1;
|
| 670 |
|
| 671 |
return $node;
|
| 672 |
}
|
| 673 |
|
| 674 |
/**
|
| 675 |
* Sets $node-> attributes to create a new thread.
|
| 676 |
*/
|
| 677 |
function listhandler_new_thread($node) {
|
| 678 |
$node->type = 'forum';
|
| 679 |
$node->nid = 0;
|
| 680 |
$node->taxonomy[] = $node->tid;
|
| 681 |
$node->pid = 0;
|
| 682 |
$node->comment = 2;
|
| 683 |
|
| 684 |
return $node;
|
| 685 |
}
|
| 686 |
|
| 687 |
/**
|
| 688 |
* Implementation of hook_simpletest().
|
| 689 |
*/
|
| 690 |
function listhandler_simpletest() {
|
| 691 |
$dir = drupal_get_path('module', 'listhandler') .'/tests';
|
| 692 |
$tests = file_scan_directory($dir, '\.test$');
|
| 693 |
return array_keys($tests);
|
| 694 |
}
|