Résumé

  • RFC 3391 permettait de découper plusieurs messages MIME en fragments numérotés et de les entrelacer, afin qu’une image soit placée juste avant ou juste après sa référence dans le document racine.
  • Cette proximité restait une décision du producteur : sans retour du consommateur, elle ne prouvait ni un rendu plus rapide, ni une mémoire suffisante, ni l’arrivée de tous les composants attendus.

Un document peut être simple pour son lecteur et embarrassant pour son expéditeur. Prenons une suite de pages produites progressivement par un scanner. Le texte racine annonce une image au moment où la page est construite. L’image doit parvenir à une imprimante distante, mais ni trop tôt, au risque d’occuper sa mémoire, ni trop tard, au risque d’arrêter l’impression.

Le conteneur multipart/related rangeait les parties les unes après les autres. Mettre les images avant le document supposait de les connaître et de les stocker d’avance. Les mettre après obligeait le destinataire à traverser le document racine avant d’en recevoir les ressources. La représentation était correcte ; son ordre pouvait être coûteux.

Publié en décembre 2002 comme RFC informatif, RFC 3391 a proposé un autre rangement. Le type application/vnd.pwg-multiplexed transformait une entité composée en une succession de fragments. Les morceaux du document racine et ceux des images pouvaient alterner. Lorsqu’une référence apparaissait, la ressource correspondante pouvait se trouver à quelques octets, et non à l’autre extrémité du conteneur.

Le texte maintenait une distinction utile. L’objet composé et ses composants étaient des abstractions. L’entité transportée et les messages qu’elle contenait étaient leurs représentations. Le nouveau format ne changeait donc pas l’image, le texte ni le lien qui les unissait. Il changeait l’ordre dans lequel leurs octets devenaient disponibles.

Chaque fragment commençait par un en-tête très court : le mot CHK, un numéro de message, une longueur, puis MORE ou LAST. La longueur délimitait la charge utile sans recourir aux séparateurs de multipart. MORE annonçait que le même message continuait ; LAST en fermait la dernière partie. Les fragments de plusieurs messages pouvaient s’intercaler, mais ceux d’un même message devaient garder leur ordre.

Le premier fragment appartenait au message racine, en totalité ou en partie. Une charge vide était même admise, ce qui permettait au producteur de respecter la règle tout en retardant les premiers octets réels. À la fin, CHK 0 0 LAST signalait la fermeture de l’entité. Ce marqueur n’était pas un certificat rétroactif : s’il arrivait avant le dernier fragment de chaque message, le comportement du consommateur devenait indéfini.

Les numéros étaient normalement uniques. Leur réutilisation demeurait possible, quoique déconseillée, à condition de terminer le premier message avant de commencer le suivant portant le même numéro. Des fragments adjacents pouvaient partager un numéro ; une charge pouvait mesurer zéro octet. Ces tolérances facilitaient certains programmes d’écriture, sans modifier la règle de reconstruction.

Le paramètre obligatoire type annonçait le type MIME du message racine. Le consommateur pouvait ainsi identifier l’objet avant d’ouvrir le premier message. Si cette annonce contredisait le Content-Type racine, le RFC ne promettait aucun comportement. Les identifiants Content-ID et Content-Location pouvaient reprendre les usages de MHTML ; la nouvelle spécification ne définissait pas elle-même la sémantique des relations.

Dans le scénario d’impression, le gain était concret dans la structure. Le producteur avançait dans un long flux de descriptions de pages. Dès qu’il découvrait la première référence à une image, il pouvait interrompre le message racine, envoyer le message image, puis reprendre le texte. Le consommateur rencontrait alors la référence avec la ressource déjà reçue. L’écart en octets était réduit sans attendre la fin du document.

Le scénario de numérisation acceptait aussi l’ordre inverse : l’image juste après sa référence. Le destinataire apprenait d’abord où la ranger, puis la recevait. Dans les deux cas, le format évitait de transformer tout le travail en un grand lot préalable.

Cette élégance dépendait pourtant d’une hypothèse sur le lecteur. Si le consommateur décidait la mise en page, le producteur ignorait où un texte contournerait une image. Couper le texte trop tôt pouvait forcer le destinataire à conserver toute l’image ou à interrompre le contour. Le couper trop tard pouvait imposer trop de texte en mémoire ou repousser l’image. Le RFC conseillait d’envoyer plutôt trop de texte que pas assez, parce que le texte occupait généralement moins d’espace que l’image. C’était une heuristique, pas une connaissance du destinataire.

Deux images côte à côte révélaient une autre limite. Entrelacer leurs bandes pouvait paraître efficace, mais une panne de mémoire laisserait des portions alternées d’images impossibles à achever proprement. Le document recommandait de ne pas les entrelacer dans ce cas. Le simple pouvoir de fractionner ne disait pas quand il fallait s’en servir.

La note de l’IESG a donc une portée plus grande qu’un avertissement administratif. Elle jugeait ce type approprié uniquement lorsque le producteur connaissait pleinement les capacités et les limites du consommateur. Le flux ne possédait aucun moyen de découvrir ce dont un lecteur particulier aurait besoin ni à quel moment. Lorsque ce savoir manquait, une solution bidirectionnelle fondée par exemple sur BEEP méritait d’être envisagée.

La différence ne portait pas seulement sur des en-têtes. Dans un flux multiplexé, le producteur prédit le besoin et pousse les octets. Avec des échanges bidirectionnels, le consommateur peut demander une image ou une bande lorsqu’il en a besoin. La demande risque d’ajouter une attente ; la prédiction risque d’être fausse. Le choix oppose le coût du dialogue au coût de l’ignorance.

Le consommateur gardait aussi l’autorité de présentation. S’il reconnaissait le conteneur et le type racine, il affichait les composants dans le contexte de l’objet composé. Une indication Content-Disposition pouvait alors être trompeuse et devait être ignorée pour l’affichage. S’il reconnaissait le conteneur mais pas la racine, il pouvait supprimer l’ensemble ou présenter les messages comme des pièces mixtes. S’il ne reconnaissait rien, l’entité restait opaque.

La sécurité prolonge exactement ce problème d’information. Un producteur défectueux ou hostile pouvait ouvrir un message, éloigner sa suite de millions d’octets ou ne jamais envoyer son fragment final. Il pouvait ouvrir un grand nombre de messages en parallèle, promettre des composants qui n’arriveraient pas, ou livrer tant de composants en avance que le consommateur ne saurait jamais lesquels libérer.

Chaque fragment pouvait être localement bien formé. Sa longueur pouvait être exacte ; son numéro valide ; son indicateur cohérent. Pourtant, l’obligation de stockage globale pouvait croître sans borne utile. Une preuve syntaxique ne suffisait donc pas à prouver que le flux était consommable.

Le principe de spécification initiale minimale de Lu Heng permet de lire cette retenue comme une qualité. La règle commune couvrait la reconstruction des octets : identité du message, longueur, continuité, racine et fin. La mise en page, le budget mémoire et la stratégie d’échec restaient dans le logiciel local, où ils pouvaient évoluer.

La primauté du code en fonctionnement impose ensuite une discipline de preuve. L’enregistrement d’un type MIME ne prouve pas qu’une imprimante a continué sans pause. Un marqueur LAST ne prouve pas que la référence a trouvé son image. Il faut observer les tampons, le graphe de références et le rendu réel.

RFC 3391 n’a donc pas rendu le producteur clairvoyant. Il lui a donné un meilleur métier de monteur : rapprocher les plans, déplacer les pièces, choisir le moment de leur apparition. De l’autre côté de la vitre, le lecteur conservait ses propres contraintes. L’image arrivait près de sa référence ; sa bonne réception restait une histoire d’exécution.

Sources