tiki-mailin-code.php 34.9 KB
Newer Older
1
<?php
changi67's avatar
changi67 committed
2 3 4
/**
 * @package tikiwiki
 */
5
// (c) Copyright 2002-2013 by authors of the Tiki Wiki CMS Groupware Project
changi67's avatar
changi67 committed
6
//
7 8
// All Rights Reserved. See copyright.txt for details and a complete list of authors.
// Licensed under the GNU LESSER GENERAL PUBLIC LICENSE. See license.txt for details.
changi67's avatar
changi67 committed
9 10
// $Id$

changi67's avatar
changi67 committed
11 12
require_once ('tiki-setup.php');
$access->check_script($_SERVER["SCRIPT_NAME"], basename(__FILE__));
13
include_once ('lib/mailin/mailinlib.php');
14
require_once ("lib/webmail/net_pop3.php");
15 16
include_once ("lib/mail/mimelib.php");
include_once ("lib/webmail/tikimaillib.php");
17
include_once ('lib/wiki/wikilib.php');
18
require_once ('lib/mailin/usermailinlib.php');
19 20 21 22 23 24

global $prefs;

$is_html = false;
$show_inlineImages = 'n';
$can_addAttachment = 'n';
25
$respond_email = 'y';
26
$save_html = 'y';
27

28 29 30 31 32
/**
 * @param $output
 * @param $out
 * @param $page
 * @param $user
33
 * @param $body
34
 */
35
function mailin_check_attachments(&$output, &$out, $page, $user)
36
{
37
	global $wikilib, $show_inlineImages, $can_addAttachment, $respond_email;
changi67's avatar
changi67 committed
38
	$cnt = 0;
changi67's avatar
changi67 committed
39

40 41 42
	if ($can_addAttachment !== 'y') {
		return;
	}
changi67's avatar
changi67 committed
43

44 45 46
	if (!isset($output["parts"])) {
		return;
	}
changi67's avatar
changi67 committed
47

48
	for ($it = 0, $count_outputparts = count($output['parts']); $it < $count_outputparts; $it++) {
changi67's avatar
changi67 committed
49 50 51
		if (isset($output["parts"][$it]["d_parameters"]["filename"])) {
			$attachmentPart = $output["parts"][$it];
			$fileName = $attachmentPart["d_parameters"]["filename"];
52 53
			if (isset($attachmentPart["ctype_primary"])) $fileType = $attachmentPart["ctype_primary"] . "/" . $attachmentPart["ctype_secondary"];
			else $fileType = "";
changi67's avatar
changi67 committed
54
			$fileData = $attachmentPart["body"];
55 56
			$fileSize = strlen($fileData);
			$wikilib->wiki_attach_file($page, $fileName, $fileType, $fileSize, $fileData, "attached by mail", $user, "");
changi67's avatar
changi67 committed
57
			$cnt++;
changi67's avatar
changi67 committed
58

pkdille's avatar
pkdille committed
59
			if ($show_inlineImages === 'y') {
60 61 62 63 64 65 66 67
				$contentId = $attachmentPart['header']['content-id'];
				if (!empty($contentId)) {
					$contentId = str_replace("<", "", $contentId);
					$contentId = str_replace(">", "", $contentId);

					mailin_insert_inline_image($body, $contentId, $attId, $page);
				}
			}
changi67's avatar
changi67 committed
68 69 70 71
		}
	}
	$out.= $cnt;
	$out.= " attachment(s) added<br />";
72
}
73 74 75 76 77 78

/**
 * @param $output
 * @return string
 */
function mailin_get_body($output)
79
{
80 81 82 83
	if (isset($output['text'][0])) $body = $output["text"][0];
	elseif (isset($output['parts'][0]) && isset($output['parts'][0]["text"][0])) $body = $output['parts'][0]["text"][0];
	elseif (isset($output['parts'][0]) && isset($output['parts'][0]['parts'][0]) && isset($output['parts'][0]['parts'][0]["text"][0])) $body = $output['parts'][0]['parts'][0]["text"][0];
	else $body = '';
84

changi67's avatar
changi67 committed
85
	return $body;
86
}
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
/**
 * @param $output
 * @return HTML string
 */
function mailin_get_html($output)
{
	if (isset($output['html'][0])) {
		$html = $output["html"][0];
	} elseif (isset($output['parts'][1]) && isset($output['parts'][1]["html"][0])) {
		$html = $output['parts'][1]["html"][0];
	} elseif (isset($output['parts'][0]) && isset($output['parts'][0]['parts'][1]) && isset($output['parts'][0]['parts'][1]["html"][0])) {
		$html = $output['parts'][0]['parts'][1]["html"][0];
	} elseif (isset($output['parts'][0]) && isset($output['parts'][0]['parts'][0]) && isset($output['parts'][0]['parts'][0]['parts'][1]) && isset($output['parts'][0]['parts'][0]['parts'][1]["html"][0])) {
		$html = $output['parts'][0]['parts'][0]['parts'][1]["html"][0];
	} else {
		$html = '';
	}
	return $html;
}
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
/**
 * @param $body
 * @return parsed content
 */
function mailin_parse_body($body, $acc)
{
	global $prefs;

	$is_html = false;
	$wysiwyg = NULL;
	if (mailin_containsStringHTML($body)) {
		$is_html = true;
		$wysiwyg = 'y';
	}

	if ($is_html && $acc['save_html'] === 'y') {
		// Keep HTML setting. Always save as HTML
		return array(
			'body'=>$body,
			'is_html'=>$is_html,
			'wysiwyg'=>$wysiwyg,
			);
	}
	if ($prefs['feature_wysiwyg'] === 'y' && $prefs['wysiwyg_default'] === 'y' && $prefs['wysiwyg_htmltowiki'] !== 'y' ) {
		// WYSIWYG HTML editor is active
		$is_html = true;
		$wysiwyg = 'y';
		return array(
			'body'=>$body,
			'is_html'=>$is_html,
			'wysiwyg'=>$wysiwyg,
			);
	}
changi67's avatar
changi67 committed
139

140 141 142 143 144 145 146 147 148 149 150 151 152 153
	if ($is_html) {
		include_once "lib/wiki/editlib.php";
		$editlib = new EditLib;
		$body = $editlib->parseToWiki($body);
		$is_html = false;
		$wysiwyg = NULL;
	}
	return array(
		'body'=>$body,
		'is_html'=>$is_html,
		'wysiwyg'=>$wysiwyg,
		);
}

changi67's avatar
changi67 committed
154
function mailin_containsStringHTML($str)
155
{
changi67's avatar
changi67 committed
156
	return preg_match('/<[^>]*>/', $str) == 1;
157
}
158 159 160 161 162 163 164 165 166 167 168 169 170 171

/**
 * This is function mailin_extract_inline_images
 * NOTE: Will force the use the HTML source as the page body
 * HTML is required in order to be able to identify the image in the email.
 *
 * @param string $pageName The name of the wiki page
 * @param mixed $output Array of email values
 * @param string $body The email body. Will be used as the wiki page body
 * @param string $out Log output
 * @param string $user The user; for logging purposes
 * @return nothing
 *
 */
172
function mailin_extract_inline_images($pageName, $output, &$body, &$out, $user)
173 174
{
	global $wikilib, $is_html, $show_inlineImages, $can_addAttachment;
changi67's avatar
changi67 committed
175

pkdille's avatar
pkdille committed
176
	if ($show_inlineImages !== 'y') {
177 178 179 180 181
		return;
	}
	if ($can_addAttachment !== 'y') {
		return;
	}
changi67's avatar
changi67 committed
182

183 184 185 186 187 188 189 190
	$cnt = 0;
	$errCnt = 0;
	if (!isset($output["parts"])) {
		return;
	}

	// Only for HTML email
	$html = mailin_get_html($output);
pkdille's avatar
pkdille committed
191
	if (empty($html)) {
192 193 194
		$out.= "inline attachments are only supported for email in html format<br />";
		return;
	}
changi67's avatar
changi67 committed
195

196
	// Replace the text version, and use use the HTML as the page body
changi67's avatar
changi67 committed
197

198 199 200 201 202 203 204 205
	// Locate the HTML
	$matches = array();
	preg_match("/<body[^>]*>(.*?)<\/body>/is", $html, $matches);
	$htmlBody = $matches[1];
	if (empty($htmlBody)) {
		// Assume the html is the body
		$htmlBody = $html;
	}
changi67's avatar
changi67 committed
206

207 208
	// Get rid of "id" attributes, as they may cause a failure to load the image
	$htmlBody = str_ireplace('id=', 'xid=', $htmlBody);
changi67's avatar
changi67 committed
209

210 211 212 213
	// Assign the HTML as the new body
	$body = $htmlBody;
	$is_html = true;

changi67's avatar
changi67 committed
214
	// Locate the page with inline attachments
215
	// Check deep level first, to avoid detecting extra, non-inlined attachments
216
	$activeParts = array();
217
	if (isset($output["parts"][0]["parts"][0]['parts'][1]["type"]) && isset($output["parts"][0]["parts"][0]["parts"][1]['ctype_parameters']['name'])) {
218
		$activeParts = $output["parts"][0]["parts"];
219
	} elseif (isset($output["parts"][0]['parts'][1]["type"]) && isset($output["parts"][0]["parts"][1]['ctype_parameters']['name'])) {
220
		$activeParts = $output["parts"][0]['parts'][1];
221 222
	} elseif (isset($output["parts"][1]) && isset($output["parts"][1]['ctype_parameters']['name'])) {
		$activeParts = $output["parts"];
changi67's avatar
changi67 committed
223 224
	}

225 226 227 228 229 230 231 232 233 234
	// Scroll the page attachments
	for ($it = 0, $count_outputparts = count($activeParts); $it < $count_outputparts; $it++) {
		if (isset($activeParts[$it]["ctype_parameters"]["name"])) {
			$attachmentPart = $activeParts[$it];
			$fileName = $attachmentPart["ctype_parameters"]["name"];
			if (isset($attachmentPart["type"])) {
				$fileType = $attachmentPart["type"];
			} else {
				$fileType = "";
			}
changi67's avatar
changi67 committed
235

236
			// Only process images
pkdille's avatar
pkdille committed
237
			if (strpos($fileType, 'image/', 0) === false) {
238 239 240
				$errCnt++;
				continue;
			}
changi67's avatar
changi67 committed
241

242 243 244 245 246
			// Process inline image
			$fileData = $attachmentPart['body'];
			$fileSize = function_exists('mb_strlen') ? mb_strlen($fileData, '8bit') : strlen($fileData);
			$attId = $wikilib->wiki_attach_file($pageName, $fileName, $fileType, $fileSize, $fileData, "inline image by mail", $user, "");
			$cnt++;
changi67's avatar
changi67 committed
247

248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268
			$contentId = $attachmentPart['header']['content-id'];
			if (empty($contentId)) {
				$errCnt++;
				continue;
			}
			$contentId = str_replace("<", "", $contentId);
			$contentId = str_replace(">", "", $contentId);

			mailin_insert_inline_image($body, $contentId, $attId, $pageName);
		}
	}
	$out.= $cnt;
	$out.= " inline attachment(s) added. ".$errCnt." failed<br />";
}

function mailin_insert_inline_image(&$body, $contentId, $attId, $pageName)
{
	$search = array();
	$replace = array();
	$search[] = 'cid:'.$contentId;		// This string may differ depending on the senders email client, I guess. Tested using Outlook 2010 as the sender
	$replace[] = 'tiki-download_wiki_attachment.php?attId='.$attId.'&page='.urlencode($pageName);
changi67's avatar
changi67 committed
269

270
	$newBody = str_replace($search, $replace, $body);
pkdille's avatar
pkdille committed
271
	if ($newBody == $body) {
272 273 274 275 276 277
		$errCnt++;
		continue;
	}
	$body = $newBody;
}

arildb's avatar
arildb committed
278 279 280
function mailin_preplog($msg)
{
	$logMessage = strip_tags($msg);
pkdille's avatar
pkdille committed
281
	$logMessage = str_replace('&nbsp;', ' ', $logMessage);
arildb's avatar
arildb committed
282 283 284 285
	return $logMessage;
}


286 287 288 289 290
/**
 * The tiki-mailin.php script is used to get / set wiki pages or articles
 * using a POP email account.
 */
global $debugger;
changi67's avatar
changi67 committed
291
if (defined($debugger)) $debugger->msg("tiki-mailin-code.php");
292 293
// Get a list of ACTIVE emails accounts configured for mailin procedures
$accs = $mailinlib->list_active_mailin_accounts(0, -1, 'account_desc', '');
294 295 296 297 298

if (empty($accs['data'])) {
	$content = '';
	return;
}
299
$content = '<br /><br />';
300 301 302

$userlib = TikiLib::lib('user');

arildb's avatar
arildb committed
303 304 305 306 307
// Logger
$logUser = $aux["sender"]["user"];
$logslib = TikiLib::lib('logs');


308
// foreach account
309
foreach ($accs['data'] as $acc) {
changi67's avatar
changi67 committed
310

311 312
	$show_inlineImages = $acc['show_inlineImages'];
	$can_addAttachment = $prefs['feature_wiki_attachments'];
pkdille's avatar
pkdille committed
313
	if ($can_addAttachment === 'y') {
314 315
		$can_addAttachment = $acc['attachments'];
	}
changi67's avatar
changi67 committed
316

317 318 319
	if (empty($acc['account'])) {
		continue;
	}
changi67's avatar
changi67 committed
320

changi67's avatar
changi67 committed
321 322 323 324
	$content.= "<b>Processing account</b><br />";
	$content.= "Account :" . $acc['account'] . "<br />";
	$content.= "Type    :" . $acc['type'] . "<br />";
	$content.= "--------------------------<br />";
325

changi67's avatar
changi67 committed
326 327 328 329 330
	$pop3 = new Net_Pop3();
	$content.= "Connecting...";
	if ($pop3->connect($acc["pop"], $acc["port"])) {
		$content.= "OK.<br />";
		$content.= "Logging in...";
changi67's avatar
changi67 committed
331

332
		// Login
changi67's avatar
changi67 committed
333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351
		if ($status = ($pop3->login($acc["username"], $acc["pass"], "USER")) !== FALSE) {
			$content.= "OK (" . $status . ").<br />";
			if (defined($debugger)) $debugger->msg("Logged in, status " . $status);
		} else {
			$content.= "FAILED.<br />";
			if (defined($debugger)) {
				$debugger->msg("Login failed, status " . $status);
				$debugger->msg("dump of pop3:");
				$debugger->var_dump('$pop3');
			}
		}
		$mailsum = $pop3->numMsg();
		if ($mailsum === FALSE) {
			$content.= "No messages.<br />";
			if (defined($debugger)) {
				$debugger->msg("No messages.");
				$debugger->msg("dump of pop3:");
				$debugger->var_dump('$pop3');
			}
352
		} else {
353
			$hasError = true;
changi67's avatar
changi67 committed
354

changi67's avatar
changi67 committed
355 356 357 358 359 360
			$content.= "Messages:" . $mailsum . "<br />";
			for ($i = 1; $i <= $mailsum; $i++) {
				$aux = $pop3->getParsedHeaders($i);
				if ($aux === FALSE) {
					$content.= "Headers not parsed.<br />";
				} else { // else $aux not FALSE
361 362 363
					if (!isset($aux["From"])) {
						$aux['From'] = $aux['Return-path'];
					}
arildb's avatar
arildb committed
364
					$fromEmail = $aux["From"];
pkdille's avatar
pkdille committed
365 366
					$fromEmail = str_replace('<', '', $fromEmail);
					$fromEmail = str_replace('>', '', $fromEmail);
arildb's avatar
arildb committed
367

changi67's avatar
changi67 committed
368

changi67's avatar
changi67 committed
369 370 371
					preg_match('/<?([-!#$%&\'*+\.\/0-9=?A-Z^_`a-z{|}~][email protected][-!#$%&\'*+\/0-9=?A-Z^_`a-z{|}~]+\.[-!#$%&\'*+\.\/0-9=?A-Z^_`a-z{|}~]+)>?/', $aux["From"], $mail);
					$email_from = $mail[1];
					$aux["msgid"] = $i;
372
					$aux["realmsgid"] = preg_replace('/[<>]/', '', $aux["Message-ID"]);
changi67's avatar
changi67 committed
373
					$message = $pop3->getMsg($i);
374 375
					$mimelib = new mime();
					$output = $mimelib->decode($message);
376

377
					$content.= "<br />Reading a request.<br />From: " . $aux["From"] . "<br />Subject: " . $output['header']['subject'] . "<br />";
changi67's avatar
changi67 committed
378 379 380 381 382
					$content.= "sender email: " . $email_from . "<br />";
					$aux["sender"]["user"] = $userlib->get_user_by_email($email_from);
					$content.= "sender user: " . $aux["sender"]["user"] . "<br />";
					$cantUseMailIn = $acc["anonymous"] == 'n' && empty($aux["sender"]["user"]);
					if ($cantUseMailIn) {
arildb's avatar
arildb committed
383 384 385 386
						$errorMsg = "Anonymous user access denied, sending auto-reply to email address:&nbsp;" . $fromEmail . "<br />";
						$logslib->add_log('mailin', mailin_preplog($errorMsg), $logUser);

						$content.= $errorMsg;
changi67's avatar
changi67 committed
387 388 389 390 391
						$mail = new TikiMail();
						$mail->setFrom($acc["account"]);
						$l = $prefs['language'];
						$mail->setSubject(tra('Tiki mail-in auto-reply', $l));
						$mail->setText(tra("Sorry, you can't use this feature.", $l));
392 393 394 395 396 397
						if ($acc['respond_email'] === 'y') {
							$res = $mail->send(array($email_from), 'mail');
							$content.= "Response sent<br />";
						} else {
							$content.= "Response by email is disabled<br />";
						}
changi67's avatar
changi67 committed
398
					} else {
changi67's avatar
changi67 committed
399

400
						$processEmail = true;
changi67's avatar
changi67 committed
401

402
						// Validate user's send permission
403 404
						$chkUser = $aux["sender"]["user"];
						if (($acc["anonymous"] == 'n') && (!$userlib->user_has_permission($chkUser, 'tiki_p_admin'))) {
405

406
							if (!$userlib->user_has_permission($chkUser, 'tiki_p_send_mailin')) {
arildb's avatar
arildb committed
407 408
								$errorMsg = "Access denied, sending auto-reply to email address:&nbsp;" . $fromEmail . "<br />";
								$logslib->add_log('mailin', mailin_preplog($errorMsg), $logUser);
changi67's avatar
changi67 committed
409

arildb's avatar
arildb committed
410
								$content.= $errorMsg;
411 412 413 414 415 416 417 418 419 420
								$mail = new TikiMail();
								$mail->setFrom($acc["account"]);
								$l = $prefs['language'];
								$mail->setSubject(tra('Tiki mail-in auto-reply', $l));
								$mail->setText(tra("Sorry, you can't use this feature.", $l));
								if ($acc['respond_email'] === 'y') {
									$res = $mail->send(array($email_from), 'mail');
									$content.= "Response sent<br />";
								} else {
									$content.= "Response by email is disabled<br />";
changi67's avatar
changi67 committed
421
								}
422
								$processEmail = false;
changi67's avatar
changi67 committed
423
							}
changi67's avatar
changi67 committed
424
						}
425
						if (($acc["admin"] === 'n') && ($userlib->user_has_permission($chkUser, 'tiki_p_admin'))) {
arildb's avatar
arildb committed
426 427
								$errorMsg = "Admin access is blocked, sending auto-reply to email address:&nbsp;" . $fromEmail . "<br />";
								$logslib->add_log('mailin', mailin_preplog($errorMsg), $logUser);
changi67's avatar
changi67 committed
428

arildb's avatar
arildb committed
429
								$content.= $errorMsg;
430 431 432 433 434 435 436 437 438 439 440 441 442
								$mail = new TikiMail();
								$mail->setFrom($acc["account"]);
								$l = $prefs['language'];
								$mail->setSubject(tra('Tiki mail-in auto-reply', $l));
								$mail->setText(tra("Sorry, you can't use this feature.", $l));
								if ($acc['respond_email'] === 'y') {
									$res = $mail->send(array($email_from), 'mail');
									$content.= "Response sent<br />";
								} else {
									$content.= "Response by email is disabled<br />";
								}
								$processEmail = false;
						}
changi67's avatar
changi67 committed
443

444
						if ($processEmail) {
changi67's avatar
changi67 committed
445

446 447 448 449 450
							if (empty($aux["sender"]["user"])) {
								$aux["sender"]["user"] = $email_from;
							}
							if (empty($aux["sender"]["name"])) {
								$aux["sender"]["name"] = $email_from;
451
							}
changi67's avatar
changi67 committed
452

453
							if ($prefs['feature_articles'] && $acc['type'] == 'article-put') {
454 455 456
								//////////////
								//	article-put
								//////////////////////////////////////////////////////////////////////////////////
457

458 459
								$title = trim($output['header']['subject']);
								$topicId = isset($acc['article_topicId']) ? $acc['article_topicId'] : 0;
460
								$chkUser = $aux["sender"]["user"];
461
								if (($acc["anonymous"] == 'n') && (!$userlib->user_has_permission($chkUser, 'tiki_p_admin'))) {
462
									if (!$wikilib->user_has_perm_on_object($chkUser, $topicId, 'topic', 'tiki_p_submit_article', 'tiki_p_edit_submission')) {
arildb's avatar
arildb committed
463 464
										$errorMsg = $chkUser." cannot submit the article: ".$title."<br />";
										$logslib->add_log('mailin', mailin_preplog($errorMsg), $logUser);
changi67's avatar
changi67 committed
465

arildb's avatar
arildb committed
466
										$content.= $errorMsg;
467
										$processEmail = false;
468 469
									} if ($tiki_p_autoapprove_submission == 'y') {
										if (!$wikilib->user_has_perm_on_object($chkUser, $topicId, 'topic', 'tiki_p_autoapprove_submission)')) {
arildb's avatar
arildb committed
470 471
											$errorMsg = $chkUser." cannot auto-approve the article: ".$title."<br />";
											$logslib->add_log('mailin', mailin_preplog($errorMsg), $logUser);
changi67's avatar
changi67 committed
472

arildb's avatar
arildb committed
473
											$content.= $errorMsg;
474 475
											$processEmail = false;
										}
476
									}
477
								}
478
								if ($processEmail) {
changi67's avatar
changi67 committed
479

480 481 482
									// This is used to CREATE articles
									$title = trim($output['header']['subject']);
									$msgbody = mailin_get_body($output);
483
									if ($msgbody && !empty($acc['discard_after'])) {
484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517
										$msgbody = preg_replace("/" . $acc['discard_after'] . ".*$/s", "", $msgbody);
									}
									$heading = $msgbody;
									$topicId = isset($acc['article_topicId']) ? $acc['article_topicId'] : 0;
									$userm = $aux['sender']['user'];
									$authorName = $userm;
									$body = '';
									$publishDate = $tikilib->now;
									$cur_time = explode(',', $tikilib->date_format('%Y,%m,%d,%H,%M,%S', $publishDate));
									$expireDate = $tikilib->make_time($cur_time[3], $cur_time[4], $cur_time[5], $cur_time[1], $cur_time[2], $cur_time[0] + 1);
									$subId = 0;
									$type = $acc['article_type'];
									$useImage = 'n';
									$image_x = '';
									$image_y = '';
									$imgname = '';
									$imgsize = '';
									$imgtype = '';
									$imgdata = '';
									$topline = '';
									$subtitle = '';
									$linkto = '';
									$image_caption = '';
									$lang = '';
									$rating = 7;
									$isfloat = 'n';
									global $artlib;
									if (!is_object($artlib)) {
										include_once ('lib/articles/artlib.php');
									}
									$subid = $artlib->replace_submission($title, $authorName, $topicId, $useImage, $imgname, $imgsize, $imgtype, $imgdata, $heading, $body, $publishDate, $expireDate, $userm, $subId, $image_x, $image_y, $type, $topline, $subtitle, $linkto, $image_caption, $lang, $rating, $isfloat);
									global $tiki_p_autoapprove_submission;
									if ($tiki_p_autoapprove_submission == 'y') {
										$artlib->approve_submission($subid);
arildb's avatar
arildb committed
518 519
										$errorMsg = "Article: $title has been submitted by email: " . $fromEmail . "<br />";
										$logslib->add_log('mailin', mailin_preplog($errorMsg), $logUser);
changi67's avatar
changi67 committed
520

arildb's avatar
arildb committed
521
										$content.= $errorMsg;
522
									} else {
arildb's avatar
arildb committed
523 524
										$errorMsg = "Article: $title has been created by email: " . $fromEmail . "<br />";
										$logslib->add_log('mailin', mailin_preplog($errorMsg), $logUser);
changi67's avatar
changi67 committed
525

arildb's avatar
arildb committed
526
										$content.= $errorMsg;
527
									}
528
									$hasError = false;
529 530 531 532 533 534 535 536
								}
							} else { //else if ($acc['type'] == 'article-put')
								if ($acc['type'] == 'wiki') {
									$p_page = trim($aux['Subject']);
									$parts = explode(':', $p_page);
									if (!isset($parts[1])) {
										$parts[1] = $parts[0];
										$parts[0] = 'GET';
537
									}
538 539
									$method = $parts[0];
									$page = $parts[1];
changi67's avatar
changi67 committed
540
								} else {
541
									$page = trim($aux['Subject']);
changi67's avatar
changi67 committed
542
								}
changi67's avatar
changi67 committed
543 544

								// Strip invalid characters from the page name
545
								$wikilib = TikiLib::lib('wiki');
pkdille's avatar
pkdille committed
546
								if ($wikilib->contains_badchars($page)) {
547
									$badChars = $wikilib->get_badchars();
changi67's avatar
changi67 committed
548

549
									// Replace bad characters with a '_'
changi67's avatar
changi67 committed
550 551
									$iStrlenBadChars = strlen($badChars);
									for ($j = 0; $j < $iStrlenBadChars; $j++) {
552 553
										$char = $badChars[$j];
										$page = str_replace($char, "_", $page);
554
									}
555
								}
changi67's avatar
changi67 committed
556

557
								if ($acc['type'] == 'wiki-get' || ($acc['type'] == 'wiki' && $method == "GET")) {
558 559 560
									//////////////
									//	wiki-get, wiki GET: Get a new wiki page. System emails page to user
									//////////////////////////////////////////////////////////////////////////////////
561 562 563 564 565
									// A wiki-get account sends a copy of the page to the sender
									// and also sends the source of the page
									$mail = new TikiMail();
									$mail->setFrom($acc["account"]);
									if ($tikilib->page_exists($page)) {
changi67's avatar
changi67 committed
566

567 568
										// Check permissions
										$chkUser = $aux["sender"]["user"];
569
										if (($acc["anonymous"] == 'n') && (!$userlib->user_has_permission($chkUser, 'tiki_p_admin'))) {
pkdille's avatar
pkdille committed
570
											if (!$wikilib->user_has_perm_on_object($chkUser, $page, 'wiki page', 'tiki_p_view')) {
arildb's avatar
arildb committed
571 572
												$errorMsg = $chkUser." cannot view the page: ".$page."<br />";
												$logslib->add_log('mailin', mailin_preplog($errorMsg), $logUser);
changi67's avatar
changi67 committed
573

arildb's avatar
arildb committed
574
												$content.= $errorMsg;
575 576
												$processEmail = false;
											}
577
										}
578 579 580 581 582 583 584
										if ($processEmail) {
											$mail->setSubject($page);
											$info = $tikilib->get_page_info($page);
											$data = $tikilib->parse_data($info["data"]);
											$mail->addAttachment($info['data'], 'source.txt', 'plain/txt');
											$mail->setHTML($data, strip_tags($data));
										}
585 586 587 588
									} else {
										$l = $prefs['language'];
										$mail_data = $smarty->fetchLang($l, "mail/mailin_reply_subject.tpl");
										$mail->setSubject($mail_data . $page);
589
									}
590 591 592 593 594
									if ($processEmail) {
										$res = $mail->send(array($email_from), 'mail');
										$content.= "Response sent<br />";
										$hasError = false;
									}
595

596
								} elseif ($acc['type'] == 'wiki-put' || ($acc['type'] == 'wiki' && $method == "PUT")) {
597 598 599
									//////////////
									//	wiki-put, wiki PUT: Send a wiki page. User emails page to System
									//////////////////////////////////////////////////////////////////////////////////
changi67's avatar
changi67 committed
600

601 602 603 604 605 606 607 608
									// This is used to Create/Update wiki pages
									$chkUser = $aux["sender"]["user"];

									// Attempt to use HTML, if it exists
									$body = mailin_get_html($output);
									if (empty($body)) {
										$body = mailin_get_body($output);
									}
changi67's avatar
changi67 committed
609

610
									// Load user routing
611 612 613 614 615 616 617
									$route = array();
									if ($acc['routing'] === 'y') {
										$routes = $usermailinlib->locate_struct($chkUser, $aux['Subject'], $body);
										if (!empty($routes['data'])) {
											$content.= "User route from pattern: '".$routes['data'][0]['subj_pattern']."' / '".$routes['data'][0]['body_pattern']."'<br />";
											$route = $routes['data'][0];	// Only use the first route
										}
618 619
									}

620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637
									// Add namespace, if specified.
									// If no explicit namespace is specified, pages routed to structured may inherit, the structure namespace
									if ($prefs['namespace_enabled'] === 'y') {
										$nsName = trim($acc['namespace']);
										$ns = $prefs['namespace_separator'];
										if (!empty($nsName)) {
											// Use mail-in specified namespace
											if (!empty($ns)) {
												$page = $nsName.$ns.$page;
											}
										} elseif (!empty($route)) {
											// Inherit structure namespace
											$wikilib = TikiLib::lib('wiki');
											$nsName = $wikilib->get_namespace($route['structName']);
											if (!empty($nsName)) {
												if (!empty($ns)) {
													$page = $nsName.$ns.$page;
												}
changi67's avatar
changi67 committed
638
											}
639 640 641 642
										}
									}


643 644
									// Check permissions
									if (($acc["anonymous"] == 'n') && (!$userlib->user_has_permission($chkUser, 'tiki_p_admin'))) {
645
										if ($tikilib->page_exists($page)) {
646
											// Check permissions for page
647
											if (!$wikilib->user_has_perm_on_object($chkUser, $page, 'wiki page', 'tiki_p_edit')) {
arildb's avatar
arildb committed
648 649
												$errorMsg = $chkUser." cannot edit the page: ".$page."<br />";
												$logslib->add_log('mailin', mailin_preplog($errorMsg), $logUser);
changi67's avatar
changi67 committed
650

arildb's avatar
arildb committed
651
												$content.= $errorMsg;
652 653
												$processEmail = false;
											}
654
											if (!$wikilib->user_has_perm_on_object($chkUser, $page, 'wiki page', 'tiki_p_wiki_attach_files')) {
655 656 657 658
												$can_addAttachment = 'n';
												$show_inlineImages = 'n';
											}
										} else {
659

660
											$userlib = TikiLib::lib('user');
changi67's avatar
changi67 committed
661

662 663 664
											// Check the edit structure permissions on the target structure category, if defined for the routed structure
											$structCateg = array();
											if (!empty($route)) {
pkdille's avatar
pkdille committed
665
												if ($prefs['feature_categories'] === 'y') {
changi67's avatar
changi67 committed
666

667 668 669 670 671 672 673 674 675 676 677 678 679
													$structName = $route['structName'];
													$categlib = TikiLib::lib('categ');
													$categParent = $categlib->get_object_categories('wiki page', $structName, -1, false);
													$catPermOK = false;
													foreach ($categParent as $c) {
														$categoryId = $c['categoryId'];
														if ($userlib->object_has_permission($chkUser, $categoryId, 'category', 'tiki_p_edit_structures')) {
															$catPermOK = true;
														}
														$structCateg[] = $categoryId;
													}
													if ($catPermOK == false) {
														$content.= $chkUser." cannot edit structure: ".$page."<br />";
680 681
														$processEmail = false;
													}
682 683
												} else {
													// Check global permissions
684
													if (!$userlib->user_has_permission($chkUser, 'tiki_p_edit_structures')) {
685
														$content.= $chkUser." cannot edit structure: ".$page."<br />";
686 687 688
														$processEmail = false;
													}
												}
689
											}
690

changi67's avatar
changi67 committed
691

692 693 694 695 696
											// Check category permission, if auto-assigning a category.
											// Otherwise checkglobal permissions
											if ($processEmail) {
												if ($prefs['feature_categories'] === 'y' && isset($acc['categoryId'])) {
													if (!$userlib->object_has_permission($chkUser, $acc['categoryId'], 'category', 'tiki_p_edit')) {
arildb's avatar
arildb committed
697 698
														$errorMsg = $chkUser." cannot create the page: ".$page."<br />";
														$logslib->add_log('mailin', mailin_preplog($errorMsg), $logUser);
changi67's avatar
changi67 committed
699

arildb's avatar
arildb committed
700
														$content.= $errorMsg;
701 702 703 704 705 706 707 708
														$processEmail = false;
													}
													if (!$userlib->object_has_permission($chkUser, $acc['categoryId'], 'category', 'tiki_p_wiki_attach_files')) {
														$can_addAttachment = 'n';
														$show_inlineImages = 'n';
													}
												} else {
													if (!$userlib->user_has_permission($chkUser, 'tiki_p_edit')) {
arildb's avatar
arildb committed
709 710
														$errorMsg = $chkUser." cannot create the page: ".$page."<br />";
														$logslib->add_log('mailin', mailin_preplog($errorMsg), $logUser);
changi67's avatar
changi67 committed
711

arildb's avatar
arildb committed
712
														$content.= $errorMsg;
713 714 715 716 717
														$processEmail = false;
													}
													if (!$userlib->user_has_permission($chkUser, 'tiki_p_wiki_attach_files')) {
														$can_addAttachment = 'n';
														$show_inlineImages = 'n';
718
													}
719
												}
720 721
											}
										}
722 723
									}
									if ($processEmail) {
724

725 726
										if (!empty($acc['discard_after']) && $body) {
											$body = preg_replace("/" . $acc['discard_after'] . ".*$/s", "", $body);
727
										}
728 729 730 731 732
										if (!empty($body)) {
											if ($prefs['feature_wiki_attachments'] === 'y') {
												mailin_extract_inline_images($page, $output, $body, $content, $aux["sender"]["user"]);
												mailin_check_attachments($output, $content, $page, $aux["sender"]["user"], $body);
											}
733 734 735 736

											$parsed_data = mailin_parse_body($body, $acc);
											$body = $parsed_data['body'];

737
											if (!$tikilib->page_exists($page)) {
738

739 740 741
												// Check User structure routing
												if (!empty($route)) {
													// Structure routing is active. Create a structure node/page
changi67's avatar
changi67 committed
742

743
													// Use the page structure node, if specified, otherwise link to the rrot of the structure
pkdille's avatar
pkdille committed
744
													if ($route['page_id'] > 0) {
745 746
														$parent_id = $route['page_struct_refid'];	// page_ref_id
													} else {
changi67's avatar
changi67 committed
747
														$parent_id = $route['page_ref_id'];
748
													}
changi67's avatar
changi67 committed
749

750 751
													$structure_id = $route['structure_id'];
													$begin = true;
changi67's avatar
changi67 committed
752

753 754 755
													$after_ref_id = null;
													$alias='';
													$options = array();
changi67's avatar
changi67 committed
756

757
													$options['hide_toc'] = 'y';
758
													$options['creator'] = $aux["sender"]["user"];
759 760
													$options['creator_msg'] = tra('created from mail-in');
													$options['ip_source'] = '0.0.0.0';
changi67's avatar
changi67 committed
761

762 763 764 765
													$structlib = TikiLib::lib('struct');
													$structlib->s_create_page($parent_id, $after_ref_id, $page, $alias, $structure_id, $options);
													$content.= "Page: $page has been added to structureId: ".$structure_id."<br />";

pkdille's avatar
pkdille committed
766
													$tikilib->update_page(
changi67's avatar
changi67 committed
767 768 769 770 771 772 773 774 775 776 777 778
														$page,
														$body,
														"Updated from " . $acc["account"],
														$aux["sender"]["user"],
														$options['ip_source'],
														'', //desc
														0, //edit_minor
														'', //lang
														$parsed_data['is_html'], //is_html
														'', //hash
														null, //saveLastModif
														$parsed_data['wysiwyg']	//wysiwyg
779
													);
arildb's avatar
arildb committed
780 781
													$errorMsg = "Page: $page has been updated by email: " . $fromEmail . "<br />";
													$logslib->add_log('mailin', mailin_preplog($errorMsg), $logUser);
changi67's avatar
changi67 committed
782

arildb's avatar
arildb committed
783
													$content.= $errorMsg;
784
													$hasError = false;
785
												} else {
changi67's avatar
changi67 committed
786

787
													// Create a regular page
pkdille's avatar
pkdille committed
788
													$tikilib->create_page(
changi67's avatar
changi67 committed
789 790 791 792 793 794 795 796 797 798 799 800
														$page,
														0,
														$body,
														$tikilib->now,
														"Created from " . $acc["account"],
														$aux["sender"]["user"],
														'0.0.0.0',
														'', //description
														'', //lang
														$parsed_data['is_html'], //is_html
														'', //hash
														$parsed_data['wysiwyg'] //wysiwyg
pkdille's avatar
pkdille committed
801
													);
arildb's avatar
arildb committed
802 803
													$errorMsg = "Page: $page has been created by email: " . $fromEmail . "<br />";
													$logslib->add_log('mailin', mailin_preplog($errorMsg), $logUser);
changi67's avatar
changi67 committed
804

arildb's avatar
arildb committed
805
													$content.= $errorMsg;
806
													$hasError = false;
807
												}
808

809 810 811
												// Assign category, if specified.
												//	Include the routed structure categories, if defined
												if ($prefs['feature_categories'] === 'y') {
changi67's avatar
changi67 committed
812

813 814 815 816 817 818 819 820 821 822 823 824 825 826 827
													$catList = array_merge($structCateg, array($acc['categoryId']));
													if (!empty($catList)) {
														try {
															foreach ($catList as $c) {
																$categoryId = intval($c);

																// Validate the category before adding it
																$categlib = TikiLib::lib('categ');
																$categories = $categlib->get_category($categoryId);
																if ($categories !== false && !empty($categories)) {
																	$categlib->categorizePage($page, $categoryId, $aux["sender"]["user"]);
																	$content.= "Page: $page categorized. Id: ".$categoryId."<br />";
																} else {
																	$content.= "Page: $page not categorized. Invalid categoryId: ".$categoryId."<br />";
																}
828
															}
829 830
														} catch (Exception $e) {
															$content.= "Failed to categorize page: $page  categoryId: ".$categoryId.". Error: ".$e->getMessage()."<br />";
831
														}
832
													}
833
												}
changi67's avatar
changi67 committed
834

835
											} else {
pkdille's avatar
pkdille committed
836
												$tikilib->update_page(
changi67's avatar
changi67 committed
837 838 839 840 841 842 843 844 845 846 847 848
													$page,
													$body,
													"Updated from " . $acc["account"],
													$aux["sender"]["user"],
													'0.0.0.0',
													'', //desc
													0, //edit_minor
													'', //lang
													$parsed_data['is_html'], //is_html
													'', //hash
													null, //saveLastModif
													$parsed_data['wysiwyg']	//wysiwyg
849
												);
arildb's avatar
arildb committed
850 851
												$errorMsg = "Page: $page has been updated by email: " . $fromEmail . "<br />";
												$logslib->add_log('mailin', mailin_preplog($errorMsg), $logUser);
changi67's avatar
changi67 committed
852

arildb's avatar
arildb committed
853
												$content.= $errorMsg;
854
												$hasError = false;
855 856
											}
										}
changi67's avatar
changi67 committed
857
									}
858
								} elseif ($acc['type'] == 'wiki-append' || $acc['type'] == 'wiki-prepend' || ($acc['type'] == 'wiki' && $method == "APPEND") || ($acc['type'] == 'wiki' && $method == "PREPEND")) {
859 860 861
									//////////////
									//	wiki-append, wiki-prepend, wiki APPEND, wiki PREPEND
									//////////////////////////////////////////////////////////////////////////////////
862

863 864
									// Check permissions
									$chkUser = $aux["sender"]["user"];
865
									if (($acc["anonymous"] == 'n') && (!$userlib->user_has_permission($chkUser, 'tiki_p_admin'))) {
pkdille's avatar
pkdille committed
866
										if (!$wikilib->user_has_perm_on_object($chkUser, $page, 'wiki page', 'tiki_p_edit')) {
arildb's avatar
arildb committed
867 868
											$errorMsg = $chkUser." cannot edit the page: ".$page."<br />";
											$logslib->add_log('mailin', mailin_preplog($errorMsg), $logUser);
changi67's avatar
changi67 committed
869

arildb's avatar
arildb committed
870
											$content.= $errorMsg;
871 872
											$processEmail = false;
										}
pkdille's avatar
pkdille committed
873
										if (!$wikilib->user_has_perm_on_object($chkUser, $page, 'wiki page', 'tiki_p_wiki_attach_files')) {
874 875 876
											$can_addAttachment = 'n';
											$show_inlineImages = 'n';
										}
877
									}
878
									if ($processEmail) {
879

880 881 882 883
										// Attempt to use HTML, if it exists
										$body = mailin_get_html($output);
										if (empty($body)) {
											$body = mailin_get_body($output);
884
										}
885 886 887 888

										if ($body && !empty($acc['discard_after'])) {
											$body = preg_replace("/" . $acc['discard_after'] . ".*$/s", "", $body);
										}
889 890
										$parsed_data = mailin_parse_body($body, $acc);
										$body = $parsed_data['body'];
891 892 893 894 895 896
										if (isset($body)) {
											if ($prefs['feature_wiki_attachments'] === 'y') {
												mailin_extract_inline_images($page, $output, $body, $content, $aux["sender"]["user"]);
												mailin_check_attachments($output, $content, $page, $aux["sender"]["user"], $body);
											}
											if (!$tikilib->page_exists($page)) {
pkdille's avatar
pkdille committed
897
												$tikilib->create_page(
changi67's avatar
changi67 committed
898 899 900 901 902 903 904 905 906 907 908 909
													$page,
													0,
													$body,
													$tikilib->now,
													"Created from " . $acc["account"],
													$aux["sender"]["user"],
													'0.0.0.0',
													'', //description
													'', //lang
													$parsed_data['is_html'], //is_html
													'', //hash
													$parsed_data['wysiwyg']	//wysiwyg
910
												);
arildb's avatar
arildb committed
911 912
												$errorMsg = "Page: $page has been created by email: " . $fromEmail . "<br />";
												$logslib->add_log('mailin', mailin_preplog($errorMsg), $logUser);
changi67's avatar
changi67 committed
913

arildb's avatar
arildb committed
914
												$content.= $errorMsg;
915
												$hasError = false;
916
											} else {
917 918 919 920 921 922
												$info = $tikilib->get_page_info($page);
												if ($acc['type'] == 'wiki-append' || $acc['type'] == 'wiki' && $method == "APPEND") {
													$body = $info['data'] . $body;
												} else {
													$body = $body . $info['data'];
												}
pkdille's avatar
pkdille committed
923
												$tikilib->update_page(
changi67's avatar
changi67 committed
924 925 926 927 928 929 930 931 932 933 934 935
													$page,
													$body,
													"Created from " . $acc["account"],
													$aux["sender"]["user"],
													'0.0.0.0',
													'', //desc
													0, //edit_minor
													'', //lang
													$parsed_data['is_html'], //is_html
													'', //hash
													null, //saveLastModif
													$parsed_data['wysiwyg']	//wysiwyg
936
												);
arildb's avatar
arildb committed
937 938
												$errorMsg = "Page: $page has been updated by email: " . $fromEmail . "<br />";
												$logslib->add_log('mailin', mailin_preplog($errorMsg), $logUser);
changi67's avatar
changi67 committed
939

arildb's avatar
arildb committed
940
												$content.= $errorMsg;
941
												$hasError = false;
942
											}
943 944 945
										}
									}
								} else {
946 947 948
									//////////////
									//	Invalid mail-in type
									//////////////////////////////////////////////////////////////////////////////////
949 950 951 952 953 954 955 956 957 958 959
									$mail = new TikiMail();
									$mail->setFrom($acc["account"]);
									$l = $prefs['language'];
									$mail_data = $smarty->fetchLang($l, "mail/mailin_help_subject.tpl");
									$mail->setSubject($mail_data);
									$smarty->assign('subject', $output['header']['subject']);
									$mail_data = $smarty->fetchLang($l, "mail/mailin_help.tpl");
									$mail->setText($mail_data);
									if ($acc['respond_email'] === 'y') {
										$res = $mail->send(array($email_from), 'mail');
										$content.= "Help response sent<br />";
changi67's avatar
changi67 committed
960
									} else {
961
										$content.= "Response by email is disabled<br />";
changi67's avatar
changi67 committed
962
									}
arildb's avatar
arildb committed
963 964
									$errorMsg = "Invalid mail-in type";
									$logslib->add_log('mailin', mailin_preplog($errorMsg), $logUser);
changi67's avatar
changi67 committed
965 966
								}
							}
changi67's avatar
changi67 committed
967
						}
968
					}
changi67's avatar
changi67 committed
969
					// Remove the email from the pop3 server
970 971
					if (!$hasError || ($hasError && ($acc['leave_email'] !== 'y'))) {
						$pop3->deleteMsg($i);
arildb's avatar
arildb committed
972 973
						$errorMsg = "Deleted message on email server. From: ".$fromEmail." Subject: ".$aux['Subject']."<br />";
						$content.= $errorMsg;
changi67's avatar
changi67 committed
974

arildb's avatar
arildb committed
975 976
						// Cleanup log message and write to log
						$logslib->add_log('mailin', mailin_preplog($errorMsg), $logUser);
977
					}
978 979 980
				}
			}
		}
changi67's avatar
changi67 committed
981 982
	} else {
		$content.= "FAILED.<br />";
983
	}
changi67's avatar
changi67 committed
984
	$pop3->disconnect();
changi67's avatar
changi67 committed
985

986
}