tiki-mailin-code.php 35.6 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;
39 40 41 42 43 44 45 46
	
	if ($can_addAttachment !== 'y') {
		return;
	}
	
	if (!isset($output["parts"])) {
		return;
	}
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++;
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 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
/**
 * @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,
			);
	}
	
	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,
		);
}

function mailin_containsStringHTML($str) 
{
pkdille's avatar
pkdille 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 175
{
	global $wikilib, $is_html, $show_inlineImages, $can_addAttachment;
	
pkdille's avatar
pkdille committed
176
	if ($show_inlineImages !== 'y') {
177 178 179 180 181 182 183 184 185 186 187 188 189 190
		return;
	}
	if ($can_addAttachment !== 'y') {
		return;
	}
	
	$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 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214
		$out.= "inline attachments are only supported for email in html format<br />";
		return;
	}
	
	// Replace the text version, and use use the HTML as the page body
	
	// 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;
	}
	
	// Get rid of "id" attributes, as they may cause a failure to load the image
	$htmlBody = str_ireplace('id=', 'xid=', $htmlBody);
	
	// Assign the HTML as the new body
	$body = $htmlBody;
	$is_html = true;

	// 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 223
	} elseif (isset($output["parts"][1]) && isset($output["parts"][1]['ctype_parameters']['name'])) {
		$activeParts = $output["parts"];
	} 
224 225 226 227 228 229 230 231 232 233 234 235 236
	
	// 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 = "";
			}
			
			// Only process images
pkdille's avatar
pkdille committed
237
			if (strpos($fileType, 'image/', 0) === false) {
238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270
				$errCnt++;
				continue;
			}
			
			// 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++;
		
			$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);
	
	$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) {
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 316
		$can_addAttachment = $acc['attachments'];
	}
	
317 318 319 320
	if (empty($acc['account'])) {
		continue;
	}
	
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...";
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 354
			$hasError = true;
			
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 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 {
399
						
400
						$processEmail = true;
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 409 410
								$errorMsg = "Access denied, sending auto-reply to email address:&nbsp;" . $fromEmail . "<br />";
								$logslib->add_log('mailin', mailin_preplog($errorMsg), $logUser);
								
								$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
							}
424
						} 
425
						if (($acc["admin"] === 'n') && ($userlib->user_has_permission($chkUser, 'tiki_p_admin'))) {
arildb's avatar
arildb committed
426 427 428 429
								$errorMsg = "Admin access is blocked, sending auto-reply to email address:&nbsp;" . $fromEmail . "<br />";
								$logslib->add_log('mailin', mailin_preplog($errorMsg), $logUser);
								
								$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;
						}
443 444
						
						if ($processEmail) {
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 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 465 466
										$errorMsg = $chkUser." cannot submit the article: ".$title."<br />";
										$logslib->add_log('mailin', mailin_preplog($errorMsg), $logUser);
										
										$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 472 473
											$errorMsg = $chkUser." cannot auto-approve the article: ".$title."<br />";
											$logslib->add_log('mailin', mailin_preplog($errorMsg), $logUser);
											
											$content.= $errorMsg;
474 475
											$processEmail = false;
										}
476
									}
477
								}
478 479 480 481 482
								if ($processEmail) {
									
									// 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 520 521
										$errorMsg = "Article: $title has been submitted by email: " . $fromEmail . "<br />";
										$logslib->add_log('mailin', mailin_preplog($errorMsg), $logUser);
										
										$content.= $errorMsg;
522
									} else {
arildb's avatar
arildb committed
523 524 525 526
										$errorMsg = "Article: $title has been created by email: " . $fromEmail . "<br />";
										$logslib->add_log('mailin', mailin_preplog($errorMsg), $logUser);
										
										$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
								}
543
								
544 545
								// Strip invalid characters from the page name 
								$wikilib = TikiLib::lib('wiki');
pkdille's avatar
pkdille committed
546
								if ($wikilib->contains_badchars($page)) {
547 548 549 550 551 552
									$badChars = $wikilib->get_badchars();
									
									// Replace bad characters with a '_'
									for ($j = 0; $j < strlen($badChars); $j++) { 
										$char = $badChars[$j];
										$page = str_replace($char, "_", $page);
553
									}
554 555 556
								}
								
								if ($acc['type'] == 'wiki-get' || ($acc['type'] == 'wiki' && $method == "GET")) {
557 558 559
									//////////////
									//	wiki-get, wiki GET: Get a new wiki page. System emails page to user
									//////////////////////////////////////////////////////////////////////////////////
560 561 562 563 564 565 566 567
									// 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)) {
										
										// Check permissions
										$chkUser = $aux["sender"]["user"];
568
										if (($acc["anonymous"] == 'n') && (!$userlib->user_has_permission($chkUser, 'tiki_p_admin'))) {
pkdille's avatar
pkdille committed
569
											if (!$wikilib->user_has_perm_on_object($chkUser, $page, 'wiki page', 'tiki_p_view')) {
arildb's avatar
arildb committed
570 571 572 573
												$errorMsg = $chkUser." cannot view the page: ".$page."<br />";
												$logslib->add_log('mailin', mailin_preplog($errorMsg), $logUser);
												
												$content.= $errorMsg;
574 575
												$processEmail = false;
											}
576
										}
577 578 579 580 581 582 583
										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));
										}
584 585 586 587
									} else {
										$l = $prefs['language'];
										$mail_data = $smarty->fetchLang($l, "mail/mailin_reply_subject.tpl");
										$mail->setSubject($mail_data . $page);
588
									}
589 590 591 592 593
									if ($processEmail) {
										$res = $mail->send(array($email_from), 'mail');
										$content.= "Response sent<br />";
										$hasError = false;
									}
594

595
								} elseif ($acc['type'] == 'wiki-put' || ($acc['type'] == 'wiki' && $method == "PUT")) {
596 597 598 599 600 601 602 603 604 605 606 607
									//////////////
									//	wiki-put, wiki PUT: Send a wiki page. User emails page to System
									//////////////////////////////////////////////////////////////////////////////////
									
									// 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);
									}
608
									
609
									// Load user routing
610 611 612 613 614 615 616
									$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
										}
617 618
									}

619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641
									// 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;
												}
											}												
										}
									}


642 643
									// Check permissions
									if (($acc["anonymous"] == 'n') && (!$userlib->user_has_permission($chkUser, 'tiki_p_admin'))) {
644
										if ($tikilib->page_exists($page)) {
645
											// Check permissions for page
646
											if (!$wikilib->user_has_perm_on_object($chkUser, $page, 'wiki page', 'tiki_p_edit')) {
arildb's avatar
arildb committed
647 648 649 650
												$errorMsg = $chkUser." cannot edit the page: ".$page."<br />";
												$logslib->add_log('mailin', mailin_preplog($errorMsg), $logUser);
												
												$content.= $errorMsg;
651 652
												$processEmail = false;
											}
653
											if (!$wikilib->user_has_perm_on_object($chkUser, $page, 'wiki page', 'tiki_p_wiki_attach_files')) {
654 655 656 657
												$can_addAttachment = 'n';
												$show_inlineImages = 'n';
											}
										} else {
658

659
											$userlib = TikiLib::lib('user');
660 661 662 663
											
											// 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
664
												if ($prefs['feature_categories'] === 'y') {
665 666 667 668 669 670 671 672 673 674 675 676 677 678
													
													$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 />";
679 680
														$processEmail = false;
													}
681 682
												} else {
													// Check global permissions
683
													if (!$userlib->user_has_permission($chkUser, 'tiki_p_edit_structures')) {
684
														$content.= $chkUser." cannot edit structure: ".$page."<br />";
685 686 687
														$processEmail = false;
													}
												}
688
											}
689

690 691 692 693 694 695
											
											// 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
696 697 698 699
														$errorMsg = $chkUser." cannot create the page: ".$page."<br />";
														$logslib->add_log('mailin', mailin_preplog($errorMsg), $logUser);
														
														$content.= $errorMsg;
700 701 702 703 704 705 706 707
														$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
708 709 710 711
														$errorMsg = $chkUser." cannot create the page: ".$page."<br />";
														$logslib->add_log('mailin', mailin_preplog($errorMsg), $logUser);
														
														$content.= $errorMsg;
712 713 714 715 716
														$processEmail = false;
													}
													if (!$userlib->user_has_permission($chkUser, 'tiki_p_wiki_attach_files')) {
														$can_addAttachment = 'n';
														$show_inlineImages = 'n';
717
													}
718
												}
719 720
											}
										}
721 722
									}
									if ($processEmail) {
723

724 725
										if (!empty($acc['discard_after']) && $body) {
											$body = preg_replace("/" . $acc['discard_after'] . ".*$/s", "", $body);
726
										}
727 728 729 730 731
										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);
											}
732 733 734 735

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

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

738 739 740
												// Check User structure routing
												if (!empty($route)) {
													// Structure routing is active. Create a structure node/page
741 742
													
													// Use the page structure node, if specified, otherwise link to the rrot of the structure
pkdille's avatar
pkdille committed
743
													if ($route['page_id'] > 0) {
744 745 746 747 748
														$parent_id = $route['page_struct_refid'];	// page_ref_id
													} else {
														$parent_id = $route['page_ref_id'];	
													}
													
749 750 751 752 753 754 755 756
													$structure_id = $route['structure_id'];
													$begin = true;
														
													$after_ref_id = null;
													$alias='';
													$options = array();
														
													$options['hide_toc'] = 'y';
757
													$options['creator'] = $aux["sender"]["user"];
758 759 760 761 762 763 764
													$options['creator_msg'] = tra('created from mail-in');
													$options['ip_source'] = '0.0.0.0';
														
													$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
765 766 767 768 769 770 771 772 773 774 775 776 777
													$tikilib->update_page(
																	$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
778
													);
arildb's avatar
arildb committed
779 780 781 782
													$errorMsg = "Page: $page has been updated by email: " . $fromEmail . "<br />";
													$logslib->add_log('mailin', mailin_preplog($errorMsg), $logUser);
													
													$content.= $errorMsg;
783
													$hasError = false;
784 785 786
												} else {
													
													// Create a regular page
pkdille's avatar
pkdille committed
787 788 789 790 791 792 793 794 795 796 797 798 799 800
													$tikilib->create_page(
																	$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
													);
arildb's avatar
arildb committed
801 802 803 804
													$errorMsg = "Page: $page has been created by email: " . $fromEmail . "<br />";
													$logslib->add_log('mailin', mailin_preplog($errorMsg), $logUser);
													
													$content.= $errorMsg;
805
													$hasError = false;
806
												}
807

808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826
												// Assign category, if specified.
												//	Include the routed structure categories, if defined
												if ($prefs['feature_categories'] === 'y') {
													
													$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 />";
																}
827
															}
828 829
														} catch (Exception $e) {
															$content.= "Failed to categorize page: $page  categoryId: ".$categoryId.". Error: ".$e->getMessage()."<br />";
830
														}
831
													}
832
												}
833 834
												
											} else {
pkdille's avatar
pkdille committed
835 836 837 838 839 840 841 842 843 844 845 846 847
												$tikilib->update_page(
																$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
848
												);
arildb's avatar
arildb committed
849 850 851 852
												$errorMsg = "Page: $page has been updated by email: " . $fromEmail . "<br />";
												$logslib->add_log('mailin', mailin_preplog($errorMsg), $logUser);
												
												$content.= $errorMsg;
853
												$hasError = false;
854 855
											}
										}
changi67's avatar
changi67 committed
856
									}
857
								} elseif ($acc['type'] == 'wiki-append' || $acc['type'] == 'wiki-prepend' || ($acc['type'] == 'wiki' && $method == "APPEND") || ($acc['type'] == 'wiki' && $method == "PREPEND")) {
858 859 860
									//////////////
									//	wiki-append, wiki-prepend, wiki APPEND, wiki PREPEND
									//////////////////////////////////////////////////////////////////////////////////
861

862 863
									// Check permissions
									$chkUser = $aux["sender"]["user"];
864
									if (($acc["anonymous"] == 'n') && (!$userlib->user_has_permission($chkUser, 'tiki_p_admin'))) {
pkdille's avatar
pkdille committed
865
										if (!$wikilib->user_has_perm_on_object($chkUser, $page, 'wiki page', 'tiki_p_edit')) {
arildb's avatar
arildb committed
866 867 868 869
											$errorMsg = $chkUser." cannot edit the page: ".$page."<br />";
											$logslib->add_log('mailin', mailin_preplog($errorMsg), $logUser);
											
											$content.= $errorMsg;
870 871
											$processEmail = false;
										}
pkdille's avatar
pkdille committed
872
										if (!$wikilib->user_has_perm_on_object($chkUser, $page, 'wiki page', 'tiki_p_wiki_attach_files')) {
873 874 875
											$can_addAttachment = 'n';
											$show_inlineImages = 'n';
										}
876
									}
877
									if ($processEmail) {
878

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

										if ($body && !empty($acc['discard_after'])) {
											$body = preg_replace("/" . $acc['discard_after'] . ".*$/s", "", $body);
										}
888 889
										$parsed_data = mailin_parse_body($body, $acc);
										$body = $parsed_data['body'];
890 891 892 893 894 895
										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
896 897 898 899 900 901 902 903 904 905 906 907 908
												$tikilib->create_page(
																$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
909
												);
arildb's avatar
arildb committed
910 911 912 913
												$errorMsg = "Page: $page has been created by email: " . $fromEmail . "<br />";
												$logslib->add_log('mailin', mailin_preplog($errorMsg), $logUser);
												
												$content.= $errorMsg;
914
												$hasError = false;
915
											} else {
916 917 918 919 920 921
												$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
922 923 924 925 926 927 928 929 930 931 932 933 934
												$tikilib->update_page(
																$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
935
												);
arildb's avatar
arildb committed
936 937 938 939
												$errorMsg = "Page: $page has been updated by email: " . $fromEmail . "<br />";
												$logslib->add_log('mailin', mailin_preplog($errorMsg), $logUser);
												
												$content.= $errorMsg;
940
												$hasError = false;
941
											}
942 943 944
										}
									}
								} else {
945 946 947
									//////////////
									//	Invalid mail-in type
									//////////////////////////////////////////////////////////////////////////////////
948 949 950 951 952 953 954 955 956 957 958
									$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
959
									} else {
960
										$content.= "Response by email is disabled<br />";
changi67's avatar
changi67 committed
961
									}
arildb's avatar
arildb committed
962 963
									$errorMsg = "Invalid mail-in type";
									$logslib->add_log('mailin', mailin_preplog($errorMsg), $logUser);
changi67's avatar
changi67 committed
964 965
								}
							}
966
						}						
967
					}
changi67's avatar
changi67 committed
968
					// Remove the email from the pop3 server
969 970
					if (!$hasError || ($hasError && ($acc['leave_email'] !== 'y'))) {
						$pop3->deleteMsg($i);
arildb's avatar
arildb committed
971 972 973 974 975
						$errorMsg = "Deleted message on email server. From: ".$fromEmail." Subject: ".$aux['Subject']."<br />";
						$content.= $errorMsg;
	
						// Cleanup log message and write to log
						$logslib->add_log('mailin', mailin_preplog($errorMsg), $logUser);
976
					}
977 978 979
				}
			}
		}
changi67's avatar
changi67 committed
980 981
	} else {
		$content.= "FAILED.<br />";
982
	}
changi67's avatar
changi67 committed
983 984
	$pop3->disconnect();
	
985
}