[Bbs2ch-cvs 428] [410] ServerScript を JSM にした

Back to archive index

svnno****@sourc***** svnno****@sourc*****
2008年 3月 15日 (土) 23:50:01 JST


Revision: 410
          http://svn.sourceforge.jp/cgi-bin/viewcvs.cgi?root=bbs2ch&view=rev&rev=410
Author:   flyson
Date:     2008-03-15 23:50:00 +0900 (Sat, 15 Mar 2008)

Log Message:
-----------
ServerScript を JSM にした

Modified Paths:
--------------
    trunk/bbs2chreader/components/b2rServer.js

Added Paths:
-----------
    trunk/bbs2chreader/chrome/content/bbs2chreader/server/skin.jsm
    trunk/bbs2chreader/chrome/content/bbs2chreader/server/thread.jsm

Removed Paths:
-------------
    trunk/bbs2chreader/chrome/content/bbs2chreader/server/skin.js
    trunk/bbs2chreader/chrome/content/bbs2chreader/server/thread.js


-------------- next part --------------
Deleted: trunk/bbs2chreader/chrome/content/bbs2chreader/server/skin.js
===================================================================
--- trunk/bbs2chreader/chrome/content/bbs2chreader/server/skin.js	2008-03-15 13:03:28 UTC (rev 409)
+++ trunk/bbs2chreader/chrome/content/bbs2chreader/server/skin.js	2008-03-15 14:50:00 UTC (rev 410)
@@ -1,74 +0,0 @@
-this.script = {
-
-	start: function(aServerHandler){
-		var filePath = aServerHandler.requestURL.filePath.substring(6);
-		var skinFile = this.resolveSkinFile(filePath);
-
-			// File Not Found
-		if(!skinFile.exists()){
-			aServerHandler.sendErrorPage(404, aServerHandler.requestURL.spec);
-			return;
-		}
-
-		var lastModifiedString = new Date(skinFile.lastModifiedTime).toUTCString();
-		aServerHandler.setResponseHeader("Last-Modified", lastModifiedString);
-		aServerHandler.setResponseHeader("Cache-Control", "max-age=0, must-revalidate");
-
-			// If-Modified-Since ‚ª‘¶Ý‚µƒtƒ@ƒCƒ‹‚ªXV‚³‚ê‚Ä‚¢‚È‚¯‚ê‚Î 304
-		if(aServerHandler.requestHeaders["If-Modified-Since"]){
-			var lastModified = parseInt(new Date(skinFile.lastModifiedTime).getTime() / 1000);
-			var ifLastModified = parseInt(new Date(aServerHandler.requestHeaders["If-Modified-Since"]).getTime() / 1000);
-			if(lastModified == ifLastModified){
-				aServerHandler.writeResponseHeader(304);
-				aServerHandler.close();
-				return;
-			}
-		}
-
-		var mimeService = Components.classes["@mozilla.org/uriloader/external-helper-app-service;1"]
-								.getService(Components.interfaces.nsIMIMEService);
-		var contentType = mimeService.getTypeFromFile(skinFile);
-		aServerHandler.setResponseHeader("Content-Type", contentType);
-		aServerHandler.writeResponseHeader(200);
-		var fileStream = Components.classes["@mozilla.org/network/file-input-stream;1"]
-							.createInstance(Components.interfaces.nsIFileInputStream);
-		fileStream.init(skinFile, 0x01, 0444, fileStream.CLOSE_ON_EOF);
-		aServerHandler._output.writeFrom(fileStream, skinFile.fileSize);
-		fileStream.close();
-		aServerHandler.close();
-	},
-
-	cancel: function(){
-	},
-
-	resolveSkinFile: function(aFilePath){
-		var b2rService  = Components.classes["@bbs2ch.sourceforge.jp/b2r-global-service;1"]
-				.getService(Components.interfaces.b2rIGlobalService);
-		var pref = Components.classes["@mozilla.org/preferences-service;1"]
-				.getService(Components.interfaces.nsIPrefBranch);
-
-		var skinName = pref.getComplexValue("extensions.bbs2chreader.thread_skin",
-							Components.interfaces.nsISupportsString).data;
-
-		var skinFile = null;
-		if(skinName){
-			skinFile = b2rService.io.getDataDir();
-			skinFile.appendRelativePath("skin");
-			skinFile.appendRelativePath(skinName);
-		}else{
-			var bbs2chreaderID = "{0B9D558E-6983-486b-9AAD-B6CBCD2FC807}";
-			var extensionManager = Components.classes["@mozilla.org/extensions/manager;1"]
-					.getService(Components.interfaces.nsIExtensionManager);
-			var installLocation = extensionManager.getInstallLocation(bbs2chreaderID);
-			skinFile = installLocation.getItemFile(bbs2chreaderID, "defaults/skin").clone()
-							.QueryInterface(Components.interfaces.nsILocalFile);
-		}
-
-		for(let [i, value] in Iterator(aFilePath.split("/"))){
-			skinFile.appendRelativePath(value);
-		}
-
-		return skinFile;
-	}
-}
-

Copied: trunk/bbs2chreader/chrome/content/bbs2chreader/server/skin.jsm (from rev 389, trunk/bbs2chreader/chrome/content/bbs2chreader/server/skin.js)
===================================================================
--- trunk/bbs2chreader/chrome/content/bbs2chreader/server/skin.js	2008-02-29 14:22:52 UTC (rev 389)
+++ trunk/bbs2chreader/chrome/content/bbs2chreader/server/skin.jsm	2008-03-15 14:50:00 UTC (rev 410)
@@ -0,0 +1,91 @@
+EXPORTED_SYMBOLS = ["SkinServerScript"];
+
+const Ci = Components.interfaces;
+const Cc = Components.classes;
+const XPC = {
+	createInstance: function(aContractId, aInterface){
+		return Components.classes[aContractId].createInstance(Components.interfaces[aInterface]);
+	},
+	getService: function(aContractId, aInterface){
+	    return Components.classes[aContractId].getService(Components.interfaces[aInterface]);
+	}
+};
+
+function SkinServerScript(aRequestURL){
+}
+
+
+SkinServerScript.prototype = {
+
+	start: function(aServerHandler){
+		var filePath = aServerHandler.requestURL.filePath.substring(6);
+		var skinFile = this.resolveSkinFile(filePath);
+
+			// File Not Found
+		if(!skinFile.exists()){
+			aServerHandler.sendErrorPage(404, aServerHandler.requestURL.spec);
+			return;
+		}
+
+		var lastModifiedString = new Date(skinFile.lastModifiedTime).toUTCString();
+		aServerHandler.setResponseHeader("Last-Modified", lastModifiedString);
+		aServerHandler.setResponseHeader("Cache-Control", "max-age=0, must-revalidate");
+
+			// If-Modified-Since ‚ª‘¶Ý‚µƒtƒ@ƒCƒ‹‚ªXV‚³‚ê‚Ä‚¢‚È‚¯‚ê‚Î 304
+		if(aServerHandler.requestHeaders["If-Modified-Since"]){
+			var lastModified = parseInt(new Date(skinFile.lastModifiedTime).getTime() / 1000);
+			var ifLastModified = parseInt(new Date(aServerHandler.requestHeaders["If-Modified-Since"]).getTime() / 1000);
+			if(lastModified == ifLastModified){
+				aServerHandler.writeResponseHeader(304);
+				aServerHandler.close();
+				return;
+			}
+		}
+
+		var mimeService = Components.classes["@mozilla.org/uriloader/external-helper-app-service;1"]
+								.getService(Components.interfaces.nsIMIMEService);
+		var contentType = mimeService.getTypeFromFile(skinFile);
+		aServerHandler.setResponseHeader("Content-Type", contentType);
+		aServerHandler.writeResponseHeader(200);
+		var fileStream = Components.classes["@mozilla.org/network/file-input-stream;1"]
+							.createInstance(Components.interfaces.nsIFileInputStream);
+		fileStream.init(skinFile, 0x01, 0444, fileStream.CLOSE_ON_EOF);
+		aServerHandler._output.writeFrom(fileStream, skinFile.fileSize);
+		fileStream.close();
+		aServerHandler.close();
+	},
+
+	cancel: function(){
+	},
+
+	resolveSkinFile: function(aFilePath){
+		var b2rService  = Components.classes["@bbs2ch.sourceforge.jp/b2r-global-service;1"]
+				.getService(Components.interfaces.b2rIGlobalService);
+		var pref = Components.classes["@mozilla.org/preferences-service;1"]
+				.getService(Components.interfaces.nsIPrefBranch);
+
+		var skinName = pref.getComplexValue("extensions.bbs2chreader.thread_skin",
+							Components.interfaces.nsISupportsString).data;
+
+		var skinFile = null;
+		if(skinName){
+			skinFile = b2rService.io.getDataDir();
+			skinFile.appendRelativePath("skin");
+			skinFile.appendRelativePath(skinName);
+		}else{
+			var bbs2chreaderID = "{0B9D558E-6983-486b-9AAD-B6CBCD2FC807}";
+			var extensionManager = Components.classes["@mozilla.org/extensions/manager;1"]
+					.getService(Components.interfaces.nsIExtensionManager);
+			var installLocation = extensionManager.getInstallLocation(bbs2chreaderID);
+			skinFile = installLocation.getItemFile(bbs2chreaderID, "defaults/skin").clone()
+							.QueryInterface(Components.interfaces.nsILocalFile);
+		}
+
+		for(let [i, value] in Iterator(aFilePath.split("/"))){
+			skinFile.appendRelativePath(value);
+		}
+
+		return skinFile;
+	}
+
+};
\ No newline at end of file

Deleted: trunk/bbs2chreader/chrome/content/bbs2chreader/server/thread.js
===================================================================
--- trunk/bbs2chreader/chrome/content/bbs2chreader/server/thread.js	2008-03-15 13:03:28 UTC (rev 409)
+++ trunk/bbs2chreader/chrome/content/bbs2chreader/server/thread.js	2008-03-15 14:50:00 UTC (rev 410)
@@ -1,1339 +0,0 @@
-this.script = {
-
-	start: function(aServerHandler){
-		aServerHandler.setResponseHeader("Content-Type", "text/html; charset=Shift_JIS");
-		aServerHandler.writeResponseHeader(200);
-
-		var threadURL = this.getThreadURL(aServerHandler.requestURL);
-		if(!threadURL){
-			aServerHandler.write("BAD URL");
-			aServerHandler.close();
-			return;
-		}
-
-		var b2rService = Components.classes["@bbs2ch.sourceforge.jp/b2r-global-service;1"]
-				.getService(Components.interfaces.b2rIGlobalService);
-
-		var boardURL = b2rService.threadUtils.getBoardURL(threadURL);
-		var type = b2rService.threadUtils.getBoardType(threadURL);
-			// ”‚̃^ƒCƒv‚ªABOARD_TYPE_PAGE ‚Å‚àA
-			// URL ‚É /test/read.cgi/ ‚ðŠÜ‚ñ‚Å‚¢‚½‚ç 2chŒÝŠ·‚Æ‚Ý‚È‚·
-		if(type == b2rService.BOARD_TYPE_PAGE && threadURL.spec.indexOf("/test/read.cgi/") != -1){
-			type = b2rService.BOARD_TYPE_2CH;
-		}
-
-		switch(type){
-			case b2rService.BOARD_TYPE_2CH:
-				this.thread = new b2rThread2ch();
-				break;
-			case b2rService.BOARD_TYPE_JBBS:
-				this.thread = new b2rThreadJbbs();
-				break;
-			case b2rService.BOARD_TYPE_MACHI:
-				this.thread = new b2rThreadMachi();
-				break;
-			default:
-				this.thread = null;
-				break;
-		}
-
-		if(this.thread){
-			this.thread.init(aServerHandler, threadURL, boardURL, type);
-		}else{
-			aServerHandler.write("No Supported Boad");
-			aServerHandler.close();
-		}
-	},
-
-	cancel: function(){
-		if(this.thread){
-			this.thread.close();
-			this.thread = null;
-		}
-	},
-
-	getThreadURL: function(aRequestURL){
-		var threadURLSpec = aRequestURL.path.substring(8);
-		if(threadURLSpec == "") return null;
-
-		// threadURLSpec = decodeURIComponent(threadURLSpec);
-
-		try{
-			var ioService = Components.classes["@mozilla.org/network/io-service;1"]
-					.getService(Components.interfaces.nsIIOService);
-			var threadURL = ioService.newURI(threadURLSpec, null, null)
-					.QueryInterface(Components.interfaces.nsIURL);
-				// URL ‚ªADAT ID ‚ŏI‚í‚é‚Æ‚«‚Í "/" ‚ð’ljÁ‚·‚é
-			if(threadURL.fileName.match(/^\d{9,10}$/)){
-				threadURL = ioService.newURI(threadURLSpec + "/", null, null)
-						.QueryInterface(Components.interfaces.nsIURL);
-			}
-			return threadURL;
-		}catch(ex){}
-
-		return null;
-	}
-
-};
-
-
-// ***** ***** ***** ***** ***** b2rThread2ch ***** ***** ***** ***** *****
-function b2rThread2ch(){
-}
-
-b2rThread2ch.prototype = {
-
-	get optionsOnes(){
-		return (this.dat.threadURL.fileName.match(/^(\d+)n?$/)) ? parseInt(RegExp.$1) : null;
-	},
-	get optionsStart(){
-		return (this.dat.threadURL.fileName.match(/(\d+)\-/)) ? parseInt(RegExp.$1) : null;
-	},
-	get optionsLast(){
-		return (this.dat.threadURL.fileName.match(/l(\d+)/)) ? parseInt(RegExp.$1) : null;
-	},
-	get optionsEnd(){
-		return (this.dat.threadURL.fileName.match(/\-(\d+)/)) ? parseInt(RegExp.$1) : null;
-	},
-	get optionsNoFirst(){
-		return (this.dat.threadURL.fileName.indexOf("n") != -1);
-	},
-
-	init: function(aHandler, aThreadURL, aBoardURL, aType){
-		this._handler = aHandler;
-
-		this._bbs2chService = Components.classes["@mozilla.org/bbs2ch-service;1"]
-					.getService(Components.interfaces.nsIBbs2chService);
-		this._b2rService  = Components.classes["@bbs2ch.sourceforge.jp/b2r-global-service;1"]
-					.getService(Components.interfaces.b2rIGlobalService);
-		this._pref = Components.classes["@mozilla.org/preferences-service;1"]
-					.getService(Components.interfaces.nsIPrefBranch);
-
-		this._ioService = Components.classes["@mozilla.org/network/io-service;1"]
-					.getService(Components.interfaces.nsIIOService);
-
-		this._chainAboneNumbers = new Array();
-		this._enableChainAbone = this._pref.getBoolPref("extensions.bbs2chreader.thread_chain_abone")
-
-			// HTML ƒwƒbƒ_‚𑗐M‚µ‚½‚ç true ‚É‚È‚é
-		this._headerResponded = false;
-		this._opend = true;
-		this.httpChannel = null;
-
-		this.dat = new b2rDat();
-		this.dat.init(aThreadURL, aBoardURL, aType);
-		if(!this.dat.id){
-			this.write("BAD URL");
-			this.close();
-			return;
-		}
-
-		this.converter = new b2rThreadConverter();
-		try{
-			this.converter.init(this, this.dat.threadURL, this.dat.boardURL, this.dat.type);
-		}catch(ex){
-			if(ex == Components.results.NS_ERROR_FILE_NOT_FOUND){
-				var skinName = this._pref.getComplexValue("extensions.bbs2chreader.thread_skin",
-						Components.interfaces.nsISupportsString).data;
-				skinName = this._bbs2chService.toSJIS(skinName);
-				this.write("ƒXƒLƒ“ ("+ skinName +") ‚̓ǂݍž‚Ý‚ÉŽ¸”s‚µ‚½‚½‚߁A");
-				this.write("Ý’è‚ðƒfƒtƒHƒ‹ƒgƒXƒLƒ“‚É–ß‚µ‚Ü‚µ‚½B<br>ƒy[ƒW‚ðXV‚µ‚Ä‚­‚¾‚³‚¢B");
-				this.close();
-				this._pref.setCharPref("extensions.bbs2chreader.thread_skin", "");
-				return;
-			}else {
-				this.write(ex.toSource());
-				this.close();
-				return;
-			}
-		}
-
-		/*
-		this.write("<!-- \n");
-		this.write("Thread URL    : " + this.dat.threadURL.spec + "\n");
-		this.write("Board URL     : " + this.dat.boardURL.spec + "\n");
-		this.write("Type          : " + this.dat.type + "\n");
-		this.write("DAT URL       : " + this.dat.datURL.spec + "\n");
-		this.write("DAT ID        : " + this.dat.id + "\n");
-		this.write("DAT File      : " + this.dat.datFile.path + "\n");
-		this.write("----- ----- -----\n");
-		this.write("Title         : " + this.dat.title + "\n");
-		this.write("LineCount     : " + this.dat.lineCount + "\n");
-		this.write("LastModified  : " + this.dat.lastModified + "\n");
-		this.write("----- ----- -----\n");
-		this.write("URL Options \n");
-		this.write("  Ones        : " + this.optionsOnes + "\n");
-		this.write("  Start       : " + this.optionsStart + "\n");
-		this.write("  Last        : " + this.optionsLast + "\n");
-		this.write("  End         : " + this.optionsEnd + "\n");
-		this.write("  NoFirst     : " + this.optionsNoFirst + "\n");
-		this.write("-->\n\n");
-		*/
-
-		this._logLineCount = 0;
-			// Žæ“¾Ï‚݃ƒO‚Ì‘—M
-		if(this.dat.datFile.exists()){
-			var datLines = this._bbs2chService.readFileLine(this.dat.datFile.path, {});
-
-			this._logLineCount = datLines.length;
-
-			if(this.optionsOnes && this.optionsOnes <= this._logLineCount){
-				this._headerResponded = true;
-				var header = this.converter.getHeader(this.dat.title);
-				this.write(header);
-				this.write(this.datLineParse(datLines[this.optionsOnes-1],
-								this.optionsOnes, false));
-				this.write(this.converter.getFooter("log_pickup_mode"));
-				this.close();
-				return;
-
-			}else if(this.optionsEnd){
-				this._headerResponded = true;
-				var header = this.converter.getHeader(this.dat.title);
-				this.write(header);
-
-				var start = this.optionsStart ? this.optionsStart : 1;
-				if(start < 1) start = 1;
-				var end = this.optionsEnd;
-				if(end > datLines.length) end = datLines.length;
-				if(start > end) start = end;
-
-				for(var i=start-1; i<end; i++){
-					this.write(this.datLineParse(datLines[i], i+1, false) +"\n");
-				}
-
-				this.write(this.converter.getFooter("log_pickup_mode"));
-				this.close();
-				return;
-
-			}else{
-				if(!this.optionsNoFirst){
-					this.write(this.datLineParse(datLines[0], 1, false) +"\n");
-				}else if(this.dat.title){
-					this._headerResponded = true;
-					var header = this.converter.getHeader(this.dat.title);
-					this.write(header);
-				}else{
-					this.write(this.datLineParse(datLines[0], 1, false) +"\n");
-				}
-
-				var start = 1;
-				var end = datLines.length;
-				if(this.optionsLast == 0){
-					this.write(this.converter.getNewMark() +"\n");
-					this.datDownload();
-					return;
-				}else if(this.optionsLast){
-					start = end - this.optionsLast;
-					if(start < 1) start = 1;
-				}else if(this.optionsStart){
-					start = this.optionsStart - 1;
-					if(start > end) start = end;
-				}
-
-				for(var i=start; i<end; i++){
-					this.write(this.datLineParse(datLines[i], i+1, false) +"\n");
-				}
-
-				this.write(this.converter.getNewMark() +"\n");
-			}
-		}
-
-		if(this.dat.maruGetted){
-			this.write(this.converter.getFooter("ok"));
-			this.close();
-		}
-
-		this._handler.flush();
-		this.datDownload();
-	},
-
-	write: function(aString){
-		this._handler.write(aString);
-	},
-
-	close: function(){
-		if(this._headerResponded && this.dat){
-			var title = this._bbs2chService.fromSJIS(this.dat.title);
-			this._b2rService.history.visitPage(this.dat.threadPlainURL, title, 1);
-		}
-		this._opend = false;
-		this._httpChannel = null;
-		this._handler.close();
-		this._handler = null;
-	},
-
-
-	htmlToText: function(aStr){
-		var fromStr = Components.classes["@mozilla.org/supports-string;1"]
-									.createInstance(Components.interfaces.nsISupportsString);
-		fromStr.data = aStr;
-		try{
-			var toStr = { value: null };
-			var	formatConverter = Components.classes["@mozilla.org/widget/htmlformatconverter;1"]
-									.createInstance(Components.interfaces.nsIFormatConverter);
-			formatConverter.convert("text/html", fromStr, fromStr.toString().length,
-										"text/unicode", toStr, {});
-		}catch(e){
-			return aStr;
-		}
-		if(toStr.value){
-			toStr = toStr.value.QueryInterface(Components.interfaces.nsISupportsString);
-			return toStr.toString();
-		}
-		return aStr;
-	},
-
-
-	datLineParse: function(aLine, aNumber, aNew){
-		if(!aLine) return "";
-
-		var resArray = aLine.split("<>");
-		var resNumber = aNumber;
-		var resName = "BROKEN";
-		var resMail = "";
-		var resDate = "BROKEN";
-		var resID = "";
-		var resBeID = "";
-		var resMes	= "";
-
-		if(resArray.length > 3){
-			resName = resArray[0].replace(/<\/?b>|/g, "");
-			resMail = resArray[1];
-			resDate = resArray[2];
-			resMes = resArray[3];
-		}
-
-		if(resDate.indexOf("<") != -1){
-			resDate	= this.htmlToText(resDate);
-		}
-
-			// resDate ‚ð DATEABeID ‚É•ªŠ„
-		if(resDate.indexOf("BE:")!=-1 && resDate.match(/(.+)BE:([^ ]+) ?/)){
-			resDate = RegExp.$1 + RegExp.rightContext;
-			resBeID = RegExp.$2;
-		}
-			// resDate ‚ð DATE ‚Æ ID ‚É•ªŠ„
-		if(resDate.indexOf("ID:")!=-1 && resDate.match(/(.+)ID:([^ ]+) ?/)){
-			resDate = RegExp.$1 + RegExp.rightContext;
-			resID = RegExp.$2;
-		}
-
-			// resDate ‚É IP ‚ªŠÜ‚Ü‚ê‚Ä‚¢‚éê‡‚Í IP ‚ð ID ‚Æ‚µ‚Ĉµ‚¤
-		/*
-		if(resDate.match(/(.+)”­MŒ³:(.+)/)){
-			resDate = RegExp.$1;
-			resID = RegExp.$2;
-		}
-		*/
-
-		if(this._b2rService.abone.shouldAbone(resName, resMail, resID, resMes)){
-			this._chainAboneNumbers.push(aNumber);
-			resName = resMail = resDate = resMes = "ABONE";
-			if(aNumber>1 && this._pref.getBoolPref("extensions.bbs2chreader.thread_hide_abone")){
-				return "";
-			}
-		}
-
-		if(resBeID){
-			var regBeID = /^(\d+)/;
-			if(resBeID.match(regBeID)){
-				var idInfoUrl = "http://be.2ch.net/test/p.php?i=" + RegExp.$1 +
-						"&u=d:" + this.dat.threadURL.resolve("./") + aNumber;
-				resBeID = resBeID.replace(regBeID, String("$1").link(idInfoUrl));
-			}
-		}
-
-			// JS‚Å‚Í "\" ‚ª“ÁŽê‚ȈӖ¡‚ðŽ‚Â‚½‚߁A”’l•¶ŽšŽQÆ‚É•ÏŠ·
-		resName = resName.replace(/([^\x81-\xfc]|^)\x5C/g,"$1&#x5C;");
-		resMail = resMail.replace(/([^\x81-\xfc]|^)\x5C/g,"$1&#x5C;");
-
-		var resMailName = resName;
-		if(resMail) resMailName = '<a href="mailto:' + resMail + '">' + resName + '</a>';
-
-			// ƒŒƒX”ÔƒŠƒ“ƒNˆ— & ˜A½‚ ‚ځ[‚ñ
-		var regResPointer = /(?:<a .*?>)?(&gt;&gt;|&gt;)([0-9]{1,4})(\-[0-9]{1,4})?(?:<\/a>)?/g;
-
-		var chainAboneNumbers = this._chainAboneNumbers;
-		var chainAbone = false;
-		resMes = resMes.replace(regResPointer, function(aStr, aP1, aP2, aP3, aOffset, aS){
-			chainAbone = chainAbone || (chainAboneNumbers.indexOf(parseInt(aP2)) != -1);
-			return '<a href="#res' + aP2 + '" class="resPointer">' + aP1 + aP2 + aP3 + '</a>';
-		});
-		if(this._enableChainAbone && chainAbone){
-			resName = resMail = resDate = resMes = "ABONE";
-			if(aNumber>1 && this._pref.getBoolPref("extensions.bbs2chreader.thread_hide_abone")){
-				return "";
-			}
-		}
-
-			// ’ʏ탊ƒ“ƒNˆ—
-		if(resMes.indexOf("ttp")!=-1){
-			var regUrlLink = /(h?ttp)(s)?\:([\-_\.\!\~\*\'\(\)a-zA-Z0-9\;\/\?\:\@\&\=\+\$\,\%\#]+)/g;
-			resMes = resMes.replace(regUrlLink, '<a href="http$2:$3" class="outLink">$1$2:$3</a>');
-		}
-			// ƒŒƒXID
-		var regResID = / (ID:)([0-9a-z\+\/]+)/ig;
-		resMes = resMes.replace(regResID, ' <span class="resMesID"><span class="mesID_$2">$1$2</span></span>');
-
-			// ƒXƒŒƒbƒh‚̃^ƒCƒgƒ‹‚ªŒ©‚‚©‚Á‚½‚Æ‚«‚Í HTML ƒwƒbƒ_‚ð’ljÁ‚µ‚Ä‘—‚é
-		if(!this._headerResponded && resArray[4]){
-			this._headerResponded = true;
-			this.dat.title = resArray[4];
-
-			var header = this.converter.getHeader(this.dat.title);
-			this.write(header);
-			this._handler.flush();
-		}
-		var response = this.converter.getResponse(aNew, aNumber, resName, resMail,
-								resMailName, resDate, resID, resBeID, resMes);
-		return response;
-	},
-
-
-	datDownload: function(aKako){
-		if(aKako){
-			if(this._b2rService.viewer.logined){
-				var sid = encodeURIComponent(this._b2rService.viewer.sessionID);
-				var datURLSpec = this.dat.threadPlainURL.spec.replace(/\/read\.cgi\//, "/offlaw.cgi/");
-				datURLSpec += "?raw=.0&sid=" + sid;
-				var datKakoURL = this._ioService.newURI(datURLSpec, null, null)
-						.QueryInterface(Components.interfaces.nsIURL);
-				this.httpChannel = this._b2rService.getHttpChannel(datKakoURL);
-				this._maruMode = true;
-			}else{
-				this.httpChannel = this._b2rService.getHttpChannel(this.dat.datKakoURL);
-			}
-			this._kakoDatDownload = true;
-
-		}else{
-			this.httpChannel = this._b2rService.getHttpChannel(this.dat.datURL);
-			this._kakoDatDownload = false;
-		}
-		this.httpChannel.requestMethod = "GET";
-		this.httpChannel.redirectionLimit = 0; // 302 “™‚̃Šƒ_ƒCƒŒƒNƒg‚ðs‚í‚È‚¢
-		this.httpChannel.loadFlags = this.httpChannel.LOAD_BYPASS_CACHE;
-		this._aboneChecked = true;
-		this._threadAbone = false;
-
-			// ·•ªGET
-		if(this.dat.datFile.exists() && this.dat.lastModified){
-			var lastModified = this.dat.lastModified;
-			var range = this.dat.datFile.fileSize - 1;
-			this.httpChannel.setRequestHeader("Accept-Encoding", "", false);
-			this.httpChannel.setRequestHeader("If-Modified-Since", lastModified, false);
-			this.httpChannel.setRequestHeader("Range", "bytes=" + range + "-", false);
-			this._aboneChecked = false;
-		}else{
-			this.httpChannel.setRequestHeader("Accept-Encoding", "gzip", false);
-		}
-
-		this.httpChannel.asyncOpen(this, null);
-	},
-
-	onStartRequest: function(aRequest, aContext){
-		this._bInputStream = Components.classes["@mozilla.org/binaryinputstream;1"]
-					.createInstance(Components.interfaces.nsIBinaryInputStream);
-		this._data = new Array();
-		this._datBuffer = "";
-	},
-
-	onDataAvailable: function (aRequest, aContext, aInputStream, aOffset, aCount){
-		if(!this._opend) return;
-
-		aRequest.QueryInterface(Components.interfaces.nsIHttpChannel);
-		var httpStatus = aRequest.responseStatus;
-			// •K—v‚ȏî•ñ‚ª‚È‚¢‚È‚çI—¹
-		if(!(httpStatus==200 || httpStatus==206)) return;
-		if(aCount == 0) return;
-
-		this._bInputStream.setInputStream(aInputStream);
-
-		var availableData = "";
-		if(!this._aboneChecked){
-			var firstChar = this._bInputStream.readBytes(1)
-			availableData = this._bInputStream.readBytes(aCount - 1);
-			if(firstChar.charCodeAt(0) != 10){
-				this._threadAbone = true;
-			}
-
-		}else{
-			availableData = this._bInputStream.readBytes(aCount);
-		}
-		this._aboneChecked = true;
-
-
-		if(this._maruMode && this._data.length == 0){
-			if(availableData.match(/\n/)){
-				availableData = RegExp.rightContext;
-			}else{
-				return;
-			}
-		}
-
-			// NULL •¶Žš
-		availableData = availableData.replace(/\x00/g, "*");
-			// •ÏŠ·‘O‚Ì DAT ‚ð•Û‘¶‚µ‚Ä‚¨‚­
-		this._data.push(availableData);
-
-		var availableData = this._datBuffer + availableData;
-			// ‰üs‚ðŠÜ‚Ü‚È‚¢‚È‚çƒoƒbƒtƒ@‚ɒljÁ‚µ‚ďI—¹
-		if(!availableData.match(/\n/)){
-			this._datBuffer = availableData;
-			return;
-		}
-
-			// Žæ“¾‚µ‚½ DAT ‚ðs‚²‚Æ‚É”z—ñ‚É‚µAÅŒã‚̍s‚ðƒoƒbƒtƒ@‚ɒljÁ
-		var datLines = availableData.split("\n");
-		this._datBuffer = (datLines.length>1) ? datLines.pop() : "";
-
-			// DAT ‚ð •ÏŠ·‚µ‚ď‘‚«o‚·
-		for(var i=0; i<datLines.length; i++){
-			this.dat.lineCount++;
-			this.write(this.datLineParse(datLines[i], this.dat.lineCount, true) +"\n");
-		}
-		this._handler.flush();
-	},
-
-	onStopRequest: function(aRequest, aContext, aStatus){
-		if(!this._opend) return;
-
-		this._bInputStream = null;
-		aRequest.QueryInterface(Components.interfaces.nsIHttpChannel);
-		try{
-			var httpStatus = aRequest.responseStatus;
-		}catch(ex){
-			this.write(this.converter.getFooter("network_error"));
-			this.close();
-			return;
-		}
-
-		try{
-			this.dat.lastModified = aRequest.getResponseHeader("Last-Modified");
-		}catch(ex){}
-
-		switch(httpStatus){
-			case 200: // ’ʏíGET OK
-			case 206: // ·•ªGET OK
-				break;
-			case 302: // DAT—Ž‚¿
-				if(this._kakoDatDownload){
-					this.write(this.converter.getFooter("dat_down"));
-					this.close();
-				}else{
-					this.datDownload(true);
-				}
-				return;
-			case 304: // –¢XV
-				this.write(this.converter.getFooter("not_modified"));
-				this.close();
-				return;
-			case 416: //‚ ‚ځ[‚ñ
-				this.write(this.converter.getFooter("abone"));
-				this.close();
-				return;
-			default: // HTTP ƒGƒ‰[
-				this.write(this.converter.getFooter(httpStatus));
-				this.close();
-				return;
-		}
-
-		if(this._threadAbone){ //‚ ‚ځ[‚ñ
-			this.write(this.converter.getFooter("abone"));
-			this.close();
-			return;
-		}
-
-			// XXX TODO ˆê•”ŒÝŠ·ƒXƒNƒŠƒvƒg‚ɂ́A–¢XV‚Å‚à 206 ‚ð•Ô‚·‚à‚Ì‚ª‚ ‚é?
-		var newResLength = this.dat.lineCount - this._logLineCount;
-		if(newResLength == 0){
-			this.write(this.converter.getFooter("not_modified"));
-			this.close();
-			return;
-		}
-
-		if(this._datBuffer){
-			this.dat.lineCount++;
-			this._datBuffer = this.dat.lineCount +"\t: "+ this._datBuffer;
-			this.write(this._datBuffer);
-			this._datBuffer = "";
-		}
-
-		if(httpStatus == 200 || httpStatus == 206){
-			this.datSave(this._data.join(""));
-		}
-		this.write(this.converter.getFooter("ok"));
-		this.close();
-		this._data = null;
-	},
-
-	datSave: function(aDatContent){
-				// ‘‚«ž‚݂̃oƒbƒeƒBƒ“ƒO‚ð”ð‚¯‚é
-
-		var b2rStorageService = Cc["@bbs2ch.sourceforge.jp/b2r-storage-service;1"].getService(Ci.b2rIStorageService);
-		var threadData = b2rStorageService.getThreadData(this.dat.boardURL, this.dat.id);
-		var tmpLineCount = 0;
-		if(threadData){
-			tmpLineCount = threadData.lineCount;
-		}
-		if(this.dat.lineCount > tmpLineCount){
-				// .dat ‚Ì’Ç‹L‘‚«ž‚Ý
-			this.dat.appendContent(aDatContent);
-
-			if(this._maruMode) this.dat.maruGetted = true;
-			this.dat.setThreadData();
-		}
-	}
-
-};
-
-
-// ***** ***** ***** ***** ***** b2rThreadJbbs ***** ***** ***** ***** *****
-function b2rThreadJbbs(){
-}
-
-b2rThreadJbbs.prototype = {
-	datDownload: function(){
-		var datURLSpec = this.dat.threadURL.resolve("./").replace("read.cgi", "rawmode.cgi");
-		this._aboneChecked = true;
-		this._threadAbone = false;
-
-			// ·•ªGET
-		if(this.dat.datFile.exists() && this.dat.lineCount){
-			datURLSpec += (this.dat.lineCount + 1) + "-";
-		}
-
-		var datURL = this._ioService.newURI(datURLSpec, null, null)
-				.QueryInterface(Components.interfaces.nsIURL);
-
-		this.httpChannel = this._b2rService.getHttpChannel(datURL);
-		this.httpChannel.requestMethod = "GET";
-		this.httpChannel.redirectionLimit = 0; // 302 “™‚̃Šƒ_ƒCƒŒƒNƒg‚ðs‚í‚È‚¢
-		this.httpChannel.loadFlags = this.httpChannel.LOAD_BYPASS_CACHE;
-
-		this.httpChannel.asyncOpen(this, null);
-	},
-
-	datLineParse: function(aLine, aNumber, aNew){
-		if(!aLine) return "";
-
-			// EUC-JP ‚©‚ç SJIS ‚Ö•ÏŠ·
-		var line = this._bbs2chService.fromEUC(aLine);
-		line = this._bbs2chService.toSJIS(line);
-		var resArray = line.split("<>");
-		var resNumber = aNumber;
-		var resName = "BROKEN";
-		var resMail = "";
-		var resDate = "BROKEN";
-		var resID = "";
-		var resBeID = "";
-		var resMes	= "";
-
-		if(resArray.length > 5){
-			resName = resArray[1].replace(/<\/?b>|/g, "");
-			resMail = resArray[2];
-			resDate = resArray[3];
-			resMes = resArray[4];
-			resID = resArray[6];
-		}
-
-		if(this._b2rService.abone.shouldAbone(resName, resMail, resID, resMes)){
-			this._chainAboneNumbers.push(aNumber);
-			resName = resMail = resDate = resMes = "ABONE";
-			if(aNumber>1 && this._pref.getBoolPref("extensions.bbs2chreader.thread_hide_abone")){
-				return "";
-			}
-		}
-
-			// JS‚Å‚Í "\" ‚ª“ÁŽê‚ȈӖ¡‚ðŽ‚Â‚½‚߁A”’l•¶ŽšŽQÆ‚É•ÏŠ·
-		resName = resName.replace(/([^\x81-\xfc]|^)\x5C/g,"$1&#x5C;");
-		resMail = resMail.replace(/([^\x81-\xfc]|^)\x5C/g,"$1&#x5C;");
-
-		var resMailName = resName;
-		if(resMail) resMailName = '<a href="mailto:' + resMail + '">' + resName + '</a>';
-
-
-			// ƒŒƒX”ÔƒŠƒ“ƒNˆ— & ˜A½‚ ‚ځ[‚ñ
-		var regResPointer = /(?:<a .*?>)?(&gt;&gt;|&gt;)([0-9]{1,4})(\-[0-9]{1,4})?(?:<\/a>)?/g;
-
-		var chainAboneNumbers = this._chainAboneNumbers;
-		var chainAbone = false;
-		resMes = resMes.replace(regResPointer, function(aStr, aP1, aP2, aP3, aOffset, aS){
-			chainAbone = chainAbone || (chainAboneNumbers.indexOf(parseInt(aP2)) != -1);
-			return '<a href="#res' + aP2 + '" class="resPointer">' + aP1 + aP2 + aP3 + '</a>';
-		});
-		if(this._enableChainAbone && chainAbone){
-			resName = resMail = resDate = resMes = "ABONE";
-			if(aNumber>1 && this._pref.getBoolPref("extensions.bbs2chreader.thread_hide_abone")){
-				return "";
-			}
-		}
-
-
-			// ’ʏ탊ƒ“ƒNˆ—
-		var regUrlLink = /(h?ttp)(s)?\:([\-_\.\!\~\*\'\(\)a-zA-Z0-9\;\/\?\:\@\&\=\+\$\,\%\#]+)/g;
-		resMes = resMes.replace(regUrlLink, '<a href="http$2:$3" class="outLink">$1$2:$3</a>');
-
-			// ƒXƒŒƒbƒh‚̃^ƒCƒgƒ‹‚ªŒ©‚‚©‚Á‚½‚Æ‚«‚Í HTML ƒwƒbƒ_‚ð’ljÁ‚µ‚Ä‘—‚é
-		if(!this._headerResponded && resArray[5]!= ""){
-			this._headerResponded = true;
-			this.dat.title = resArray[5];
-
-			var header = this.converter.getHeader(this.dat.title);
-			this.write(header);
-			this._handler.flush();
-		}
-		var response = this.converter.getResponse(aNew, aNumber, resName, resMail,
-								resMailName, resDate, resID, resBeID, resMes);
-		return response;
-	},
-
-	onStopRequest: function(aRequest, aContext, aStatus){
-		if(!this._opend) return;
-
-		aRequest.QueryInterface(Components.interfaces.nsIHttpChannel);
-		var httpStatus = aRequest.responseStatus;
-		var jbbsError = "";
-		try{
-			jbbsError = aRequest.getResponseHeader("ERROR");
-		}catch(ex){}
-
-
-		switch(jbbsError){
-			case "BBS NOT FOUND":
-			case "KEY NOT FOUND":
-			case "THREAD NOT FOUND":
-				this.write(this.converter.getFooter(999));
-				this.close();
-				return;
-			case "STORAGE IN":
-				this.write(this.converter.getFooter("dat_down"));
-				this.close();
-				return;
-		}
-
-		if(this._datBuffer){
-			this.dat.lineCount++;
-			this._datBuffer = this.dat.lineCount +"\t: "+ this._datBuffer;
-			this.write(this._datBuffer);
-			this._datBuffer = "";
-		}
-
-		if(httpStatus == 200 || httpStatus == 206){
-			this.datSave(this._data.join(""));
-		}
-		this.write(this.converter.getFooter("ok"));
-		this.close();
-		this._data = null;
-	}
-};
-
-b2rThreadJbbs.prototype.__proto__ = b2rThread2ch.prototype;
-
-
-// ***** ***** ***** ***** ***** b2rThreadMachi ***** ***** ***** ***** *****
-function b2rThreadMachi(){
-}
-
-b2rThreadMachi.prototype = {
-	get optionsStart(){
-		return (this.dat.queryHash["START"]) ? parseInt(this.dat.queryHash["START"]) : null;
-	},
-	get optionsLast(){
-		return (this.dat.queryHash["LAST"]) ? parseInt(this.dat.queryHash["LAST"]) : null;
-	},
-	get optionsEnd(){
-		return (this.dat.queryHash["END"]) ? parseInt(this.dat.queryHash["END"]) : null;
-	},
-	get optionsNoFirst(){
-		return (this.dat.queryHash["NOFIRST"] == "TRUE") ? true : false;
-	},
-
-	datDownload: function(){
-		var datURLSpec = this.dat.datURL.spec
-		this._aboneChecked = true;
-		this._threadAbone = false;
-
-				// ·•ªGET
-		if(this.dat.datFile.exists() && this.dat.lineCount){
-			datURLSpec += "&NOFIRST=TRUE&START=" + (this.dat.lineCount + 1);
-		}
-		var datURL = this._ioService.newURI(datURLSpec, null, null)
-				.QueryInterface(Components.interfaces.nsIURL);
-
-		this.httpChannel = this._b2rService.getHttpChannel(datURL);
-		this.httpChannel.requestMethod = "GET";
-		this.httpChannel.redirectionLimit = 0; // 302 “™‚̃Šƒ_ƒCƒŒƒNƒg‚ðs‚í‚È‚¢
-		this.httpChannel.loadFlags = this.httpChannel.LOAD_BYPASS_CACHE;
-
-		this.httpChannel.asyncOpen(this, null);
-	},
-
-	onStartRequest: function(aRequest, aContext){
-		this._bInputStream = Components.classes["@mozilla.org/binaryinputstream;1"]
-					.createInstance(Components.interfaces.nsIBinaryInputStream);
-		this._htmlData = new Array();
-	},
-
-	onDataAvailable: function (aRequest, aContext, aInputStream, aOffset, aCount){
-		if(!this._opend) return;
-
-		aRequest.QueryInterface(Components.interfaces.nsIHttpChannel);
-		var httpStatus = aRequest.responseStatus;
-			// •K—v‚ȏî•ñ‚ª‚È‚¢‚È‚çI—¹
-		if(!(httpStatus==200 || httpStatus==206)) return;
-		if(aCount == 0) return;
-
-		this._bInputStream.setInputStream(aInputStream);
-		var availableData = this._bInputStream.readBytes(aCount);
-			// NULL •¶Žš
-		availableData = availableData.replace(/\x00/g, "*");
-
-		this._htmlData.push(availableData);
-		this.write(" ");
-	},
-
-	onStopRequest: function(aRequest, aContext, aStatus){
-		if(!this._opend) return;
-
-		this._bInputStream = null;
-		aRequest.QueryInterface(Components.interfaces.nsIHttpChannel);
-		var httpStatus = aRequest.responseStatus;
-
-		switch(httpStatus){
-			case 200: // ’ʏíGET OK
-			case 206: // ·•ªGET OK
-				break;
-			default: // HTTP ƒGƒ‰[
-				this.write(this.converter.getFooter(httpStatus));
-				this.close();
-				return;
-		}
-
-		var datLines = this.machiHTML2DAT(this._htmlData.join(""));
-		this._htmlData = null;
-
-		if(datLines.length == 0){ // –¢XV
-			this.write(this.converter.getFooter("not_modified"));
-			this.close();
-			return;
-		}
-
-		for(var i=0; i<datLines.length; i++){
-			this.write(this.datLineParse(datLines[i], this.dat.lineCount+i+1, true));
-		}
-
-		if(httpStatus == 200 || httpStatus == 206){
-			this.dat.lineCount += datLines.length;
-
-			var datData = datLines.join("\n");
-			this.datSave(datData);
-		}
-
-		this.write(this.converter.getFooter("ok"));
-		this.close();
-
-		this._data = null;
-	},
-
-	machiHTML2DAT: function(aResponse){
-	        // ƒƒbƒZ[ƒW•”•ª‚ª“ñs‚É•ª‚©‚ê‚Ä‚¢‚é‚̂ňês‚É‚·‚é
-	    var datLines = aResponse.replace(/\n \]\<\/font\>/gm, " ]</font>");
-	    datLines = datLines.split("\n");
-
-	        // ƒƒbƒZ[ƒW‚ƃ^ƒCƒgƒ‹ˆÈŠO‚̍s‚ðíœ
-	    var reg = /^<(?:title>|dt>\d)/;
-	    datLines = datLines.filter(function(aElement, aIndex, aArray){
-	        return reg.test(aElement);
-	    });
-
-	        // ”z—ñ‚̈ê‚–ڂ̓^ƒCƒgƒ‹
-	    var datTitle = datLines.shift().replace(/<\/?title>/g, "");
-
-	    datLines = datLines.map(function(aElement, aIndex, aArray){
-	        var datLine = aElement;
-	        var name = (datLine.match(/<b> ([^<]+) <\/b>/i)) ? RegExp.$1 : "";
-	        var mail = (datLine.match(/<a href="mailto:([^"]+)"><b>/i)) ? RegExp.$1 : "";
-	        var date = (datLine.match(/“Še“úF ([^<]+) <font/)) ? RegExp.$1 : "";
-	        var message = (datLine.match(/<br><dd>/)) ? RegExp.rightContext : "";
-	        message = message.replace(/  <br><br>$/, "");
-	        message = message.replace(/<a href="[^"]+" target="_blank">([^<]+)<\/a>/g, "$1");
-	        var datNumber = (datLine.match(/<dt>(\d+) –¼‘O/)) ? parseInt(RegExp.$1) : 0;
-	        var title = (datNumber==1) ? datTitle : "";
-	        return name +"<>"+ mail +"<>"+ date +"<>"+ message +"<>" + title;
-	    });
-
-	    return datLines;
-	}
-
-};
-
-b2rThreadMachi.prototype.__proto__ = b2rThread2ch.prototype;
-
-
-// ***** ***** ***** ***** ***** b2rDat ***** ***** ***** ***** *****
-function b2rDat(){
-}
-
-b2rDat.prototype = {
-	get threadURL(){
-		return this._threadURL;
-	},
-
-	get threadPlainURL(){
-		if(!this._threadPlainURL){
-			if(this.type == this._b2rService.BOARD_TYPE_MACHI){
-				this._threadPlainURL = this.datURL;
-			}else{
-				var threadPlainSpec = this.threadURL.resolve("./");
-				this._threadPlainURL = this._ioService.newURI(threadPlainSpec, null, null)
-							.QueryInterface(Components.interfaces.nsIURL);
-			}
-		}
-		return this._threadPlainURL;
-	},
-
-	get boardURL(){
-		return this._boardURL;
-	},
-
-	get datURL(){
-		if(!this._datURL){
-			if(this.type == this._b2rService.BOARD_TYPE_MACHI){
-				var datURLSpec = this.threadURL.resolve("./read.cgi");
-				datURLSpec += "?BBS=" + this.queryHash["BBS"] + "&KEY=" + this.queryHash["KEY"];
-				this._datURL = this._ioService.newURI(datURLSpec, null, null)
-						.QueryInterface(Components.interfaces.nsIURL);
-			}else{
-				var datURLSpec = this.boardURL.resolve("dat/" + this.id + ".dat");
-				this._datURL = this._ioService.newURI(datURLSpec, null, null)
-						.QueryInterface(Components.interfaces.nsIURL);
-			}
-		}
-		return this._datURL;
-	},
-
-	get datKakoURL(){
-		if(this.type != this._b2rService.BOARD_TYPE_2CH){
-			return this.datURL;
-		}
-
-		if(!this._datKakoURL){
-			var datURLSpec = this.boardURL.resolve("kako/" +
-					this.id.substring(0,4) +"/"+ this.id.substring(0,5) +"/" + this.id + ".dat");
-			this._datKakoURL = this._ioService.newURI(datURLSpec, null, null)
-					.QueryInterface(Components.interfaces.nsIURL);
-		}
-		return this._datKakoURL;
-	},
-
-
-	get type(){
-		return this._type;
-	},
-
-	get datFile(){
-		return this._datFile;
-	},
-
-	get id(){
-		if(!this._id){
-			if(this.type == this._b2rService.BOARD_TYPE_MACHI){
-				this._id = this.queryHash["KEY"] || null;
-			}else{
-				this._id = this.threadURL.directory.match(/\/(\d{9,10})/) ? RegExp.$1 : null;
-			}
-		}
-		return this._id;
-	},
-
-	get title(){
-		return this._title;
-	},
-	set title(aValue){
-		return this._title = aValue;
-	},
-
-	get lineCount(){
-		return this._lineCount;
-	},
-	set lineCount(aValue){
-		return this._lineCount = aValue;
-	},
-
-	get lastModified(){
-		return this._lastModified;
-	},
-	set lastModified(aValue){
-		return this._lastModified = aValue;
-	},
-
-	get maruGetted(){
-		return this._maruGetted;
-	},
-	set maruGetted(aValue){
-		return this._maruGetted = aValue;
-	},
-
-
-	get queryHash(){
-		if(!this._queryHash){
-			this._queryHash = new Array();
-			var queryArray = this.threadURL.query.split("&");
-			for(var i=0; i<queryArray.length; i++){
-				var query = queryArray[i].split("=");
-				if(query.length == 2) this._queryHash[query[0]] = query[1];
-			}
-		}
-		return this._queryHash;
-	},
-
-	init: function(aThreadURL, aBoardURL, aType){
-		this._bbs2chService = Components.classes["@mozilla.org/bbs2ch-service;1"]
-				.getService(Components.interfaces.nsIBbs2chService);
-		this._b2rService  = Components.classes["@bbs2ch.sourceforge.jp/b2r-global-service;1"]
-					.getService(Components.interfaces.b2rIGlobalService);
-		this._ioService = Components.classes["@mozilla.org/network/io-service;1"]
-					.getService(Components.interfaces.nsIIOService);
-
-		this._threadURL = aThreadURL;
-
-		this._boardURL = (!aBoardURL) ?
-				this._b2rService.threadUtils.getBoardURL(this.threadURL) : aBoardURL;
-		this._type = (isNaN(parseInt(aType))) ?
-				this._b2rService.threadUtils.getBoardType(this.threadURL) : aType;
-
-			// ”‚̃^ƒCƒv‚ªABOARD_TYPE_PAGE ‚Å‚àA
-			// URL ‚É /test/read.cgi/ ‚ðŠÜ‚ñ‚Å‚¢‚½‚ç 2chŒÝŠ·‚Æ‚Ý‚È‚·
-		if(this._type == this._b2rService.BOARD_TYPE_PAGE &&
-					this._threadURL.spec.indexOf("/test/read.cgi/") != -1){
-			this._type = this._b2rService.BOARD_TYPE_2CH;
-		}
-
-		this._datFile = this._b2rService.io.getLogFileAtURL(
-								this.boardURL.resolve(this.id + ".dat"));
-
-
-		var b2rStorageService = Cc["@bbs2ch.sourceforge.jp/b2r-storage-service;1"].getService(Ci.b2rIStorageService);
-		var threadData = b2rStorageService.getThreadData(this.boardURL, this.id);
-
-		if(this.datFile.exists() && !threadData){
-			this.remove();
-		}
-		if(!this.datFile.exists() && threadData){
-			b2rStorageService.deleteThreadData(this.boardURL, this.id, false);
-			threadData = null;
-		}
-
-		if(threadData){
-			this._title = this._bbs2chService.toSJIS(threadData.title);
-			this._lineCount = threadData.lineCount;
-			this._lastModified = threadData.httpLastModified;
-			this._maruGetted = threadData.maruGetted;
-		}else{
-			this._title = "";
-			this._lineCount = 0;
-			this._lastModified = "";
-			this._maruGetted = false;
-		}
-	},
-
-
-	setThreadData: function(){
-		var b2rStorageService = Cc["@bbs2ch.sourceforge.jp/b2r-storage-service;1"].getService(Ci.b2rIStorageService);
-		b2rStorageService.setThreadData(
-				this.threadPlainURL,
-				this.boardURL,
-				this.id,
-				this._bbs2chService.fromSJIS(this.title),
-				this.lineCount,
-				this.lastModified,
-				this._maruGetted);
-	},
-
-
-	readContent: function(){
-		return this._bbs2chService.readFile(this.datFile.path);
-	},
-
-	writeContent: function(aContent){
-		this._bbs2chService.writeFile(this.datFile.path, aContent, false);
-	},
-
-	appendContent: function(aContent){
-		this._bbs2chService.writeFile(this.datFile.path, aContent, true);
-	},
-
-	remove: function(){
-		try{
-			if(this.datFile.exists()) this.datFile.remove(false);
-
-			this._title = "";
-			this._lineCount = 0;
-			this._lastModified = "";
-		}catch(ex){}
-	}
-};
-
-
-// ***** ***** ***** ***** ***** b2rId2Color ***** ***** ***** ***** *****
-/**
- * id‚©‚çF‚ð•Ô‚µ‚Ü‚·B
- */
-function b2rId2Color(){
-}
-
-b2rId2Color.prototype = {
-	_char64To8: new Array(),
-	_cache: new Array(),
-	_bgcache: new Array(),
-
-	init: function(){
-		var idChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-		var i=0;
-		for(var m in idChars){
-			this._char64To8[idChars[m]]=i
-			if(((parseInt(m)+1)%8)==0) i++;
-		}
-	},
-
-	/**
-	 * id‚©‚çCSS‚̐F‚ð•Ô‚µ‚Ü‚·B
-	 *
-	 * @param aID {string} 2ch‚ÌID
-	 * @param aIsBackground {bool} ”wŒi‚©
-	 * @type string
-	 * @return CSS‚̐F
-	 */
-	getColor: function(aID, aIsBackground){
-		if(aID.length < 8) return "inherit";
-
-		aID = aID.substring(0,8);
-		var cache = (aIsBackground) ? this._bgcache : this._cache;
-
-		if(!(aID in cache)){
-			var newint = 0;
-			for each(var s in aID){
-				newint <<= 3;
-				newint |= this._char64To8[s];
-			}
-			// hsl(0-360,0-100%,0-100%);
-			var h = newint%360;
-			newint = Math.floor(newint/360);
-			var s = newint%100;
-			newint = Math.floor(newint/100);
-			var l;
-			if(aIsBackground)
-				l = newint % 20 + 80;
-			else
-				l = newint%60;
-			cache[aID] = "hsl("+ h +","+ s +"%,"+ l +"%)";
-		}
-		return cache[aID];
-	}
-}
-
-
-// ***** ***** ***** ***** ***** b2rThreadConverter ***** ***** ***** ***** *****
-function b2rThreadConverter(){
-}
-
-b2rThreadConverter.prototype = {
-
-	init: function(aContext, aThreadURL, aBoardURL, aType){
-		this._context = aContext;
-		this._threadURL = aThreadURL;
-		this._boardURL = aBoardURL;
-		this._type = aType;
-
-		this._bbs2chService = Components.classes["@mozilla.org/bbs2ch-service;1"]
-				.getService(Components.interfaces.nsIBbs2chService);
-		this._b2rService  = Components.classes["@bbs2ch.sourceforge.jp/b2r-global-service;1"]
-				.getService(Components.interfaces.b2rIGlobalService);
-		this._ioService = Components.classes["@mozilla.org/network/io-service;1"]
-				.getService(Components.interfaces.nsIIOService);
-		this._pref = Components.classes["@mozilla.org/preferences-service;1"]
-				.getService(Components.interfaces.nsIPrefBranch);
-
-		this._dd2Color = new b2rId2Color();
-		this._dd2Color.init();
-
-
-		this._tmpHeader   = this._bbs2chService.readFile(this._resolveSkinFile("Header.html").path);
-		this._tmpFooter   = this._bbs2chService.readFile(this._resolveSkinFile("Footer.html").path);
-		this._tmpRes	  = this._bbs2chService.readFile(this._resolveSkinFile("Res.html").path);
-		this._tmpNewRes	  = this._bbs2chService.readFile(this._resolveSkinFile("NewRes.html").path);
-		this._tmpNewMark  = this._bbs2chService.readFile(this._resolveSkinFile("NewMark.html").path);
-
-		if(this._tmpHeader===null || this._tmpFooter===null || this._tmpRes===null || this._tmpNewRes===null || this._tmpNewMark===null){
-			throw Components.results.NS_ERROR_FILE_NOT_FOUND
-		}
-
-			// Šî–{ƒXƒLƒ“ƒ^ƒO‚Ì’uŠ·
-		this._tmpHeader = this._replaceBaseTag(this._tmpHeader);
-		this._tmpFooter = this._replaceBaseTag(this._tmpFooter);
-		this._tmpRes = this._replaceBaseTag(this._tmpRes);
-		this._tmpNewRes = this._replaceBaseTag(this._tmpNewRes);
-		this._tmpNewMark = this._replaceBaseTag(this._tmpNewMark);
-
-		this._tmpGetRes = this.toFunction(this._tmpRes);
-		this._tmpGetNewRes = this.toFunction(this._tmpNewRes);
-
-				// ‹ŒŽd—l‚̌݊·«Šm•Û
-		if(!this._tmpFooter.match(/<STATUS\/>/)){
-			this._tmpFooter = '<p class="info"><STATUS/></p>\n' + this._tmpFooter;
-		}
-	},
-
-	_resolveSkinFile: function(aFilePath){
-		var skinName = this._pref.getComplexValue("extensions.bbs2chreader.thread_skin",
-							Components.interfaces.nsISupportsString).data;
-
-		var skinFile = null;
-		if(skinName){
-			skinFile = this._b2rService.io.getDataDir();
-			skinFile.appendRelativePath("skin");
-			skinFile.appendRelativePath(skinName);
-		}else{
-			var bbs2chreaderID = "{0B9D558E-6983-486b-9AAD-B6CBCD2FC807}";
-			var extensionManager = Components.classes["@mozilla.org/extensions/manager;1"]
-					.getService(Components.interfaces.nsIExtensionManager);
-			var installLocation = extensionManager.getInstallLocation(bbs2chreaderID);
-			skinFile = installLocation.getItemFile(bbs2chreaderID, "defaults/skin").clone()
-							.QueryInterface(Components.interfaces.nsILocalFile);
-		}
-		skinFile.appendRelativePath(aFilePath);
-		return skinFile;
-	},
-
-	/**
-	 * Šî–{ƒXƒLƒ“ƒ^ƒO‚Ì’uŠ·
-	 * @param aString string ’uŠ·‚³‚ê‚镶Žš—ñ
-	 */
-	_replaceBaseTag: function(aString){
-		var requestURL = this._context._handler.requestURL;
-		var threadURLSpec = requestURL.path.substring(8);
-		var skinURISpec = this._b2rService.serverURL.resolve("./skin/");
-		var serverURLSpec = this._b2rService.serverURL.resolve("./thread/");
-		var fontName = this._pref.getComplexValue("extensions.bbs2chreader.thread_font_name",
-							Components.interfaces.nsISupportsString).data;
-		fontName = this._bbs2chService.toSJIS(fontName);
-		var fontSize = this._pref.getIntPref("extensions.bbs2chreader.thread_font_size");
-		var aaFontName = this._pref.getComplexValue("extensions.bbs2chreader.thread_aa_font_name",
-							Components.interfaces.nsISupportsString).data;
-		aaFontName = this._bbs2chService.toSJIS(aaFontName);
-		var aaFontSize = this._pref.getIntPref("extensions.bbs2chreader.thread_aa_font_size");
-
-		return aString.replace(/<SKINPATH\/>/g, skinURISpec)
-				.replace(/<THREADURL\/>/g, this._threadURL.resolve("./"))
-				.replace(/<BOARDURL\/>/g, this._boardURL.spec)
-				.replace(/<SERVERURL\/>/g, serverURLSpec)
-				.replace(/<FONTNAME\/>/g, "\'" + fontName + "\'")
-				.replace(/<FONTSIZE\/>/g, fontSize + "px")
-				.replace(/<AAFONTNAME\/>/g, "\'" + aaFontName + "\'")
-				.replace(/<AAFONTSIZE\/>/g, aaFontSize + "px");
-	},
-
-	getHeader: function(aTitle){
-		return this._tmpHeader.replace(/<THREADNAME\/>/g, aTitle);
-	},
-
-	getFooter: function(aStatusText){
-		var datSize = 0;
-		var datSizeKB = 0;
-		var datFile = this._context.dat.datFile.clone();
-		if(datFile.exists()){
-			datSize = datFile.fileSize;
-			datSizeKB = Math.round(datSize / 1024);
-		}
-		var logLineCount = this._context._logLineCount;
-		var lineCount = this._context.dat.lineCount;
-
-		return this._tmpFooter.replace(/<STATUS\/>/g, this.getStatusText(aStatusText))
-					.replace(/<SIZE\/>/g, datSize)
-					.replace(/<SIZEKB\/>/g, datSizeKB)
-					.replace(/<GETRESCOUNT\/>/g, logLineCount)
-					.replace(/<NEWRESCOUNT\/>/g, lineCount - logLineCount)
-					.replace(/<ALLRESCOUNT\/>/g, lineCount);
-	},
-
-	getStatusText: function(aStatus){
-	    var strBundleService = Components.classes["@mozilla.org/intl/stringbundle;1"]
-                                      .getService(Components.interfaces.nsIStringBundleService);
-		var statusBundle = strBundleService.createBundle(
-								"chrome://bbs2chreader/content/server/thread-status.properties");
-		var statusText = "";
-		if(typeof(aStatus) == "string"){
-			try{
-				statusText = statusBundle.GetStringFromName(aStatus);
-			}catch(ex){}
-		}else{
-			try{
-				statusText = statusBundle.formatStringFromName("error", [String(aStatus)], 1);
-			}catch(ex){}
-		}
-		return this._bbs2chService.toSJIS(statusText);
-	},
-
-	getNewMark: function(){
-		return this._tmpNewMark;
-	},
-
-	toFunction: function(aRes){
-		return eval(
-			"(function(aNumber, aName, aMail, aMailName, aDate, aID, resIDColor, resIDBgColor, aBeID, aMessage){return \""+aRes
-				.replace(/\\/g,"\\\\").replace(/\"/g,"\\\"")
-				.replace(/(\r|\n|\t)/g,"").replace(/<!--.*?-->/g,"")
-				.replace(/<PLAINNUMBER\/>/g, "\"+aNumber+\"")
-				.replace(/<NUMBER\/>/g, "\"+aNumber+\"")
-				.replace(/<NAME\/>/g, "\"+aName+\"")
-				.replace(/<MAIL\/>/g, "\"+aMail+\"")
-				.replace(/<MAILNAME\/>/g, "\"+aMailName+\"")
-				.replace(/<DATE\/>/g, "\"+aDate+\"")
-				.replace(/<ID\/>/g, "\"+aID+\"")
-				.replace(/<IDCOLOR\/>/g, "\"+resIDColor+\"")
-				.replace(/<IDBACKGROUNDCOLOR\/>/g, "\"+resIDBgColor+\"")
-				.replace(/<BEID\/>/g, "\"+aBeID+\"")
-				.replace(/<MESSAGE\/>/g, "\"+aMessage+\"")+"\";})"
-		);
-	},
-
-	getResponse: function(aNew, aNumber, aName, aMail, aMailName, aDate, aID, aBeID, aMessage){
-		var template = aNew ? this._tmpNewRes : this._tmpRes;
-		if(!template.match(/<ID\/>/))
-			aDate = aDate + " ID:" + aID;
-		if(!template.match(/<BEID\/>/))
-			aDate = aDate + " Be:" + aBeID;
-
-		var resIDColor = (template.search(/<IDCOLOR\/>/) != -1) ?
-				this._dd2Color.getColor(aID, false) : "inherit";
-		var resIDBgColor = (template.search(/<IDBACKGROUNDCOLOR\/>/) != -1) ?
-				this._dd2Color.getColor(aID, true) : "inherit";
-
-		if(this.isAA(aMessage)){
-			aMessage = '<span class="aaRes">' + aMessage + '</span>';
-		}
-
-		var result;
-		if(aNew){
-			result = this._tmpGetNewRes(aNumber, aName, aMail, aMailName, aDate, aID,
-						resIDColor, resIDBgColor,aBeID, aMessage);
-		}else{
-			result = this._tmpGetRes(aNumber, aName, aMail, aMailName, aDate, aID,
-						resIDColor, resIDBgColor,aBeID, aMessage);
-		}
-		return result;
-	},
-
-	isAA: function(aMessage) {
-		var lineCount = aMessage.match(/<br>/g);
-		if(lineCount && lineCount.length >= 3){
-			var spaceCount = aMessage.match(/[ @\.:i\|]/g);
-			if(spaceCount && (spaceCount.length / aMessage.length) >= 0.3){
-				return true;
-			}
-		}
-		return false;
-	}
-
-};
\ No newline at end of file

Copied: trunk/bbs2chreader/chrome/content/bbs2chreader/server/thread.jsm (from rev 406, trunk/bbs2chreader/chrome/content/bbs2chreader/server/thread.js)
===================================================================
--- trunk/bbs2chreader/chrome/content/bbs2chreader/server/thread.js	2008-03-12 13:54:26 UTC (rev 406)
+++ trunk/bbs2chreader/chrome/content/bbs2chreader/server/thread.jsm	2008-03-15 14:50:00 UTC (rev 410)
@@ -0,0 +1,1357 @@
+EXPORTED_SYMBOLS = ["ThreadServerScript"];
+
+const Ci = Components.interfaces;
+const Cc = Components.classes;
+const XPC = {
+	createInstance: function(aContractId, aInterface){
+		return Components.classes[aContractId].createInstance(Components.interfaces[aInterface]);
+	},
+	getService: function(aContractId, aInterface){
+	    return Components.classes[aContractId].getService(Components.interfaces[aInterface]);
+	}
+};
+
+
+function ThreadServerScript(aRequestURL){
+}
+
+
+ThreadServerScript.prototype  = {
+
+	start: function(aServerHandler){
+		aServerHandler.setResponseHeader("Content-Type", "text/html; charset=Shift_JIS");
+		aServerHandler.writeResponseHeader(200);
+
+		var threadURL = this.getThreadURL(aServerHandler.requestURL);
+		if(!threadURL){
+			aServerHandler.write("BAD URL");
+			aServerHandler.close();
+			return;
+		}
+
+		var b2rService = Components.classes["@bbs2ch.sourceforge.jp/b2r-global-service;1"]
+				.getService(Components.interfaces.b2rIGlobalService);
+
+		var boardURL = b2rService.threadUtils.getBoardURL(threadURL);
+		var type = b2rService.threadUtils.getBoardType(threadURL);
+			// ”‚̃^ƒCƒv‚ªABOARD_TYPE_PAGE ‚Å‚àA
+			// URL ‚É /test/read.cgi/ ‚ðŠÜ‚ñ‚Å‚¢‚½‚ç 2chŒÝŠ·‚Æ‚Ý‚È‚·
+		if(type == b2rService.BOARD_TYPE_PAGE && threadURL.spec.indexOf("/test/read.cgi/") != -1){
+			type = b2rService.BOARD_TYPE_2CH;
+		}
+
+		switch(type){
+			case b2rService.BOARD_TYPE_2CH:
+				this.thread = new b2rThread2ch();
+				break;
+			case b2rService.BOARD_TYPE_JBBS:
+				this.thread = new b2rThreadJbbs();
+				break;
+			case b2rService.BOARD_TYPE_MACHI:
+				this.thread = new b2rThreadMachi();
+				break;
+			default:
+				this.thread = null;
+				break;
+		}
+
+		if(this.thread){
+			this.thread.init(aServerHandler, threadURL, boardURL, type);
+		}else{
+			aServerHandler.write("No Supported Boad");
+			aServerHandler.close();
+		}
+	},
+
+	cancel: function(){
+		if(this.thread){
+			this.thread.close();
+			this.thread = null;
+		}
+	},
+
+	getThreadURL: function(aRequestURL){
+		var threadURLSpec = aRequestURL.path.substring(8);
+		if(threadURLSpec == "") return null;
+
+		// threadURLSpec = decodeURIComponent(threadURLSpec);
+
+		try{
+			var ioService = Components.classes["@mozilla.org/network/io-service;1"]
+					.getService(Components.interfaces.nsIIOService);
+			var threadURL = ioService.newURI(threadURLSpec, null, null)
+					.QueryInterface(Components.interfaces.nsIURL);
+				// URL ‚ªADAT ID ‚ŏI‚í‚é‚Æ‚«‚Í "/" ‚ð’ljÁ‚·‚é
+			if(threadURL.fileName.match(/^\d{9,10}$/)){
+				threadURL = ioService.newURI(threadURLSpec + "/", null, null)
+						.QueryInterface(Components.interfaces.nsIURL);
+			}
+			return threadURL;
+		}catch(ex){}
+
+		return null;
+	}
+
+};
+
+
+// ***** ***** ***** ***** ***** b2rThread2ch ***** ***** ***** ***** *****
+function b2rThread2ch(){
+}
+
+b2rThread2ch.prototype = {
+
+	get optionsOnes(){
+		return (this.dat.threadURL.fileName.match(/^(\d+)n?$/)) ? parseInt(RegExp.$1) : null;
+	},
+	get optionsStart(){
+		return (this.dat.threadURL.fileName.match(/(\d+)\-/)) ? parseInt(RegExp.$1) : null;
+	},
+	get optionsLast(){
+		return (this.dat.threadURL.fileName.match(/l(\d+)/)) ? parseInt(RegExp.$1) : null;
+	},
+	get optionsEnd(){
+		return (this.dat.threadURL.fileName.match(/\-(\d+)/)) ? parseInt(RegExp.$1) : null;
+	},
+	get optionsNoFirst(){
+		return (this.dat.threadURL.fileName.indexOf("n") != -1);
+	},
+
+	init: function(aHandler, aThreadURL, aBoardURL, aType){
+		this._handler = aHandler;
+
+		this._bbs2chService = Components.classes["@mozilla.org/bbs2ch-service;1"]
+					.getService(Components.interfaces.nsIBbs2chService);
+		this._b2rService  = Components.classes["@bbs2ch.sourceforge.jp/b2r-global-service;1"]
+					.getService(Components.interfaces.b2rIGlobalService);
+		this._pref = Components.classes["@mozilla.org/preferences-service;1"]
+					.getService(Components.interfaces.nsIPrefBranch);
+
+		this._ioService = Components.classes["@mozilla.org/network/io-service;1"]
+					.getService(Components.interfaces.nsIIOService);
+
+		this._chainAboneNumbers = new Array();
+		this._enableChainAbone = this._pref.getBoolPref("extensions.bbs2chreader.thread_chain_abone")
+
+			// HTML ƒwƒbƒ_‚𑗐M‚µ‚½‚ç true ‚É‚È‚é
+		this._headerResponded = false;
+		this._opend = true;
+		this.httpChannel = null;
+
+		this.dat = new b2rDat();
+		this.dat.init(aThreadURL, aBoardURL, aType);
+		if(!this.dat.id){
+			this.write("BAD URL");
+			this.close();
+			return;
+		}
+
+		this.converter = new b2rThreadConverter();
+		try{
+			this.converter.init(this, this.dat.threadURL, this.dat.boardURL, this.dat.type);
+		}catch(ex){
+			if(ex == Components.results.NS_ERROR_FILE_NOT_FOUND){
+				var skinName = this._pref.getComplexValue("extensions.bbs2chreader.thread_skin",
+						Components.interfaces.nsISupportsString).data;
+				skinName = this._bbs2chService.toSJIS(skinName);
+				this.write("ƒXƒLƒ“ ("+ skinName +") ‚̓ǂݍž‚Ý‚ÉŽ¸”s‚µ‚½‚½‚߁A");
+				this.write("Ý’è‚ðƒfƒtƒHƒ‹ƒgƒXƒLƒ“‚É–ß‚µ‚Ü‚µ‚½B<br>ƒy[ƒW‚ðXV‚µ‚Ä‚­‚¾‚³‚¢B");
+				this.close();
+				this._pref.setCharPref("extensions.bbs2chreader.thread_skin", "");
+				return;
+			}else {
+				this.write(ex.toSource());
+				this.close();
+				return;
+			}
+		}
+
+		/*
+		this.write("<!-- \n");
+		this.write("Thread URL    : " + this.dat.threadURL.spec + "\n");
+		this.write("Board URL     : " + this.dat.boardURL.spec + "\n");
+		this.write("Type          : " + this.dat.type + "\n");
+		this.write("DAT URL       : " + this.dat.datURL.spec + "\n");
+		this.write("DAT ID        : " + this.dat.id + "\n");
+		this.write("DAT File      : " + this.dat.datFile.path + "\n");
+		this.write("----- ----- -----\n");
+		this.write("Title         : " + this.dat.title + "\n");
+		this.write("LineCount     : " + this.dat.lineCount + "\n");
+		this.write("LastModified  : " + this.dat.lastModified + "\n");
+		this.write("----- ----- -----\n");
+		this.write("URL Options \n");
+		this.write("  Ones        : " + this.optionsOnes + "\n");
+		this.write("  Start       : " + this.optionsStart + "\n");
+		this.write("  Last        : " + this.optionsLast + "\n");
+		this.write("  End         : " + this.optionsEnd + "\n");
+		this.write("  NoFirst     : " + this.optionsNoFirst + "\n");
+		this.write("-->\n\n");
+		*/
+
+		this._logLineCount = 0;
+			// Žæ“¾Ï‚݃ƒO‚Ì‘—M
+		if(this.dat.datFile.exists()){
+			var datLines = this._bbs2chService.readFileLine(this.dat.datFile.path, {});
+
+			this._logLineCount = datLines.length;
+
+			if(this.optionsOnes && this.optionsOnes <= this._logLineCount){
+				this._headerResponded = true;
+				var header = this.converter.getHeader(this.dat.title);
+				this.write(header);
+				this.write(this.datLineParse(datLines[this.optionsOnes-1],
+								this.optionsOnes, false));
+				this.write(this.converter.getFooter("log_pickup_mode"));
+				this.close();
+				return;
+
+			}else if(this.optionsEnd){
+				this._headerResponded = true;
+				var header = this.converter.getHeader(this.dat.title);
+				this.write(header);
+
+				var start = this.optionsStart ? this.optionsStart : 1;
+				if(start < 1) start = 1;
+				var end = this.optionsEnd;
+				if(end > datLines.length) end = datLines.length;
+				if(start > end) start = end;
+
+				for(var i=start-1; i<end; i++){
+					this.write(this.datLineParse(datLines[i], i+1, false) +"\n");
+				}
+
+				this.write(this.converter.getFooter("log_pickup_mode"));
+				this.close();
+				return;
+
+			}else{
+				if(!this.optionsNoFirst){
+					this.write(this.datLineParse(datLines[0], 1, false) +"\n");
+				}else if(this.dat.title){
+					this._headerResponded = true;
+					var header = this.converter.getHeader(this.dat.title);
+					this.write(header);
+				}else{
+					this.write(this.datLineParse(datLines[0], 1, false) +"\n");
+				}
+
+				var start = 1;
+				var end = datLines.length;
+				if(this.optionsLast == 0){
+					this.write(this.converter.getNewMark() +"\n");
+					this.datDownload();
+					return;
+				}else if(this.optionsLast){
+					start = end - this.optionsLast;
+					if(start < 1) start = 1;
+				}else if(this.optionsStart){
+					start = this.optionsStart - 1;
+					if(start > end) start = end;
+				}
+
+				for(var i=start; i<end; i++){
+					this.write(this.datLineParse(datLines[i], i+1, false) +"\n");
+				}
+
+				this.write(this.converter.getNewMark() +"\n");
+			}
+		}
+
+		if(this.dat.maruGetted){
+			this.write(this.converter.getFooter("ok"));
+			this.close();
+		}
+
+		this._handler.flush();
+		this.datDownload();
+	},
+
+	write: function(aString){
+		this._handler.write(aString);
+	},
+
+	close: function(){
+		if(this._headerResponded && this.dat){
+			var title = this._bbs2chService.fromSJIS(this.dat.title);
+			this._b2rService.history.visitPage(this.dat.threadPlainURL, title, 1);
+		}
+		this._opend = false;
+		this._httpChannel = null;
+		this._handler.close();
+		this._handler = null;
+	},
+
+
+	htmlToText: function(aStr){
+		var fromStr = Components.classes["@mozilla.org/supports-string;1"]
+									.createInstance(Components.interfaces.nsISupportsString);
+		fromStr.data = aStr;
+		try{
+			var toStr = { value: null };
+			var	formatConverter = Components.classes["@mozilla.org/widget/htmlformatconverter;1"]
+									.createInstance(Components.interfaces.nsIFormatConverter);
+			formatConverter.convert("text/html", fromStr, fromStr.toString().length,
+										"text/unicode", toStr, {});
+		}catch(e){
+			return aStr;
+		}
+		if(toStr.value){
+			toStr = toStr.value.QueryInterface(Components.interfaces.nsISupportsString);
+			return toStr.toString();
+		}
+		return aStr;
+	},
+
+
+	datLineParse: function(aLine, aNumber, aNew){
+		if(!aLine) return "";
+
+		var resArray = aLine.split("<>");
+		var resNumber = aNumber;
+		var resName = "BROKEN";
+		var resMail = "";
+		var resDate = "BROKEN";
+		var resID = "";
+		var resBeID = "";
+		var resMes	= "";
+
+		if(resArray.length > 3){
+			resName = resArray[0].replace(/<\/?b>|/g, "");
+			resMail = resArray[1];
+			resDate = resArray[2];
+			resMes = resArray[3];
+		}
+
+		if(resDate.indexOf("<") != -1){
+			resDate	= this.htmlToText(resDate);
+		}
+
+			// resDate ‚ð DATEABeID ‚É•ªŠ„
+		if(resDate.indexOf("BE:")!=-1 && resDate.match(/(.+)BE:([^ ]+) ?/)){
+			resDate = RegExp.$1 + RegExp.rightContext;
+			resBeID = RegExp.$2;
+		}
+			// resDate ‚ð DATE ‚Æ ID ‚É•ªŠ„
+		if(resDate.indexOf("ID:")!=-1 && resDate.match(/(.+)ID:([^ ]+) ?/)){
+			resDate = RegExp.$1 + RegExp.rightContext;
+			resID = RegExp.$2;
+		}
+
+			// resDate ‚É IP ‚ªŠÜ‚Ü‚ê‚Ä‚¢‚éê‡‚Í IP ‚ð ID ‚Æ‚µ‚Ĉµ‚¤
+		/*
+		if(resDate.match(/(.+)”­MŒ³:(.+)/)){
+			resDate = RegExp.$1;
+			resID = RegExp.$2;
+		}
+		*/
+
+		if(this._b2rService.abone.shouldAbone(resName, resMail, resID, resMes)){
+			this._chainAboneNumbers.push(aNumber);
+			resName = resMail = resDate = resMes = "ABONE";
+			if(aNumber>1 && this._pref.getBoolPref("extensions.bbs2chreader.thread_hide_abone")){
+				return "";
+			}
+		}
+
+		if(resBeID){
+			var regBeID = /^(\d+)/;
+			if(resBeID.match(regBeID)){
+				var idInfoUrl = "http://be.2ch.net/test/p.php?i=" + RegExp.$1 +
+						"&u=d:" + this.dat.threadURL.resolve("./") + aNumber;
+				resBeID = resBeID.replace(regBeID, String("$1").link(idInfoUrl));
+			}
+		}
+
+			// JS‚Å‚Í "\" ‚ª“ÁŽê‚ȈӖ¡‚ðŽ‚Â‚½‚߁A”’l•¶ŽšŽQÆ‚É•ÏŠ·
+		resName = resName.replace(/([^\x81-\xfc]|^)\x5C/g,"$1&#x5C;");
+		resMail = resMail.replace(/([^\x81-\xfc]|^)\x5C/g,"$1&#x5C;");
+
+		var resMailName = resName;
+		if(resMail) resMailName = '<a href="mailto:' + resMail + '">' + resName + '</a>';
+
+			// ƒŒƒX”ÔƒŠƒ“ƒNˆ— & ˜A½‚ ‚ځ[‚ñ
+		var regResPointer = /(?:<a .*?>)?(&gt;&gt;|&gt;)([0-9]{1,4})(\-[0-9]{1,4})?(?:<\/a>)?/g;
+
+		var chainAboneNumbers = this._chainAboneNumbers;
+		var chainAbone = false;
+		resMes = resMes.replace(regResPointer, function(aStr, aP1, aP2, aP3, aOffset, aS){
+			chainAbone = chainAbone || (chainAboneNumbers.indexOf(parseInt(aP2)) != -1);
+			return '<a href="#res' + aP2 + '" class="resPointer">' + aP1 + aP2 + aP3 + '</a>';
+		});
+		if(this._enableChainAbone && chainAbone){
+			resName = resMail = resDate = resMes = "ABONE";
+			if(aNumber>1 && this._pref.getBoolPref("extensions.bbs2chreader.thread_hide_abone")){
+				return "";
+			}
+		}
+
+			// ’ʏ탊ƒ“ƒNˆ—
+		if(resMes.indexOf("ttp")!=-1){
+			var regUrlLink = /(h?ttp)(s)?\:([\-_\.\!\~\*\'\(\)a-zA-Z0-9\;\/\?\:\@\&\=\+\$\,\%\#]+)/g;
+			resMes = resMes.replace(regUrlLink, '<a href="http$2:$3" class="outLink">$1$2:$3</a>');
+		}
+			// ƒŒƒXID
+		var regResID = / (ID:)([0-9a-z\+\/]+)/ig;
+		resMes = resMes.replace(regResID, ' <span class="resMesID"><span class="mesID_$2">$1$2</span></span>');
+
+			// ƒXƒŒƒbƒh‚̃^ƒCƒgƒ‹‚ªŒ©‚‚©‚Á‚½‚Æ‚«‚Í HTML ƒwƒbƒ_‚ð’ljÁ‚µ‚Ä‘—‚é
+		if(!this._headerResponded && resArray[4]){
+			this._headerResponded = true;
+			this.dat.title = resArray[4];
+
+			var header = this.converter.getHeader(this.dat.title);
+			this.write(header);
+			this._handler.flush();
+		}
+		var response = this.converter.getResponse(aNew, aNumber, resName, resMail,
+								resMailName, resDate, resID, resBeID, resMes);
+		return response;
+	},
+
+
+	datDownload: function(aKako){
+		if(aKako){
+			if(this._b2rService.viewer.logined){
+				var sid = encodeURIComponent(this._b2rService.viewer.sessionID);
+				var datURLSpec = this.dat.threadPlainURL.spec.replace(/\/read\.cgi\//, "/offlaw.cgi/");
+				datURLSpec += "?raw=.0&sid=" + sid;
+				var datKakoURL = this._ioService.newURI(datURLSpec, null, null)
+						.QueryInterface(Components.interfaces.nsIURL);
+				this.httpChannel = this._b2rService.getHttpChannel(datKakoURL);
+				this._maruMode = true;
+			}else{
+				this.httpChannel = this._b2rService.getHttpChannel(this.dat.datKakoURL);
+			}
+			this._kakoDatDownload = true;
+
+		}else{
+			this.httpChannel = this._b2rService.getHttpChannel(this.dat.datURL);
+			this._kakoDatDownload = false;
+		}
+		this.httpChannel.requestMethod = "GET";
+		this.httpChannel.redirectionLimit = 0; // 302 “™‚̃Šƒ_ƒCƒŒƒNƒg‚ðs‚í‚È‚¢
+		this.httpChannel.loadFlags = this.httpChannel.LOAD_BYPASS_CACHE;
+		this._aboneChecked = true;
+		this._threadAbone = false;
+
+			// ·•ªGET
+		if(this.dat.datFile.exists() && this.dat.lastModified){
+			var lastModified = this.dat.lastModified;
+			var range = this.dat.datFile.fileSize - 1;
+			this.httpChannel.setRequestHeader("Accept-Encoding", "", false);
+			this.httpChannel.setRequestHeader("If-Modified-Since", lastModified, false);
+			this.httpChannel.setRequestHeader("Range", "bytes=" + range + "-", false);
+			this._aboneChecked = false;
+		}else{
+			this.httpChannel.setRequestHeader("Accept-Encoding", "gzip", false);
+		}
+
+		this.httpChannel.asyncOpen(this, null);
+	},
+
+	onStartRequest: function(aRequest, aContext){
+		this._bInputStream = Components.classes["@mozilla.org/binaryinputstream;1"]
+					.createInstance(Components.interfaces.nsIBinaryInputStream);
+		this._data = new Array();
+		this._datBuffer = "";
+	},
+
+	onDataAvailable: function (aRequest, aContext, aInputStream, aOffset, aCount){
+		if(!this._opend) return;
+
+		aRequest.QueryInterface(Components.interfaces.nsIHttpChannel);
+		var httpStatus = aRequest.responseStatus;
+			// •K—v‚ȏî•ñ‚ª‚È‚¢‚È‚çI—¹
+		if(!(httpStatus==200 || httpStatus==206)) return;
+		if(aCount == 0) return;
+
+		this._bInputStream.setInputStream(aInputStream);
+
+		var availableData = "";
+		if(!this._aboneChecked){
+			var firstChar = this._bInputStream.readBytes(1)
+			availableData = this._bInputStream.readBytes(aCount - 1);
+			if(firstChar.charCodeAt(0) != 10){
+				this._threadAbone = true;
+			}
+
+		}else{
+			availableData = this._bInputStream.readBytes(aCount);
+		}
+		this._aboneChecked = true;
+
+
+		if(this._maruMode && this._data.length == 0){
+			if(availableData.match(/\n/)){
+				availableData = RegExp.rightContext;
+			}else{
+				return;
+			}
+		}
+
+			// NULL •¶Žš
+		availableData = availableData.replace(/\x00/g, "*");
+			// •ÏŠ·‘O‚Ì DAT ‚ð•Û‘¶‚µ‚Ä‚¨‚­
+		this._data.push(availableData);
+
+		var availableData = this._datBuffer + availableData;
+			// ‰üs‚ðŠÜ‚Ü‚È‚¢‚È‚çƒoƒbƒtƒ@‚ɒljÁ‚µ‚ďI—¹
+		if(!availableData.match(/\n/)){
+			this._datBuffer = availableData;
+			return;
+		}
+
+			// Žæ“¾‚µ‚½ DAT ‚ðs‚²‚Æ‚É”z—ñ‚É‚µAÅŒã‚̍s‚ðƒoƒbƒtƒ@‚ɒljÁ
+		var datLines = availableData.split("\n");
+		this._datBuffer = (datLines.length>1) ? datLines.pop() : "";
+
+			// DAT ‚ð •ÏŠ·‚µ‚ď‘‚«o‚·
+		for(var i=0; i<datLines.length; i++){
+			this.dat.lineCount++;
+			this.write(this.datLineParse(datLines[i], this.dat.lineCount, true) +"\n");
+		}
+		this._handler.flush();
+	},
+
+	onStopRequest: function(aRequest, aContext, aStatus){
+		if(!this._opend) return;
+
+		this._bInputStream = null;
+		aRequest.QueryInterface(Components.interfaces.nsIHttpChannel);
+		try{
+			var httpStatus = aRequest.responseStatus;
+		}catch(ex){
+			this.write(this.converter.getFooter("network_error"));
+			this.close();
+			return;
+		}
+
+		try{
+			this.dat.lastModified = aRequest.getResponseHeader("Last-Modified");
+		}catch(ex){}
+
+		switch(httpStatus){
+			case 200: // ’ʏíGET OK
+			case 206: // ·•ªGET OK
+				break;
+			case 302: // DAT—Ž‚¿
+				if(this._kakoDatDownload){
+					this.write(this.converter.getFooter("dat_down"));
+					this.close();
+				}else{
+					this.datDownload(true);
+				}
+				return;
+			case 304: // –¢XV
+				this.write(this.converter.getFooter("not_modified"));
+				this.close();
+				return;
+			case 416: //‚ ‚ځ[‚ñ
+				this.write(this.converter.getFooter("abone"));
+				this.close();
+				return;
+			default: // HTTP ƒGƒ‰[
+				this.write(this.converter.getFooter(httpStatus));
+				this.close();
+				return;
+		}
+
+		if(this._threadAbone){ //‚ ‚ځ[‚ñ
+			this.write(this.converter.getFooter("abone"));
+			this.close();
+			return;
+		}
+
+			// XXX TODO ˆê•”ŒÝŠ·ƒXƒNƒŠƒvƒg‚ɂ́A–¢XV‚Å‚à 206 ‚ð•Ô‚·‚à‚Ì‚ª‚ ‚é?
+		var newResLength = this.dat.lineCount - this._logLineCount;
+		if(newResLength == 0){
+			this.write(this.converter.getFooter("not_modified"));
+			this.close();
+			return;
+		}
+
+		if(this._datBuffer){
+			this.dat.lineCount++;
+			this._datBuffer = this.dat.lineCount +"\t: "+ this._datBuffer;
+			this.write(this._datBuffer);
+			this._datBuffer = "";
+		}
+
+		if(httpStatus == 200 || httpStatus == 206){
+			this.datSave(this._data.join(""));
+		}
+		this.write(this.converter.getFooter("ok"));
+		this.close();
+		this._data = null;
+	},
+
+	datSave: function(aDatContent){
+				// ‘‚«ž‚݂̃oƒbƒeƒBƒ“ƒO‚ð”ð‚¯‚é
+
+		var b2rStorageService = Cc["@bbs2ch.sourceforge.jp/b2r-storage-service;1"].getService(Ci.b2rIStorageService);
+		var threadData = b2rStorageService.getThreadData(this.dat.boardURL, this.dat.id);
+		var tmpLineCount = 0;
+		if(threadData){
+			tmpLineCount = threadData.lineCount;
+		}
+		if(this.dat.lineCount > tmpLineCount){
+				// .dat ‚Ì’Ç‹L‘‚«ž‚Ý
+			this.dat.appendContent(aDatContent);
+
+			if(this._maruMode) this.dat.maruGetted = true;
+			this.dat.setThreadData();
+		}
+	}
+
+};
+
+
+// ***** ***** ***** ***** ***** b2rThreadJbbs ***** ***** ***** ***** *****
+function b2rThreadJbbs(){
+}
+
+b2rThreadJbbs.prototype = {
+	datDownload: function(){
+		var datURLSpec = this.dat.threadURL.resolve("./").replace("read.cgi", "rawmode.cgi");
+		this._aboneChecked = true;
+		this._threadAbone = false;
+
+			// ·•ªGET
+		if(this.dat.datFile.exists() && this.dat.lineCount){
+			datURLSpec += (this.dat.lineCount + 1) + "-";
+		}
+
+		var datURL = this._ioService.newURI(datURLSpec, null, null)
+				.QueryInterface(Components.interfaces.nsIURL);
+
+		this.httpChannel = this._b2rService.getHttpChannel(datURL);
+		this.httpChannel.requestMethod = "GET";
+		this.httpChannel.redirectionLimit = 0; // 302 “™‚̃Šƒ_ƒCƒŒƒNƒg‚ðs‚í‚È‚¢
+		this.httpChannel.loadFlags = this.httpChannel.LOAD_BYPASS_CACHE;
+
+		this.httpChannel.asyncOpen(this, null);
+	},
+
+	datLineParse: function(aLine, aNumber, aNew){
+		if(!aLine) return "";
+
+			// EUC-JP ‚©‚ç SJIS ‚Ö•ÏŠ·
+		var line = this._bbs2chService.fromEUC(aLine);
+		line = this._bbs2chService.toSJIS(line);
+		var resArray = line.split("<>");
+		var resNumber = aNumber;
+		var resName = "BROKEN";
+		var resMail = "";
+		var resDate = "BROKEN";
+		var resID = "";
+		var resBeID = "";
+		var resMes	= "";
+
+		if(resArray.length > 5){
+			resName = resArray[1].replace(/<\/?b>|/g, "");
+			resMail = resArray[2];
+			resDate = resArray[3];
+			resMes = resArray[4];
+			resID = resArray[6];
+		}
+
+		if(this._b2rService.abone.shouldAbone(resName, resMail, resID, resMes)){
+			this._chainAboneNumbers.push(aNumber);
+			resName = resMail = resDate = resMes = "ABONE";
+			if(aNumber>1 && this._pref.getBoolPref("extensions.bbs2chreader.thread_hide_abone")){
+				return "";
+			}
+		}
+
+			// JS‚Å‚Í "\" ‚ª“ÁŽê‚ȈӖ¡‚ðŽ‚Â‚½‚߁A”’l•¶ŽšŽQÆ‚É•ÏŠ·
+		resName = resName.replace(/([^\x81-\xfc]|^)\x5C/g,"$1&#x5C;");
+		resMail = resMail.replace(/([^\x81-\xfc]|^)\x5C/g,"$1&#x5C;");
+
+		var resMailName = resName;
+		if(resMail) resMailName = '<a href="mailto:' + resMail + '">' + resName + '</a>';
+
+
+			// ƒŒƒX”ÔƒŠƒ“ƒNˆ— & ˜A½‚ ‚ځ[‚ñ
+		var regResPointer = /(?:<a .*?>)?(&gt;&gt;|&gt;)([0-9]{1,4})(\-[0-9]{1,4})?(?:<\/a>)?/g;
+
+		var chainAboneNumbers = this._chainAboneNumbers;
+		var chainAbone = false;
+		resMes = resMes.replace(regResPointer, function(aStr, aP1, aP2, aP3, aOffset, aS){
+			chainAbone = chainAbone || (chainAboneNumbers.indexOf(parseInt(aP2)) != -1);
+			return '<a href="#res' + aP2 + '" class="resPointer">' + aP1 + aP2 + aP3 + '</a>';
+		});
+		if(this._enableChainAbone && chainAbone){
+			resName = resMail = resDate = resMes = "ABONE";
+			if(aNumber>1 && this._pref.getBoolPref("extensions.bbs2chreader.thread_hide_abone")){
+				return "";
+			}
+		}
+
+
+			// ’ʏ탊ƒ“ƒNˆ—
+		var regUrlLink = /(h?ttp)(s)?\:([\-_\.\!\~\*\'\(\)a-zA-Z0-9\;\/\?\:\@\&\=\+\$\,\%\#]+)/g;
+		resMes = resMes.replace(regUrlLink, '<a href="http$2:$3" class="outLink">$1$2:$3</a>');
+
+			// ƒXƒŒƒbƒh‚̃^ƒCƒgƒ‹‚ªŒ©‚‚©‚Á‚½‚Æ‚«‚Í HTML ƒwƒbƒ_‚ð’ljÁ‚µ‚Ä‘—‚é
+		if(!this._headerResponded && resArray[5]!= ""){
+			this._headerResponded = true;
+			this.dat.title = resArray[5];
+
+			var header = this.converter.getHeader(this.dat.title);
+			this.write(header);
+			this._handler.flush();
+		}
+		var response = this.converter.getResponse(aNew, aNumber, resName, resMail,
+								resMailName, resDate, resID, resBeID, resMes);
+		return response;
+	},
+
+	onStopRequest: function(aRequest, aContext, aStatus){
+		if(!this._opend) return;
+
+		aRequest.QueryInterface(Components.interfaces.nsIHttpChannel);
+		var httpStatus = aRequest.responseStatus;
+		var jbbsError = "";
+		try{
+			jbbsError = aRequest.getResponseHeader("ERROR");
+		}catch(ex){}
+
+
+		switch(jbbsError){
+			case "BBS NOT FOUND":
+			case "KEY NOT FOUND":
+			case "THREAD NOT FOUND":
+				this.write(this.converter.getFooter(999));
+				this.close();
+				return;
+			case "STORAGE IN":
+				this.write(this.converter.getFooter("dat_down"));
+				this.close();
+				return;
+		}
+
+		if(this._datBuffer){
+			this.dat.lineCount++;
+			this._datBuffer = this.dat.lineCount +"\t: "+ this._datBuffer;
+			this.write(this._datBuffer);
+			this._datBuffer = "";
+		}
+
+		if(httpStatus == 200 || httpStatus == 206){
+			this.datSave(this._data.join(""));
+		}
+		this.write(this.converter.getFooter("ok"));
+		this.close();
+		this._data = null;
+	}
+};
+
+b2rThreadJbbs.prototype.__proto__ = b2rThread2ch.prototype;
+
+
+// ***** ***** ***** ***** ***** b2rThreadMachi ***** ***** ***** ***** *****
+function b2rThreadMachi(){
+}
+
+b2rThreadMachi.prototype = {
+	get optionsStart(){
+		return (this.dat.queryHash["START"]) ? parseInt(this.dat.queryHash["START"]) : null;
+	},
+	get optionsLast(){
+		return (this.dat.queryHash["LAST"]) ? parseInt(this.dat.queryHash["LAST"]) : null;
+	},
+	get optionsEnd(){
+		return (this.dat.queryHash["END"]) ? parseInt(this.dat.queryHash["END"]) : null;
+	},
+	get optionsNoFirst(){
+		return (this.dat.queryHash["NOFIRST"] == "TRUE") ? true : false;
+	},
+
+	datDownload: function(){
+		var datURLSpec = this.dat.datURL.spec
+		this._aboneChecked = true;
+		this._threadAbone = false;
+
+				// ·•ªGET
+		if(this.dat.datFile.exists() && this.dat.lineCount){
+			datURLSpec += "&NOFIRST=TRUE&START=" + (this.dat.lineCount + 1);
+		}
+		var datURL = this._ioService.newURI(datURLSpec, null, null)
+				.QueryInterface(Components.interfaces.nsIURL);
+
+		this.httpChannel = this._b2rService.getHttpChannel(datURL);
+		this.httpChannel.requestMethod = "GET";
+		this.httpChannel.redirectionLimit = 0; // 302 “™‚̃Šƒ_ƒCƒŒƒNƒg‚ðs‚í‚È‚¢
+		this.httpChannel.loadFlags = this.httpChannel.LOAD_BYPASS_CACHE;
+
+		this.httpChannel.asyncOpen(this, null);
+	},
+
+	onStartRequest: function(aRequest, aContext){
+		this._bInputStream = Components.classes["@mozilla.org/binaryinputstream;1"]
+					.createInstance(Components.interfaces.nsIBinaryInputStream);
+		this._htmlData = new Array();
+	},
+
+	onDataAvailable: function (aRequest, aContext, aInputStream, aOffset, aCount){
+		if(!this._opend) return;
+
+		aRequest.QueryInterface(Components.interfaces.nsIHttpChannel);
+		var httpStatus = aRequest.responseStatus;
+			// •K—v‚ȏî•ñ‚ª‚È‚¢‚È‚çI—¹
+		if(!(httpStatus==200 || httpStatus==206)) return;
+		if(aCount == 0) return;
+
+		this._bInputStream.setInputStream(aInputStream);
+		var availableData = this._bInputStream.readBytes(aCount);
+			// NULL •¶Žš
+		availableData = availableData.replace(/\x00/g, "*");
+
+		this._htmlData.push(availableData);
+		this.write(" ");
+	},
+
+	onStopRequest: function(aRequest, aContext, aStatus){
+		if(!this._opend) return;
+
+		this._bInputStream = null;
+		aRequest.QueryInterface(Components.interfaces.nsIHttpChannel);
+		var httpStatus = aRequest.responseStatus;
+
+		switch(httpStatus){
+			case 200: // ’ʏíGET OK
+			case 206: // ·•ªGET OK
+				break;
+			default: // HTTP ƒGƒ‰[
+				this.write(this.converter.getFooter(httpStatus));
+				this.close();
+				return;
+		}
+
+		var datLines = this.machiHTML2DAT(this._htmlData.join(""));
+		this._htmlData = null;
+
+		if(datLines.length == 0){ // –¢XV
+			this.write(this.converter.getFooter("not_modified"));
+			this.close();
+			return;
+		}
+
+		for(var i=0; i<datLines.length; i++){
+			this.write(this.datLineParse(datLines[i], this.dat.lineCount+i+1, true));
+		}
+
+		if(httpStatus == 200 || httpStatus == 206){
+			this.dat.lineCount += datLines.length;
+
+			var datData = datLines.join("\n");
+			this.datSave(datData);
+		}
+
+		this.write(this.converter.getFooter("ok"));
+		this.close();
+
+		this._data = null;
+	},
+
+	machiHTML2DAT: function(aResponse){
+	        // ƒƒbƒZ[ƒW•”•ª‚ª“ñs‚É•ª‚©‚ê‚Ä‚¢‚é‚̂ňês‚É‚·‚é
+	    var datLines = aResponse.replace(/\n \]\<\/font\>/gm, " ]</font>");
+	    datLines = datLines.split("\n");
+
+	        // ƒƒbƒZ[ƒW‚ƃ^ƒCƒgƒ‹ˆÈŠO‚̍s‚ðíœ
+	    var reg = /^<(?:title>|dt>\d)/;
+	    datLines = datLines.filter(function(aElement, aIndex, aArray){
+	        return reg.test(aElement);
+	    });
+
+	        // ”z—ñ‚̈ê‚–ڂ̓^ƒCƒgƒ‹
+	    var datTitle = datLines.shift().replace(/<\/?title>/g, "");
+
+	    datLines = datLines.map(function(aElement, aIndex, aArray){
+	        var datLine = aElement;
+	        var name = (datLine.match(/<b> ([^<]+) <\/b>/i)) ? RegExp.$1 : "";
+	        var mail = (datLine.match(/<a href="mailto:([^"]+)"><b>/i)) ? RegExp.$1 : "";
+	        var date = (datLine.match(/“Še“úF ([^<]+) <font/)) ? RegExp.$1 : "";
+	        var message = (datLine.match(/<br><dd>/)) ? RegExp.rightContext : "";
+	        message = message.replace(/  <br><br>$/, "");
+	        message = message.replace(/<a href="[^"]+" target="_blank">([^<]+)<\/a>/g, "$1");
+	        var datNumber = (datLine.match(/<dt>(\d+) –¼‘O/)) ? parseInt(RegExp.$1) : 0;
+	        var title = (datNumber==1) ? datTitle : "";
+	        return name +"<>"+ mail +"<>"+ date +"<>"+ message +"<>" + title;
+	    });
+
+	    return datLines;
+	}
+
+};
+
+b2rThreadMachi.prototype.__proto__ = b2rThread2ch.prototype;
+
+
+// ***** ***** ***** ***** ***** b2rDat ***** ***** ***** ***** *****
+function b2rDat(){
+}
+
+b2rDat.prototype = {
+	get threadURL(){
+		return this._threadURL;
+	},
+
+	get threadPlainURL(){
+		if(!this._threadPlainURL){
+			if(this.type == this._b2rService.BOARD_TYPE_MACHI){
+				this._threadPlainURL = this.datURL;
+			}else{
+				var threadPlainSpec = this.threadURL.resolve("./");
+				this._threadPlainURL = this._ioService.newURI(threadPlainSpec, null, null)
+							.QueryInterface(Components.interfaces.nsIURL);
+			}
+		}
+		return this._threadPlainURL;
+	},
+
+	get boardURL(){
+		return this._boardURL;
+	},
+
+	get datURL(){
+		if(!this._datURL){
+			if(this.type == this._b2rService.BOARD_TYPE_MACHI){
+				var datURLSpec = this.threadURL.resolve("./read.cgi");
+				datURLSpec += "?BBS=" + this.queryHash["BBS"] + "&KEY=" + this.queryHash["KEY"];
+				this._datURL = this._ioService.newURI(datURLSpec, null, null)
+						.QueryInterface(Components.interfaces.nsIURL);
+			}else{
+				var datURLSpec = this.boardURL.resolve("dat/" + this.id + ".dat");
+				this._datURL = this._ioService.newURI(datURLSpec, null, null)
+						.QueryInterface(Components.interfaces.nsIURL);
+			}
+		}
+		return this._datURL;
+	},
+
+	get datKakoURL(){
+		if(this.type != this._b2rService.BOARD_TYPE_2CH){
+			return this.datURL;
+		}
+
+		if(!this._datKakoURL){
+			var datURLSpec = this.boardURL.resolve("kako/" +
+					this.id.substring(0,4) +"/"+ this.id.substring(0,5) +"/" + this.id + ".dat");
+			this._datKakoURL = this._ioService.newURI(datURLSpec, null, null)
+					.QueryInterface(Components.interfaces.nsIURL);
+		}
+		return this._datKakoURL;
+	},
+
+
+	get type(){
+		return this._type;
+	},
+
+	get datFile(){
+		return this._datFile;
+	},
+
+	get id(){
+		if(!this._id){
+			if(this.type == this._b2rService.BOARD_TYPE_MACHI){
+				this._id = this.queryHash["KEY"] || null;
+			}else{
+				this._id = this.threadURL.directory.match(/\/(\d{9,10})/) ? RegExp.$1 : null;
+			}
+		}
+		return this._id;
+	},
+
+	get title(){
+		return this._title;
+	},
+	set title(aValue){
+		return this._title = aValue;
+	},
+
+	get lineCount(){
+		return this._lineCount;
+	},
+	set lineCount(aValue){
+		return this._lineCount = aValue;
+	},
+
+	get lastModified(){
+		return this._lastModified;
+	},
+	set lastModified(aValue){
+		return this._lastModified = aValue;
+	},
+
+	get maruGetted(){
+		return this._maruGetted;
+	},
+	set maruGetted(aValue){
+		return this._maruGetted = aValue;
+	},
+
+
+	get queryHash(){
+		if(!this._queryHash){
+			this._queryHash = new Array();
+			var queryArray = this.threadURL.query.split("&");
+			for(var i=0; i<queryArray.length; i++){
+				var query = queryArray[i].split("=");
+				if(query.length == 2) this._queryHash[query[0]] = query[1];
+			}
+		}
+		return this._queryHash;
+	},
+
+	init: function(aThreadURL, aBoardURL, aType){
+		this._bbs2chService = Components.classes["@mozilla.org/bbs2ch-service;1"]
+				.getService(Components.interfaces.nsIBbs2chService);
+		this._b2rService  = Components.classes["@bbs2ch.sourceforge.jp/b2r-global-service;1"]
+					.getService(Components.interfaces.b2rIGlobalService);
+		this._ioService = Components.classes["@mozilla.org/network/io-service;1"]
+					.getService(Components.interfaces.nsIIOService);
+
+		this._threadURL = aThreadURL;
+
+		this._boardURL = (!aBoardURL) ?
+				this._b2rService.threadUtils.getBoardURL(this.threadURL) : aBoardURL;
+		this._type = (isNaN(parseInt(aType))) ?
+				this._b2rService.threadUtils.getBoardType(this.threadURL) : aType;
+
+			// ”‚̃^ƒCƒv‚ªABOARD_TYPE_PAGE ‚Å‚àA
+			// URL ‚É /test/read.cgi/ ‚ðŠÜ‚ñ‚Å‚¢‚½‚ç 2chŒÝŠ·‚Æ‚Ý‚È‚·
+		if(this._type == this._b2rService.BOARD_TYPE_PAGE &&
+					this._threadURL.spec.indexOf("/test/read.cgi/") != -1){
+			this._type = this._b2rService.BOARD_TYPE_2CH;
+		}
+
+		this._datFile = this._b2rService.io.getLogFileAtURL(
+								this.boardURL.resolve(this.id + ".dat"));
+
+
+		var b2rStorageService = Cc["@bbs2ch.sourceforge.jp/b2r-storage-service;1"].getService(Ci.b2rIStorageService);
+		var threadData = b2rStorageService.getThreadData(this.boardURL, this.id);
+
+		if(this.datFile.exists() && !threadData){
+			this.remove();
+		}
+		if(!this.datFile.exists() && threadData){
+			b2rStorageService.deleteThreadData(this.boardURL, this.id, false);
+			threadData = null;
+		}
+
+		if(threadData){
+			this._title = this._bbs2chService.toSJIS(threadData.title);
+			this._lineCount = threadData.lineCount;
+			this._lastModified = threadData.httpLastModified;
+			this._maruGetted = threadData.maruGetted;
+		}else{
+			this._title = "";
+			this._lineCount = 0;
+			this._lastModified = "";
+			this._maruGetted = false;
+		}
+	},
+
+
+	setThreadData: function(){
+		var b2rStorageService = Cc["@bbs2ch.sourceforge.jp/b2r-storage-service;1"].getService(Ci.b2rIStorageService);
+		b2rStorageService.setThreadData(
+				this.threadPlainURL,
+				this.boardURL,
+				this.id,
+				this._bbs2chService.fromSJIS(this.title),
+				this.lineCount,
+				this.lastModified,
+				this._maruGetted);
+	},
+
+
+	readContent: function(){
+		return this._bbs2chService.readFile(this.datFile.path);
+	},
+
+	writeContent: function(aContent){
+		this._bbs2chService.writeFile(this.datFile.path, aContent, false);
+	},
+
+	appendContent: function(aContent){
+		this._bbs2chService.writeFile(this.datFile.path, aContent, true);
+	},
+
+	remove: function(){
+		try{
+			if(this.datFile.exists()) this.datFile.remove(false);
+
+			this._title = "";
+			this._lineCount = 0;
+			this._lastModified = "";
+		}catch(ex){}
+	}
+};
+
+
+// ***** ***** ***** ***** ***** b2rId2Color ***** ***** ***** ***** *****
+/**
+ * id‚©‚çF‚ð•Ô‚µ‚Ü‚·B
+ */
+function b2rId2Color(){
+}
+
+b2rId2Color.prototype = {
+	_char64To8: new Array(),
+	_cache: new Array(),
+	_bgcache: new Array(),
+
+	init: function(){
+		var idChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+		var i=0;
+		for(var m in idChars){
+			this._char64To8[idChars[m]]=i
+			if(((parseInt(m)+1)%8)==0) i++;
+		}
+	},
+
+	/**
+	 * id‚©‚çCSS‚̐F‚ð•Ô‚µ‚Ü‚·B
+	 *
+	 * @param aID {string} 2ch‚ÌID
+	 * @param aIsBackground {bool} ”wŒi‚©
+	 * @type string
+	 * @return CSS‚̐F
+	 */
+	getColor: function(aID, aIsBackground){
+		if(aID.length < 8) return "inherit";
+
+		aID = aID.substring(0,8);
+		var cache = (aIsBackground) ? this._bgcache : this._cache;
+
+		if(!(aID in cache)){
+			var newint = 0;
+			for each(var s in aID){
+				newint <<= 3;
+				newint |= this._char64To8[s];
+			}
+			// hsl(0-360,0-100%,0-100%);
+			var h = newint%360;
+			newint = Math.floor(newint/360);
+			var s = newint%100;
+			newint = Math.floor(newint/100);
+			var l;
+			if(aIsBackground)
+				l = newint % 20 + 80;
+			else
+				l = newint%60;
+			cache[aID] = "hsl("+ h +","+ s +"%,"+ l +"%)";
+		}
+		return cache[aID];
+	}
+}
+
+
+// ***** ***** ***** ***** ***** b2rThreadConverter ***** ***** ***** ***** *****
+function b2rThreadConverter(){
+}
+
+b2rThreadConverter.prototype = {
+
+	init: function(aContext, aThreadURL, aBoardURL, aType){
+		this._context = aContext;
+		this._threadURL = aThreadURL;
+		this._boardURL = aBoardURL;
+		this._type = aType;
+
+		this._bbs2chService = Components.classes["@mozilla.org/bbs2ch-service;1"]
+				.getService(Components.interfaces.nsIBbs2chService);
+		this._b2rService  = Components.classes["@bbs2ch.sourceforge.jp/b2r-global-service;1"]
+				.getService(Components.interfaces.b2rIGlobalService);
+		this._ioService = Components.classes["@mozilla.org/network/io-service;1"]
+				.getService(Components.interfaces.nsIIOService);
+		this._pref = Components.classes["@mozilla.org/preferences-service;1"]
+				.getService(Components.interfaces.nsIPrefBranch);
+
+		this._dd2Color = new b2rId2Color();
+		this._dd2Color.init();
+
+
+		this._tmpHeader   = this._bbs2chService.readFile(this._resolveSkinFile("Header.html").path);
+		this._tmpFooter   = this._bbs2chService.readFile(this._resolveSkinFile("Footer.html").path);
+		this._tmpRes	  = this._bbs2chService.readFile(this._resolveSkinFile("Res.html").path);
+		this._tmpNewRes	  = this._bbs2chService.readFile(this._resolveSkinFile("NewRes.html").path);
+		this._tmpNewMark  = this._bbs2chService.readFile(this._resolveSkinFile("NewMark.html").path);
+
+		if(this._tmpHeader===null || this._tmpFooter===null || this._tmpRes===null || this._tmpNewRes===null || this._tmpNewMark===null){
+			throw Components.results.NS_ERROR_FILE_NOT_FOUND
+		}
+
+			// Šî–{ƒXƒLƒ“ƒ^ƒO‚Ì’uŠ·
+		this._tmpHeader = this._replaceBaseTag(this._tmpHeader);
+		this._tmpFooter = this._replaceBaseTag(this._tmpFooter);
+		this._tmpRes = this._replaceBaseTag(this._tmpRes);
+		this._tmpNewRes = this._replaceBaseTag(this._tmpNewRes);
+		this._tmpNewMark = this._replaceBaseTag(this._tmpNewMark);
+
+		this._tmpGetRes = this.toFunction(this._tmpRes);
+		this._tmpGetNewRes = this.toFunction(this._tmpNewRes);
+
+				// ‹ŒŽd—l‚̌݊·«Šm•Û
+		if(!this._tmpFooter.match(/<STATUS\/>/)){
+			this._tmpFooter = '<p class="info"><STATUS/></p>\n' + this._tmpFooter;
+		}
+	},
+
+	_resolveSkinFile: function(aFilePath){
+		var skinName = this._pref.getComplexValue("extensions.bbs2chreader.thread_skin",
+							Components.interfaces.nsISupportsString).data;
+
+		var skinFile = null;
+		if(skinName){
+			skinFile = this._b2rService.io.getDataDir();
+			skinFile.appendRelativePath("skin");
+			skinFile.appendRelativePath(skinName);
+		}else{
+			var bbs2chreaderID = "{0B9D558E-6983-486b-9AAD-B6CBCD2FC807}";
+			var extensionManager = Components.classes["@mozilla.org/extensions/manager;1"]
+					.getService(Components.interfaces.nsIExtensionManager);
+			var installLocation = extensionManager.getInstallLocation(bbs2chreaderID);
+			skinFile = installLocation.getItemFile(bbs2chreaderID, "defaults/skin").clone()
+							.QueryInterface(Components.interfaces.nsILocalFile);
+		}
+		skinFile.appendRelativePath(aFilePath);
+		return skinFile;
+	},
+
+	/**
+	 * Šî–{ƒXƒLƒ“ƒ^ƒO‚Ì’uŠ·
+	 * @param aString string ’uŠ·‚³‚ê‚镶Žš—ñ
+	 */
+	_replaceBaseTag: function(aString){
+		var requestURL = this._context._handler.requestURL;
+		var threadURLSpec = requestURL.path.substring(8);
+		var skinURISpec = this._b2rService.serverURL.resolve("./skin/");
+		var serverURLSpec = this._b2rService.serverURL.resolve("./thread/");
+		var fontName = this._pref.getComplexValue("extensions.bbs2chreader.thread_font_name",
+							Components.interfaces.nsISupportsString).data;
+		fontName = this._bbs2chService.toSJIS(fontName);
+		var fontSize = this._pref.getIntPref("extensions.bbs2chreader.thread_font_size");
+		var aaFontName = this._pref.getComplexValue("extensions.bbs2chreader.thread_aa_font_name",
+							Components.interfaces.nsISupportsString).data;
+		aaFontName = this._bbs2chService.toSJIS(aaFontName);
+		var aaFontSize = this._pref.getIntPref("extensions.bbs2chreader.thread_aa_font_size");
+
+		return aString.replace(/<SKINPATH\/>/g, skinURISpec)
+				.replace(/<THREADURL\/>/g, this._threadURL.resolve("./"))
+				.replace(/<BOARDURL\/>/g, this._boardURL.spec)
+				.replace(/<SERVERURL\/>/g, serverURLSpec)
+				.replace(/<FONTNAME\/>/g, "\'" + fontName + "\'")
+				.replace(/<FONTSIZE\/>/g, fontSize + "px")
+				.replace(/<AAFONTNAME\/>/g, "\'" + aaFontName + "\'")
+				.replace(/<AAFONTSIZE\/>/g, aaFontSize + "px");
+	},
+
+	getHeader: function(aTitle){
+		return this._tmpHeader.replace(/<THREADNAME\/>/g, aTitle);
+	},
+
+	getFooter: function(aStatusText){
+		var datSize = 0;
+		var datSizeKB = 0;
+		var datFile = this._context.dat.datFile.clone();
+		if(datFile.exists()){
+			datSize = datFile.fileSize;
+			datSizeKB = Math.round(datSize / 1024);
+		}
+		var logLineCount = this._context._logLineCount;
+		var lineCount = this._context.dat.lineCount;
+
+		return this._tmpFooter.replace(/<STATUS\/>/g, this.getStatusText(aStatusText))
+					.replace(/<SIZE\/>/g, datSize)
+					.replace(/<SIZEKB\/>/g, datSizeKB)
+					.replace(/<GETRESCOUNT\/>/g, logLineCount)
+					.replace(/<NEWRESCOUNT\/>/g, lineCount - logLineCount)
+					.replace(/<ALLRESCOUNT\/>/g, lineCount);
+	},
+
+	getStatusText: function(aStatus){
+	    var strBundleService = Components.classes["@mozilla.org/intl/stringbundle;1"]
+                                      .getService(Components.interfaces.nsIStringBundleService);
+		var statusBundle = strBundleService.createBundle(
+								"chrome://bbs2chreader/content/server/thread-status.properties");
+		var statusText = "";
+		if(typeof(aStatus) == "string"){
+			try{
+				statusText = statusBundle.GetStringFromName(aStatus);
+			}catch(ex){}
+		}else{
+			try{
+				statusText = statusBundle.formatStringFromName("error", [String(aStatus)], 1);
+			}catch(ex){}
+		}
+		return this._bbs2chService.toSJIS(statusText);
+	},
+
+	getNewMark: function(){
+		return this._tmpNewMark;
+	},
+
+	toFunction: function(aRes){
+		return eval(
+			"(function(aNumber, aName, aMail, aMailName, aDate, aID, resIDColor, resIDBgColor, aBeID, aMessage){return \""+aRes
+				.replace(/\\/g,"\\\\").replace(/\"/g,"\\\"")
+				.replace(/(\r|\n|\t)/g,"").replace(/<!--.*?-->/g,"")
+				.replace(/<PLAINNUMBER\/>/g, "\"+aNumber+\"")
+				.replace(/<NUMBER\/>/g, "\"+aNumber+\"")
+				.replace(/<NAME\/>/g, "\"+aName+\"")
+				.replace(/<MAIL\/>/g, "\"+aMail+\"")
+				.replace(/<MAILNAME\/>/g, "\"+aMailName+\"")
+				.replace(/<DATE\/>/g, "\"+aDate+\"")
+				.replace(/<ID\/>/g, "\"+aID+\"")
+				.replace(/<IDCOLOR\/>/g, "\"+resIDColor+\"")
+				.replace(/<IDBACKGROUNDCOLOR\/>/g, "\"+resIDBgColor+\"")
+				.replace(/<BEID\/>/g, "\"+aBeID+\"")
+				.replace(/<MESSAGE\/>/g, "\"+aMessage+\"")+"\";})"
+		);
+	},
+
+	getResponse: function(aNew, aNumber, aName, aMail, aMailName, aDate, aID, aBeID, aMessage){
+		var template = aNew ? this._tmpNewRes : this._tmpRes;
+		if(!template.match(/<ID\/>/))
+			aDate = aDate + " ID:" + aID;
+		if(!template.match(/<BEID\/>/))
+			aDate = aDate + " Be:" + aBeID;
+
+		var resIDColor = (template.search(/<IDCOLOR\/>/) != -1) ?
+				this._dd2Color.getColor(aID, false) : "inherit";
+		var resIDBgColor = (template.search(/<IDBACKGROUNDCOLOR\/>/) != -1) ?
+				this._dd2Color.getColor(aID, true) : "inherit";
+
+		if(this.isAA(aMessage)){
+			aMessage = '<span class="aaRes">' + aMessage + '</span>';
+		}
+
+		var result;
+		if(aNew){
+			result = this._tmpGetNewRes(aNumber, aName, aMail, aMailName, aDate, aID,
+						resIDColor, resIDBgColor,aBeID, aMessage);
+		}else{
+			result = this._tmpGetRes(aNumber, aName, aMail, aMailName, aDate, aID,
+						resIDColor, resIDBgColor,aBeID, aMessage);
+		}
+		return result;
+	},
+
+	isAA: function(aMessage) {
+		var lineCount = aMessage.match(/<br>/g);
+		if(lineCount && lineCount.length >= 3){
+			var spaceCount = aMessage.match(/[ @\.:i\|]/g);
+			if(spaceCount && (spaceCount.length / aMessage.length) >= 0.3){
+				return true;
+			}
+		}
+		return false;
+	}
+
+};
\ No newline at end of file

Modified: trunk/bbs2chreader/components/b2rServer.js
===================================================================
--- trunk/bbs2chreader/components/b2rServer.js	2008-03-15 13:03:28 UTC (rev 409)
+++ trunk/bbs2chreader/components/b2rServer.js	2008-03-15 14:50:00 UTC (rev 410)
@@ -47,10 +47,14 @@
 }
 
 Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
+Components.utils.import("resource://bbs2chreader/server/skin.jsm");
+Components.utils.import("resource://bbs2chreader/server/thread.jsm");
 
+var gServerScriptList = new Array();
+gServerScriptList["skin"] = SkinServerScript;
+gServerScriptList["thread"] = ThreadServerScript;
 
 
-
 var StatusCode = {
 
 	getStatusCode: function(aCode){
@@ -352,24 +356,14 @@
 			this.sendErrorPage(404, this.requestURL.spec);
 			return;
 		}
+		if(!gServerScriptList[mode]){
+			this.sendErrorPage(404, this.requestURL.spec);
+			return;
+		}
 
-		var scriptURL = "chrome://bbs2chreader/content/server/%MODE%.js";
-		scriptURL = scriptURL.replace("%MODE%", mode);
-
-		var subScrLoader = Cc["@mozilla.org/moz/jssubscript-loader;1"].getService(Ci.mozIJSSubScriptLoader);
 		try{
-			this._scope = { script:null };
-			try{
-				subScrLoader.loadSubScript(scriptURL, this._scope);
-			}catch(ex if ex instanceof SyntaxError){
-				var message = ex.message + "\n" + ex.fileName +" : "+ ex.lineNumber;
-				this.sendErrorPage(500, message);
-				return;
-			}catch(ex){
-				this.sendErrorPage(404, this.requestURL.spec);
-				return;
-			}
-			this._scope.script.start(this);
+			this._script = new gServerScriptList[mode](this.requestURL);
+			this._script.start(this);
 		}catch(ex){
 			var message = (typeof(ex) == "string") ? ex : ex.message + "\n" + ex.fileName +" : "+ ex.lineNumber;
 			this.sendErrorPage(500, message);
@@ -380,9 +374,9 @@
 		if(this._isAlive){
 			var str = String(aString);
 			this._output.write(str, str.length);
-		}else if(this._scope && this._scope.script){
-			this._scope.script.cancel();
-			this._scope = null;
+		}else if(this._script){
+			this._script.cancel();
+			this._script = null;
 		}
 	},
 
@@ -418,7 +412,7 @@
 			this._input = null;
 		}
 		this._isAlive = false;
-		this._scope = null;
+		this._script = null;
 	},
 
 	sendErrorPage: function(aStatusCode, aMessage){


bbs2ch-cvs メーリングリストの案内
Back to archive index