challenge 一部のHTMLタグを通すフィルタ

ユーザが入力した文字列から、一部のタグだけを許可して他をエスケープするコードを書いてください。要件は次のようになります。
  • 通すタグはAとBRとSTRONGのみ。大文字小文字は区別しない。
  • それ以外のタグとして意味を持ちうる文字列は<を&lt;に変換することで無効化する(削除するのではない。>は変換してもしなくてもよい)
  • Aタグのhrefとname以外の属性は削除する。BRやSTRONGの属性はすべて削除する。

このお題はperezvonさんの提案を元にしています。ありがとうございました。 ただ、いきなりだと難しいかと思ったので、肝の部分以外を先に出題しました。このお題は続編で徐々に難しくなっていきます。

追記:属性に<や>が含まれてしまうケースに漏れのある解答が多いようなのでテストケースを追加します。
これは「この出力なら十分」という意味です。この出力の通りでなければいけないという意味ではありません。

<script foo="<script>alert('bar')</script>">alert('foo')</script>
&lt;script foo="&lt;script&gt;alert('bar')&lt;/script&gt;"&gt;alert('foo')&lt;/script&gt;


<script foo="<a href='link'>link</a>">alert('foo')</script>
&lt;script foo="&lt;a href='link'&gt;link&lt;/a&gt;"&gt;alert('foo')&lt;/script&gt;

<a href='www.g>oogle.com'>link</a>

<a href="./www.g%3Eoogle.com">link</a>

Posted feedbacks - C

ごり押しですが、strncasecmp に救われた気がします。
 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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define BUFSIZE 1024
char in[BUFSIZE];


int main( void ){

   char *p, *tmp;
   char q, attr=0, s='<';
   int len=0, remain;

   while( (remain = fgets( in + len, BUFSIZE - len, stdin )) || *p ) {
      for(p=in;*p;p++){
         if( remain && (len = strlen( p )) < strlen("<string") ){
            tmp = (char*)malloc( sizeof(char) * len );
            strcpy( tmp, p );
            strcpy( in, tmp );
            free(tmp);
            break;
         }
         if( s == '<' ){
            if( *p == '>' ){ printf("&gt;"); }
            else if( *p == '\'' || *p == '"' ){ putchar(s=*p); }
            else if( *p != '<' ){ putchar(*p); }
            else if( !strncasecmp( p, "</a>", 4) ){ printf("</a>"), attr=0; p+=3; }
            else if( !strncasecmp( p, "<br", 3 ) ){
               if( *(p+3) == '>' ){ printf("<br>"); p+=3; }
               else if( *(p+3) == ' ' ){ printf("<br");  p+=3; s='>'; }
            }
            else if( !strncasecmp( p, "<strong", 7 ) ){
               if( *(p+7) == '>' ){ printf("<strong>"); p+=7; }
               else if( *(p+7) == ' ' ){ printf("<strong");  p+=7; s='>'; }
            }
            else if( !strncasecmp( p, "<a", 2 ) ){
               if( *(p+2) == '>' ){ printf("<a>"); p+=2; }
               else if( *(p+2) == ' ' ){ printf("<a");  p+=2; s='@'; }
            }
            else{ printf("&lt;"); }
         }
         else if( s == '>' && *p == '>' ){ putchar(*p); s='<'; }
         else if( s == '@' ){
            q = *(p+5);
            if( *p == '>' ){ putchar(*p); s='<'; }
            else if( !strncasecmp( p, "href=", 5 ) && (q == '\'' || q == '"') ){
               printf(" href=%c", s=q ); p+=6; attr='h';
            }
            else if( !strncasecmp( p, "name=", 5 ) && (q == '\'' || q == '"') ){
               printf(" name=%c", s=q ); p+=6; attr='n';
            }
         }
         else if( s == '"' || s == '\'' ){
            if( !attr ){
               if (*p == '<' ){ printf("&lt;"); }
               else if( *p == '>' ){  printf("&gt;"); }
               else{ putchar(*p); }
            }
            else{
               if( *p == s ){ putchar(s); s='@'; }
               else if( *p == '\\' && *(p+1) == s ){ printf("\\%c",s), p+=1; }
               else if( attr=='h' && (tmp = strchr("!#$%'=|^\\[]`{}+<>", *p )) ){ printf("%%%X", *tmp); }
               else{ putchar(*p); }
            }
         }
      }
   }

   return 0;

}

Index

Feed

Other

Link

Pathtraq

loading...