messages_thread.php 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425
  1. <?php
  2. /*
  3. FusionPBX
  4. Version: MPL 1.1
  5. The contents of this file are subject to the Mozilla Public License Version
  6. 1.1 (the "License"); you may not use this file except in compliance with
  7. the License. You may obtain a copy of the License at
  8. http://www.mozilla.org/MPL/
  9. Software distributed under the License is distributed on an "AS IS" basis,
  10. WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  11. for the specific language governing rights and limitations under the
  12. License.
  13. The Original Code is FusionPBX
  14. The Initial Developer of the Original Code is
  15. Mark J Crane <[email protected]>
  16. Portions created by the Initial Developer are Copyright (C) 2024
  17. the Initial Developer. All Rights Reserved.
  18. Contributor(s):
  19. Mark J Crane <[email protected]>
  20. */
  21. //includes files
  22. require_once dirname(__DIR__, 2) . "/resources/require.php";
  23. require_once "resources/check_auth.php";
  24. //check permissions
  25. if (!permission_exists('message_view')) {
  26. echo "access denied";
  27. exit;
  28. }
  29. //add multi-lingual support
  30. $language = new text;
  31. $text = $language->get();
  32. //connect to the database
  33. $database = database::new();
  34. //santize the contact number, allow the + to support e.164 format
  35. if (isset($_GET['number'])) {
  36. $number = preg_replace("/[^\+?0-9]/", "", $_GET['number']);
  37. $_SESSION['user']['contact_number'] = $number;
  38. }
  39. //get the number from the php session
  40. if (isset($_SESSION['user']['contact_number'])) {
  41. $number = $_SESSION['user']['contact_number'];
  42. }
  43. //get the contact uuid
  44. $contact_uuid = !empty($_GET['contact_uuid']) && is_uuid($_GET['contact_uuid']) ? $_GET['contact_uuid'] : null;
  45. //get the limit
  46. if (isset($_SESSION['message']['limit']['numeric']) && is_numeric($_SESSION['message']['limit']['numeric'])) {
  47. $message_limit = $_SESSION['message']['limit']['numeric'];
  48. }
  49. else {
  50. $message_limit = 80;
  51. }
  52. //build a list of groups the user is a member of to be used in a SQL in
  53. foreach($_SESSION['user']['groups'] as $group) {
  54. if (is_uuid($group['group_uuid'])) {
  55. $group_uuids[] = $group['group_uuid'];
  56. }
  57. }
  58. $group_uuids_in = "'".implode("','", $group_uuids)."'";
  59. //get the list of messages
  60. $sql = "select ";
  61. $sql .= "message_uuid, ";
  62. $sql .= "domain_uuid, ";
  63. $sql .= "user_uuid, ";
  64. $sql .= "contact_uuid, ";
  65. $sql .= "message_type, ";
  66. $sql .= "message_direction, ";
  67. if (!empty($_SESSION['domain']['time_zone']['name'])) {
  68. $sql .= "message_date at time zone :time_zone as message_date, ";
  69. }
  70. else {
  71. $sql .= "message_date, ";
  72. }
  73. $sql .= "message_read, ";
  74. $sql .= "message_from, ";
  75. $sql .= "message_to, ";
  76. $sql .= "message_text ";
  77. $sql .= "from v_messages ";
  78. $sql .= "where (domain_uuid = :domain_uuid or domain_uuid is null) ";
  79. $sql .= "and ( ";
  80. $sql .= " user_uuid = :user_uuid ";
  81. $sql .= " or ";
  82. $sql .= " group_uuid in (".$group_uuids_in.")";
  83. $sql .= ")\n";
  84. //$sql .= "and message_date > NOW() - INTERVAL '3 days' ";
  85. $sql .= "and (message_from = :message_number or message_to = :message_number) ";
  86. $sql .= "order by message_date desc ";
  87. $sql .= "limit :message_limit ";
  88. if (!empty($_SESSION['domain']['time_zone']['name'])) {
  89. $parameters['time_zone'] = $_SESSION['domain']['time_zone']['name'];
  90. }
  91. $parameters['user_uuid'] = $_SESSION['user_uuid'];
  92. $parameters['domain_uuid'] = $domain_uuid;
  93. $parameters['message_number'] = $number ?? null;
  94. $parameters['message_limit'] = $message_limit;
  95. $messages = $database->select($sql, $parameters, 'all');
  96. unset($sql, $parameters);
  97. if (is_array($messages) && @sizeof($messages) != 0) {
  98. $messages = array_reverse($messages);
  99. //get media (if any)
  100. $sql = "select ";
  101. $sql .= "message_uuid, ";
  102. $sql .= "message_media_uuid, ";
  103. $sql .= "message_media_type, ";
  104. $sql .= "length(decode(message_media_content,'base64')) as message_media_size ";
  105. $sql .= "from v_message_media ";
  106. $sql .= "where (domain_uuid = :domain_uuid or domain_uuid is null) ";
  107. $sql .= "and ( ";
  108. foreach ($messages as $index => $message) {
  109. $message_uuids[] = "message_uuid = :message_uuid_".$index;
  110. $parameters['message_uuid_'.$index] = $message['message_uuid'];
  111. }
  112. $sql .= implode(' or ', $message_uuids);
  113. $sql .= ") ";
  114. $sql .= "and message_media_type <> 'txt' ";
  115. $parameters['domain_uuid'] = $domain_uuid;
  116. $rows = $database->select($sql, $parameters, 'all');
  117. unset($sql, $parameters, $index);
  118. //prep media array
  119. if (is_array($rows) && @sizeof($rows) != 0) {
  120. foreach ($rows as $index => $row) {
  121. $message_media[$row['message_uuid']][$index]['uuid'] = $row['message_media_uuid'];
  122. $message_media[$row['message_uuid']][$index]['type'] = $row['message_media_type'];
  123. $message_media[$row['message_uuid']][$index]['size'] = $row['message_media_size'];
  124. }
  125. }
  126. }
  127. //flag messages as read
  128. $sql = "update v_messages ";
  129. $sql .= "set message_read = 'true' ";
  130. $sql .= "where user_uuid = :user_uuid ";
  131. $sql .= "and (domain_uuid = :domain_uuid or domain_uuid is null) ";
  132. $sql .= "and (message_from like :message_number or message_to like :message_number) ";
  133. $parameters['user_uuid'] = $_SESSION['user_uuid'];
  134. $parameters['domain_uuid'] = $domain_uuid;
  135. $parameters['message_number'] = $number ?? null;
  136. $database->execute($sql, $parameters);
  137. unset($sql, $parameters);
  138. //show the content
  139. echo "<!DOCTYPE html>\n";
  140. echo "<html>\n";
  141. echo "<head>\n";
  142. //include icons
  143. echo "<link rel='stylesheet' type='text/css' href='/resources/fontawesome/css/all.min.css.php'>\n";
  144. // echo "<script language='JavaScript' type='text/javascript' src='/resources/fontawesome/js/solid.min.js.php' defer></script>\n";
  145. //css styles
  146. echo "<style>\n";
  147. echo " body {\n";
  148. echo " margin: 0;\n";
  149. echo " padding: 5px;\n";
  150. echo " padding-top: 15px;\n";
  151. echo " }\n";
  152. echo " .message-bubble {\n";
  153. echo " display: table;\n";
  154. echo " padding: 10px;\n";
  155. echo " border: 1px solid;\n";
  156. echo " margin-bottom: 10px;\n";
  157. echo " clear: both;\n";
  158. echo " }\n";
  159. echo " .message-bubble-em {\n";
  160. echo " padding-right: 15px;\n";
  161. echo " border-radius: ".($_SESSION['theme']['message_bubble_em_border_radius']['text'] ?? '0 20px 20px 20px').";\n";
  162. echo " border-color: ".($_SESSION['theme']['message_bubble_em_border_color']['text'] ?? '#abefa0').";\n";
  163. echo " background: ".($_SESSION['theme']['message_bubble_em_background_color']['text'] ?? '#daffd4').";\n";
  164. echo " background: linear-gradient(180deg, ".($_SESSION['theme']['message_bubble_em_border_color']['text'] ?? '#abefa0')." 0%, ".($_SESSION['theme']['message_bubble_em_background_color']['text'] ?? '#daffd4')." 15px);\n";
  165. echo " color: ".($_SESSION['theme']['message_bubble_em_text_color']['text'] ?? '#000').";\n";
  166. echo " }\n";
  167. echo " .message-bubble-me {\n";
  168. echo " float: right;\n";
  169. echo " padding-left: 15px;\n";
  170. echo " border-radius: ".($_SESSION['theme']['message_bubble_me_border_radius']['text'] ?? '20px 20px 0 20px').";\n";
  171. echo " border-color: ".($_SESSION['theme']['message_bubble_me_border_color']['text'] ?? '#a3e1fd').";\n";
  172. echo " background: ".($_SESSION['theme']['message_bubble_me_background_color']['text'] ?? '#cbf0ff').";\n";
  173. echo " background: linear-gradient(180deg, ".($_SESSION['theme']['message_bubble_me_background_color']['text'] ?? '#cbf0ff')." calc(100% - 15px), ".($_SESSION['theme']['message_bubble_me_border_color']['text'] ?? '#a3e1fd')." 100%);\n";
  174. echo " color: ".($_SESSION['theme']['message_bubble_me_text_color']['text'] ?? '#000').";\n";
  175. echo " }\n";
  176. echo " img.message-bubble-image-em {\n";
  177. echo " width: 100px;\n";
  178. echo " height: auto;\n";
  179. echo " border-radius: 0 11px 11px 11px;\n";
  180. echo " border: 1px solid #cffec7;\n";
  181. echo " }\n";
  182. echo " img.message-bubble-image-me {\n";
  183. echo " width: 100px;\n";
  184. echo " height: auto;\n";
  185. echo " border-radius: 11px 11px 0 11px;\n";
  186. echo " border: 1px solid #cbf0ff;\n";
  187. echo " }\n";
  188. echo " div.message-bubble-image-em {\n";
  189. echo " float: left;\n";
  190. echo " text-align: left;\n";
  191. echo " }\n";
  192. echo " div.message-bubble-image-me {\n";
  193. echo " float: right;\n";
  194. echo " text-align: right;\n";
  195. echo " }\n";
  196. echo " .message-bubble-em-text {\n";
  197. echo " font-family: ".($_SESSION['theme']['message_bubble_em_text_font']['text'] ?? 'arial').";\n";
  198. echo " color: ".($_SESSION['theme']['message_bubble_em_text_color']['text'] ?? '#000').";\n";
  199. echo " font-size: ".($_SESSION['theme']['message_bubble_em_text_size']['text'] ?? '90%').";\n";
  200. echo " }\n";
  201. echo " .message-bubble-me-text {\n";
  202. echo " font-family: ".($_SESSION['theme']['message_bubble_me_text_font']['text'] ?? 'arial').";\n";
  203. echo " color: ".($_SESSION['theme']['message_bubble_me_text_color']['text'] ?? '#000').";\n";
  204. echo " font-size: ".($_SESSION['theme']['message_bubble_me_text_size']['text'] ?? '90%').";\n";
  205. echo " }\n";
  206. echo " .message-bubble-when-em {\n";
  207. echo " font-family: ".($_SESSION['theme']['message_bubble_when_font']['text'] ?? 'arial').";\n";
  208. echo " font-size: ".($_SESSION['theme']['message_bubble_when_size']['text'] ?? '71%').";\n";
  209. echo " color: ".($_SESSION['theme']['message_bubble_em_when_color']['text'] ?? '#52b342').";\n";
  210. echo " letter-spacing: -0.02em;\n";
  211. echo " float: left;\n";
  212. echo " }\n";
  213. echo " .message-bubble-when-me {\n";
  214. echo " font-family: ".($_SESSION['theme']['message_bubble_when_font']['text'] ?? 'arial').";\n";
  215. echo " font-size: ".($_SESSION['theme']['message_bubble_when_size']['text'] ?? '71%').";\n";
  216. echo " color: ".($_SESSION['theme']['message_bubble_me_when_color']['text'] ?? '#4593b6').";\n";
  217. echo " letter-spacing: -0.02em;\n";
  218. echo " float: right;\n";
  219. echo " }\n";
  220. echo " div.message-media {\n";
  221. echo " margin: 8px 0 8px 0;\n";
  222. echo " text-align: center;\n";
  223. echo " font-family: ".($_SESSION['theme']['message_bubble_when_font']['text'] ?? 'arial').";\n";
  224. echo " font-size: ".($_SESSION['theme']['message_bubble_when_size']['text'] ?? '71%').";\n";
  225. echo " letter-spacing: -0.02em;\n";
  226. echo " white-space: nowrap;\n";
  227. echo " text-decoration: none;\n";
  228. echo " }\n";
  229. echo " a.message-media-link-me,\n";
  230. echo " a.message-media-link-em {\n";
  231. echo " text-decoration: none;\n";
  232. echo " }\n";
  233. echo " a.message-media-link-em {\n";
  234. echo " color: ".($_SESSION['theme']['message_bubble_em_when_color']['text'] ?? '#52b342').";\n";
  235. echo " }\n";
  236. echo " a.message-media-link-me {\n";
  237. echo " color: ".($_SESSION['theme']['message_bubble_me_when_color']['text'] ?? '#4593b6').";\n";
  238. echo " }\n";
  239. echo " a.message-media-link-me:hover,\n";
  240. echo " a.message-media-link-em:hover {\n";
  241. echo " text-decoration: underline;\n";
  242. echo " }\n";
  243. echo " a.message-media-link-me > img,\n";
  244. echo " a.message-media-link-em > img {\n";
  245. echo " border-radius: 7px;\n";
  246. echo " margin: 0 auto;\n";
  247. echo " margin-bottom: 3px;\n";
  248. echo " width: 100%;\n";
  249. echo " max-width: ".($_SESSION['theme']['message_bubble_media_width_max']['text'] ?? '300px').";\n";
  250. echo " height: auto;\n";
  251. echo " }\n";
  252. echo " a.message-media-link-em > img {\n";
  253. echo " border: 2px solid ".($_SESSION['theme']['message_bubble_em_border_color']['text'] ?? '#abefa0').";\n";
  254. echo " }\n";
  255. echo " a.message-media-link-me > img {\n";
  256. echo " border: 2px solid ".($_SESSION['theme']['message_bubble_me_border_color']['text'] ?? '#a3e1fd').";\n";
  257. echo " }\n";
  258. echo "</style>\n";
  259. //end the header and start the body
  260. echo "</head>\n";
  261. echo "<body>\n";
  262. // //display media
  263. // echo "<script language='JavaScript' type='text/javascript'>\n";
  264. // echo " function display_media(id, src) {\n";
  265. // echo " $('#message_media_layer').load('message_media.php?id=' + id + '&src=' + src + '&action=display', function(){\n";
  266. // echo " $('#message_media_layer').fadeIn(200);\n";
  267. // echo " });\n";
  268. // echo " }\n";
  269. // echo "</script>\n";
  270. //
  271. // //message media layer
  272. // echo "<div id='message_media_layer' style='display: none;'></div>\n";
  273. if (empty($refresh) || !$refresh) {
  274. echo "<div id='thread_messages' style='min-height: 300px; overflow: auto;'>\n";
  275. }
  276. //output messages
  277. if (is_array($messages) && @sizeof($messages) != 0) {
  278. foreach ($messages as $message) {
  279. //parse from message
  280. if ($message['message_direction'] == 'inbound') {
  281. $message_from = $message['message_to'];
  282. $media_source = format_phone($message['message_from']);
  283. }
  284. if ($message['message_direction'] == 'outbound') {
  285. $message_from = $message['message_from'];
  286. $media_source = format_phone($message['message_to']);
  287. }
  288. //message bubble
  289. echo "<span class='message-bubble message-bubble-".($message['message_direction'] == 'inbound' ? 'em' : 'me')."'>";
  290. //contact image em
  291. if ($message['message_direction'] == 'inbound') {
  292. if (!empty($_SESSION['tmp']['messages']['contact_em'][$contact_uuid]) && @sizeof($_SESSION['tmp']['messages']['contact_em'][$contact_uuid]) != 0) {
  293. echo "<div class='message-bubble-image-em'>\n";
  294. echo " <img class='message-bubble-image-em'><br />\n";
  295. echo "</div>\n";
  296. }
  297. }
  298. //contact image me
  299. else {
  300. if (!empty($_SESSION['tmp']['messages']['contact_me']) && @sizeof($_SESSION['tmp']['messages']['contact_me']) != 0) {
  301. echo "<div class='message-bubble-image-me'>\n";
  302. echo " <img class='message-bubble-image-me'><br />\n";
  303. echo "</div>\n";
  304. }
  305. }
  306. echo "<div style='display: table;'>\n";
  307. //attachments
  308. if (!empty($message_media[$message['message_uuid']]) && @sizeof($message_media[$message['message_uuid']]) != 0) {
  309. foreach ($message_media[$message['message_uuid']] as $media) {
  310. if ($media['type'] != 'txt') {
  311. echo "<div class='message-media'>\n";
  312. if (in_array($media['type'], ['jpg','jpeg','gif','png'])) {
  313. echo "<a href='message_media.php?id=".$media['uuid']."&src=".$media_source."&action=download' class='message-media-link-".($message['message_direction'] == 'inbound' ? 'em' : 'me')."' title=\"".$text['label-download']."\">";
  314. }
  315. echo "<img src='message_media.php?id=".$media['uuid']."&src=".$media_source."&action=thumbnail&width=".($_SESSION['theme']['message_bubble_media_width_max']['text'] ?? '300px')."'><br />\n";
  316. //echo "<img src='resources/images/attachment.png' style='width: 16px; height: 16px; border: none; margin-right: 10px;'>";
  317. echo strtoupper($media['type']).' &middot; '.strtoupper(byte_convert($media['size']));
  318. if (in_array($media['type'], ['jpg','jpeg','gif','png'])) {
  319. echo "<i class='fas fa-download fa-xs' style='margin-left: 8px;'></i>";
  320. echo "</a>\n";
  321. }
  322. echo "</div>\n";
  323. }
  324. }
  325. }
  326. //message
  327. if (!empty($message['message_text'])) {
  328. //$message['message_text'] = str_replace("&NewLine;", "<br />", escape($message['message_text']));
  329. $allowed = ['http', 'https'];
  330. $scheme = parse_url($message['message_text'], PHP_URL_SCHEME);
  331. if ($scheme === false) {
  332. // seriously malformed URL
  333. $is_url = false;
  334. }
  335. else if (!in_array($scheme, $allowed, true)) {
  336. // protocol not allowed, don't display the link!
  337. $is_url = false;
  338. }
  339. else {
  340. // everything OK
  341. $is_url = true;
  342. }
  343. echo "<div class='message-bubble-".($message['message_direction'] == 'inbound' ? 'em' : 'me')."-text'>\n";
  344. if ($is_url) {
  345. echo "<a href='".$message['message_text']."' target='_blank'>".$message['message_text']."</a>\n";
  346. }
  347. else {
  348. echo str_replace("&NewLine;",'<br />',escape($message['message_text']))."\n";
  349. }
  350. echo "</div>\n";
  351. }
  352. //message when
  353. echo "<span class='message-bubble-when-".($message['message_direction'] == 'inbound' ? 'em' : 'me')."'>".(date('m-d-Y') != format_when_local($message['message_date'],'d') ? format_when_local($message['message_date']) : format_when_local($message['message_date'],'t'))."</span>\n";
  354. echo "</div>\n";
  355. echo "</span>\n";
  356. }
  357. // echo "<span id='thread_bottom'></span>\n";
  358. echo "<a name='bottom'></a>\n";
  359. }
  360. echo "<script>\n";
  361. //set current contact
  362. // echo " $('#contact_current_number').val('".$number."');\n";
  363. //set bubble contact images from src images
  364. // echo " $('img.message-bubble-image-em').attr('src', $('img#src_message-bubble-image-em_".$contact_uuid."').attr('src'));\n";
  365. // echo " $('img.message-bubble-image-me').attr('src', $('img#src_message-bubble-image-me').attr('src'));\n";
  366. echo "</script>\n";
  367. if (empty($refresh) || !$refresh) {
  368. echo "</div>\n";
  369. }
  370. echo "</body>\n";
  371. echo "</html>\n";
  372. ?>