SproutCMS

This is the code documentation for the SproutCMS project

source of /sprout/Controllers/EmailShareController.php

  1. <?php
  2. /*
  3.  * Copyright (C) 2017 Karmabunny Pty Ltd.
  4.  *
  5.  * This file is a part of SproutCMS.
  6.  *
  7.  * SproutCMS is free software: you can redistribute it and/or modify it under the terms
  8.  * of the GNU General Public License as published by the Free Software Foundation, either
  9.  * version 2 of the License, or (at your option) any later version.
  10.  *
  11.  * For more information, visit <http://getsproutcms.com>.
  12.  */
  13.  
  14. namespace Sprout\Controllers;
  15.  
  16. use Exception;
  17.  
  18. use Kohana;
  19.  
  20. use Sprout\Helpers\Captcha;
  21. use Sprout\Helpers\Csrf;
  22. use Sprout\Helpers\Email;
  23. use Sprout\Helpers\Enc;
  24. use Sprout\Helpers\Notification;
  25. use Sprout\Helpers\RateLimit;
  26. use Sprout\Helpers\Session;
  27. use Sprout\Helpers\Spam;
  28. use Sprout\Helpers\Sprout;
  29. use Sprout\Helpers\Url;
  30. use Sprout\Helpers\Validator;
  31. use Sprout\Helpers\View;
  32.  
  33.  
  34. /**
  35. * - No description yet -
  36. **/
  37. class EmailShareController extends Controller
  38. {
  39.  
  40. /**
  41.   * Constructor
  42.   **/
  43. public function __construct()
  44. {
  45. parent::__construct();
  46. Session::instance();
  47. }
  48.  
  49.  
  50. /**
  51.   * Validate that a given URL is absolute and for this site
  52.   *
  53.   * Allows for subdomains of the current site, so example.com can share a link to app.example.com
  54.   * This is a ends-with chec, so example.com cannot share example.com.au
  55.   *
  56.   * @param string $url
  57.   * @return bool True if valid, false if not
  58.   */
  59. private static function validateUrl($url)
  60. {
  61. $parts = parse_url($url);
  62.  
  63. // Require an absolute url, i.e. has a scheme and a host
  64. if (empty($parts['scheme'])) return false;
  65. if (empty($parts['host'])) return false;
  66.  
  67. // Require the hostname to end in the the server name
  68. $server_name = preg_replace('!^www\.!', '', $_SERVER['SERVER_NAME']);
  69. $length = strlen($server_name);
  70. if (substr($parts['host'], -$length) !== $server_name) {
  71. return false;
  72. }
  73.  
  74. return true;
  75. }
  76.  
  77.  
  78. /**
  79.   * Form to share
  80.   **/
  81. public function share()
  82. {
  83. $data = @$_SESSION['email_share']['field_values'];
  84. if (!$data) $data = [];
  85.  
  86. if (empty($data['url']) and !empty($_GET['url'])) {
  87. if (self::validateUrl($_GET['url'])) {
  88. $data['url'] = $_GET['url'];
  89. } else {
  90. throw new Exception('Invalid URL');
  91. }
  92. }
  93.  
  94. if (empty($data['title'])) {
  95. if (!empty($_GET['title'])) {
  96. $data['title'] = $_GET['title'];
  97. } else if (!empty($data['url'])) {
  98. $data['title'] = $data['url'];
  99. }
  100. }
  101.  
  102. if (empty($data['url'])) {
  103. Notification::error('No URL to share');
  104. Url::redirect('result/error');
  105. }
  106.  
  107. $form = new View('sprout/email_share_form');
  108. $form->data = $data;
  109. if (!empty($_SESSION['email_share']['field_errors'])) {
  110. $form->errors = $_SESSION['email_share']['field_errors'];
  111. } else {
  112. $form->errors = [];
  113. }
  114. if (empty($_SESSION['email_share']['captcha_passed'])) {
  115. $form->use_captcha = true;
  116. }
  117.  
  118. $page_view = new View('skin/inner');
  119. $page_view->page_title = 'Share a page: ' . $data['title'];
  120. $page_view->main_content = $form;
  121. $page_view->controller = 'email_share';
  122.  
  123. echo $page_view->render();
  124. }
  125.  
  126. /**
  127.   * Send a shared email
  128.   **/
  129. public function submit()
  130. {
  131. Csrf::checkOrDie();
  132. Spam::checkOrDie();
  133.  
  134. // Cap submissions (both success and failure)
  135. $result = RateLimit::checkLimitIP('email-share-action', null, 25, 10 * 60);
  136. if ($result === false) {
  137. throw new Exception("Rate limit exceeded: 25 submissions per 10 mins");
  138. }
  139.  
  140. $_POST['title'] = trim(@$_POST['title']);
  141. $_POST['url'] = trim(@$_POST['url']);
  142. $_POST['their_name'] = trim(@$_POST['their_name']);
  143. $_POST['their_email'] = trim(@$_POST['their_email']);
  144. $_POST['message'] = trim(@$_POST['message']);
  145.  
  146. if (!self::validateUrl($_POST['url'])) {
  147. throw new Exception('Invalid URL');
  148. }
  149.  
  150. $_SESSION['email_share']['field_values'] = Validator::trim($_POST);
  151.  
  152. $valid = new Validator($_POST);
  153. $valid->required(['url', 'their_name', 'their_email']);
  154. $valid->check('title', 'Validity::length', 0, 255);
  155. $valid->check('url', 'Validity::length', 0, 255);
  156. $valid->check('their_name', 'Validity::length', 0, 255);
  157. $valid->check('their_email', 'Validity::email');
  158. $valid->check('their_email', 'Validity::length', 0, 255);
  159. $valid->check('message', 'Validity::length', 0, 500);
  160.  
  161. if (empty($_SESSION['email_share']['captcha_passed'])) {
  162. if (Captcha::check()) {
  163. $_SESSION['email_share']['captcha_passed'] = true;
  164. } else {
  165. $valid->addGeneralError('Incorrect CAPTCHA response');
  166. }
  167. }
  168.  
  169. if ($valid->hasErrors()) {
  170. RateLimit::logHitFailure('email-share-action');
  171. $_SESSION['email_share']['field_errors'] = $valid->getFieldErrors();
  172. $valid->createNotifications();
  173. Url::redirect('email_share/share');
  174. }
  175.  
  176.  
  177. $view = new View('sprout/email/email_share');
  178. $view->site_title = Kohana::config('sprout.site_title');
  179. $view->page_title = $_POST['title'];
  180. $view->page_url = $_POST['url'];
  181. $view->their_name = $_POST['their_name'];
  182. $view->message = $_POST['message'];
  183.  
  184. $mail = new Email();
  185. $mail->AddAddress($_POST['their_email']);
  186. $mail->Subject = 'Shared page on ' . $view->site_title;
  187. $mail->SkinnedHTML($view->render());
  188. $mail->Send();
  189.  
  190. RateLimit::logHitSuccess('email-share-action');
  191.  
  192. unset($_SESSION['email_share']);
  193. Notification::confirm('Message sent');
  194. Url::redirect ('email_share/thanks?url=' . Enc::url($_POST['url']));
  195. }
  196.  
  197.  
  198. /**
  199.   * Thank you page
  200.   **/
  201. public function thanks()
  202. {
  203. $match = false;
  204. $siteRoot = substr(Sprout::absRoot(), 0, -1);
  205. if (empty($_GET['url']) or strpos($_GET['url'], $siteRoot) !== 0) {
  206. Notification::error('The URL you provided appears invalid');
  207. Url::redirect ('');
  208. }
  209.  
  210. $form = new View('sprout/email_share_thanks');
  211. $form->url = $_GET['url'];
  212.  
  213. // Prepare the view
  214. $page_view = new View('skin/inner');
  215. $page_view->page_title = 'Share a page';
  216. $page_view->main_content = $form;
  217. $page_view->controller_name = 'email_share';
  218.  
  219. echo $page_view->render();
  220. }
  221.  
  222. }
  223.  
  224.  
  225.