Advertisement
Guest User

Untitled

a guest
Mar 24th, 2022
44
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.36 KB | None | 0 0
  1. <?php
  2. header("Content-Type: text/event-stream");
  3. header("Cache-Control: no-cache"); // Il client non dovrebbe usare meccanismi di cache
  4.  
  5. define("_WEBROOT", "../");
  6. //define("SKIP_AUTH", 1);
  7.  
  8. include_once "../bootstrap.php";
  9. include_once _FILEROOT . "lib/mysqli_wrapper/__init.hphp";
  10.  
  11. ignore_user_abort(false);
  12. set_time_limit(0);
  13. /**
  14. * Questa pagina usa lo standard SSE (https://www.w3.org/TR/eventsource/)
  15. * per inviare ad un cliente notifiche di eventuali nuove risposte ad uno dei suoi thread
  16. * oppure uno dei suoi commenti.
  17. *
  18. * Il cliente passa tramite query GET la data, in formato ISO e nel fuso orario universale,
  19. * dal quale il programma che segue inzia a ricercare per nuove riposte; altrimenti, se il
  20. * cliente non passa nulla il programma usa la data attuale del DBMS.
  21. *
  22. * Il programma lavora come segue:
  23. * fintanto un cliente resta collegato al servente invia:
  24. * - L'ora attuale del DMBS
  25. * - Eventuali notifiche di nuove risposte ai commenti
  26. *
  27. * L'applicazione cliente dovrebbe memorizzare nella sua memoria l'ora delle ultime richieste in
  28. * modo da poterla riutilizzare in una conessione ex-nova per permettere a questo programma
  29. * di riprendere a notificare da dov'era rimasto.
  30. *
  31. * Per debug dello script eseguire in una riga di comando
  32. * curl -N http://127.0.0.1/notifications/stream.php
  33. */
  34.  
  35. define("START_SSE_ID", "id: ");
  36. define("STOP_SSE_ID", "\n");
  37. define("START_SSE_EVENT", "event: ");
  38. define("STOP_SSE_EVENT", "\n");
  39. define("START_SSE_MESSAGE", "data: ");
  40. define("END_SSE_MESSAGE", "\n\n");
  41.  
  42.  
  43. /**
  44. * Invia un SSE al cliente collegato a questa pagina
  45. * @param $data mixed
  46. * @param $event String
  47. * @param $id int
  48. */
  49. function send_sse($data, $event = null, $id = null)
  50. {
  51. // Stampo eventuale ID
  52. if($id !== null)
  53. echo START_SSE_ID . (int)$id . STOP_SSE_ID;
  54.  
  55. // Stampo eventuale EVENT
  56. if($event !== null)
  57. echo START_SSE_EVENT . (string)$event . STOP_SSE_EVENT;
  58.  
  59. // Stampa corpo messaggio
  60. echo START_SSE_MESSAGE;
  61. echo json_encode($data, JSON_UNESCAPED_UNICODE);
  62. echo END_SSE_MESSAGE;
  63.  
  64. // Forzo l'invio del buffer nel server WEB al client
  65. flush();
  66. }
  67.  
  68. $server = new \mysqli_wrapper\mysqli();
  69.  
  70. /**
  71. * Da quando devo cominciare a notificare i nuovi commenti?
  72. * Dal paramatreto GET timestart altrimenti, se timestart non è
  73. * definito, uso l'ora attaule del DBMS
  74. */
  75. $timestart = (! empty($_GET["timestart"])) ?
  76. $_GET["timestart"] :
  77. $server->dbms_timestamp();
  78. $timestop = "1970-01-01 00:00:00Z";
  79. $username = $auth->get_user_id();
  80.  
  81. /**
  82. * Interrogazione per chiedere alla base dati quali sono i nuovi commenti apparsi
  83. * sotto i miei thread oppure commenti
  84. */
  85. $checkForNewNotificationsStatement = $server->prepare("
  86. SELECT
  87. RR.`thread` AS `threadId`,
  88.  
  89. RR.`id` AS `fatherThreadComment`,
  90. RL.`id` AS `sonThreadComment`,
  91.  
  92. RL.`timestamp` AS `replyTime`
  93. FROM Poster P
  94. INNER JOIN Reply RR ON RR.`author` = P.`username` AND RR.`thread` = P.`thread`
  95. INNER JOIN Reply RL ON
  96. RL.`replies` = RR.`id` AND -- Chi ha risposto ai suoi commenti
  97. RL.`author` <> P.`username` -- Eccetto quelle che si è fatto da solo!
  98. WHERE
  99. P.`username` = ? AND
  100. RL.`timestamp` >= ? AND RL.`timestamp` < ? -- Intervallo temporale
  101. ORDER BY RL.`timestamp` ASC
  102. ", false
  103. );
  104. $checkForNewNotificationsStatement->bind_param("sss", $username, $timestart, $timestop);
  105.  
  106. if(!empty($_GET["watch"])) {
  107. $checkForNewCommentsForThread = $server->prepare("
  108. SELECT
  109. S.`id` AS `comment id`,
  110. S.`content` AS `content`,
  111.  
  112. S.`timestamp` AS `timestamp`,
  113.  
  114. 0 AS `number of childs`,
  115.  
  116. S.`is locked` OR T.`is locked` AS `is locked`,
  117. T.`is locked` AS `thread is locked`,
  118.  
  119. F.id AS `father`,
  120.  
  121. -- Informazioni sull'autore
  122. S.`author` AS `author`, -- L'id dell'autore
  123. CONCAT('#', HEX(P.`anon color`)) AS `color hex`, -- Il colore assegnato in HEX
  124. P.`is op` AS `is op`, -- È l'autore del thread?
  125. P.`username` = ? AS `is you`, -- Sei te?
  126. P.blocked OR EXISTS(
  127. SELECT 1 FROM `Banned poster in section` BPS WHERE BPS.`username_banned` = P.`username` AND BPS.section = T.id
  128. ) OR EXISTS(
  129. SELECT 1 FROM `Banned poster in site` BPS WHERE BPS.`username_banned` = P.`username`
  130. ) AS `banned` -- È bandito ?
  131. FROM Reply S
  132. INNER JOIN Poster P ON P.`username` = S.author AND P.thread = S.thread
  133. INNER JOIN Thread T ON S.thread = T.id
  134. LEFT JOIN Reply F ON F.id = S.replies AND F.thread = S.thread
  135. WHERE
  136. S.thread = ? AND -- Il thread da osservare
  137. S.timestamp >= ? AND S.timestamp < ? -- Intervallo
  138. ORDER BY S.timestamp ASC", false);
  139.  
  140. $checkForNewCommentsForThread->bind_param("siss",$username, $_GET["watch"], $timestart, $timestop);
  141. }
  142.  
  143.  
  144. /***********************************************
  145. * INZIO SSE
  146. ***********************************************/
  147. // Disabilit il maccanismo di buffering del PHP
  148. ob_end_flush();
  149.  
  150. // Finché c'è un client collegato invio notifiche
  151. while(!connection_aborted())
  152. {
  153. // Decido fino a dove verificare per nuovi messaggi
  154. $timestop = $server->dbms_timestamp();
  155.  
  156. // Verifica nuove risposte
  157. $checkForNewNotificationsStatement->execute();
  158. $result = $checkForNewNotificationsStatement->get_result();
  159.  
  160. while($notification = $result->fetch_assoc())
  161. send_sse($notification, "notification");
  162.  
  163. // Verifica nuovi commenti al thread attualmente aperto
  164. if(!empty($_GET["watch"])) {
  165. $checkForNewCommentsForThread->execute();
  166. $result = $checkForNewCommentsForThread->get_result();
  167.  
  168. while ($comment = $result->fetch_assoc())
  169. send_sse($comment, "comment");
  170. }
  171.  
  172. // Invio il nuovo timestpo
  173. send_sse($timestop, "timestop");
  174.  
  175. // Sposto il margine temporale avanti all'ultima interrogazione
  176. $timestart = $timestop;
  177. $timeslept = 0;
  178. while(connection_aborted() == CONNECTION_NORMAL && $timeslept < NOTIFICATION_STREAM_SLEEP_TIME){
  179. if(connection_status() != CONNECTION_NORMAL){
  180. exit();
  181. }
  182. usleep(500*1000);
  183. $timeslept = $timeslept + 0.5;
  184.  
  185.  
  186. }
  187.  
  188. }
  189.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement