discovery-media-player 0.1.18 → 0.1.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/server/handler.js +45 -4
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "discovery-media-player",
3
- "version": "0.1.18",
3
+ "version": "0.1.19",
4
4
  "description": "Self-hosted document viewer: per-recipient tracked links, reading analytics, live presentation. The core knows nothing about the application hosting it — everything it borrows arrives through an injected context.",
5
5
  "keywords": [
6
6
  "pdf-viewer",
package/server/handler.js CHANGED
@@ -399,12 +399,53 @@ var Live=(function(){
399
399
  ch.on('presence',{event:'sync'},function(){renderPres(ch.presenceState());});
400
400
  // Plus d'abonnement à la table des messages : elle n'est plus publiée ni lisible
401
401
  // publiquement. Tout passe par la diffusion, et l'historique par la route de chat.
402
- ch.on('broadcast',{event:'msg'},function(p){if(p&&p.payload&&addMsg(p.payload))notifyMsg(p.payload);});
403
- ch.on('broadcast',{event:'msg-upd'},function(p){if(p&&p.payload)updateMsg(p.payload);});
402
+ // ⚠️ UNE DIFFUSION EST UN SIGNAL, PAS UNE VÉRITÉ.
403
+ //
404
+ // Ce canal est PUBLIC : la clé publiable et le slug sont dans la page, donc tout participant
405
+ // peut émettre. Appliquer directement la charge utile revenait à laisser n'importe quel
406
+ // spectateur annoncer la fin de la présentation, changer la page affichée, verrouiller le
407
+ // chat, ou publier un message signé du nom de quelqu'un d'autre.
408
+ //
409
+ // Déplacer l'émission vers le serveur n'y changerait rien : sur un canal public, un
410
+ // attaquant émet quand même, et le client ne distingue pas les deux sources. La seule
411
+ // défense qui tienne est de CESSER DE CROIRE le transport — on relit auprès du serveur, qui
412
+ // est déjà la source de vérité (routes state=1 et chat=1, elles existaient).
413
+ //
414
+ // Un attaquant peut donc toujours émettre : il déclenche une relecture, et n'obtient rien.
415
+ // C'est une meilleure propriété que d'essayer de l'empêcher — elle vaut aussi le jour où le
416
+ // transport lui-même a un défaut.
417
+ //
418
+ // ⚠️ 'map' et 'typing' restent appliqués tels quels, et c'est un choix : ce sont des signaux
419
+ // ÉPHÉMÈRES (mouvements de carte, « untel écrit »), sans état serveur à confronter et à
420
+ // fréquence élevée. Les revérifier coûterait un aller-retour par déplacement de souris pour
421
+ // protéger… un déplacement de souris. Ce qui fait autorité — la page affichée, le document,
422
+ // la fin de la présentation — passe par 'state', qui est relu.
423
+ function relire(url,applique){
424
+ fetch('/api/doc?present='+encodeURIComponent(SLUG)+url)
425
+ .then(function(r){return r.json();})
426
+ .then(function(d){if(d&&d.ok)applique(d);})
427
+ .catch(function(){});
428
+ }
429
+ var _relEtat=null,_relChat=null;
430
+ // Groupé : dix diffusions d'affilée ne doivent pas produire dix requêtes.
431
+ function relireEtat(){clearTimeout(_relEtat);_relEtat=setTimeout(function(){
432
+ relire('&state=1',function(d){if(d.state&&_onState)_onState(d.state);});
433
+ },120);}
434
+ function relireChat(){clearTimeout(_relChat);_relChat=setTimeout(function(){
435
+ relire('&chat=1',function(d){
436
+ if(d.messages)d.messages.forEach(function(m){if(!addMsg(m))updateMsg(m);});
437
+ if(typeof d.locked!=='undefined')applyLock(d.locked);
438
+ });
439
+ },120);}
440
+
441
+ // Le message reçu sert à savoir QU'IL SE PASSE quelque chose, et à notifier ; son CONTENU
442
+ // vient de la relecture. Sans ça, une notification pourrait afficher un texte forgé.
443
+ ch.on('broadcast',{event:'msg'},function(){relireChat();});
444
+ ch.on('broadcast',{event:'msg-upd'},function(){relireChat();});
445
+ ch.on('broadcast',{event:'lock'},function(){relireChat();});
446
+ ch.on('broadcast',{event:'state'},function(){relireEtat();});
404
447
  ch.on('broadcast',{event:'typing'},function(p){onTyping(p&&p.payload);});
405
- ch.on('broadcast',{event:'lock'},function(p){if(p&&p.payload)applyLock(p.payload.locked);});
406
448
  ch.on('broadcast',{event:'map'},function(p){if(_onMap&&p&&p.payload)_onMap(p.payload);});
407
- ch.on('broadcast',{event:'state'},function(p){if(_onState&&p&&p.payload)_onState(p.payload);});
408
449
  ch.subscribe(function(st){if(st==='SUBSCRIBED'){ch.track({name:me.name,email:me.email,avatar:me.avatar,role:me.role,member:!!me.member,uid:attKey(me)});sendAttend();}});
409
450
  _tyIv=setInterval(renderTyping,1500);
410
451
  _atIv=setInterval(sendAttend,25000);