Question

Je dois mettre en place un éditeur de configuration rapide et sale. Le flux va quelque chose comme ça:

Les configurations

(les POCO sur le serveur) sont sérialisées au format XML.
Le XML est bien formé à ce stade. La configuration est envoyée au serveur Web dans XElements.
Sur le serveur Web, le XML (oui, tout le monde) est transféré dans une zone de texte pour modification.
L'utilisateur édite le code XML directement dans la page Web et clique sur Soumettre.
Dans la réponse, je récupère le texte modifié de la configuration XML. À ce stade, TOUTES les fuites ont été annulées par le processus d'affichage dans une page Web.
Je tente de charger la chaîne dans un objet XML (XmlElement, XElement, peu importe). KABOOM.

Le problème est que la sérialisation échappe aux chaînes d'attributs, mais que cette traduction est perdue en cours de route.

Par exemple, disons que j'ai un objet qui a une regex. Voici la configuration du serveur Web:

<Configuration>
  <Validator Expression="[^&lt;]" />
</Configuration>

Donc, je mets ceci dans une zone de texte, où il ressemble à ceci pour l'utilisateur:

<Configuration>
  <Validator Expression="[^<]" />
</Configuration>

Ainsi, l’utilisateur apporte une légère modification et soumet les modifications. Sur le serveur Web, la chaîne de réponse se présente comme suit:

<Configuration>
  <Validator Expression="[^<]" />
  <Validator Expression="[^&]" />
</Configuration>

Ainsi, l'utilisateur a ajouté un autre outil de validation, et maintenant, DEUX ont des attributs avec des caractères non autorisés. Si j'essaye de charger ceci dans n'importe quel objet XML, il lève une exception parce que & Lt; et & amp; ne sont pas valides dans une chaîne de texte. Je ne peux pas ne peux pas ne peux pas utiliser n'importe quel type de fonction d'encodage, car il encode tout ce qui est sanglant:

var result = Server.HttpEncode (editedconfig);

résultats dans

&lt;Configuration&gt;
  &lt;Validator Expression="[^&lt;]" /&gt;
  &lt;Validator Expression="[^&amp;]" /&gt;
&lt;/Configuration&gt;

Ceci n'est pas un XML valide. Si j'essaye de charger ceci dans un élément XML, je serai frappé par une enclume qui tombe. Je n'aime pas tomber les enclumes.

SO, la question demeure ... Est-ce la SEULE façon de préparer cette chaîne XML prête à être analysée dans un objet XML en utilisant des expressions rationnelles? Existe-t-il un moyen de & "Désactiver les contraintes &"; quand je charge? Comment vous en sortir ???

Une dernière réponse, puis un wiki, car je ne pense pas qu'il existe une réponse valable.

Le XML que je place dans la zone de texte est valide, sauf le XML. Le processus 1) de le placer dans la zone de texte 2) de l’envoyer au client 3) de l’afficher au client 4) de soumettre le formulaire dans lequel il se trouve 5) de le renvoyer au serveur et 6) de récupérer la valeur du formulaire ENLEVE TOUTES LES ESCAPADES.

Permettez-moi de répéter ceci: je ne réussis pas à rien. Cela ne fait que l’afficher dans le navigateur!

Choses à ruminer: y a-t-il un moyen d'empêcher que cette invasion ne se produise en premier lieu? Existe-t-il un moyen de prendre du XML presque valide et de & Quot; nettoyer & Quot; de manière sûre?

Cette question a maintenant une prime. Pour collecter la prime, vous montrez comment modifier VALID XML dans une fenêtre de navigateur SANS outil tierce partie / open source ne nécessitant pas l’utilisation manuelle de regex pour échapper les valeurs d’attributs, ni obligeant les utilisateurs à échapper leurs attributs, et cela n'échoue pas lors des tournées (& amp; amp; amp; amp; amp; etc;)

Était-ce utile?

La solution

Erm & # 8230; & nbsp; Comment sérialisez-vous? En règle générale, le sérialiseur XML ne doit jamais générer de code XML non valide.

/ EDIT en réponse à votre mise à jour: pas d'afficher du code XML non valide pour permettre à votre utilisateur de le modifier! Au lieu de cela, affichez le code XML correctement échappé dans la zone de texte. Réparer du XML cassé n’est pas amusant et je ne vois aucune raison de ne pas afficher / modifier le XML sous une forme valide et échappée.

Encore une fois, je pourrais demander: comment affichez-vous le code XML dans la zone de texte? Vous semblez délibérément vouloir échapper au XML à un moment donné.

/ EDIT en réponse à votre dernier commentaire: Eh bien oui, évidemment, car il peut contenir du HTML. Vous devez échapper correctement à votre code XML avant de l'écrire dans une page HTML. Par cela, je veux dire le entier XML. Donc ceci:

<foo mean-attribute="&lt;">

devient ceci:

&lt;foo mean-attribute="&amp;&lt;"&gt;

Autres conseils

Bien sûr, lorsque vous placez des références d’entités dans une zone de texte, elles s’échappent. Les zones de texte ne sont pas magiques, vous devez & Amp; escape; tout ce que vous mettez en eux, comme tous les autres éléments. Les navigateurs peuvent afficher un '& Lt;' brut; ' dans une zone de texte, mais uniquement parce qu'ils essaient de nettoyer vos erreurs.

Donc, si vous mettez du XML modifiable dans une zone de texte, vous devez échapper une fois la valeur de l'attribut pour le rendre valide, puis le code XML complet pour le rendre valide. La source finale que vous souhaitez voir apparaître sur la page serait:

<textarea name="somexml">
    &lt;Configuration&gt;
        &lt;Validator Expression="[^&amp;lt;]" /&gt;
        &lt;Validator Expression="[^&amp;amp;]" /&gt;
    &lt;/Configuration&gt;
</textarea>

La question est basée sur une incompréhension du modèle de contenu de l'élément textarea - un validateur aurait immédiatement relevé le problème.

Commentaire ETA: Eh bien, quel problème reste? C'est le problème du côté de la sérialisation. Il ne reste plus qu'à le réanalyser, ce qui suppose que l'utilisateur puisse créer un fichier XML bien formé.

Essayer d'analyser du XML non bien formé, afin de permettre des erreurs comme celles-ci: '<' ou '& amp;' ne pas échapper dans une valeur d'attribut est une perte, totalement contre la façon dont XML est supposé fonctionner. Si vous ne pouvez pas faire confiance à vos utilisateurs pour écrire du code XML bien formé, proposez-leur une interface non XML plus simple, telle qu'une simple liste de chaînes de regexp séparées par des lignes,

.

Comme vous le dites, le sérialiseur normal devrait tout échapper pour vous.

Le problème est donc le bloc de texte: vous devez gérer vous-même tout ce qui est passé dans le bloc de texte.

Vous pouvez essayer HttpUtility.HtmlEncode (), mais je pense que la méthode la plus simple est d’envelopper tout ce que vous passez à travers le bloc de texte d’une section CDATA.

Normalement, bien sûr, je voudrais que tout soit correctement échappé plutôt que de compter sur la béquille &, de CDATA, mais je voudrais aussi utiliser les outils intégrés pour échapper à la bêtise. Pour quelque chose qui est édité dans c'est & Quot; en hibernation & Quot; état par un utilisateur, je pense que CDATA pourrait être la voie à suivre.

Voir aussi cette question précédente:
Méthode idéale pour coder les données texte au format XML

Mettre à jour
Sur la base d'un commentaire à une autre réponse, j'ai compris que vous montriez le balisage aux utilisateurs, pas seulement le contenu. Les analyseurs syntaxiques XML sont, bien, difficiles. Je pense que la meilleure chose à faire dans ce cas-ci est de vérifier la bonne formation avant d'accepter le fichier XML modifié.

Essayez peut-être de corriger automatiquement certains types d’erreurs (comme les esperluettes de ma question liée), mais obtenez ensuite le numéro de ligne et le numéro de colonne de la première erreur de validation de l’analyseur .Net xml et utilisez-les pour montrer aux utilisateurs où se trouve leur l'erreur est jusqu'à ce qu'ils vous donnent quelque chose d'acceptable. Points bonus si vous validez également un schéma.

Vous pouvez jeter un coup d'œil à quelque chose comme TinyMCE , qui vous permet de modifier du code HTML dans un texte enrichi. boîte. Si vous ne pouvez pas le configurer pour faire exactement ce que vous voulez, vous pouvez vous en inspirer.

Remarque: Firefox (dans mon test) ne se déchaîne pas dans les zones de texte comme vous le décrivez. Plus précisément, ce code:

<textarea cols="80" rows="10" id="1"></textarea>

<script>
elem = document.getElementById("1");

elem.value = '\
<Configuration>\n\
  <Validator Expression="[^&lt;]" />\n\
</Configuration>\
'
alert(elem.value);
</script>

est alerté et affiché à l'utilisateur inchangé , sous la forme:

<Configuration>
  <Validator Expression="[^&lt;]" />
</Configuration>

Donc, une solution (non viable?) consiste pour vos utilisateurs à utiliser Firefox.

Il semble que votre question comporte deux parties:

1 Le code XML que vous affichez devient incontournable.

Par exemple, " &lt; " n'est pas échappé comme & "; < &" ;. Mais depuis & Quot; & Lt; & Quot; est également non échappé en tant que & "; < &" ;, les informations sont perdues et vous ne pouvez pas les récupérer.

Une solution consiste à vous échapper à tous les " & " caractères, de sorte que " &amp;lt; " devient " &amp; " ;. Ceci sera alors non échappé par la zone de texte sous la forme & "; \ &"; Quand vous le reluirez, ce sera comme avant. (Je suppose que textarea change réellement la chaîne, mais firefox ne se comporte pas comme vous le signalez, je ne peux donc pas vérifier cela)

Une autre solution (déjà mentionnée, je pense) est de construire / acheter / emprunter une zone de texte personnalisée (pas mal si simple, mais il y a toutes les touches d'édition, ctrl-C, ctrl-shift-gauche, etc.).

2 Vous souhaitez que les utilisateurs n'aient pas à se soucier de s'échapper.

Vous êtes en fuite-enfer:

Un remplacement de regex fonctionnera généralement ... mais comment pouvez-vous détecter de manière fiable le guillemet final ("), lorsque l'utilisateur peut (légitimement, dans les termes que vous avez donnés) entrer:

<Configuration>
  <Validator Expression="[^"<]" />
</Configuration>

En le regardant du point de vue de la syntaxe regex, il ne peut pas non plus dire si le " final; fait partie de la regex, ou la fin de celle-ci. La syntaxe regex résout généralement ce problème avec un terminateur explicite, par exemple:

/[^"<]/

Si les utilisateurs utilisaient cette syntaxe (avec le terminateur) et que vous écriviez un analyseur syntaxique, vous pourrez alors déterminer à quel moment la regex est terminée et par conséquent que la prochaine " caractère ne fait pas partie de l'expression rationnelle, mais fait partie de XML, et donc quelles parties doivent être échappées. Je ne dis pas que tu devrais ça! Je dis que c'est théoriquement possible. C'est assez loin d'être rapide et sale.

BTW: Le même problème se pose pour le texte dans un élément. Ce qui suit est légitime, dans les termes que vous avez donnés, mais présente les mêmes problèmes d’analyse:

<Configuration>
  <Expression></Expression></Expression>
</Configuration>

La règle de base dans une syntaxe qui autorise " n'importe quel texte " est que le délimiteur doit être échappé (par exemple " ou <)), afin que la fin puisse être reconnue. La plupart des syntaxes échappent également à d’autres tâches, pour des raisons de commodité et de désagrément. ( EDIT , le caractère d'échappement lui-même aura besoin d'un caractère d'échappement: pour XML, il s'agit de & "; \\ &"), qui, lorsque le littéral est échappé, & "&lt &" Pour regex, il s’agit du style C / unix & "<=> &", qui lorsque le littéral est échappé sous forme de & "; <>> !> quot;).

Vous pouvez imbriquer les syntaxes et vous vous retrouvez dans un enfer.

Une solution simple consiste à avertir vos utilisateurs: il s'agit d'un éditeur de configuration rapide et sale . Vous n'avez donc aucune fantaisie & ";" pas besoin d'échapper " mamby-pamby:

  • Liste les personnages et échappe à la suite dans la zone de texte, par exemple: " < " comme " <=> ".
  • Pour XML qui ne le fera pas validez, montrez-leur à nouveau la liste.

En regardant en arrière, je vois bobince a donné la même réponse de base devant moi.

Insérer CDATA autour de tout le texte vous donnerait un autre mécanisme d’échappement qui permettrait (1) d’éviter que les utilisateurs s’échappent manuellement et (2) de permettre la lecture correcte du texte automatiquement non échappé par la zone de texte.

 <Configuration>
   <Validator Expression="<![CDATA[  [^<]   ]]>" />
 </Configuration>

: -)

Ce caractère spécial - & "; < &"; - aurait dû être remplacé par d'autres caractères pour que votre code XML soit valide. Vérifiez ce lien pour les caractères spéciaux XML:

http://en.wikipedia.org/wiki/List_of_XML_et_HTML_character_reity_reities

Essayez également de coder votre contenu TextBlock avant de l'envoyer au désérialiseur:

HttpServerUtility utility = new HttpServerUtility();
string encodedText = utility.HtmlEncode(text);

Est-ce vraiment ma seule option? N’est-ce pas un problème assez courant pour qu’il trouve une solution quelque part dans le cadre?

private string EscapeAttributes(string configuration)
{
    var lt = @"(?<=\w+\s*=\s*""[^""]*)<(?=[^""]*"")";
    configuration = Regex.Replace(configuration, lt, "&lt;");

    return configuration;
}

(modifier: remplacement des esperluettes supprimées car cela pose des problèmes d’aller-retour)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top