IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Scripts/Batch Discussion :

EscapeDataString et paranthèses [PowerShell]


Sujet :

Scripts/Batch

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Inscrit en
    Juin 2008
    Messages
    47
    Détails du profil
    Informations personnelles :
    Âge : 44

    Informations forums :
    Inscription : Juin 2008
    Messages : 47
    Par défaut EscapeDataString et paranthèses
    Bonjour à tous,

    Je suis en train de rédiger un script qui fait appel à la fonction [URI]::EscapeDataString().

    Ce qui est étrange, c'est que le résultat de l'appel à cette fonction me donne un résultat différent si je joue le script via ISE ou direct sur une invite PowerShell (cf. PJ).
    En ISE les parenthèses sont correctement encodées, sous Powershell elles ne le sont pas.
    J'ai vu que la fonction donnait des résultats différents entre le FX 4.0 et le 4.5, cf. l'échange ici : https://github.com/restsharp/RestSharp/issues/1104

    Aussi, je me suis dit que le contexte d'exécution devait utiliser une version différente du framework, j'ai donc ajouté cet ordre au script : [System.Reflection.Assembly]::GetExecutingAssembly().ImageRuntimeVersion
    A ma grande surprise, les 2 execs donne la même valeur de framework.

    Une idée ? sachant que dans mon cas j'ai bien besoin que les parenthèses soient échappées.

    Merci,
    Images attachées Images attachées  

  2. #2
    Membre confirmé
    Homme Profil pro
    Lycéen
    Inscrit en
    Avril 2016
    Messages
    18
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 25
    Localisation : France, Vosges (Lorraine)

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Avril 2016
    Messages : 18
    Par défaut
    Bonjour,

    Si on regarde le code source (ici : https://referencesource.microsoft.co...b4c38749000c9b ), on peut voir que Powershell va utiliser la version V2 si le target framework est inférieur à 4.5 sinon, il va utiliser la version V3 du UriParser.

    (le code en question)
    Code c# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    private enum UriQuirksVersion {
        // V1 = 1, // RFC 1738 - Not supported
        V2 = 2, // RFC 2396
        V3 = 3, // RFC 3986, 3987
    }
     
    // Store in a static field to allow for test manipulation and emergency workarounds via reflection.
    // Note this is not placed in the Uri class in order to avoid circular static dependencies.
    private static readonly UriQuirksVersion s_QuirksVersion =
        (BinaryCompatibility.TargetsAtLeast_Desktop_V4_5
            // || BinaryCompatibility.TargetsAtLeast_Silverlight_V6
            // || BinaryCompatibility.TargetsAtLeast_Phone_V8_0
        ) ? UriQuirksVersion.V3 : UriQuirksVersion.V2;
     
    internal static bool ShouldUseLegacyV2Quirks {
        get {
            return s_QuirksVersion <= UriQuirksVersion.V2;
        }
    }

    Probablement plus d'infos ici : https://www.py4u.net/discuss/744693


    On peut tester ça en runtime avec la commande suivante :
    Code powershell : Sélectionner tout - Visualiser dans une fenêtre à part
    [System.UriParser].GetField('s_QuirksVersion', [Reflection.BindingFlags] 'Static, NonPublic').GetValue($null)

    Voici ce que j'obtiens :
    Nom : Capture d’écran 2021-09-06 182717.png
Affichages : 142
Taille : 66,1 Ko


    En intégrant la solution d'ici (pour appliquer la RFC 3986) : https://stackoverflow.com/questions/...-with-rfc-3986
    On peut aboutir à ce code :

    Code powershell : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    if (-not ([System.Management.Automation.PSTypeName]'PowerShell.Uri3986').Type) {
        Add-Type "
        using System;
        using System.Text;
        namespace PowerShell
        {
            public static class Uri3986
            {
                public static string EscapeUriString(string s)
                {
                    StringBuilder sb = new StringBuilder(s.Length*2);
                    byte[] arr = Encoding.UTF8.GetBytes(s);
     
                    for (int i = 0; i < arr.Length; i++)
                    {
                        byte c = arr[i];
     
                        if(c >= 0x41 && c <=0x5A)//alpha
                            sb.Append((char)c);
                        else if(c >= 0x61 && c <=0x7A)//ALPHA
                            sb.Append((char)c);
                        else if(c >= 0x30 && c <=0x39)//123456789
                            sb.Append((char)c);
                        else if (c == '-' || c == '.' || c == '_' || c == '~')
                            sb.Append((char)c);
                        else
                        {
                            sb.Append('%');
                            sb.Append(Convert.ToString(c, 16).ToUpper());
                        }
                    }
                    return sb.ToString();
                }
            }
        }"
    }
     
    [PowerShell.Uri3986]::EscapeUriString("()")

    J'obtiens maintenant ceci :
    Nom : Capture d’écran 2021-09-06 194708.png
Affichages : 118
Taille : 90,5 Ko

  3. #3
    Membre averti
    Inscrit en
    Juin 2008
    Messages
    47
    Détails du profil
    Informations personnelles :
    Âge : 44

    Informations forums :
    Inscription : Juin 2008
    Messages : 47
    Par défaut
    Merci pour ce retour.

    En effet, j'obtiens v2 sous PowerShell et v3 sous ISE.

    J'ai contourné le problème de façon un peu identique mais plus "cracra" en faisant cela.

    Code PowerShell : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
    function Encoder-Chaine {
     
        param (
            [parameter(Mandatory=$true)] [string] $chaine
        )
     
        $encode = [Uri]::EscapeDataString($chaine)
     
        $speciaux = @("!", "*", "'", "(", ")")
        foreach ($special in $speciaux) {
            $encode = $encode.Replace($special, [Uri]::HexEscape($special))
        }
     
        $encode
    }

    Je vais adapter ma fonction en m'inspirant de celle proposée.

    Peut-être un début d'explication, j'ai dans le powershell_ise.exe.config la section suivante

    <startup useLegacyV2RuntimeActivationPolicy="true">
    <supportedRuntime version="v4.0" />
    </startup>

    Cette section n'est pas dans le powershell.exe.config.

    Je voulais modifier le powershell.exe.config pour y ajouter la section mais même en compte admin le fichier est en lecture seule et, s'agissant d'un poste pro, je n'ai pas trop envie de jouer avec les droits sur ce fichier.

    [edit]
    Marrant, je viens de voir que le code proposé en premier dans le lien est très proche de ma version.
    [/edit]

  4. #4
    Membre confirmé
    Homme Profil pro
    Lycéen
    Inscrit en
    Avril 2016
    Messages
    18
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 25
    Localisation : France, Vosges (Lorraine)

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Avril 2016
    Messages : 18
    Par défaut
    Attention, ton code ne respecte pas la RFC 3986. C'est pas forcément grave.
    Mais ça peut donner des résultats différents et donc incompatible.

    J'ai transpilé le code en powershell et j'ai rajouté la fonction pour unescape :

    Code powershell : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    function Escape {
        param (
            [parameter(Mandatory=$true)] [string] $string
        )
        $e = ""
        $arr = [system.Text.Encoding]::UTF8.GetBytes($string)
        foreach ($c in $arr) {
            if ($c -ge 0x41 -and $c -le 0x5A) {#alpha
                $e += [System.Text.Encoding]::ASCII.GetString($c)
            } elseif ($c -ge 0x61 -and $c -le 0x7A) {#ALPHA
                $e += [System.Text.Encoding]::ASCII.GetString($c)
            } elseif ($c -ge 0x30 -and $c -le 0x39) {#123456789
                $e += [System.Text.Encoding]::ASCII.GetString($c)
            } elseif ($c -eq [int][char]'-' -or $c -eq [int][char]'.' -or $c -eq [int][char]'_' -or $c -eq [int][char]'~') {
                $e += [System.Text.Encoding]::ASCII.GetString($c)
            } else {
                $e += "%"
                $e += [System.Convert]::ToString($c,16).ToUpper()
            }
        }
        $e
    }
    function Unescape {
        param (
            [parameter(Mandatory=$true)] [string] $string
        )
        $e = ""
        $arr = [regex]::split($string, '%?([0-9A-F]{2})|(.)') | ? {$_} 
        $bytes = @()
        foreach ($c in $arr) {
            if ($c.length -eq 2) {
                $bytes += [Convert]::ToInt32($c, 16)
            } else {
                $bytes += [int]$c
            }
        }
        [System.Text.Encoding]::UTF8.GetString($bytes)
    }
     
    $escape = Escape -string "()"
    $escape
     
    $unescape = Unescape -string $escape
    $unescape

  5. #5
    Membre averti
    Inscrit en
    Juin 2008
    Messages
    47
    Détails du profil
    Informations personnelles :
    Âge : 44

    Informations forums :
    Inscription : Juin 2008
    Messages : 47
    Par défaut
    Pour en dire un peu plus.

    Le but de la fonction est d'encoder les paramètres qui sont envoyés à l'API Twitter (url, x-www-form-urlencoded ou multipart/form-data suivant l'appel).

    J'ai adapté ta fonction d'encodage pour 2 raisons :
    1 - les gouts et les couleurs - j'ai préféré des -or sur les conditions pour ne pas répéter le code d'ajout et je suis passé par un StringBuilder
    2 - un problème d'appel à l'API Twitter avec la fonction

    Concernant 2, ce qu'il se passe c'est que lorsqu'on Tweete par l'API, on peut envoyer des retours charriots.

    Dans ta version, l'encodage de "`r`n" donne "%D%A", ce que Twitter n'a pas l'air d'accepter.
    Je ne sais pas si c'est propre à la RFC mais lui semble attendre le code hexa sur 2 caractères soit %0D%0A

    J'ai donc changer
    Code PowerShell : Sélectionner tout - Visualiser dans une fenêtre à part
    [System.Convert]::ToString($c,16).ToUpper()
    en
    Code PowerShell : Sélectionner tout - Visualiser dans une fenêtre à part
    [Uri]::HexEscape($octet)

    Le code complet est disponible ici : https://github.com/CD30-Devil/SI3P0/...ns_twitter.ps1

    @Flammrock : Je t'ai mentionné dans l'entête de la méthode, j'espère que cela ne te pose pas de pb...

  6. #6
    Membre confirmé
    Homme Profil pro
    Lycéen
    Inscrit en
    Avril 2016
    Messages
    18
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 25
    Localisation : France, Vosges (Lorraine)

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Avril 2016
    Messages : 18
    Par défaut
    Nan ça ne me dérange pas que tu me cite. Par contre, bien vu pour le problème du "`r`n" qui donne "%D%A".
    Et oui dans la RFC il faut bien 2 caractères :

    2.1. Percent-Encoding

    A percent-encoding mechanism is used to represent a data octet in a
    component when that octet's corresponding character is outside the
    allowed set or is being used as a delimiter of, or within, the
    component. A percent-encoded octet is encoded as a character
    triplet, consisting of the percent character "%" followed by the two
    hexadecimal digits representing that octet's numeric value. For
    example, "%20" is the percent-encoding for the binary octet
    "00100000" (ABNF: %x20), which in US-ASCII corresponds to the space
    character (SP). Section 2.4 describes when percent-encoding and
    decoding is applied.

    pct-encoded = "%" HEXDIG HEXDIG

    The uppercase hexadecimal digits 'A' through 'F' are equivalent to
    the lowercase digits 'a' through 'f', respectively. If two URIs
    differ only in the case of hexadecimal digits used in percent-encoded
    octets, they are equivalent. For consistency, URI producers and
    normalizers should use uppercase hexadecimal digits for all percent-
    encodings.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. indicateur de groupe de paranthèse et d'accolades
    Par Battant dans le forum Eclipse
    Réponses: 1
    Dernier message: 20/05/2009, 09h35
  2. [CS3] Coloration des paranthèses et accolades
    Par Tchupacabra dans le forum Dreamweaver
    Réponses: 3
    Dernier message: 22/09/2008, 10h34
  3. [RegEx] Problème de balises /paranthèses imbriquée
    Par bugmenot dans le forum Langage
    Réponses: 6
    Dernier message: 17/04/2007, 21h08
  4. question de paranthèse?
    Par deubelte dans le forum C++
    Réponses: 1
    Dernier message: 28/01/2007, 00h43
  5. Problème de paranthèse manquante
    Par mariemor64 dans le forum Général JavaScript
    Réponses: 14
    Dernier message: 21/07/2006, 17h05

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo