2010-02-18 6 views
6

J'essaie de comprendre cette instruction RegEx en détails. Il est supposé valider le nom de fichier du contrôle ASP.Net FileUpload pour autoriser uniquement les fichiers jpeg et gif. Il a été conçu par quelqu'un d'autre et je ne le comprends pas complètement. Cela fonctionne très bien dans Internet Explorer 7.0 mais pas dans Firefox 3.6.Comprendre cette instruction RegEx

<asp:RegularExpressionValidator id="FileUpLoadValidator" runat="server" 
    ErrorMessage="Upload Jpegs and Gifs only." 
    ValidationExpression="^(([a-zA-Z]:)|(\\{2}\w+)\$?)(\\(\w[\w].*))(.jpg|.JPG|.gif|.GIF)$" 
    ControlToValidate="LogoFileUpload"> 
</asp:RegularExpressionValidator> 
+0

Vous ne savez pas pourquoi cela a été déclassé. –

+2

parce que c'est demander aux gens de pêcher pour lui, ne pas lui apprendre à pêcher. 3 upvotes vraiment? Postez un milion "ce que ce regex signifie" des questions je suppose. –

+0

Je suis d'accord avec Brian, c'est assez ridicule. –

Répondre

4

Ceci est une mauvaise regex.

^(([a-zA-Z]:)|(\\{2}\w+)\$?)(\\(\w[\w].*))(.jpg|.JPG|.gif|.GIF)$ 

Faisons-le partie par partie.

([a-zA-Z]:) 

Cela nécessite le chemin du fichier commence par un driveletter comme C:, d:, etc.

(\\{2}\w+)\$?) 

\\{2} signifie que la barre oblique inverse répétée deux fois (notez les \ a besoin d'être échappées), suivi de quelques caractères alphanumériques (\w+), et peut-être un signe dollar (\$?). C'est la partie hôte du chemin UNC. Le | signifie "ou". Donc soit commence par une lettre de lecteur ou un chemin UNC. Félicitations pour avoir chassé les utilisateurs non-Windows.

(\\(\w[\w].*)) 

Cela devrait la partie répertoire du chemin, mais est en fait 2 caractères alphanumériques suivis de quoi que ce soit, sauf nouvelles lignes (.*), comme \[email protected]#*(#$*).

Le regex approprié pour cette partie devrait être (?:\\\w+)+

(.jpg|.JPG|.gif|.GIF)$ 

Cela signifie que les 3 derniers caractères du chemin doit être jpg, JPG, gif ou GIF. Notez que . est pas un point, mais correspond à tout sauf \n, donc un nom de fichier comme haha.abcgif ou malicious.exe\0gif passera.

Le regex approprié pour cette partie devrait être \.(?:jpg|JPG|gif|GIF)$

Ensemble,

^(([a-zA-Z]:)|(\\{2}\w+)\$?)(\\(\w[\w].*))(.jpg|.JPG|.gif|.GIF)$ 

correspondront

D:\foo.jpg 
\\remote$\dummy\..\C:\Windows\System32\Logo.gif 
C:\Windows\System32\cmd.exe;--gif 

et échouera

/home/user/pictures/myself.jpg 
C:\a.jpg 
C:\d\e.jpg 

Le bon regex est /\.(?:jpg|gif)$/i et vérifier si le fichier téléchargé est vraiment une image sur le côté serveur.

+0

WOW! Merci beaucoup pour les détails. C'est ce que je cherchais. Résout mon problème. Toujours curieux de savoir pourquoi l'original ne fonctionne pas dans Firefox. Peut être un sujet pour une question distincte, mais probablement pas très pertinent pour le sujet principal ici. – myforums

+0

Désolé. Juste trouvé que '' ne fonctionne pas pour 'C: \ doc \ Mes images \ cat-fish.gif' – myforums

9

Voici une brève explication:

^    # match the beginning of the input 
(    # start capture group 1 
    (   # start capture group 2 
    [a-zA-Z] #  match any character from the set {'A'..'Z', 'a'..'z'} 
    :   #  match the character ':' 
)    # end capture group 2 
    |    # OR 
    (   # start capture group 3 
    \\{2}  #  match the character '\' and repeat it exactly 2 times 
    \w+   #  match a word character: [a-zA-Z_0-9] and repeat it one or more times 
)    # end capture group 3 
    \$?   # match the character '$' and match it once or none at all 
)    # end capture group 1 
(    # start capture group 4 
    \\   # match the character '\' 
    (   # start capture group 5 
    \w   #  match a word character: [a-zA-Z_0-9] 
    [\w]  #  match any character from the set {'0'..'9', 'A'..'Z', '_', 'a'..'z'} 
    .*   #  match any character except line breaks and repeat it zero or more times 
)    # end capture group 5 
)    # end capture group 4 
(    # start capture group 6 
    .    # match any character except line breaks 
    jpg   # match the characters 'jpg' 
    |    # OR 
    .    # match any character except line breaks 
    JPG   # match the characters 'JPG' 
    |    # OR 
    .    # match any character except line breaks 
    gif   # match the characters 'gif' 
    |    # OR 
    .    # match any character except line breaks 
    GIF   # match the characters 'GIF' 
)    # end capture group 6 
$    # match the end of the input 

EDIT

Comme certains de la demande de commentaires, ce qui précède est généré par un petit outil que j'ai écrit. Vous pouvez télécharger ici est: http://www.big-o.nl/apps/pcreparser/pcre/PCREParser.html (ATTENTION: fortement en développement!)

EDIT 2

Il en fonction de chaînes comme celles-ci:

x:\abc\def\ghi.JPG 
c:\foo\bar.gif 
\\foo$\baz.jpg 

Voici ce que les groupes 1, 4 et 6 individuellement correspondent à:

group 1 | group 4  | group 6 
--------+--------------+-------- 
     |    | 
x:  | \abc\def\ghi | .JPG 
     |    | 
c:  | \foo\bar  | .gif 
     |    | 
\\foo$ | \baz   | .jpg 
     |    | 

Notez qu'il correspond également à une chaîne comme c:\foo\[email protected] depuis le tapis DOT ches n'importe quel caractère (sauf les sauts de ligne). Et il rejettera une chaîne comme c:\foo\bar.Gif (capital G dans gif).

+0

Puis-je demander par ignorance quel outil vous avez utilisé pour cela? – Skilldrick

+0

Bart K. Pourriez-vous s'il vous plaît poster URL qui permet de faire ce genre d'analyse? – myforums

+0

+1 détaillé! Moi aussi je voudrais savoir si cela a été produit par un outil. – Pharabus

1

Il divise un nom de fichier en driveletter, chemin, nom de fichier et extension.

Très probablement IE utilise des barres obliques inverses tandis que FireFox utilise des barres obliques. Essayez de remplacer les \\ parts par [\\ /] afin que l'expression accepte les barres obliques et les barres obliques inverses.

+0

Non. Échanger \\ avec [\\\ /] n'a pas aidé. Ne fonctionne toujours pas dans Firefox. – myforums

0

De Expresso c'est ce que dit Expresso:

 
/// A description of the regular expression: 
/// 
/// Beginning of line or string 
/// [1]: A numbered capture group. [([a-zA-Z]:)|(\\{2}\w+)\$?] 
///  Select from 2 alternatives 
///   [2]: A numbered capture group. [[a-zA-Z]:] 
///    [a-zA-Z]: 
///     Any character in this class: [a-zA-Z] 
///     : 
///   (\\{2}\w+)\$? 
///    [3]: A numbered capture group. [\\{2}\w+] 
///     \\{2}\w+ 
///      Literal \, exactly 2 repetitions 
///      Alphanumeric, one or more repetitions 
///    Literal $, zero or one repetitions 
/// [4]: A numbered capture group. [\\(\w[\w].*)] 
///  \\(\w[\w].*) 
///   Literal \ 
///   [5]: A numbered capture group. [\w[\w].*] 
///    \w[\w].* 
///     Alphanumeric 
///     Any character in this class: [\w] 
///     Any character, any number of repetitions 
/// [6]: A numbered capture group. [.jpg|.JPG|.gif|.GIF] 
///  Select from 4 alternatives 
///   .jpg 
///    Any character 
///    jpg 
///   .JPG 
///    Any character 
///    JPG 
///   .gif 
///    Any character 
///    gif 
///   .GIF 
///    Any character 
///    GIF 
/// End of line or string 
/// 

Hope this helps, Meilleures salutations, Tom.

0

Vous devrez peut-être implémenter la validation côté serveur. Consultez cet article.

Solving the Challenges of ASP.NET Validation

En outre, il y a quelques bons outils en ligne pour la création ou l'interprétation des expressions Regex. mais je soupçonne que la question n'est pas avec l'expression.