`
edwardpro
  • 浏览: 300562 次
  • 性别: Icon_minigender_1
社区版块
存档分类
最新评论

lexer html解析一个js过滤的改进

 
阅读更多

问题描述,使用htmlparser的lexer解析器进行页面解析时发现类似如下的页面会有问题:

 

 

<script>
for(i=0;i<a;i++){

}
</script>

解析后代码变成了:
<script>
for(i=0;i<a;i++){

}
></script>

 

 通过lexer代码发现,实际上只要js代码改成:

<script>
<!--
for(i=0;i<a;i++){

}
-->
</script>

 就不会有问题了,从代码中主要发现它的解析其实没有问题,主要是我们平时的页面规范做的不好,它在解析时会看到字符解析时发现<后面如果有字母就认为它是一个tag:

	protected Node parseString(int start, boolean quotesmart)
			throws ParserException {
		boolean done;
		char ch;
		char quote;

		done = false;
		quote = 0;
		while (!done) {
			ch = mPage.getCharacter(mCursor);
			if (Page.EOF == ch)
				done = true;
			else if (0x1b == ch) // escape
			{
				ch = mPage.getCharacter(mCursor);
				if (Page.EOF == ch)
					done = true;
				else if ('$' == ch) {
					ch = mPage.getCharacter(mCursor);
					if (Page.EOF == ch)
						done = true;
					// JIS X 0208-1978 and JIS X 0208-1983
					else if ('@' == ch || 'B' == ch)
						scanJIS(mCursor);
					/*
					 * // JIS X 0212-1990 else if ('(' == ch) { ch =
					 * mPage.getCharacter (mCursor); if (Page.EOF == ch) done =
					 * true; else if ('D' == ch) scanJIS (mCursor); else {
					 * mPage.ungetCharacter (mCursor); mPage.ungetCharacter
					 * (mCursor); mPage.ungetCharacter (mCursor); } }
					 */
					else {
						mPage.ungetCharacter(mCursor);
						mPage.ungetCharacter(mCursor);
					}
				} else
					mPage.ungetCharacter(mCursor);
			} else if (quotesmart && (0 == quote)
					&& (('\'' == ch) || ('"' == ch)))
				quote = ch; // enter quoted state
			// patch from Gernot Fricke to handle escaped closing quote
			else if (quotesmart && (0 != quote) && ('\\' == ch)) {
				ch = mPage.getCharacter(mCursor); // try to consume escape
				if ((Page.EOF != ch) && ('\\' != ch) // escaped backslash
						&& (ch != quote)) // escaped quote character
					// ( reflects ["] or ['] whichever opened the quotation)
					mPage.ungetCharacter(mCursor); // unconsume char if char not
													// an escape
			} else if (quotesmart && (ch == quote))
				quote = 0; // exit quoted state
			else if (quotesmart && (0 == quote) && (ch == '/')) {
				// handle multiline and double slash comments (with a quote)
				// in script like:
				// I can't handle single quotations.
				ch = mPage.getCharacter(mCursor);
				if (Page.EOF == ch)
					done = true;
				else if ('/' == ch) {
					do
						ch = mPage.getCharacter(mCursor);
					while ((Page.EOF != ch) && ('\n' != ch));
				} else if ('*' == ch) {
					do {
						do
							ch = mPage.getCharacter(mCursor);
						while ((Page.EOF != ch) && ('*' != ch));
						ch = mPage.getCharacter(mCursor);
						if (ch == '*')
							mPage.ungetCharacter(mCursor);
					} while ((Page.EOF != ch) && ('/' != ch));
				} else
					mPage.ungetCharacter(mCursor);
			} else if ((0 == quote) && ('<' == ch)) {
				ch = mPage.getCharacter(mCursor);
				if (Page.EOF == ch)
					done = true;
				// the order of these tests might be optimized for speed:
				else if ('/' == ch
						|| Character.isLetter(ch)
						|| '!' == ch || '%' == ch || '?' == ch) {
					done = true;
					mPage.ungetCharacter(mCursor);
					mPage.ungetCharacter(mCursor);
				} else {
					// it's not a tag, so keep going, but check for quotes
					mPage.ungetCharacter(mCursor);
				}
			}
		}

		return (makeString(start, mCursor.getPosition()));
	}

 因此为了解决这个问题,现在要在上面做一个手脚:

首先在类中间增加了一个标记,script

这个标记是修改了nexNode方法,在返回前判断下是否前一个标签是<script> 或者</script>

然后在parseString中修改其解析方法就可以了,下面是完整的代码:

import java.net.URLConnection;

import org.htmlparser.Node;
import org.htmlparser.lexer.Lexer;
import org.htmlparser.lexer.Page;
import org.htmlparser.nodes.TagNode;
import org.htmlparser.util.ParserException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author edwardpro
 * 
 */
public class LexerFixed extends Lexer {
	private static final Logger logger = LoggerFactory
			.getLogger(LexerFixed.class);

	/**
	 * 
	 */
	private static final long serialVersionUID = 8425806017089419815L;

	//script标签标记,如果发现当前在script里就掠过所有的< >
	private int script=0;

	/**
	 * 
	 */
	public LexerFixed() {
		super();
	}

	/**
	 * @param page
	 */
	public LexerFixed(Page page) {
		super(page);
	}

	/**
	 * @param text
	 */
	public LexerFixed(String text) {
		super(text);
	}

	/**
	 * @param connection
	 * @throws ParserException
	 */
	public LexerFixed(URLConnection connection) throws ParserException {
		super(connection);
	}

	@Override
	public Node nextNode(boolean quotesmart) throws ParserException {
		Node ret = super.nextNode(quotesmart);
		checkTag(ret);
		return (ret);
	}

	/**
	 * checkTag用于修改tagNode的方法当有入参数时都会进行一次参数修正另外對內容進行一下escape操作並且會進行判斷是否存在已經escape的蹟象
	 * 
	 * @param node
	 */
	private void checkTag(Node node) {
		if (node != null && node instanceof TagNode
				&& !((TagNode) node).isEmptyXmlTag()) {
			String tagName = ((TagNode) node).getTagName();
			if("SCRIPT".equalsIgnoreCase(tagName)){
				if (!((TagNode) node).isEndTag() ) {
					this.script=1;
				} else{
					this.script=0;
				}
			}
		}
	}

	@Override
	protected Node parseString(int start, boolean quotesmart)
			throws ParserException {
		boolean done;
		char ch;
		char quote;

		done = false;
		quote = 0;
		while (!done) {
			ch = mPage.getCharacter(mCursor);
			if (Page.EOF == ch)
				done = true;
			else if (0x1b == ch) // escape
			{
				ch = mPage.getCharacter(mCursor);
				if (Page.EOF == ch)
					done = true;
				else if ('$' == ch) {
					ch = mPage.getCharacter(mCursor);
					if (Page.EOF == ch)
						done = true;
					// JIS X 0208-1978 and JIS X 0208-1983
					else if ('@' == ch || 'B' == ch)
						scanJIS(mCursor);
					/*
					 * // JIS X 0212-1990 else if ('(' == ch) { ch =
					 * mPage.getCharacter (mCursor); if (Page.EOF == ch) done =
					 * true; else if ('D' == ch) scanJIS (mCursor); else {
					 * mPage.ungetCharacter (mCursor); mPage.ungetCharacter
					 * (mCursor); mPage.ungetCharacter (mCursor); } }
					 */
					else {
						mPage.ungetCharacter(mCursor);
						mPage.ungetCharacter(mCursor);
					}
				} else
					mPage.ungetCharacter(mCursor);
			} else if (quotesmart && (0 == quote)
					&& (('\'' == ch) || ('"' == ch)))
				quote = ch; // enter quoted state
			// patch from Gernot Fricke to handle escaped closing quote
			else if (quotesmart && (0 != quote) && ('\\' == ch)) {
				ch = mPage.getCharacter(mCursor); // try to consume escape
				if ((Page.EOF != ch) && ('\\' != ch) // escaped backslash
						&& (ch != quote)) // escaped quote character
					// ( reflects ["] or ['] whichever opened the quotation)
					mPage.ungetCharacter(mCursor); // unconsume char if char not
													// an escape
			} else if (quotesmart && (ch == quote))
				quote = 0; // exit quoted state
			else if (quotesmart && (0 == quote) && (ch == '/')) {
				// handle multiline and double slash comments (with a quote)
				// in script like:
				// I can't handle single quotations.
				ch = mPage.getCharacter(mCursor);
				if (Page.EOF == ch)
					done = true;
				else if ('/' == ch) {
					do
						ch = mPage.getCharacter(mCursor);
					while ((Page.EOF != ch) && ('\n' != ch));
				} else if ('*' == ch) {
					do {
						do
							ch = mPage.getCharacter(mCursor);
						while ((Page.EOF != ch) && ('*' != ch));
						ch = mPage.getCharacter(mCursor);
						if (ch == '*')
							mPage.ungetCharacter(mCursor);
					} while ((Page.EOF != ch) && ('/' != ch));
				} else
					mPage.ungetCharacter(mCursor);
			} else if ((0 == quote) && ('<' == ch)) {
				ch = mPage.getCharacter(mCursor);
				if (Page.EOF == ch)
					done = true;
				// the order of these tests might be optimized for speed:
				else if ('/' == ch
						|| (Character.isLetter(ch) && this.script==0)
						|| '!' == ch || '%' == ch || '?' == ch) {
					done = true;
					mPage.ungetCharacter(mCursor);
					mPage.ungetCharacter(mCursor);
				} else {
					// it's not a tag, so keep going, but check for quotes
					mPage.ungetCharacter(mCursor);
				}
			}
		}

		return (makeString(start, mCursor.getPosition()));
	}
}
 
分享到:
评论

相关推荐

    Lexar雷克沙U盘加密软件EncryptStick Lite官方版.rar

    本应用程序仅用于Lexar闪存盘。通过加密软件对U盘进行高达256位的AES加密来保护数据安全,创建唯一的密码保护,支持文件粉碎功能,让U盘中的数据更安全。保护你的文件不被未授权的人打开,避免数据误删和丢失,创建...

    雷克沙U盘u盘量产工具.zip

    雷克沙U盘u盘量产工具.zip

    LEXAR固态硬盘加密程序

    雷克沙固态硬盘加密程序

    雷克沙萤火虫16GU盘量产工具.rar

    软件介绍: 坛友共享出来的16G的雷克沙萤火虫...所使用的软件版本分别是慧荣V2.03.67(支持更多SMI主控型号)和V2.03.47(仅支持SM3255ENA1芯片),如果你有此型号U盘,可以下载试一试。主程序为sm32Xtest,设置密码是320

    SMIMPTool2.5.30_v7雷克沙u盘量产工具.rar

    SMIMPTool2.5.30_v7雷克沙u盘量产工具.rar

    雷克沙u盘加密软件

    插上雷克沙u盘方可使用 支持加密储存区 加密文件文件夹 文件粉碎

    lexar_usb_tool.zip

    部分老u盘可用的boot启动盘制作工具,只支持usb2.0的接口,对于大多数现在的u盘无效,手头有老U盘的朋友可以试试,免费分享,有需要自取

    图片恢复软件Lexar Image Rescue 2.0.rar

    Lexar Media Image Rescue: Image Recovery 2.0是一个专业的图片恢复工具;Image Recovery图片恢复;Card Test存储卡测试;Format Card存储卡内存卡;Secure Erase存储卡内存卡;可以恢复以下格式的图片:...

    加密软件 U盘加密 实用程序

    加密操作简易 支持拖放加密,右键加密,主程序中加密。   三种加密强度 三种加密强度,可以满足各层次用户的需要   多种加密设置 新加入各种自定义设置,轻松打造满足您个人需要的加密文件夹 ...

    程序员考试刷题-SIP2017-Online-Quizzing-Website:PrekshaPandey制作的2017年暑期实习计划项目

    之所以推出在线考试,是因为需要一个对准备 JEE 和其他类似考试的学生有益的网站。 我们经常看到,线下检查很费时间,而且往往会延迟出结果。 通过这个网站,学生可以进行考试并查看他们的成绩。 因此,该站点的目的...

    U盘加密,移动硬盘加密

    可以方便地加密任意文件夹,并且支持U盘加密,移动硬盘加密。人性化设置,简单易用,即使是电脑新手,十秒就能掌握操作。加密速度极快,上百 G 的数据仅需1秒钟完成。 没有大小限制。本软件为绿色免费软件,无须安装,...

    U盘量产工具.rar

    能够将U盘量产为几部分,光驱、硬盘、移动硬盘,对大容量U盘非常有用。

    慧荣sm32Xtest_V2.03.67 12/03/02.rar

    软件介绍: 设置密码320sm32Xtest_V2.03.08_v3.exe - for ~ SM32xsm32Xtest_V2.03.32_v4.exe - for ~ SM32(x_54x)sm32Xtest_V2.03.50_v5_K0928.exe - for ~ SM325(5x_7x)sm32Xtest_V2.03.64_v3_L0104....

    U盘(Mass Storage Device)读取过程剖析

    利用USB分析仪捕捉了Windows Vista读取Lexar Firefly 1GB的过程

    神虎科技 数据恢复软件

    文件恢复是一款简单易用的软件,在整个恢复过程中,不需要您有多么高深的技术知识,只需您通过使用它简单的图形操作界面,即可随心操作。只要启动该程序,选择合适的模块,点击按钮“下一步”,预览可恢复的文件,并...

    慧荣方案U盘量产工具H1226汉化版

    慧荣方案U盘量产工具汉化版,可以量产LEXAR 引火虫U盘。

    分区数据恢复工具 7-Data Partition Recovery 1.9 中文多语免费版.zip

    7-Data Partition Recovery 是由香港 SharpNight 开发的的一款功能强大、专业有效的分区恢复软件,并且为中文界面企业版本,即下即用。该软件界面简洁大方,使用操作方便,免费是用来设计恢复数据丢失,删除或损坏的...

    江波龙(301308):22年或利空出尽,23年周期复苏+信创+ChatGPT应用落地高成长可期.docx

    预计价格见底后,公司 23 年业绩有望逐季度改善,库存有望好转,看好 23 年周期+消费需求复苏叠加信创催化企业级需求下,公司企业级产品推出享受信创及 ChatGPT 市场红利、Lexar 新产品持续推出+高端消费品牌价值...

    centural_source

    第一步首先,您必须安装 (如果您打算运行整个项目,请继续安装包含 。然后,我强烈建议您研究这是我们开发Minecraft Vanilla Datapacks的主要推动力。 第二步从项目的父目录中运行命令dart .\core.dart ,将...

    centural_framework:Centural Ledger的后端应用程序框架

    中枢框架Centural Ledger的后端应用程序框架目前如何使用第一步首先,您必须安装 (如果您打算运行整个项目,请继续安装包含 。然后,我强烈建议您研究这是我们开发Minecraft Vanilla Datapacks的主要推动力。 第二...

Global site tag (gtag.js) - Google Analytics