Confirm your account
+click the link below to confirm your account
+ " . $_SERVER['HTTP_HOST'] . "/account_verification.php?email=" . $email . "&token=" . $token . " + "; + $mail->isHTML(true); + if (!$mail->send()) { + #echo "Mailer Error: " . $mail->ErrorInfo; + } + } + + public function sendForgottenPasswordMailTo($email){ + if($this->checkEmailExists($email)){ + $token = $this->createToken(); + $query = mysqli_query($this->conn, "UPDATE users SET forgot_token='$token' WHERE email='$email'"); + $this->sendPasswordForgottenMail($email, $token); + return true; + } + return false; + } + + public function sendPasswordForgottenMail($email, $token){ + $mail = new PHPMailer; + $mail->isSMTP(); + $mail->SMTPDebug = 0; + $mail->Host = 'smtp.gmail.com'; + $mail->Port = 587; + $mail->SMTPSecure = 'tls'; + $mail->SMTPAuth = true; + $mail->Username = "your email id for sending mails"; + $mail->Password = "your password"; + $mail->setFrom('your email id for sending mails', 'ChatBook'); + $mail->addAddress($email); + $mail->Subject = "Reset your ChatBook Account Password"; + $mail->Body = " +Reset Password
+click the link below to reset your password
+ " . $_SERVER['HTTP_HOST'] . "/forgot_password.php?email=" . $email . "&token=" . $token . " + "; + $mail->isHTML(true); + if (!$mail->send()) { + #echo "Mailer Error: " . $mail->ErrorInfo; + } + } + + public function verifyAccount($email, $token){ + $query = mysqli_query($this->conn, "SELECT username FROM users WHERE email='$email' AND deactivate_account=0 AND verification_token='$token'"); + if(mysqli_num_rows($query)==1){ + $row = mysqli_fetch_array($query); + $username = $row['username']; + $query = mysqli_query($this->conn, "UPDATE users SET deactivate_account=1 AND username<>'$username' WHERE email='$email'"); + $query = mysqli_query($this->conn, "UPDATE users SET verification_token=NULL WHERE email='$email'"); + $_SESSION['username'] = $row['username']; + return true; + } else { + return false; + } + } + + public function validateToken($email, $token){ + $email = $this->trimTags($email); + $token = $this->trimTags($token); + $email = filter_var($email, FILTER_SANITIZE_EMAIL); + $query = mysqli_query($this->conn, "SELECT username FROM users WHERE email='$email' AND forgot_token='$token'"); + if(mysqli_num_rows($query)==1){ + $row = mysqli_fetch_array($query); + $this->username = $row['username']; + return true; + } + return false; + } + + public function changePassword($email, $password){ + $email = $this->trimTags($email); + $email = filter_var($email, FILTER_SANITIZE_EMAIL); + $password = md5($password); + $query = mysqli_query($this->conn, "UPDATE users SET password='$password', forgot_token=NULL WHERE email='$email'"); + if($query){ + return true; + } + return false; + } + public function getLogin($email, $password) { $email = filter_var($email, FILTER_SANITIZE_EMAIL); $password = md5($password); - $query = mysqli_query($this->conn, "SELECT * FROM users WHERE email='$email' AND password='$password' AND deactivate_account=0"); + $query = mysqli_query($this->conn, "SELECT * FROM users WHERE email='$email' AND password='$password' AND deactivate_account=0 AND verification_token IS NULL"); if (mysqli_num_rows($query) == 1) { $row = mysqli_fetch_array($query); $this->username = $row['username']; diff --git a/includes/classes/User.php b/includes/classes/User.php index 2c3aa8d..d94f3f8 100644 --- a/includes/classes/User.php +++ b/includes/classes/User.php @@ -27,10 +27,10 @@ class User { wrong addfriend actions getFriendArray() : return user's friend_array getNumOfFriends() : return number of friends - isOnline() : return weather user's is online or not - isClosed() : return weather user's account is closed or not - isFriend($friend_username) : return weather given username is user's friend or not - isUser($username) : return weather given username is a user or not + isOnline() : return wheather user's is online or not + isClosed() : return wheather user's account is closed or not + isFriend($friend_username) : return wheather given username is user's friend or not + isUser($username) : return wheather given username is a user or not addFriend($friend_username) : add friend to user's friend_array and vice-versa removeFriend($friend_username) : remove username of user from friend's friend_array and vice-versa getMutualFriendsCount($friend_username) : return numbers of mutual_friends @@ -48,8 +48,10 @@ class User { setCollege($college) : set user college uploadCoverPic($filepath) : upload cover_pic of user uploadProfilePic($filepath) : upload profile_pic of user + setOnline() : set user online + setOffline() : set user offline closeAccount() : eactivate_account of that user - checkEmailIdExists($email) : check email weather email already in use or not + checkEmailIdExists($email) : check email wheather email already in use or not changeEmail($email) : change email changePassword($old_password, $new_password): change password getNumOfPosts() : return number of posts by the user @@ -103,6 +105,11 @@ public function getFriendArray() { public function getNumOfFriends() { return count($this->getFriendArray())-2; } + public function isOnline() { + if($this->user_details['is_online'] == 0){ return false; } + else { return true; } + } + public function isClosed() { $query = mysqli_query($this->conn, "SELECT deactivate_account FROM users WHERE username='$this->username'"); $row = mysqli_fetch_array($query); @@ -155,14 +162,14 @@ public function getMutualFriendsCount($friend_username) { return $mutual_friends-2; } - public function searchUsers($input_name, $last_username, $limit) { + public function searchUsers($input_name, $limit) { $first_last_name = explode(" ", $input_name); if(strpos($input_name, "_") == true) { - $query = mysqli_query($this->conn, "SELECT * FROM users WHERE username LIKE '%$input_name%' AND deactivate_account=0 LIMIT $limit"); + $query = mysqli_query($this->conn, "SELECT * FROM users WHERE username LIKE '%$input_name%' AND deactivate_account=0 AND verification_token IS NULL LIMIT $limit"); } else if(count($first_last_name) == 2) { - $query = mysqli_query($this->conn, "SELECT * FROM users WHERE (first_name LIKE '%$first_last_name[0]%' AND last_name LIKE '%$first_last_name[1]%') AND deactivate_account=0 LIMIT $limit"); + $query = mysqli_query($this->conn, "SELECT * FROM users WHERE (first_name LIKE '%$first_last_name[0]%' AND last_name LIKE '%$first_last_name[1]%') AND deactivate_account=0 AND verification_token IS NULL LIMIT $limit"); } else { - $query = mysqli_query($this->conn, "SELECT * FROM users WHERE (first_name LIKE '%$first_last_name[0]%' OR last_name LIKE '%$first_last_name[0]%') AND deactivate_account=0 LIMIT $limit"); + $query = mysqli_query($this->conn, "SELECT * FROM users WHERE (first_name LIKE '%$first_last_name[0]%' OR last_name LIKE '%$first_last_name[0]%') AND deactivate_account=0 AND verification_token IS NULL LIMIT $limit"); } return $query; } @@ -193,6 +200,10 @@ public function uploadCoverPic($filepath) { $query = mysqli_query($this->conn, "UPDATE users SET cover_pic='$filepath' WHERE username='$this->username'"); } public function uploadProfilePic($filepath) { $query = mysqli_query($this->conn, "UPDATE users SET profile_pic='$filepath' WHERE username='$this->username'"); } + public function setOnline(){ + $query = mysqli_query($this->conn, "UPDATE users SET is_online=1 WHERE username='$this->username'"); } + public function setOffline(){ + $query = mysqli_query($this->conn, "UPDATE users SET is_online=0 WHERE username='$this->username'"); } public function closeAccount() { $query = mysqli_query($this->conn, "UPDATE users SET deactivate_account=1 WHERE username='$this->username'"); @@ -206,7 +217,7 @@ public function closeAccount() { } public function checkEmailIdExists($email) { - $query = mysqli_query($this->conn, "SELECT email FROM users WHERE email='$email' and deactivate_account=0"); + $query = mysqli_query($this->conn, "SELECT email FROM users WHERE email='$email' and deactivate_account=0 AND verification_token IS NULL"); if (mysqli_num_rows($query) == 1) { return true; } else { return false; } diff --git a/includes/close_session.php b/includes/close_session.php new file mode 100644 index 0000000..83afc0a --- /dev/null +++ b/includes/close_session.php @@ -0,0 +1,13 @@ +setOffline(); + } + } +?> \ No newline at end of file diff --git a/includes/is_online.php b/includes/is_online.php new file mode 100644 index 0000000..b202a79 --- /dev/null +++ b/includes/is_online.php @@ -0,0 +1,8 @@ +isOnline(); + } +?> \ No newline at end of file diff --git a/includes/load_friend_request_count.php b/includes/load_friend_request_count.php index 03540fb..89d6bb2 100644 --- a/includes/load_friend_request_count.php +++ b/includes/load_friend_request_count.php @@ -1,14 +1,16 @@ window.location = 'index.php';"; - } - $request = new FriendRequest($conn, $_SESSION['username']); - $count = $request->getFriendRequestsCount(); - if($count > 99){ - echo "99+"; - }elseif($count != 0){ - echo $count; + include 'session_isalive.php'; + try{ + $request = new FriendRequest($conn, $_SESSION['username']); + $count = $request->getFriendRequestsCount(); + if($count > 99){ + echo "99+"; + }elseif($count != 0){ + echo $count; + } + }catch(Exception $e){ + // do nothing on session out } ?> \ No newline at end of file diff --git a/includes/load_new_messages.php b/includes/load_new_messages.php index a6b0ae5..e9ee6ae 100644 --- a/includes/load_new_messages.php +++ b/includes/load_new_messages.php @@ -4,6 +4,7 @@ require 'classes/Message.php'; require '../functions/timeframe_function.php'; require '../functions/text_filter.php'; + require 'session_isalive.php'; $name = $_POST['name']; $fullname = $_POST['fullname']; diff --git a/includes/load_new_notifications_count.php b/includes/load_new_notifications_count.php index bdcb76a..6fdd73f 100644 --- a/includes/load_new_notifications_count.php +++ b/includes/load_new_notifications_count.php @@ -1,11 +1,15 @@ getUnreadNotificationsCount(); - if($count > 99){ - echo "99+"; - }elseif($count != 0){ - echo $count; + try{ + $notification = new Notification($conn, $_SESSION['username']); + $count = $notification->getUnreadNotificationsCount(); + if($count > 99){ + echo "99+"; + }elseif($count != 0){ + echo $count; + } + }catch(Exception $e){ + // do nothing on session out } ?> \ No newline at end of file diff --git a/includes/load_posts.php b/includes/load_posts.php index 2849e8c..9c32525 100644 --- a/includes/load_posts.php +++ b/includes/load_posts.php @@ -79,12 +79,12 @@
and must not be empty
+ * will look for an image file in $basedir/images/a.png and convert it to inline.
+ * If you don't provide a $basedir, relative paths will be left untouched (and thus probably break in email)
+ * Converts data-uri images into embedded attachments.
+ * If you don't want to apply these transformations to your HTML, just set Body and AltBody directly.
+ *
+ * @param string $message HTML message string
+ * @param string $basedir Absolute path to a base directory to prepend to relative paths to images
+ * @param bool|callable $advanced Whether to use the internal HTML to text converter
+ * or your own custom converter @see PHPMailer::html2text()
+ *
+ * @return string $message The transformed message Body
+ */
+ public function msgHTML($message, $basedir = '', $advanced = false)
+ {
+ preg_match_all('/(src|background)=["\'](.*)["\']/Ui', $message, $images);
+ if (array_key_exists(2, $images)) {
+ if (strlen($basedir) > 1 && '/' != substr($basedir, -1)) {
+ // Ensure $basedir has a trailing /
+ $basedir .= '/';
+ }
+ foreach ($images[2] as $imgindex => $url) {
+ // Convert data URIs into embedded images
+ //e.g. "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="
+ if (preg_match('#^data:(image/(?:jpe?g|gif|png));?(base64)?,(.+)#', $url, $match)) {
+ if (count($match) == 4 and static::ENCODING_BASE64 == $match[2]) {
+ $data = base64_decode($match[3]);
+ } elseif ('' == $match[2]) {
+ $data = rawurldecode($match[3]);
+ } else {
+ //Not recognised so leave it alone
+ continue;
+ }
+ //Hash the decoded data, not the URL so that the same data-URI image used in multiple places
+ //will only be embedded once, even if it used a different encoding
+ $cid = hash('sha256', $data) . '@phpmailer.0'; // RFC2392 S 2
+
+ if (!$this->cidExists($cid)) {
+ $this->addStringEmbeddedImage($data, $cid, 'embed' . $imgindex, static::ENCODING_BASE64, $match[1]);
+ }
+ $message = str_replace(
+ $images[0][$imgindex],
+ $images[1][$imgindex] . '="cid:' . $cid . '"',
+ $message
+ );
+ continue;
+ }
+ if (// Only process relative URLs if a basedir is provided (i.e. no absolute local paths)
+ !empty($basedir)
+ // Ignore URLs containing parent dir traversal (..)
+ and (strpos($url, '..') === false)
+ // Do not change urls that are already inline images
+ and 0 !== strpos($url, 'cid:')
+ // Do not change absolute URLs, including anonymous protocol
+ and !preg_match('#^[a-z][a-z0-9+.-]*:?//#i', $url)
+ ) {
+ $filename = basename($url);
+ $directory = dirname($url);
+ if ('.' == $directory) {
+ $directory = '';
+ }
+ $cid = hash('sha256', $url) . '@phpmailer.0'; // RFC2392 S 2
+ if (strlen($basedir) > 1 and '/' != substr($basedir, -1)) {
+ $basedir .= '/';
+ }
+ if (strlen($directory) > 1 and '/' != substr($directory, -1)) {
+ $directory .= '/';
+ }
+ if ($this->addEmbeddedImage(
+ $basedir . $directory . $filename,
+ $cid,
+ $filename,
+ static::ENCODING_BASE64,
+ static::_mime_types((string) static::mb_pathinfo($filename, PATHINFO_EXTENSION))
+ )
+ ) {
+ $message = preg_replace(
+ '/' . $images[1][$imgindex] . '=["\']' . preg_quote($url, '/') . '["\']/Ui',
+ $images[1][$imgindex] . '="cid:' . $cid . '"',
+ $message
+ );
+ }
+ }
+ }
+ }
+ $this->isHTML(true);
+ // Convert all message body line breaks to LE, makes quoted-printable encoding work much better
+ $this->Body = static::normalizeBreaks($message);
+ $this->AltBody = static::normalizeBreaks($this->html2text($message, $advanced));
+ if (!$this->alternativeExists()) {
+ $this->AltBody = 'This is an HTML-only message. To view it, activate HTML in your email application.'
+ . static::$LE;
+ }
+
+ return $this->Body;
+ }
+
+ /**
+ * Convert an HTML string into plain text.
+ * This is used by msgHTML().
+ * Note - older versions of this function used a bundled advanced converter
+ * which was removed for license reasons in #232.
+ * Example usage:
+ *
+ * ```php
+ * // Use default conversion
+ * $plain = $mail->html2text($html);
+ * // Use your own custom converter
+ * $plain = $mail->html2text($html, function($html) {
+ * $converter = new MyHtml2text($html);
+ * return $converter->get_text();
+ * });
+ * ```
+ *
+ * @param string $html The HTML text to convert
+ * @param bool|callable $advanced Any boolean value to use the internal converter,
+ * or provide your own callable for custom conversion
+ *
+ * @return string
+ */
+ public function html2text($html, $advanced = false)
+ {
+ if (is_callable($advanced)) {
+ return call_user_func($advanced, $html);
+ }
+
+ return html_entity_decode(
+ trim(strip_tags(preg_replace('/<(head|title|style|script)[^>]*>.*?<\/\\1>/si', '', $html))),
+ ENT_QUOTES,
+ $this->CharSet
+ );
+ }
+
+ /**
+ * Get the MIME type for a file extension.
+ *
+ * @param string $ext File extension
+ *
+ * @return string MIME type of file
+ */
+ public static function _mime_types($ext = '')
+ {
+ $mimes = [
+ 'xl' => 'application/excel',
+ 'js' => 'application/javascript',
+ 'hqx' => 'application/mac-binhex40',
+ 'cpt' => 'application/mac-compactpro',
+ 'bin' => 'application/macbinary',
+ 'doc' => 'application/msword',
+ 'word' => 'application/msword',
+ 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
+ 'xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template',
+ 'potx' => 'application/vnd.openxmlformats-officedocument.presentationml.template',
+ 'ppsx' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow',
+ 'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
+ 'sldx' => 'application/vnd.openxmlformats-officedocument.presentationml.slide',
+ 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
+ 'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template',
+ 'xlam' => 'application/vnd.ms-excel.addin.macroEnabled.12',
+ 'xlsb' => 'application/vnd.ms-excel.sheet.binary.macroEnabled.12',
+ 'class' => 'application/octet-stream',
+ 'dll' => 'application/octet-stream',
+ 'dms' => 'application/octet-stream',
+ 'exe' => 'application/octet-stream',
+ 'lha' => 'application/octet-stream',
+ 'lzh' => 'application/octet-stream',
+ 'psd' => 'application/octet-stream',
+ 'sea' => 'application/octet-stream',
+ 'so' => 'application/octet-stream',
+ 'oda' => 'application/oda',
+ 'pdf' => 'application/pdf',
+ 'ai' => 'application/postscript',
+ 'eps' => 'application/postscript',
+ 'ps' => 'application/postscript',
+ 'smi' => 'application/smil',
+ 'smil' => 'application/smil',
+ 'mif' => 'application/vnd.mif',
+ 'xls' => 'application/vnd.ms-excel',
+ 'ppt' => 'application/vnd.ms-powerpoint',
+ 'wbxml' => 'application/vnd.wap.wbxml',
+ 'wmlc' => 'application/vnd.wap.wmlc',
+ 'dcr' => 'application/x-director',
+ 'dir' => 'application/x-director',
+ 'dxr' => 'application/x-director',
+ 'dvi' => 'application/x-dvi',
+ 'gtar' => 'application/x-gtar',
+ 'php3' => 'application/x-httpd-php',
+ 'php4' => 'application/x-httpd-php',
+ 'php' => 'application/x-httpd-php',
+ 'phtml' => 'application/x-httpd-php',
+ 'phps' => 'application/x-httpd-php-source',
+ 'swf' => 'application/x-shockwave-flash',
+ 'sit' => 'application/x-stuffit',
+ 'tar' => 'application/x-tar',
+ 'tgz' => 'application/x-tar',
+ 'xht' => 'application/xhtml+xml',
+ 'xhtml' => 'application/xhtml+xml',
+ 'zip' => 'application/zip',
+ 'mid' => 'audio/midi',
+ 'midi' => 'audio/midi',
+ 'mp2' => 'audio/mpeg',
+ 'mp3' => 'audio/mpeg',
+ 'm4a' => 'audio/mp4',
+ 'mpga' => 'audio/mpeg',
+ 'aif' => 'audio/x-aiff',
+ 'aifc' => 'audio/x-aiff',
+ 'aiff' => 'audio/x-aiff',
+ 'ram' => 'audio/x-pn-realaudio',
+ 'rm' => 'audio/x-pn-realaudio',
+ 'rpm' => 'audio/x-pn-realaudio-plugin',
+ 'ra' => 'audio/x-realaudio',
+ 'wav' => 'audio/x-wav',
+ 'mka' => 'audio/x-matroska',
+ 'bmp' => 'image/bmp',
+ 'gif' => 'image/gif',
+ 'jpeg' => 'image/jpeg',
+ 'jpe' => 'image/jpeg',
+ 'jpg' => 'image/jpeg',
+ 'png' => 'image/png',
+ 'tiff' => 'image/tiff',
+ 'tif' => 'image/tiff',
+ 'webp' => 'image/webp',
+ 'heif' => 'image/heif',
+ 'heifs' => 'image/heif-sequence',
+ 'heic' => 'image/heic',
+ 'heics' => 'image/heic-sequence',
+ 'eml' => 'message/rfc822',
+ 'css' => 'text/css',
+ 'html' => 'text/html',
+ 'htm' => 'text/html',
+ 'shtml' => 'text/html',
+ 'log' => 'text/plain',
+ 'text' => 'text/plain',
+ 'txt' => 'text/plain',
+ 'rtx' => 'text/richtext',
+ 'rtf' => 'text/rtf',
+ 'vcf' => 'text/vcard',
+ 'vcard' => 'text/vcard',
+ 'ics' => 'text/calendar',
+ 'xml' => 'text/xml',
+ 'xsl' => 'text/xml',
+ 'wmv' => 'video/x-ms-wmv',
+ 'mpeg' => 'video/mpeg',
+ 'mpe' => 'video/mpeg',
+ 'mpg' => 'video/mpeg',
+ 'mp4' => 'video/mp4',
+ 'm4v' => 'video/mp4',
+ 'mov' => 'video/quicktime',
+ 'qt' => 'video/quicktime',
+ 'rv' => 'video/vnd.rn-realvideo',
+ 'avi' => 'video/x-msvideo',
+ 'movie' => 'video/x-sgi-movie',
+ 'webm' => 'video/webm',
+ 'mkv' => 'video/x-matroska',
+ ];
+ $ext = strtolower($ext);
+ if (array_key_exists($ext, $mimes)) {
+ return $mimes[$ext];
+ }
+
+ return 'application/octet-stream';
+ }
+
+ /**
+ * Map a file name to a MIME type.
+ * Defaults to 'application/octet-stream', i.e.. arbitrary binary data.
+ *
+ * @param string $filename A file name or full path, does not need to exist as a file
+ *
+ * @return string
+ */
+ public static function filenameToType($filename)
+ {
+ // In case the path is a URL, strip any query string before getting extension
+ $qpos = strpos($filename, '?');
+ if (false !== $qpos) {
+ $filename = substr($filename, 0, $qpos);
+ }
+ $ext = static::mb_pathinfo($filename, PATHINFO_EXTENSION);
+
+ return static::_mime_types($ext);
+ }
+
+ /**
+ * Multi-byte-safe pathinfo replacement.
+ * Drop-in replacement for pathinfo(), but multibyte- and cross-platform-safe.
+ *
+ * @see http://www.php.net/manual/en/function.pathinfo.php#107461
+ *
+ * @param string $path A filename or path, does not need to exist as a file
+ * @param int|string $options Either a PATHINFO_* constant,
+ * or a string name to return only the specified piece
+ *
+ * @return string|array
+ */
+ public static function mb_pathinfo($path, $options = null)
+ {
+ $ret = ['dirname' => '', 'basename' => '', 'extension' => '', 'filename' => ''];
+ $pathinfo = [];
+ if (preg_match('#^(.*?)[\\\\/]*(([^/\\\\]*?)(\.([^\.\\\\/]+?)|))[\\\\/\.]*$#im', $path, $pathinfo)) {
+ if (array_key_exists(1, $pathinfo)) {
+ $ret['dirname'] = $pathinfo[1];
+ }
+ if (array_key_exists(2, $pathinfo)) {
+ $ret['basename'] = $pathinfo[2];
+ }
+ if (array_key_exists(5, $pathinfo)) {
+ $ret['extension'] = $pathinfo[5];
+ }
+ if (array_key_exists(3, $pathinfo)) {
+ $ret['filename'] = $pathinfo[3];
+ }
+ }
+ switch ($options) {
+ case PATHINFO_DIRNAME:
+ case 'dirname':
+ return $ret['dirname'];
+ case PATHINFO_BASENAME:
+ case 'basename':
+ return $ret['basename'];
+ case PATHINFO_EXTENSION:
+ case 'extension':
+ return $ret['extension'];
+ case PATHINFO_FILENAME:
+ case 'filename':
+ return $ret['filename'];
+ default:
+ return $ret;
+ }
+ }
+
+ /**
+ * Set or reset instance properties.
+ * You should avoid this function - it's more verbose, less efficient, more error-prone and
+ * harder to debug than setting properties directly.
+ * Usage Example:
+ * `$mail->set('SMTPSecure', 'tls');`
+ * is the same as:
+ * `$mail->SMTPSecure = 'tls';`.
+ *
+ * @param string $name The property name to set
+ * @param mixed $value The value to set the property to
+ *
+ * @return bool
+ */
+ public function set($name, $value = '')
+ {
+ if (property_exists($this, $name)) {
+ $this->$name = $value;
+
+ return true;
+ }
+ $this->setError($this->lang('variable_set') . $name);
+
+ return false;
+ }
+
+ /**
+ * Strip newlines to prevent header injection.
+ *
+ * @param string $str
+ *
+ * @return string
+ */
+ public function secureHeader($str)
+ {
+ return trim(str_replace(["\r", "\n"], '', $str));
+ }
+
+ /**
+ * Normalize line breaks in a string.
+ * Converts UNIX LF, Mac CR and Windows CRLF line breaks into a single line break format.
+ * Defaults to CRLF (for message bodies) and preserves consecutive breaks.
+ *
+ * @param string $text
+ * @param string $breaktype What kind of line break to use; defaults to static::$LE
+ *
+ * @return string
+ */
+ public static function normalizeBreaks($text, $breaktype = null)
+ {
+ if (null === $breaktype) {
+ $breaktype = static::$LE;
+ }
+ // Normalise to \n
+ $text = str_replace(["\r\n", "\r"], "\n", $text);
+ // Now convert LE as needed
+ if ("\n" !== $breaktype) {
+ $text = str_replace("\n", $breaktype, $text);
+ }
+
+ return $text;
+ }
+
+ /**
+ * Return the current line break format string.
+ *
+ * @return string
+ */
+ public static function getLE()
+ {
+ return static::$LE;
+ }
+
+ /**
+ * Set the line break format string, e.g. "\r\n".
+ *
+ * @param string $le
+ */
+ protected static function setLE($le)
+ {
+ static::$LE = $le;
+ }
+
+ /**
+ * Set the public and private key files and password for S/MIME signing.
+ *
+ * @param string $cert_filename
+ * @param string $key_filename
+ * @param string $key_pass Password for private key
+ * @param string $extracerts_filename Optional path to chain certificate
+ */
+ public function sign($cert_filename, $key_filename, $key_pass, $extracerts_filename = '')
+ {
+ $this->sign_cert_file = $cert_filename;
+ $this->sign_key_file = $key_filename;
+ $this->sign_key_pass = $key_pass;
+ $this->sign_extracerts_file = $extracerts_filename;
+ }
+
+ /**
+ * Quoted-Printable-encode a DKIM header.
+ *
+ * @param string $txt
+ *
+ * @return string
+ */
+ public function DKIM_QP($txt)
+ {
+ $line = '';
+ $len = strlen($txt);
+ for ($i = 0; $i < $len; ++$i) {
+ $ord = ord($txt[$i]);
+ if (((0x21 <= $ord) and ($ord <= 0x3A)) or $ord == 0x3C or ((0x3E <= $ord) and ($ord <= 0x7E))) {
+ $line .= $txt[$i];
+ } else {
+ $line .= '=' . sprintf('%02X', $ord);
+ }
+ }
+
+ return $line;
+ }
+
+ /**
+ * Generate a DKIM signature.
+ *
+ * @param string $signHeader
+ *
+ * @throws Exception
+ *
+ * @return string The DKIM signature value
+ */
+ public function DKIM_Sign($signHeader)
+ {
+ if (!defined('PKCS7_TEXT')) {
+ if ($this->exceptions) {
+ throw new Exception($this->lang('extension_missing') . 'openssl');
+ }
+
+ return '';
+ }
+ $privKeyStr = !empty($this->DKIM_private_string) ?
+ $this->DKIM_private_string :
+ file_get_contents($this->DKIM_private);
+ if ('' != $this->DKIM_passphrase) {
+ $privKey = openssl_pkey_get_private($privKeyStr, $this->DKIM_passphrase);
+ } else {
+ $privKey = openssl_pkey_get_private($privKeyStr);
+ }
+ if (openssl_sign($signHeader, $signature, $privKey, 'sha256WithRSAEncryption')) {
+ openssl_pkey_free($privKey);
+
+ return base64_encode($signature);
+ }
+ openssl_pkey_free($privKey);
+
+ return '';
+ }
+
+ /**
+ * Generate a DKIM canonicalization header.
+ * Uses the 'relaxed' algorithm from RFC6376 section 3.4.2.
+ * Canonicalized headers should *always* use CRLF, regardless of mailer setting.
+ *
+ * @see https://tools.ietf.org/html/rfc6376#section-3.4.2
+ *
+ * @param string $signHeader Header
+ *
+ * @return string
+ */
+ public function DKIM_HeaderC($signHeader)
+ {
+ //Unfold all header continuation lines
+ //Also collapses folded whitespace.
+ //Note PCRE \s is too broad a definition of whitespace; RFC5322 defines it as `[ \t]`
+ //@see https://tools.ietf.org/html/rfc5322#section-2.2
+ //That means this may break if you do something daft like put vertical tabs in your headers.
+ $signHeader = preg_replace('/\r\n[ \t]+/', ' ', $signHeader);
+ $lines = explode("\r\n", $signHeader);
+ foreach ($lines as $key => $line) {
+ //If the header is missing a :, skip it as it's invalid
+ //This is likely to happen because the explode() above will also split
+ //on the trailing LE, leaving an empty line
+ if (strpos($line, ':') === false) {
+ continue;
+ }
+ list($heading, $value) = explode(':', $line, 2);
+ //Lower-case header name
+ $heading = strtolower($heading);
+ //Collapse white space within the value
+ $value = preg_replace('/[ \t]{2,}/', ' ', $value);
+ //RFC6376 is slightly unclear here - it says to delete space at the *end* of each value
+ //But then says to delete space before and after the colon.
+ //Net result is the same as trimming both ends of the value.
+ //by elimination, the same applies to the field name
+ $lines[$key] = trim($heading, " \t") . ':' . trim($value, " \t");
+ }
+
+ return implode("\r\n", $lines);
+ }
+
+ /**
+ * Generate a DKIM canonicalization body.
+ * Uses the 'simple' algorithm from RFC6376 section 3.4.3.
+ * Canonicalized bodies should *always* use CRLF, regardless of mailer setting.
+ *
+ * @see https://tools.ietf.org/html/rfc6376#section-3.4.3
+ *
+ * @param string $body Message Body
+ *
+ * @return string
+ */
+ public function DKIM_BodyC($body)
+ {
+ if (empty($body)) {
+ return "\r\n";
+ }
+ // Normalize line endings to CRLF
+ $body = static::normalizeBreaks($body, "\r\n");
+
+ //Reduce multiple trailing line breaks to a single one
+ return rtrim($body, "\r\n") . "\r\n";
+ }
+
+ /**
+ * Create the DKIM header and body in a new message header.
+ *
+ * @param string $headers_line Header lines
+ * @param string $subject Subject
+ * @param string $body Body
+ *
+ * @return string
+ */
+ public function DKIM_Add($headers_line, $subject, $body)
+ {
+ $DKIMsignatureType = 'rsa-sha256'; // Signature & hash algorithms
+ $DKIMcanonicalization = 'relaxed/simple'; // Canonicalization of header/body
+ $DKIMquery = 'dns/txt'; // Query method
+ $DKIMtime = time(); // Signature Timestamp = seconds since 00:00:00 - Jan 1, 1970 (UTC time zone)
+ $subject_header = "Subject: $subject";
+ $headers = explode(static::$LE, $headers_line);
+ $from_header = '';
+ $to_header = '';
+ $date_header = '';
+ $current = '';
+ $copiedHeaderFields = '';
+ $foundExtraHeaders = [];
+ $extraHeaderKeys = '';
+ $extraHeaderValues = '';
+ $extraCopyHeaderFields = '';
+ foreach ($headers as $header) {
+ if (strpos($header, 'From:') === 0) {
+ $from_header = $header;
+ $current = 'from_header';
+ } elseif (strpos($header, 'To:') === 0) {
+ $to_header = $header;
+ $current = 'to_header';
+ } elseif (strpos($header, 'Date:') === 0) {
+ $date_header = $header;
+ $current = 'date_header';
+ } elseif (!empty($this->DKIM_extraHeaders)) {
+ foreach ($this->DKIM_extraHeaders as $extraHeader) {
+ if (strpos($header, $extraHeader . ':') === 0) {
+ $headerValue = $header;
+ foreach ($this->CustomHeader as $customHeader) {
+ if ($customHeader[0] === $extraHeader) {
+ $headerValue = trim($customHeader[0]) .
+ ': ' .
+ $this->encodeHeader(trim($customHeader[1]));
+ break;
+ }
+ }
+ $foundExtraHeaders[$extraHeader] = $headerValue;
+ $current = '';
+ break;
+ }
+ }
+ } else {
+ if (!empty($$current) and strpos($header, ' =?') === 0) {
+ $$current .= $header;
+ } else {
+ $current = '';
+ }
+ }
+ }
+ foreach ($foundExtraHeaders as $key => $value) {
+ $extraHeaderKeys .= ':' . $key;
+ $extraHeaderValues .= $value . "\r\n";
+ if ($this->DKIM_copyHeaderFields) {
+ $extraCopyHeaderFields .= "\t|" . str_replace('|', '=7C', $this->DKIM_QP($value)) . ";\r\n";
+ }
+ }
+ if ($this->DKIM_copyHeaderFields) {
+ $from = str_replace('|', '=7C', $this->DKIM_QP($from_header));
+ $to = str_replace('|', '=7C', $this->DKIM_QP($to_header));
+ $date = str_replace('|', '=7C', $this->DKIM_QP($date_header));
+ $subject = str_replace('|', '=7C', $this->DKIM_QP($subject_header));
+ $copiedHeaderFields = "\tz=$from\r\n" .
+ "\t|$to\r\n" .
+ "\t|$date\r\n" .
+ "\t|$subject;\r\n" .
+ $extraCopyHeaderFields;
+ }
+ $body = $this->DKIM_BodyC($body);
+ $DKIMlen = strlen($body); // Length of body
+ $DKIMb64 = base64_encode(pack('H*', hash('sha256', $body))); // Base64 of packed binary SHA-256 hash of body
+ if ('' == $this->DKIM_identity) {
+ $ident = '';
+ } else {
+ $ident = ' i=' . $this->DKIM_identity . ';';
+ }
+ $dkimhdrs = 'DKIM-Signature: v=1; a=' .
+ $DKIMsignatureType . '; q=' .
+ $DKIMquery . '; l=' .
+ $DKIMlen . '; s=' .
+ $this->DKIM_selector .
+ ";\r\n" .
+ "\tt=" . $DKIMtime . '; c=' . $DKIMcanonicalization . ";\r\n" .
+ "\th=From:To:Date:Subject" . $extraHeaderKeys . ";\r\n" .
+ "\td=" . $this->DKIM_domain . ';' . $ident . "\r\n" .
+ $copiedHeaderFields .
+ "\tbh=" . $DKIMb64 . ";\r\n" .
+ "\tb=";
+ $toSign = $this->DKIM_HeaderC(
+ $from_header . "\r\n" .
+ $to_header . "\r\n" .
+ $date_header . "\r\n" .
+ $subject_header . "\r\n" .
+ $extraHeaderValues .
+ $dkimhdrs
+ );
+ $signed = $this->DKIM_Sign($toSign);
+
+ return static::normalizeBreaks($dkimhdrs . $signed) . static::$LE;
+ }
+
+ /**
+ * Detect if a string contains a line longer than the maximum line length
+ * allowed by RFC 2822 section 2.1.1.
+ *
+ * @param string $str
+ *
+ * @return bool
+ */
+ public static function hasLineLongerThanMax($str)
+ {
+ return (bool) preg_match('/^(.{' . (self::MAX_LINE_LENGTH + strlen(static::$LE)) . ',})/m', $str);
+ }
+
+ /**
+ * Allows for public read access to 'to' property.
+ * Before the send() call, queued addresses (i.e. with IDN) are not yet included.
+ *
+ * @return array
+ */
+ public function getToAddresses()
+ {
+ return $this->to;
+ }
+
+ /**
+ * Allows for public read access to 'cc' property.
+ * Before the send() call, queued addresses (i.e. with IDN) are not yet included.
+ *
+ * @return array
+ */
+ public function getCcAddresses()
+ {
+ return $this->cc;
+ }
+
+ /**
+ * Allows for public read access to 'bcc' property.
+ * Before the send() call, queued addresses (i.e. with IDN) are not yet included.
+ *
+ * @return array
+ */
+ public function getBccAddresses()
+ {
+ return $this->bcc;
+ }
+
+ /**
+ * Allows for public read access to 'ReplyTo' property.
+ * Before the send() call, queued addresses (i.e. with IDN) are not yet included.
+ *
+ * @return array
+ */
+ public function getReplyToAddresses()
+ {
+ return $this->ReplyTo;
+ }
+
+ /**
+ * Allows for public read access to 'all_recipients' property.
+ * Before the send() call, queued addresses (i.e. with IDN) are not yet included.
+ *
+ * @return array
+ */
+ public function getAllRecipientAddresses()
+ {
+ return $this->all_recipients;
+ }
+
+ /**
+ * Perform a callback.
+ *
+ * @param bool $isSent
+ * @param array $to
+ * @param array $cc
+ * @param array $bcc
+ * @param string $subject
+ * @param string $body
+ * @param string $from
+ * @param array $extra
+ */
+ protected function doCallback($isSent, $to, $cc, $bcc, $subject, $body, $from, $extra)
+ {
+ if (!empty($this->action_function) and is_callable($this->action_function)) {
+ call_user_func($this->action_function, $isSent, $to, $cc, $bcc, $subject, $body, $from, $extra);
+ }
+ }
+
+ /**
+ * Get the OAuth instance.
+ *
+ * @return OAuth
+ */
+ public function getOAuth()
+ {
+ return $this->oauth;
+ }
+
+ /**
+ * Set an OAuth instance.
+ *
+ * @param OAuth $oauth
+ */
+ public function setOAuth(OAuth $oauth)
+ {
+ $this->oauth = $oauth;
+ }
+}
diff --git a/vendor/phpmailer/phpmailer/src/POP3.php b/vendor/phpmailer/phpmailer/src/POP3.php
new file mode 100644
index 0000000..9dab992
--- /dev/null
+++ b/vendor/phpmailer/phpmailer/src/POP3.php
@@ -0,0 +1,419 @@
+
+ * @author Jim Jagielski (jimjag)