一部のHTMLタグを通すフィルタ
Posted feedbacks - awk
まあ普通こういう処理はawkではしませんが・・・
% awk -f filter.awk
<script foo="<script>alert('bar')</script>">alert('foo')</script>
<script foo="<script>alert('bar')</script>">alert('foo')</script>
<script foo="<a href='link'>link</a>">alert('foo')</script>
<script foo="<a href='link'>link</a>">alert('foo')</script>
<a href='www.g>oogle.com'>link</a>
<a href="./www.g%3Eoogle.com">link</a>
なお、タグの途中に改行が含まれるケースには対応していません。
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 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 | BEGIN {
ok_tag["A"] = ok_tag["BR"] = ok_tag["STRONG"] = 1
}
/<[A-Za-z]+/ {
delete attributes
s = $0
while (match(s,/<[A-Za-z]+/)) {
if (RSTART > 1) print substr(s,1,RSTART-1)
tag = substr(s,RSTART+1,RLENGTH-1)
s = substr(s,RSTART+RLENGTH)
if (s ~ /^>/) {
s = substr(s,2)
} else {
while (s != "") {
gsub(/^[ \t\r\n]*/,"",s)
if (match(s,/^[A-Za-z]+=/)) {
attribute = substr(s,1,RLENGTH-1)
s = substr(s,RLENGTH+1)
if (match(s,/^("[^"]*"|'[^']*'|[^"'> ]*)/)) {
value = substr(s,1,RLENGTH)
attributes[attribute] = value
s = substr(s,RLENGTH+1)
}
} else if (s ~ /^>/) {
s = substr(s,2)
break
} else {
break
}
}
}
tag_ = toupper(tag)
if (ok_tag[tag_]) {
if (tag_ == "A") {
for (attr in attributes)
if (toupper(attr) !~ /^(HREF|NAME)$/) delete attributes[attr]
} else { #if (tag ~ /^(BR|STRONG)$/)
delete attributes
}
printf("<%s", tag)
for (attr in attributes) {
value = urlencode(attributes[attr])
gsub(/(^["']|["']$)/,"",value)
if (toupper(attr) == "HREF") {
printf(" %s=\"./%s\"", attr, value)
} else {
printf(" %s=\"%s\"", attr, value)
}
}
printf(">")
} else {
printf("<%s", tag) # substr(s,RSTART+RLENGTH)
for (attr in attributes) {
printf(" %s=%s", attr, escape(attributes[attr]))
}
printf(">")
}
}
if (match(s,/<\/[A-Za-z]+>/)) {
content = substr(s,1,RSTART-1)
close_tag = substr(s,RSTART+2,RLENGTH-3)
s = substr(s,RSTART+RLENGTH)
if (content != "") printf("%s", escape(content))
tag_ = toupper(close_tag)
if (ok_tag[tag_]) {
printf("</%s>", close_tag)
} else {
printf("</%s>", close_tag)
}
} else if (s != "") {
printf("%s", s)
}
printf "\n"
next
}
{ print }
function escape(s)
{
gsub(/</,"\\<",s)
gsub(/>/,"\\>",s)
return s
}
function urlencode(s)
{
# gsub(/ /,"%20",s)
gsub(/</,"%3C",s)
# gsub(/=/,"%3D",s)
gsub(/>/,"%3E",s)
return s
}
|


にしお
#3410()
Rating0/0=0.00
このお題はperezvonさんの提案を元にしています。ありがとうございました。 ただ、いきなりだと難しいかと思ったので、肝の部分以外を先に出題しました。このお題は続編で徐々に難しくなっていきます。
追記:属性に<や>が含まれてしまうケースに漏れのある解答が多いようなのでテストケースを追加します。 これは「この出力なら十分」という意味です。この出力の通りでなければいけないという意味ではありません。 <script foo="<script>alert('bar')</script>">alert('foo')</script> <script foo="<script>alert('bar')</script>">alert('foo')</script> <script foo="<a href='link'>link</a>">alert('foo')</script> <script foo="<a href='link'>link</a>">alert('foo')</script> <a href='www.g>oogle.com'>link</a> <a href="./www.g%3Eoogle.com">link</a>[ reply ]