サニタイザ
サニタイザとは、Web(HTML)環境におけるルーチンのひとつである。WikiWikiWebなどのWebシステムにおいては重要なものではあるが、このあたりはユーザと十分な議論と合意形成が必要なため、あまり話題にはのぼらない。
概要[編集]
WikiWikiWebに代表される HTML ベースのシステムは自前のマシンに Tomcat でも載せて JSP と併用すれば簡単に構築できる。これは個人環境においては不自由はない。
これが LAN 環境において協業のために利用されるようになると、「いちいちHTMLで書くのは手間がかかる」ことから WikiWikiWeb が普及した。ところが、「ウィキ のソースコードにHTMLを貼りつけたらどうなるか?」というのが問題になる。「&(アンパサンド)」「<」「>」「行頭のタブや半角スペース」は、HTML の記述と干渉(あるいは競合)してしまう。
このとき、「文字として受けいれていいのか、それとも HTML のコードとしてそのまんま通しちゃっていいのか」が問題になるわけで、そこを切り分けるのがサニタイザである。
「遠慮なく HTML5 のコードをぶっこむ」というひともいれば、「Wiki記法に即して、編集してくれているユーザ」もいる。そのとき、切り分けてくれるのがサニタイザである。
たとえば、
'&'は「&」に、
'<'は「<」に、
'>'は「>」に、
'"'は「"」に、
'''は「'」に、
' 'は「 」に、
'˜'は「˜」に、
'¥'は「¥」に、
'˜'は「˜」に、
'©'は「©」に、
書きかえるのがサニタイザの仕事である。このとき、「HTML のコードは 3 タブ、Java のコードは 4 タブ」とかいったルールでコーディングをしていると見た目が相当鬱陶しいことになるので、
- まずコードを指定の値で detab して、
- それからサニタイズする
という二段構えになる。
ところが、サニタイザの仕様はわかりやすい形で提示されてはいないので、どなたかに交通整理を行なっていただきたいと思っている。[1]
関連項目[編集]
その他[編集]
参考文献[編集]
脚注[編集]
- ↑ 幸いMediaWikiが存外馬鹿なせいで、変に気を使ったりはしない。おかげで仕事がやりやすく、定跡通りのコードを書けばJavaのコードが無事にインデントされた形で表示され、しかもEclipseにコピペすればちゃんと動きそうだ。これでようやくJavaのソースが晒せる。
サンプルコード[編集]
WebFitter.java[編集]
/**
*
* スクロール表示ができるように改造した。
* http://animaleconomicus.blog106.fc2.com/blog-entry-1359.html に掲載。
* 旧版が Sanitizer.java。
*/
import java.awt.BorderLayout;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
public class WebFitter extends JFrame {
private static JTextArea textArea;
public static void main( String[] args ) {
new WebFitter().setVisible(true);
}
/**
* コンストラクタだ。
*/
public WebFitter() {
this.setSize(400, 350);
this.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
this.setTitle("WebFitter");
this.addWindowListener(
new WindowAdapter() {
/**
* ウィンドウがアクティブになった。
*/
@Override
public void windowActivated( WindowEvent evnt ) {
String src = "";
try {
src = ClipBoardUtility.getTextFromClipBoard();
} catch( UnsupportedFlavorException excp ){
// 文字列以外のデータが入っていた。
excp.printStackTrace();
} catch ( IOException excp ) {
// エラーになった。
excp.printStackTrace();
}
// ここで Work を呼んでいる
// String dst = tools.Work.sanitize(src);
String dst = TextConverter.HTML_Sanitize(src);
textArea.setText(dst);
}
/**
* ウィンドウがアクティブでなくなった。
*/
@Override
public void windowDeactivated( WindowEvent e ) {
// 現在表示されている内容がクリップされる。
ClipBoardUtility.setTextToClipBoard(textArea.getText());
}
}
);
/**
* キーをタイプすると、その内容が入力される。
* バックスペースと漢字は未対応。
*/
this.addKeyListener(
new KeyAdapter() {
@Override
public void keyPressed( KeyEvent evnt ) {
String msg = textArea.getText() + evnt.getKeyChar();
textArea.setText(msg);
}
}
);
textArea = new JTextArea(5, 20);
textArea.setLineWrap(true);
// label.addMouseListener(MyMouseA0);
textArea.addMouseListener(
new MouseAdapter(){
@Override
public void mouseClicked( MouseEvent evnt ){
// ダブルクリックするとクリア
// なんか、かぶってる気がするんですが。
if ( evnt.getClickCount() == 2 ){
textArea.setText("");
}
}
}
);
// JFrame である Sanitizer_x に textArea を追加
// ここにスクロールペインが入るはず。t
/*
スクロールの必要がなければ、
直接 textArea を add することもできる。
this.add(textArea, BorderLayout.CENTER);
*/
JScrollPane sp = new JScrollPane(textArea);
this.add(sp, BorderLayout.CENTER);
String tmp = "";
try {
tmp = ClipBoardUtility.getTextFromClipBoard();
} catch( IOException excp ) {
// 文字列以外のデータが入っていた。
excp.printStackTrace();
} catch( UnsupportedFlavorException excp ){
// 文字列以外のデータが入っていた。
excp.printStackTrace();
}
textArea.setText("<pre>\n"+ tmp + "<\n></pre>\n");
}
}
TextConverter.java[編集]
/**
* HTML 用サニタイザ.
*
*
*/
public class TextConverter {
public static void main( String[] args ) {
}
public static String HTML_Sanitize( String src ) {
StringBuffer buf = new StringBuffer();
int posx = 0;
for (int pos = 0; pos < src.length(); pos += 1 ){
char ch = src.charAt(pos);
switch(ch) {
case '\t':
for (int n = 0; n < (4 - (posx % 4)); n += 1) {
buf.append(' ');
posx += 1;
}
break;
case '<':
buf.append("<");
posx += 1;
break;
case '>':
buf.append(">");
posx += 1;
break;
case '&':
buf.append("&");
posx += 1;
break;
case '\'':
buf.append("'");
posx += 1;
break;
case '\"':
buf.append(""");
posx += 1;
break;
case '\n':
buf.append('\n');
posx = 1;
break;
default:
buf.append(ch);
posx += 1;
break;
}
}
return ("<pre>\n"+ buf.toString() + "</pre>\n" );
}
}
ClipBoardUtility.java[編集]
/**
* main がないので、テスト用のルーチンがどこにあるのかは用件等。
*/
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.IOException;
import javax.swing.JFrame;
public class ClipBoardUtility {
/**
* クリップボードに入っているテキストの内容を取ってくる。
* 画像とかだったらいかがなものかと思うが。
* @return クリップボードに入っているテキスト
* @throws IOException
* @throws UnsupportedFlavorException
*/
public static String getTextFromClipBoard()
throws IOException, UnsupportedFlavorException {
return getTextFromClipBoard(null);
}
/**
*
* @param frame
* @return
* @throws IOException
* @throws UnsupportedFlavorException
*/
public static String getTextFromClipBoard( JFrame frame )
throws IOException, UnsupportedFlavorException {
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
Transferable object = clipboard.getContents(frame);
String str = (String)object.getTransferData(DataFlavor.stringFlavor);
return str;
}
/**
* クリップボードに指定のテキストをセットする。
* @param str
*/
public static void setTextToClipBoard( String str ){
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
StringSelection selection = new StringSelection(str);
clipboard.setContents(selection, null);
}
}