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ªXV³êĢȯêÎ 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ªXV³êĢȯêÎ 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); - // ÂÌ^Cvª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íéÆ«Í "/" ðÇÁ·é - 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 wb_ð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("XL ("+ skinName +") ÌÇÝÝɸsµ½½ßA"); - this.write("ÝèðftHgXLÉߵܵ½B<br>y[WðXVµÄ¾³¢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 ð DATEABeID ɪ - 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ÅÍ "\" ªÁêÈÓ¡ð½ßAl¶QÆÉÏ· - resName = resName.replace(/([^\x81-\xfc]|^)\x5C/g,"$1\"); - resMail = resMail.replace(/([^\x81-\xfc]|^)\x5C/g,"$1\"); - - var resMailName = resName; - if(resMail) resMailName = '<a href="mailto:' + resMail + '">' + resName + '</a>'; - - // XÔN & A½ Ú[ñ - var regResPointer = /(?:<a .*?>)?(>>|>)([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>'); - - // XbhÌ^Cgª©Â©Á½Æ«Í HTML wb_ðÇÁµÄé - 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 Ì_CNgð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; - // KvÈîñªÈ¢Èç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ðÜÜÈ¢Èçobt@ÉÇÁµÄI¹ - if(!availableData.match(/\n/)){ - this._datBuffer = availableData; - return; - } - - // æ¾µ½ DAT ðs²ÆÉzñɵAÅãÌsðobt@ÉÇÁ - 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: // ¢XV - 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 êÝ·XNvgÉÍA¢XVÅà 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){ - // «ÝÌobeBOðð¯é - - 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 Ì_CNgð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ÅÍ "\" ªÁêÈÓ¡ð½ßAl¶QÆÉÏ· - resName = resName.replace(/([^\x81-\xfc]|^)\x5C/g,"$1\"); - resMail = resMail.replace(/([^\x81-\xfc]|^)\x5C/g,"$1\"); - - var resMailName = resName; - if(resMail) resMailName = '<a href="mailto:' + resMail + '">' + resName + '</a>'; - - - // XÔN & A½ Ú[ñ - var regResPointer = /(?:<a .*?>)?(>>|>)([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>'); - - // XbhÌ^Cgª©Â©Á½Æ«Í HTML wb_ðÇÁµÄé - 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 Ì_CNgð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; - // KvÈîñªÈ¢Èç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){ // ¢XV - 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){ - // bZ[Wªªñsɪ©êÄ¢éÌÅêsÉ·é - var datLines = aResponse.replace(/\n \]\<\/font\>/gm, " ]</font>"); - datLines = datLines.split("\n"); - - // bZ[WÆ^CgÈOÌsðí - var reg = /^<(?:title>|dt>\d)/; - datLines = datLines.filter(function(aElement, aIndex, aArray){ - return reg.test(aElement); - }); - - // zñÌêÂÚÍ^Cg - 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; - - // ÂÌ^Cvª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} wi© - * @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 - } - - // î{XL^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); - - // dlÌÝ·«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; - }, - - /** - * î{XL^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); + // ÂÌ^Cvª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íéÆ«Í "/" ðÇÁ·é + 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 wb_ð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("XL ("+ skinName +") ÌÇÝÝɸsµ½½ßA"); + this.write("ÝèðftHgXLÉߵܵ½B<br>y[WðXVµÄ¾³¢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 ð DATEABeID ɪ + 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ÅÍ "\" ªÁêÈÓ¡ð½ßAl¶QÆÉÏ· + resName = resName.replace(/([^\x81-\xfc]|^)\x5C/g,"$1\"); + resMail = resMail.replace(/([^\x81-\xfc]|^)\x5C/g,"$1\"); + + var resMailName = resName; + if(resMail) resMailName = '<a href="mailto:' + resMail + '">' + resName + '</a>'; + + // XÔN & A½ Ú[ñ + var regResPointer = /(?:<a .*?>)?(>>|>)([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>'); + + // XbhÌ^Cgª©Â©Á½Æ«Í HTML wb_ðÇÁµÄé + 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 Ì_CNgð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; + // KvÈîñªÈ¢Èç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ðÜÜÈ¢Èçobt@ÉÇÁµÄI¹ + if(!availableData.match(/\n/)){ + this._datBuffer = availableData; + return; + } + + // æ¾µ½ DAT ðs²ÆÉzñɵAÅãÌsðobt@ÉÇÁ + 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: // ¢XV + 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 êÝ·XNvgÉÍA¢XVÅà 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){ + // «ÝÌobeBOðð¯é + + 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 Ì_CNgð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ÅÍ "\" ªÁêÈÓ¡ð½ßAl¶QÆÉÏ· + resName = resName.replace(/([^\x81-\xfc]|^)\x5C/g,"$1\"); + resMail = resMail.replace(/([^\x81-\xfc]|^)\x5C/g,"$1\"); + + var resMailName = resName; + if(resMail) resMailName = '<a href="mailto:' + resMail + '">' + resName + '</a>'; + + + // XÔN & A½ Ú[ñ + var regResPointer = /(?:<a .*?>)?(>>|>)([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>'); + + // XbhÌ^Cgª©Â©Á½Æ«Í HTML wb_ðÇÁµÄé + 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 Ì_CNgð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; + // KvÈîñªÈ¢Èç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){ // ¢XV + 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){ + // bZ[Wªªñsɪ©êÄ¢éÌÅêsÉ·é + var datLines = aResponse.replace(/\n \]\<\/font\>/gm, " ]</font>"); + datLines = datLines.split("\n"); + + // bZ[WÆ^CgÈOÌsðí + var reg = /^<(?:title>|dt>\d)/; + datLines = datLines.filter(function(aElement, aIndex, aArray){ + return reg.test(aElement); + }); + + // zñÌêÂÚÍ^Cg + 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; + + // ÂÌ^Cvª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} wi© + * @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 + } + + // î{XL^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); + + // dlÌÝ·«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; + }, + + /** + * î{XL^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){