├── data ├── js │ ├── optionsDlg-cs.js │ ├── context-menu │ │ ├── downloadPost.js │ │ ├── viewImage.js │ │ ├── previewPicture.js │ │ ├── loadFile.js │ │ ├── ansiCopy.js │ │ ├── easyRead.js │ │ ├── pushThread.js │ │ ├── mouseBrowsing.js │ │ ├── changeColorTable.js │ │ ├── openThreadUrl.js │ │ ├── switchBgDisplay.js │ │ ├── openAllLink.js │ │ ├── ansiColorTool.js │ │ ├── screenKeyboard.js │ │ ├── trackClear.js │ │ ├── trackDel.js │ │ ├── trackAdd.js │ │ ├── blacklistAdd.js │ │ └── blacklistDel.js │ ├── stringutil.js │ ├── bbsfox-bg.js │ ├── optionsDlg.js │ ├── content-script.js │ ├── bbsfox-api.js │ ├── bbsfox-prefs.js │ └── bbsfox-about.js └── img │ └── logo │ └── logo.png ├── chrome ├── skin │ └── default │ │ ├── color-normal.css │ │ ├── logo │ │ └── logo.png │ │ ├── cursor │ │ ├── back.png │ │ ├── end.png │ │ ├── home.png │ │ ├── last.png │ │ ├── next.png │ │ ├── enter.png │ │ ├── first.png │ │ ├── pageup.png │ │ ├── prevous.png │ │ ├── refresh.png │ │ ├── pagedown.png │ │ └── COPYRIGHT.txt │ │ ├── colorpicker │ │ ├── 0.png │ │ ├── 1.png │ │ ├── 10.png │ │ ├── 11.png │ │ ├── 12.png │ │ ├── 13.png │ │ ├── 14.png │ │ ├── 15.png │ │ ├── 2.png │ │ ├── 3.png │ │ ├── 4.png │ │ ├── 5.png │ │ ├── 6.png │ │ ├── 7.png │ │ ├── 8.png │ │ └── 9.png │ │ ├── link_line │ │ ├── ed2k.bmp │ │ ├── ftp.bmp │ │ ├── http.bmp │ │ ├── mail.bmp │ │ ├── mms.bmp │ │ ├── news.bmp │ │ ├── https.bmp │ │ └── telnet.bmp │ │ ├── help │ │ ├── areadefine1.png │ │ └── areadefine2.png │ │ ├── pushThread.css │ │ ├── state_icon │ │ ├── error.png │ │ ├── connect.png │ │ ├── connecting.gif │ │ └── disconnect.png │ │ ├── window_icon │ │ ├── close-a.png │ │ ├── close-h.png │ │ └── close.png │ │ ├── options.css │ │ └── bbs.css ├── content │ ├── sshDef.js │ ├── telnetDef.js │ ├── uao │ │ ├── b2u.tab │ │ ├── u2b.tab │ │ └── uao.js │ ├── paramikojs │ │ ├── kryptos │ │ │ ├── Hash │ │ │ │ ├── MD5.js │ │ │ │ ├── SHA.js │ │ │ │ ├── SHA256.js │ │ │ │ ├── HMAC.js │ │ │ │ └── baseHash.js │ │ │ ├── Random │ │ │ │ ├── Fortuna │ │ │ │ │ ├── SHAd256.js │ │ │ │ │ ├── FortunaGenerator.js │ │ │ │ │ └── FortunaAccumulator.js │ │ │ │ ├── OSRNG │ │ │ │ │ └── browser.js │ │ │ │ ├── LICENSE.txt │ │ │ │ └── _UserFriendlyRNG.js │ │ │ ├── PublicKey │ │ │ │ ├── RSA.js │ │ │ │ └── DSA.js │ │ │ ├── kryptos.js │ │ │ └── Cipher │ │ │ │ └── ARC4.js │ │ ├── compress.js │ │ ├── unknown_key.js │ │ ├── sign_ssh_data_worker.js │ │ ├── readme.md │ │ ├── kex_group14.js │ │ ├── license.txt │ │ ├── common.js │ │ ├── ber.js │ │ ├── python_shim.js │ │ ├── win_pageant.js │ │ ├── kex_group1.js │ │ ├── sftp_attr.js │ │ ├── agent.js │ │ ├── kex_gex.js │ │ ├── ssh_exception.js │ │ └── sftp.js │ ├── commonDef.js │ ├── ctrlTable.js │ ├── res │ │ └── keyboard.res │ ├── addSite.xul │ ├── pushThread.xul │ ├── addSite.js │ ├── mainpage.js │ ├── pushThread.js │ ├── highlighter.js │ ├── ansiFile.js │ ├── bbsbackground.js │ ├── extPicLoader.js │ ├── aidhandler.js │ ├── alertService.js │ ├── telnet.html │ ├── prefs.json │ ├── asciiTable.js │ ├── picLoader │ │ ├── picLoader_ppt.js │ │ └── picLoader_imgur.js │ ├── browserutils.js │ └── stringutil.js └── locale │ ├── zh-TW │ ├── bbsfox.properties │ └── help.html │ └── en-US │ ├── bbsfox.properties │ └── help.html ├── chrome.manifest ├── .jpmignore ├── README.md ├── .gitignore ├── locale ├── zh-TW.properties └── en-US.properties ├── bootstrap.js └── package.json /data/js/optionsDlg-cs.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /chrome/skin/default/color-normal.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /chrome/content/sshDef.js: -------------------------------------------------------------------------------- 1 | const BBSFOX_DEFAULT_PORT = 22; 2 | -------------------------------------------------------------------------------- /chrome/content/telnetDef.js: -------------------------------------------------------------------------------- 1 | const BBSFOX_DEFAULT_PORT = 23; 2 | -------------------------------------------------------------------------------- /data/img/logo/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ettoolong/BBSFox-E10S/HEAD/data/img/logo/logo.png -------------------------------------------------------------------------------- /chrome/content/uao/b2u.tab: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ettoolong/BBSFox-E10S/HEAD/chrome/content/uao/b2u.tab -------------------------------------------------------------------------------- /chrome/content/uao/u2b.tab: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ettoolong/BBSFox-E10S/HEAD/chrome/content/uao/u2b.tab -------------------------------------------------------------------------------- /chrome/skin/default/logo/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ettoolong/BBSFox-E10S/HEAD/chrome/skin/default/logo/logo.png -------------------------------------------------------------------------------- /chrome/skin/default/cursor/back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ettoolong/BBSFox-E10S/HEAD/chrome/skin/default/cursor/back.png -------------------------------------------------------------------------------- /chrome/skin/default/cursor/end.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ettoolong/BBSFox-E10S/HEAD/chrome/skin/default/cursor/end.png -------------------------------------------------------------------------------- /chrome/skin/default/cursor/home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ettoolong/BBSFox-E10S/HEAD/chrome/skin/default/cursor/home.png -------------------------------------------------------------------------------- /chrome/skin/default/cursor/last.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ettoolong/BBSFox-E10S/HEAD/chrome/skin/default/cursor/last.png -------------------------------------------------------------------------------- /chrome/skin/default/cursor/next.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ettoolong/BBSFox-E10S/HEAD/chrome/skin/default/cursor/next.png -------------------------------------------------------------------------------- /chrome/skin/default/colorpicker/0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ettoolong/BBSFox-E10S/HEAD/chrome/skin/default/colorpicker/0.png -------------------------------------------------------------------------------- /chrome/skin/default/colorpicker/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ettoolong/BBSFox-E10S/HEAD/chrome/skin/default/colorpicker/1.png -------------------------------------------------------------------------------- /chrome/skin/default/colorpicker/10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ettoolong/BBSFox-E10S/HEAD/chrome/skin/default/colorpicker/10.png -------------------------------------------------------------------------------- /chrome/skin/default/colorpicker/11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ettoolong/BBSFox-E10S/HEAD/chrome/skin/default/colorpicker/11.png -------------------------------------------------------------------------------- /chrome/skin/default/colorpicker/12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ettoolong/BBSFox-E10S/HEAD/chrome/skin/default/colorpicker/12.png -------------------------------------------------------------------------------- /chrome/skin/default/colorpicker/13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ettoolong/BBSFox-E10S/HEAD/chrome/skin/default/colorpicker/13.png -------------------------------------------------------------------------------- /chrome/skin/default/colorpicker/14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ettoolong/BBSFox-E10S/HEAD/chrome/skin/default/colorpicker/14.png -------------------------------------------------------------------------------- /chrome/skin/default/colorpicker/15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ettoolong/BBSFox-E10S/HEAD/chrome/skin/default/colorpicker/15.png -------------------------------------------------------------------------------- /chrome/skin/default/colorpicker/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ettoolong/BBSFox-E10S/HEAD/chrome/skin/default/colorpicker/2.png -------------------------------------------------------------------------------- /chrome/skin/default/colorpicker/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ettoolong/BBSFox-E10S/HEAD/chrome/skin/default/colorpicker/3.png -------------------------------------------------------------------------------- /chrome/skin/default/colorpicker/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ettoolong/BBSFox-E10S/HEAD/chrome/skin/default/colorpicker/4.png -------------------------------------------------------------------------------- /chrome/skin/default/colorpicker/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ettoolong/BBSFox-E10S/HEAD/chrome/skin/default/colorpicker/5.png -------------------------------------------------------------------------------- /chrome/skin/default/colorpicker/6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ettoolong/BBSFox-E10S/HEAD/chrome/skin/default/colorpicker/6.png -------------------------------------------------------------------------------- /chrome/skin/default/colorpicker/7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ettoolong/BBSFox-E10S/HEAD/chrome/skin/default/colorpicker/7.png -------------------------------------------------------------------------------- /chrome/skin/default/colorpicker/8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ettoolong/BBSFox-E10S/HEAD/chrome/skin/default/colorpicker/8.png -------------------------------------------------------------------------------- /chrome/skin/default/colorpicker/9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ettoolong/BBSFox-E10S/HEAD/chrome/skin/default/colorpicker/9.png -------------------------------------------------------------------------------- /chrome/skin/default/cursor/enter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ettoolong/BBSFox-E10S/HEAD/chrome/skin/default/cursor/enter.png -------------------------------------------------------------------------------- /chrome/skin/default/cursor/first.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ettoolong/BBSFox-E10S/HEAD/chrome/skin/default/cursor/first.png -------------------------------------------------------------------------------- /chrome/skin/default/cursor/pageup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ettoolong/BBSFox-E10S/HEAD/chrome/skin/default/cursor/pageup.png -------------------------------------------------------------------------------- /chrome/skin/default/cursor/prevous.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ettoolong/BBSFox-E10S/HEAD/chrome/skin/default/cursor/prevous.png -------------------------------------------------------------------------------- /chrome/skin/default/cursor/refresh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ettoolong/BBSFox-E10S/HEAD/chrome/skin/default/cursor/refresh.png -------------------------------------------------------------------------------- /chrome/skin/default/link_line/ed2k.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ettoolong/BBSFox-E10S/HEAD/chrome/skin/default/link_line/ed2k.bmp -------------------------------------------------------------------------------- /chrome/skin/default/link_line/ftp.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ettoolong/BBSFox-E10S/HEAD/chrome/skin/default/link_line/ftp.bmp -------------------------------------------------------------------------------- /chrome/skin/default/link_line/http.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ettoolong/BBSFox-E10S/HEAD/chrome/skin/default/link_line/http.bmp -------------------------------------------------------------------------------- /chrome/skin/default/link_line/mail.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ettoolong/BBSFox-E10S/HEAD/chrome/skin/default/link_line/mail.bmp -------------------------------------------------------------------------------- /chrome/skin/default/link_line/mms.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ettoolong/BBSFox-E10S/HEAD/chrome/skin/default/link_line/mms.bmp -------------------------------------------------------------------------------- /chrome/skin/default/link_line/news.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ettoolong/BBSFox-E10S/HEAD/chrome/skin/default/link_line/news.bmp -------------------------------------------------------------------------------- /chrome/skin/default/cursor/pagedown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ettoolong/BBSFox-E10S/HEAD/chrome/skin/default/cursor/pagedown.png -------------------------------------------------------------------------------- /chrome/skin/default/help/areadefine1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ettoolong/BBSFox-E10S/HEAD/chrome/skin/default/help/areadefine1.png -------------------------------------------------------------------------------- /chrome/skin/default/help/areadefine2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ettoolong/BBSFox-E10S/HEAD/chrome/skin/default/help/areadefine2.png -------------------------------------------------------------------------------- /chrome/skin/default/link_line/https.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ettoolong/BBSFox-E10S/HEAD/chrome/skin/default/link_line/https.bmp -------------------------------------------------------------------------------- /chrome/skin/default/link_line/telnet.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ettoolong/BBSFox-E10S/HEAD/chrome/skin/default/link_line/telnet.bmp -------------------------------------------------------------------------------- /chrome/skin/default/pushThread.css: -------------------------------------------------------------------------------- 1 | @import url(chrome://global/skin/); 2 | 3 | textbox { 4 | font-family: MingLiu, monospace; 5 | } 6 | -------------------------------------------------------------------------------- /chrome/skin/default/state_icon/error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ettoolong/BBSFox-E10S/HEAD/chrome/skin/default/state_icon/error.png -------------------------------------------------------------------------------- /chrome/skin/default/state_icon/connect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ettoolong/BBSFox-E10S/HEAD/chrome/skin/default/state_icon/connect.png -------------------------------------------------------------------------------- /chrome/skin/default/window_icon/close-a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ettoolong/BBSFox-E10S/HEAD/chrome/skin/default/window_icon/close-a.png -------------------------------------------------------------------------------- /chrome/skin/default/window_icon/close-h.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ettoolong/BBSFox-E10S/HEAD/chrome/skin/default/window_icon/close-h.png -------------------------------------------------------------------------------- /chrome/skin/default/window_icon/close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ettoolong/BBSFox-E10S/HEAD/chrome/skin/default/window_icon/close.png -------------------------------------------------------------------------------- /chrome/skin/default/state_icon/connecting.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ettoolong/BBSFox-E10S/HEAD/chrome/skin/default/state_icon/connecting.gif -------------------------------------------------------------------------------- /chrome/skin/default/state_icon/disconnect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ettoolong/BBSFox-E10S/HEAD/chrome/skin/default/state_icon/disconnect.png -------------------------------------------------------------------------------- /chrome.manifest: -------------------------------------------------------------------------------- 1 | content bbsfox chrome/content/ 2 | 3 | locale bbsfox en-US chrome/locale/en-US/ 4 | locale bbsfox zh-TW chrome/locale/zh-TW/ 5 | 6 | skin bbsfox classic/1.0 chrome/skin/default/ 7 | -------------------------------------------------------------------------------- /chrome/content/paramikojs/kryptos/Hash/MD5.js: -------------------------------------------------------------------------------- 1 | kryptos.hash.MD5 = function(str) { 2 | inherit(this, new kryptos.hash.baseHash(str)); 3 | } 4 | 5 | kryptos.hash.MD5.digest_size = 16; 6 | 7 | kryptos.hash.MD5.prototype = { 8 | type : 'md5' 9 | }; 10 | -------------------------------------------------------------------------------- /.jpmignore: -------------------------------------------------------------------------------- 1 | # Ignore .DS_Store files created by mac 2 | .DS_Store 3 | .git 4 | .jpmignore 5 | .gitignore 6 | 7 | # Ignore any zip or xpi files 8 | *.zip 9 | *.xpi 10 | 11 | # other 12 | data/js/optionsDlg.js 13 | data/js/optionsDlg-cs.js 14 | -------------------------------------------------------------------------------- /chrome/content/paramikojs/kryptos/Hash/SHA.js: -------------------------------------------------------------------------------- 1 | kryptos.hash.SHA = function(str) { 2 | inherit(this, new kryptos.hash.baseHash(str)); 3 | } 4 | 5 | kryptos.hash.SHA.digest_size = 20; 6 | 7 | kryptos.hash.SHA.prototype = { 8 | type : 'sha1' 9 | }; 10 | -------------------------------------------------------------------------------- /chrome/content/paramikojs/kryptos/Hash/SHA256.js: -------------------------------------------------------------------------------- 1 | kryptos.hash.SHA256 = function(str) { 2 | inherit(this, new kryptos.hash.baseHash(str)); 3 | } 4 | 5 | kryptos.hash.SHA256.digest_size = 32; 6 | 7 | kryptos.hash.SHA256.prototype = { 8 | type : 'sha256' 9 | }; 10 | -------------------------------------------------------------------------------- /data/js/context-menu/downloadPost.js: -------------------------------------------------------------------------------- 1 | self.on("context", function (node) { 2 | if(!window.bbsfox) { 3 | return false; 4 | } 5 | return window.bbsfox.prefs.downloadPostMenu; 6 | }); 7 | 8 | self.on("click", function(node, data) { 9 | self.postMessage(data); 10 | }); 11 | -------------------------------------------------------------------------------- /data/js/context-menu/viewImage.js: -------------------------------------------------------------------------------- 1 | self.on("context", function (node) { 2 | if(!window.bbsfox) { 3 | return false; 4 | } 5 | return window.bbsfox.prefs.status.mouseOnPicWindow; 6 | }); 7 | 8 | self.on("click", function(node, data) { 9 | self.postMessage(); 10 | }); 11 | -------------------------------------------------------------------------------- /data/js/context-menu/previewPicture.js: -------------------------------------------------------------------------------- 1 | self.on("context", function (node) { 2 | if(!window.bbsfox) { 3 | return false; 4 | } 5 | return window.bbsfox.prefs.previewPictureMenu; 6 | }); 7 | 8 | self.on("click", function(node, data) { 9 | self.postMessage(data); 10 | }); 11 | -------------------------------------------------------------------------------- /chrome/content/paramikojs/compress.js: -------------------------------------------------------------------------------- 1 | paramikojs.ZlibCompressor = function () { 2 | 3 | } 4 | 5 | paramikojs.ZlibCompressor.prototype = { 6 | 7 | }; 8 | 9 | paramikojs.ZlibDecompressor = function () { 10 | 11 | } 12 | 13 | paramikojs.ZlibDecompressor.prototype = { 14 | 15 | }; 16 | -------------------------------------------------------------------------------- /data/js/context-menu/loadFile.js: -------------------------------------------------------------------------------- 1 | self.on("context", function (node) { 2 | if(!window.bbsfox) { 3 | return false; 4 | } 5 | return window.bbsfox.prefs.fileIoMenu; 6 | }); 7 | 8 | self.on("click", function(node, data) { 9 | window.bbsfox.overlaycmd.exec({command:"doLoadFile"}); 10 | }); 11 | -------------------------------------------------------------------------------- /data/js/context-menu/ansiCopy.js: -------------------------------------------------------------------------------- 1 | self.on("context", function (node) { 2 | if(!window.bbsfox) { 3 | return false; 4 | } 5 | return window.bbsfox.prefs.ansiCopyMenu; 6 | }); 7 | 8 | self.on("click", function(node, data) { 9 | window.bbsfox.overlaycmd.exec({command:"doCopyAnsi"}); 10 | }); 11 | -------------------------------------------------------------------------------- /data/js/context-menu/easyRead.js: -------------------------------------------------------------------------------- 1 | self.on("context", function (node) { 2 | if(!window.bbsfox) { 3 | return false; 4 | } 5 | return window.bbsfox.prefs.easyReadingMenu; 6 | }); 7 | 8 | self.on("click", function(node, data) { 9 | window.bbsfox.overlaycmd.exec({command:"easyReading"}); 10 | }); 11 | -------------------------------------------------------------------------------- /data/js/context-menu/pushThread.js: -------------------------------------------------------------------------------- 1 | self.on("context", function (node) { 2 | if(!window.bbsfox) { 3 | return false; 4 | } 5 | return window.bbsfox.prefs.pushThreadMenu; 6 | }); 7 | 8 | self.on("click", function(node, data) { 9 | window.bbsfox.overlaycmd.exec({command:"pushThread"}); 10 | }); 11 | -------------------------------------------------------------------------------- /data/js/context-menu/mouseBrowsing.js: -------------------------------------------------------------------------------- 1 | self.on("context", function (node) { 2 | if(!window.bbsfox) { 3 | return false; 4 | } 5 | return window.bbsfox.prefs.mouseBrowseMenu; 6 | }); 7 | 8 | self.on("click", function(node, data) { 9 | window.bbsfox.overlaycmd.exec({command:"switchMouseBrowsing"}); 10 | }); 11 | -------------------------------------------------------------------------------- /data/js/context-menu/changeColorTable.js: -------------------------------------------------------------------------------- 1 | self.on("context", function (node) { 2 | if(!window.bbsfox) { 3 | return false; 4 | } 5 | return window.bbsfox.prefs.changeColorTableMenu; 6 | }); 7 | 8 | self.on("click", function(node, data) { 9 | window.bbsfox.overlaycmd.exec({command:"changeColorTable"}); 10 | }); 11 | -------------------------------------------------------------------------------- /data/js/context-menu/openThreadUrl.js: -------------------------------------------------------------------------------- 1 | self.on("context", function (node) { 2 | if(!window.bbsfox) { 3 | return false; 4 | } 5 | return window.bbsfox.prefs.status.openThreadUrlMenu; 6 | }); 7 | 8 | self.on("click", function(node, data) { 9 | window.bbsfox.overlaycmd.exec({command:"openThreadUrl"}); 10 | }); 11 | -------------------------------------------------------------------------------- /data/js/context-menu/switchBgDisplay.js: -------------------------------------------------------------------------------- 1 | self.on("context", function (node) { 2 | if(!window.bbsfox) { 3 | return false; 4 | } 5 | return window.bbsfox.prefs.switchBgDisplayMenu && window.bbsfox.prefs.enableBackground; 6 | }); 7 | 8 | self.on("click", function(node, data) { 9 | window.bbsfox.overlaycmd.exec({command:"switchBgDisplay"}); 10 | }); 11 | -------------------------------------------------------------------------------- /data/js/context-menu/openAllLink.js: -------------------------------------------------------------------------------- 1 | self.on("context", function (node) { 2 | if(!window.bbsfox) { 3 | return false; 4 | } 5 | let allLinks = window.document.getElementsByTagName('a'); 6 | return window.bbsfox.prefs.openAllLinkMenu && (allLinks.length > 0); 7 | }); 8 | 9 | self.on("click", function(node, data) { 10 | self.postMessage(); 11 | }); 12 | -------------------------------------------------------------------------------- /chrome/skin/default/options.css: -------------------------------------------------------------------------------- 1 | @import url(chrome://global/skin/); 2 | 3 | menulist[bbsfox_images_autosize="true"] > menupopup > menuitem > .menu-iconic-left{ 4 | display: -moz-box; 5 | } 6 | menulist[bbsfox_images_autosize="true"] > menupopup > menuitem .menu-iconic-icon{ 7 | width: auto; 8 | height: auto; 9 | } 10 | .redLabel 11 | { 12 | color:#ff0000; 13 | } -------------------------------------------------------------------------------- /data/js/context-menu/ansiColorTool.js: -------------------------------------------------------------------------------- 1 | self.on("context", function (node) { 2 | if(!window.bbsfox) { 3 | return false; 4 | } 5 | return window.bbsfox.prefs.ansiColorToolMenu && !window.bbsfox.prefs.status.ansiColorToolOpened; 6 | }); 7 | 8 | self.on("click", function(node, data) { 9 | window.bbsfox.overlaycmd.exec({command:"openAnsiColorTool"}); 10 | }); 11 | -------------------------------------------------------------------------------- /data/js/context-menu/screenKeyboard.js: -------------------------------------------------------------------------------- 1 | self.on("context", function (node) { 2 | if(!window.bbsfox) { 3 | return false; 4 | } 5 | return window.bbsfox.prefs.screenKeyboardMenu && !window.bbsfox.prefs.status.screenKeyboardOpened; 6 | }); 7 | 8 | self.on("click", function(node, data) { 9 | window.bbsfox.overlaycmd.exec({command:"openSymbolInput"}); 10 | }); 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # BBSFox-E10S 2 | Firefox Add-on BBSFox for E10S support 3 | 4 | Connect to site: 5 | For example, we want to connect site aaa.bbb.ccc.ddd 6 | Type telnet://aaa.bbb.ccc.ddd in Firefox URL bar to connect site. 7 | BBSFox use telnet default port 23 to make connection. 8 | If the site use specific port such as 8888, Type telnet://aaa.bbb.ccc.ddd:8888 in Firefox URL bar to connect site. 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | COSX 2 | .DS_Store 3 | 4 | 5 | # OS generated files # 6 | ###################### 7 | */.DS_Store 8 | .DS_Store 9 | .DS_Store? 10 | ._* 11 | .Spotlight-V100 12 | .Trashes 13 | Icon? 14 | ehthumbs.db 15 | Thumbs.db 16 | 17 | # Packages # 18 | ############ 19 | # it's better to unpack these files and commit the raw source 20 | # git has its own built in compression methods 21 | *.xpi 22 | -------------------------------------------------------------------------------- /chrome/content/paramikojs/kryptos/Random/Fortuna/SHAd256.js: -------------------------------------------------------------------------------- 1 | kryptos.random.Fortuna.SHAd256 = function(str) { 2 | inherit(this, new kryptos.hash.baseHash(str)); 3 | } 4 | 5 | kryptos.random.Fortuna.SHAd256.digest_size = 32; 6 | 7 | kryptos.random.Fortuna.SHAd256.prototype = { 8 | type : 'sha256', 9 | 10 | digest : function() { 11 | return new kryptos.hash.SHA256(new kryptos.hash.SHA256(this.data).digest()).digest(); 12 | } 13 | }; 14 | -------------------------------------------------------------------------------- /data/js/context-menu/trackClear.js: -------------------------------------------------------------------------------- 1 | self.on("context", function (node) { 2 | if(!window.bbsfox) { 3 | return false; 4 | } 5 | 6 | if(window.bbsfox.prefs.keyWordTrackMenu) { 7 | let highlightWords = window.bbsfox.prefs.highlightWords_local; 8 | return (highlightWords.length > 0); 9 | } 10 | else { 11 | return false; 12 | } 13 | }); 14 | 15 | self.on("click", function(node, data) { 16 | //self.postMessage(); 17 | window.bbsfox.overlaycmd.exec({command:"doClearTrack"}); 18 | }); 19 | -------------------------------------------------------------------------------- /chrome/content/commonDef.js: -------------------------------------------------------------------------------- 1 | const { utils: Cu, classes: Cc, interfaces: Ci } = Components; 2 | const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; 3 | const ICON_LOGO = "chrome://bbsfox/skin/logo/logo.png"; 4 | const ICON_CONNECT = "chrome://bbsfox/skin/state_icon/connect.png"; 5 | const ICON_DISCONNECT = "chrome://bbsfox/skin/state_icon/disconnect.png"; 6 | const ICON_CONNECTING = "chrome://bbsfox/skin/state_icon/connecting.gif"; 7 | const ICON_ERROR = "chrome://bbsfox/skin/state_icon/error.png"; 8 | -------------------------------------------------------------------------------- /chrome/content/ctrlTable.js: -------------------------------------------------------------------------------- 1 | ctrlTable = new Object(); 2 | var a = ctrlTable; 3 | a.xa='\x01'; 4 | a.xb='\x02'; 5 | a.xc='\x03'; 6 | a.xd='\x04'; 7 | a.xe='\x05'; 8 | a.xf='\x06'; 9 | a.xg='\x07'; 10 | a.xh='\x08'; 11 | a.xi='\x09'; 12 | a.xj='\x0a'; 13 | a.xk='\x0b'; 14 | a.xl='\x0c'; 15 | a.xm='\x0d'; 16 | a.xn='\x0e'; 17 | a.xo='\x0f'; 18 | a.xp='\x10'; 19 | a.xq='\x11'; 20 | a.xr='\x12'; 21 | a.xs='\x13'; 22 | a.xt='\x14'; 23 | a.xu='\x15'; 24 | a.xv='\x16'; 25 | a.xw='\x17'; 26 | a.xx='\x18'; 27 | a.xy='\x19'; 28 | a.xz='\x1a'; 29 | -------------------------------------------------------------------------------- /chrome/content/paramikojs/kryptos/Random/OSRNG/browser.js: -------------------------------------------------------------------------------- 1 | kryptos.random.OSRNG.BrowserRNG = function() { 2 | 3 | } 4 | 5 | kryptos.random.OSRNG.BrowserRNG.prototype = { 6 | flush : function() { 7 | // pass 8 | }, 9 | 10 | read : function(N) { 11 | var array = new Uint8Array(N); 12 | crypto.getRandomValues(array); 13 | 14 | var str = ""; // todo fixme - use native array types, and move to chrome worker 15 | for (var x = 0; x < N; ++x) { 16 | str += String.fromCharCode(array[x]); 17 | } 18 | 19 | return str; 20 | }, 21 | 22 | close: function() { 23 | // pass 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /data/js/stringutil.js: -------------------------------------------------------------------------------- 1 | function parseThreadForUserId (str) { 2 | let regex = new RegExp(/(?:(?:\d+)|(?: \u2605 )) [\u002bmMsSD*!=~ ](?:(?:[-X\d\* ]{2})|(?:\u7206))[\d ]\d\/\d{2} (\w+) +[\u9396\u25a1\u8f49\u25c6\u25c7R=]:?/g); 3 | let result = regex.exec(str); 4 | if (result && result.length == 2) { 5 | return result[1].toLowerCase(); 6 | } 7 | 8 | return null; 9 | } 10 | 11 | function parsePushthreadForUserId (str) { 12 | let regex = new RegExp(/[\u2192\u63a8\u5653] (\w+) *:.+ \d{2}\/\d{2} \d{2}:\d{2}/g); 13 | let result = regex.exec(str); 14 | if (result && result.length == 2) { 15 | return result[1].toLowerCase(); 16 | } 17 | 18 | return null; 19 | }; 20 | -------------------------------------------------------------------------------- /chrome/content/paramikojs/unknown_key.js: -------------------------------------------------------------------------------- 1 | /* 2 | Representation of a key that we don't know about. 3 | */ 4 | paramikojs.UnknownKey = function(keytype, key) { 5 | inherit(this, new paramikojs.PKey()); 6 | 7 | this.keytype = keytype; 8 | this.key = key; 9 | } 10 | 11 | paramikojs.UnknownKey.prototype = { 12 | toString : function() { 13 | return this.key; 14 | }, 15 | 16 | compare : function(other) { 17 | if (this.get_name() != other.get_name()) { 18 | return false; 19 | } 20 | if (this.key != other.key) { 21 | return false; 22 | } 23 | return true; 24 | }, 25 | 26 | get_name : function() { 27 | return this.keytype; 28 | } 29 | }; 30 | 31 | -------------------------------------------------------------------------------- /chrome/content/paramikojs/sign_ssh_data_worker.js: -------------------------------------------------------------------------------- 1 | importScripts('kryptos/kryptos.js', 2 | 'kryptos/PublicKey/RSA.js', 3 | 'common.js', 4 | 'python_shim.js', 5 | 'BigInteger.js', 6 | 'util.js'); 7 | 8 | onmessage = function(event) { 9 | var rsa = new kryptos.publicKey.RSA().construct(new BigInteger(event.data.n, 10), 10 | new BigInteger(event.data.e, 10), 11 | new BigInteger(event.data.d, 10)); 12 | var inflated = paramikojs.util.inflate_long(event.data.pkcs1imified, true); 13 | postMessage(rsa.sign(inflated, '')[0].toString()); 14 | }; 15 | -------------------------------------------------------------------------------- /chrome/content/paramikojs/kryptos/Hash/HMAC.js: -------------------------------------------------------------------------------- 1 | kryptos.hash.HMAC = function(key, msg, digestmod) { 2 | var hasher = Cc["@mozilla.org/security/hmac;1"].createInstance(Ci.nsICryptoHMAC); 3 | var keyObject = Cc["@mozilla.org/security/keyobjectfactory;1"] 4 | .getService(Ci.nsIKeyObjectFactory) 5 | .keyFromString(Ci.nsIKeyObject.HMAC, key); 6 | 7 | hasher.init(digestmod, keyObject); 8 | var data = kryptos.toByteArray(msg); 9 | hasher.update(data, data.length); 10 | return hasher.finish(false); 11 | }; 12 | 13 | kryptos.hash.HMAC_SHA = Cc["@mozilla.org/security/hmac;1"].createInstance(Ci.nsICryptoHMAC).SHA1; 14 | kryptos.hash.HMAC_MD5 = Cc["@mozilla.org/security/hmac;1"].createInstance(Ci.nsICryptoHMAC).MD5; 15 | -------------------------------------------------------------------------------- /chrome/content/paramikojs/kryptos/PublicKey/RSA.js: -------------------------------------------------------------------------------- 1 | kryptos.publicKey.RSA = function() { 2 | 3 | } 4 | 5 | kryptos.publicKey.RSA.prototype = { 6 | construct : function(n, e, d) { 7 | this.n = n; 8 | this.e = e; 9 | this.d = d; 10 | 11 | return this; 12 | }, 13 | 14 | sign : function(m, K) { 15 | return [m.modPow(this.d, this.n), '']; 16 | }, 17 | 18 | verify : function(m, sig) { 19 | var s = sig[0]; // HACK - We should use the previous line instead, but 20 | // this is more compatible and we're going to replace 21 | // the Crypto.PublicKey API soon anyway. 22 | return s.modPow(this.e, this.n).equals(m); 23 | }, 24 | 25 | generate : function() { 26 | alert('NOT_IMPLEMENTED'); 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /locale/zh-TW.properties: -------------------------------------------------------------------------------- 1 | openPrefsTab_title= 偏好設定 2 | openPrefsTab_label= 設定 3 | openUserManual_title= 使用手冊 4 | openUserManual_label= 開啟 5 | reportBug_title= 回報問題 6 | reportBug_label= 回報 7 | cm_previewPicture= 顯示縮圖 8 | cm_ansiColorTool= 開啟色彩輸入工具 9 | cm_screenKeyboard= 開啟符號輸入窗 10 | cm_addTrack= 新增追蹤關鍵字 11 | cm_delTrack= 取消追蹤關鍵字 12 | cm_clearTrack= 清除所有的追蹤關鍵字 13 | cm_mouseBrowsing= 滑鼠瀏覽切換 14 | cm_switchBgDisplay= 背景圖片顯示切換 15 | cm_easyRead= 好讀模式 16 | cm_pushThread= 推文工具 17 | cm_openThreadUrl= 開啟文章網址 18 | cm_changeColorTable= 切換高亮度顯示 19 | cm_downloadPost= 下載文章 20 | cm_downText= 文字 21 | cm_downSnsi= ANSI彩色 22 | cm_downHtml= HTML 23 | cm_loadFile= 載入檔案 24 | cm_addToBlacklist= 加入黑名單 25 | cm_removeFromBlacklist= 從黑名單中移除 26 | cm_ansiCopy= 複製(包含ANSI色碼) 27 | cm_openAllLink= 開啟畫面上所有鏈結 28 | cm_viewimage= 檢視圖片 29 | -------------------------------------------------------------------------------- /chrome/skin/default/cursor/COPYRIGHT.txt: -------------------------------------------------------------------------------- 1 | Polar Cursor Theme 2 | Copyright (C) 2005 Eric Matthews 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | -------------------------------------------------------------------------------- /chrome/content/paramikojs/kryptos/Hash/baseHash.js: -------------------------------------------------------------------------------- 1 | kryptos.hash.baseHash = function(data) { 2 | if (data instanceof Array) { 3 | data = kryptos.fromByteArray(data); 4 | } 5 | this.data = data || ""; 6 | } 7 | 8 | kryptos.hash.baseHash.prototype = { 9 | type : '', 10 | 11 | update : function(data) { 12 | if (data instanceof Array) { 13 | data = kryptos.fromByteArray(data); 14 | } 15 | this.data = this.data + data; 16 | }, 17 | 18 | digest : function() { 19 | var hashData = []; 20 | for (var x = 0; x < this.data.length; ++x) { 21 | hashData.push(this.data.charCodeAt(x)); 22 | } 23 | 24 | var hashComp = Cc["@mozilla.org/security/hash;1"].createInstance(Ci.nsICryptoHash); 25 | hashComp.initWithString(this.type); 26 | hashComp.update(hashData, hashData.length); 27 | var result = hashComp.finish(false); 28 | 29 | return result; 30 | } 31 | }; 32 | -------------------------------------------------------------------------------- /chrome/content/res/keyboard.res: -------------------------------------------------------------------------------- 1 | ,,、,。,.,?,!,~,$,%,@,&,#,*,‧,;,︰,…,‥,﹐,﹒,˙,·,﹔,﹕,‘,’,“,”,〝,〞,‵,′,〃 2 | ├,─,┼,┴,┬,┤,┌,┐,│,▕,└,┘,╭,╮,╰,╯,╔,╦,╗,╠,═,╬,╣,╓,╥,╖,╒,╤,╕,║,╚,╩,╝,╟,╫,╢,╙,╨,╜,╞,╪,╡,╘,╧,╛ 3 | _,ˍ,▁,▂,▃,▄,▅,▆,▇,█,▏,▎,▍,▌,▋,▊,▉,◢,◣,◥,◤ 4 | ﹣,﹦,≡,|,∣,∥,–,︱,—,︳,╴,¯, ̄,﹉,﹊,﹍,﹎,﹋,﹌,﹏,︴,∕,﹨,╱,╲,/,\ 5 | ↑,↓,←,→,↖,↗,↙,↘,㊣,◎,○,●,⊕,⊙,△,▲,☆,★,◇,Æ,□,■,▽,▼,§,¥,〒,¢,£,※,♀,♂ 6 | 〔,〕,【,】,《,》,(,),{,},﹙,﹚,『,』,﹛,﹜,﹝,﹞,<,>,﹤,﹥,「,」 7 | ︵,︶,︷,︸,︹,︺,︻,︼,︽,︾,〈,〉,︿,﹀,﹁,﹂,﹃,﹄ 8 | Α,Β,Γ,Δ,Ε,Ζ,Η,Θ,Ι,Κ,Λ,Μ,Ν,Ξ,Ο,Π,Ρ,Σ,Τ,Υ,Φ,Χ,Ψ,Ω,α,β,γ,δ,ε,ζ,η,θ,ι,κ,λ,μ,ν,ξ,ο,π,ρ,σ,τ,υ,φ,χ,ψ,ω 9 | ㄅ,ㄆ,ㄇ,ㄈ,ㄉ,ㄊ,ㄋ,ㄌ,ㄍ,ㄎ,ㄏ,ㄐ,ㄑ,ㄒ,ㄓ,ㄔ,ㄕ,ㄖ,ㄗ,ㄘ,ㄙ,ㄚ,ㄛ,ㄜ,ㄝ,ㄞ,ㄟ,ㄠ,ㄡ,ㄢ,ㄣ,ㄤ,ㄥ,ㄦ,ㄧ,ㄨ,ㄩ,˙,ˊ,ˇ,ˋ 10 | ╳,+,﹢,-,×,÷,=,≠,≒,∞,ˇ,±,√,⊥,∠,∟,⊿,㏒,㏑,∫,∮,∵,∴,≦,≧,∩,∪ 11 | あ,い,う,え,お,か,き,く,け,こ,さ,し,す,せ,そ,た,ち,つ,て,と,な,に,ぬ,ね,の,は,ひ,ふ,へ,ほ,ま,み,む,め,も,ら,り,る,れ,ろ,が,ぎ,ぐ,げ,ご,ざ,じ,ず,ぜ,ぞ,だ,ぢ,づ,で,ど,ば,び,ぶ,べ,ぼ,ぱ,ぴ,ぷ,ぺ,ぽ,や,ゆ,よ,わ,ん,を 12 | ア,イ,ウ,エ,オ,カ,キ,ク,ケ,コ,サ,シ,ス,セ,ソ,タ,チ,ツ,テ,ト,ナ,ニ,ヌ,ネ,ノ,ハ,ヒ,フ,ヘ,ホ,マ,ミ,ム,メ,モ,ラ,リ,ル,レ,ロ,ガ,ギ,グ,ゲ,ゴ,ザ,ジ,ズ,ゼ,ゾ,ダ,ジ,ズ,デ,ド,バ,ビ,ブ,ベ,ボ,パ,ピ,プ,ペ,ポ,ヤ,ユ,ヨ,ワ,ン,ヲ -------------------------------------------------------------------------------- /data/js/bbsfox-bg.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const {Cu, Cc, Ci} = require("chrome"); 4 | 5 | const ioService = Cc["@mozilla.org/network/io-service;1"]. 6 | getService(Ci.nsIIOService); 7 | const resourceHandler = ioService.getProtocolHandler("resource"). 8 | QueryInterface(Ci.nsIResProtocolHandler); 9 | 10 | const mount = () => { 11 | Cu.import("resource://gre/modules/osfile.jsm"); 12 | let dir = OS.Path.join(OS.Constants.Path.profileDir, 'bbsfoxBg'); 13 | try{ 14 | OS.File.makeDir(dir); 15 | } catch(ex) { 16 | } 17 | let alias = ioService.newURI( OS.Path.toFileURI( OS.Path.join(OS.Constants.Path.profileDir, 'bbsfoxBg', 'bbsfox') ), null, null); 18 | resourceHandler.setSubstitution('bbsfox2', alias); 19 | Cu.unload("resource://gre/modules/osfile.jsm"); 20 | } 21 | const unmount = () => { 22 | resourceHandler.setSubstitution('bbsfox2', null); 23 | } 24 | exports.mount = mount; 25 | exports.unmount = unmount; -------------------------------------------------------------------------------- /locale/en-US.properties: -------------------------------------------------------------------------------- 1 | openPrefsTab_title= Preferences 2 | openPrefsTab_label= Preferences 3 | openUserManual_title= User Manual 4 | openUserManual_label= Open Manual 5 | reportBug_title= Report Bug 6 | reportBug_label= Go 7 | cm_previewPicture= Show Preview Image 8 | cm_ansiColorTool= Open Ansi Color Tool Window 9 | cm_screenKeyboard= Enable Punctuation Window 10 | cm_addTrack= Add To Keyword Pool 11 | cm_delTrack= Cancel This Keyword 12 | cm_clearTrack= Clear Pp Keyword Pool 13 | cm_mouseBrowsing= Mouse Browsing On/Off 14 | cm_switchBgDisplay= Background Image Display On/Off 15 | cm_easyRead= Easy Reading Mode 16 | cm_pushThread= Push Thread Tool 17 | cm_openThreadUrl= Open Thread URL 18 | cm_changeColorTable= Switch Normal/Highlight Display 19 | cm_downloadPost= Download Post 20 | cm_downText= Text 21 | cm_downAnsi= AnsiColor 22 | cm_downHtml= HTML 23 | cm_loadFile= Load File 24 | cm_addToBlacklist= Add to Blacklist 25 | cm_removeFromBlacklist= Remove from Blacklist 26 | cm_ansiCopy= Copy with ANSI Color 27 | cm_openAllLink= Open All Links 28 | cm_viewimage= View Image 29 | -------------------------------------------------------------------------------- /chrome/content/paramikojs/kryptos/kryptos.js: -------------------------------------------------------------------------------- 1 | kryptos = function() {}; 2 | kryptos.prototype = {}; 3 | 4 | kryptos.cipher = {}; 5 | kryptos.hash = {}; 6 | kryptos.protocol = {}; 7 | kryptos.publicKey = {}; 8 | kryptos.random = {}; 9 | kryptos.random.Fortuna = {}; 10 | kryptos.random.OSRNG = {}; 11 | kryptos.util = {}; 12 | 13 | kryptos.toByteArray = function(str) { 14 | function charToUint(chr) { return chr.charCodeAt(0) } 15 | return str.split('').map(charToUint); 16 | }; 17 | 18 | kryptos.fromByteArray = function(data) { 19 | function uintToChar(uint) { return String.fromCharCode(uint) } 20 | return data.map(uintToChar).join(''); 21 | }; 22 | 23 | kryptos.bytesToWords = function(bytes) { 24 | for (var words = [], i = 0, b = 0; i < bytes.length; i++, b += 8) { 25 | words[b >>> 5] |= (bytes[i] & 0xFF) << (24 - b % 32); 26 | } 27 | return words; 28 | }; 29 | 30 | kryptos.wordsToBytes = function(words) { 31 | for (var bytes = [], b = 0; b < words.length * 32; b += 8) { 32 | bytes.push((words[b >>> 5] >>> (24 - b % 32)) & 0xFF); 33 | } 34 | return bytes; 35 | }; 36 | -------------------------------------------------------------------------------- /chrome/content/addSite.xul: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 12 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 |
49 |
50 | 51 |
52 |
53 |
54 |
55 |
56 | 57 |
58 |
59 | 60 |
61 | 63 | 64 |
65 | 66 |
67 |
68 |
 
69 |
70 |
71 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /chrome/content/uao/uao.js: -------------------------------------------------------------------------------- 1 | // Javascript module for Unicode-at-on support 2 | // Reference: http://moztw.org/docs/big5/ 3 | // http://moztw.org/docs/big5/table/uao250-u2b.txt 4 | 5 | var uaoConv = { 6 | u2bTab: '', 7 | b2uTab: '', 8 | conv: Cc["@mozilla.org/intl/utf8converterservice;1"].getService(Ci.nsIUTF8ConverterService), 9 | 10 | init_u2b: function () { 11 | // load U2B table 12 | var ioService = Cc["@mozilla.org/network/io-service;1"] 13 | .getService(Ci.nsIIOService); 14 | var ssm = Cc["@mozilla.org/scriptsecuritymanager;1"].getService(Ci.nsIScriptSecurityManager); 15 | var sp = ssm.getSystemPrincipal(); 16 | var channel = ioService.newChannel2("chrome://bbsfox/content/uao/u2b.tab", //aSpec 17 | null, //aOriginCharset 18 | null, //aBaseURI 19 | null, //aLoadingNode 20 | sp, //aLoadingPrincipal 21 | null, //aTriggeringPrincipal 22 | Ci.nsILoadInfo.SEC_NORMAL, //aSecurityFlags 23 | Ci.nsIContentPolicy.TYPE_OTHER); //aContentPolicyType 24 | 25 | var ins = channel.open(); 26 | var bins = Cc["@mozilla.org/binaryinputstream;1"]. 27 | createInstance(Ci.nsIBinaryInputStream); 28 | bins.setInputStream(ins); 29 | while(bins.available()) 30 | this.u2bTab += bins.readBytes(bins.available()); 31 | bins.close(); 32 | }, 33 | 34 | init_b2u: function () { 35 | // load U2B table 36 | var ioService = Cc["@mozilla.org/network/io-service;1"] 37 | .getService(Ci.nsIIOService); 38 | var ssm = Cc["@mozilla.org/scriptsecuritymanager;1"].getService(Ci.nsIScriptSecurityManager); 39 | var sp = ssm.getSystemPrincipal(); 40 | var channel = ioService.newChannel2("chrome://bbsfox/content/uao/b2u.tab", //aSpec 41 | null, //aOriginCharset 42 | null, //aBaseURI 43 | null, //aLoadingNode 44 | sp, //aLoadingPrincipal 45 | null, //aTriggeringPrincipal 46 | Ci.nsILoadInfo.SEC_NORMAL, //aSecurityFlags 47 | Ci.nsIContentPolicy.TYPE_OTHER); //aContentPolicyType 48 | 49 | var ins = channel.open(); 50 | var bins = Cc["@mozilla.org/binaryinputstream;1"]. 51 | createInstance(Ci.nsIBinaryInputStream); 52 | bins.setInputStream(ins); 53 | while(bins.available()) 54 | this.b2uTab += bins.readBytes(bins.available()); 55 | bins.close(); 56 | }, 57 | 58 | b2u: function(data, charset) { 59 | if(charset.toLowerCase()=='big5') { 60 | if(!this.b2uTab) 61 | this.init_b2u(); // initialize UAO table 62 | var ret = ''; 63 | var b2u = this.b2uTab; // the table 64 | var i, n = data.length; 65 | for(i = 0; i < n; ++i) { 66 | if(data.charCodeAt(i) >= 129 && i < n-1) { // use UAO table 67 | var code = data.charCodeAt(i)*0x100 + data.charCodeAt(i+1); 68 | var idx = (code - 0x8001) * 2; 69 | // dump('idx = ' + idx + ', len = ' + b2u.length + '\n'); 70 | var uni = b2u.charCodeAt(idx)*0x100 + b2u.charCodeAt(idx+1); 71 | ret += String.fromCharCode(uni); 72 | ++i; 73 | } 74 | else // this is an ascii character 75 | ret += data[i]; 76 | } 77 | return ret; 78 | } else if(charset.toLowerCase()=='big5-hk') { 79 | return this.conv.convertStringToUTF8(data, 'big5', true, true); 80 | } else { 81 | return this.conv.convertStringToUTF8(data, charset, true, true); 82 | } 83 | }, 84 | 85 | u2b: function(unicode_str) { 86 | if(!this.u2bTab) 87 | this.init_u2b(); // initialize UAO table 88 | var ret = ''; 89 | var u2b = this.u2bTab; // the table 90 | var i, n = unicode_str.length; 91 | for(i = 0; i < n; ++i) { 92 | var ch = unicode_str[i]; 93 | var code = ch.charCodeAt(0); 94 | if(code >= 129) { // use UAO table 95 | var idx = (code - 129) * 2; 96 | // dump('idx = ' + idx + ', len = ' + u2b.length + '\n'); 97 | if(idx < u2b.length) { 98 | var big5 = u2b[idx] + u2b[idx + 1]; 99 | ret += big5; 100 | } 101 | } 102 | else // this is an ascii character 103 | ret += ch; 104 | } 105 | return ret; 106 | } 107 | }; 108 | -------------------------------------------------------------------------------- /chrome/locale/zh-TW/help.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | BBSFox 使用手冊 7 | 22 | 23 | 24 | 25 | 連線到站台:
26 | 例如要連線到站台aaa.bbb.ccc.ddd
27 | 在Firefox網址列輸入telnet://aaa.bbb.ccc.ddd就可以連線,此連線預設使用telnet的連接埠23
28 | 如果站台使用特定的連接埠例如8888,在Firefox網址列輸入telnet://aaa.bbb.ccc.ddd:8888即可。
29 |
30 | 一般熱鍵:
31 | (熱鍵可在設定頁開啟或關閉)
32 | Ctrl+Shift+V貼上
33 | Ctrl+A全選
34 | 圈選文字後按下 Ctrl + C複製
35 | Ctrl+D下載文章到剪貼簿
36 | Ctrl+E顯示/隱藏 BBS背景圖片
37 | Ctrl+M滑鼠瀏覽開/關
38 |
39 | 滑鼠瀏覽:
40 | (在設定頁設定滑鼠瀏覽以啟用此功能)
41 | 一般頁面
42 | 頁面左側 = 方向鍵左(返回上一層頁面)
43 | 頁面其他部份 = Enter (點擊進入)
44 |
45 | 在看板列表或文章列表時
46 | 參照下圖:
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 | 紅色區域 = Home (第一頁)
55 | 綠色區域 = End (最後一頁)
56 | 藍色區域 = Page Up (上一頁)
57 | 黃色區域 = Page Down (下一頁)
58 | 橘色區域 = 方向鍵左(返回上一層頁面)
59 | 紫色區域 = Enter (進入看板/閱讀文章)
60 |
61 | 閱讀文章內容時
62 | 參照下圖:
63 |
64 |
65 |
66 |
67 |
68 |
69 | 綠色區域 = End (最後一頁)
70 | 藍色區域 = Page Up (上一頁)
71 | 黃色區域 = Page Down (下一頁)
72 | 橘色區域 = 方向鍵左(返回上一層頁面)
73 |
74 | 幾個特別的處理:
75 | 圈選某些文字時,滑鼠瀏覽會自動不生效,以免對圈選的文字作動作時誤觸滑鼠瀏覽的動作,
76 | 單點畫面取消圈選後,滑鼠瀏覽模式會回復。
77 | 滑鼠瀏覽模式下不能用double click去圈選文字(會自動取消圈選),以免點太快造成文字被圈選,
78 | 而下一次的點擊因為圈選了文字而被略過。
79 | 使用 ctrl+M去切換滑鼠瀏覽模式,如果需要一般性的操作,
80 | 想暫時取消滑鼠瀏覽模式時可以使用此切換熱鍵,以避免操作時誤觸滑鼠瀏覽的動作。
81 |
82 | 進階滑鼠瀏覽:
83 | (在設定頁設定進階滑鼠瀏覽以啟用此功能)
84 | 文章列表或閱讀文章時
85 | 畫面左上 = 送出'=' (跳到同標題第一篇)
86 | 畫面左上第二/三列 = 送出'[' (跳到同標題上一篇)
87 | 畫面右上 = 送出']' (跳到同標題下一篇)
88 | 畫面右下 = 跳到同標題最後一篇
89 | 畫面左下 = 連續送出 方向鍵左+Enter+End (快速更新推文或顯示新的文章)
90 |
91 | 滑鼠手勢:
92 | 請至BBSFox偏好選項的頁面中製作FireGestures腳本
93 | 94 | 95 | -------------------------------------------------------------------------------- /chrome/content/paramikojs/sftp_attr.js: -------------------------------------------------------------------------------- 1 | paramikojs.SFTPAttributes = function () { 2 | /* 3 | Create a new (empty) SFTPAttributes object. All fields will be empty. 4 | */ 5 | this._flags = 0; 6 | this.st_size = null; 7 | this.st_uid = null; 8 | this.st_gid = null; 9 | this.st_mode = null; 10 | this.st_atime = null; 11 | this.st_mtime = null; 12 | this.attr = {}; 13 | } 14 | 15 | paramikojs.SFTPAttributes.prototype = { 16 | /* 17 | Representation of the attributes of a file (or proxied file) for SFTP in 18 | client or server mode. It attemps to mirror the object returned by 19 | C{os.stat} as closely as possible, so it may have the following fields, 20 | with the same meanings as those returned by an C{os.stat} object: 21 | - st_size 22 | - st_uid 23 | - st_gid 24 | - st_mode 25 | - st_atime 26 | - st_mtime 27 | 28 | Because SFTP allows flags to have other arbitrary named attributes, these 29 | are stored in a dict named C{attr}. Occasionally, the filename is also 30 | stored, in C{filename}. 31 | */ 32 | 33 | FLAG_SIZE : 1, 34 | FLAG_UIDGID : 2, 35 | FLAG_PERMISSIONS : 4, 36 | FLAG_AMTIME : 8, 37 | FLAG_EXTENDED : 0x80000000, 38 | 39 | /* 40 | Create an SFTPAttributes object from an existing C{stat} object (an 41 | object returned by C{os.stat}). 42 | 43 | @param obj: an object returned by C{os.stat} (or equivalent). 44 | @type obj: object 45 | @param filename: the filename associated with this file. 46 | @type filename: str 47 | @return: new L{SFTPAttributes} object with the same attribute fields. 48 | @rtype: L{SFTPAttributes} 49 | */ 50 | from_stat : function(obj, filename) { 51 | var attr = this; 52 | attr.st_size = obj.st_size; 53 | attr.st_uid = obj.st_uid; 54 | attr.st_gid = obj.st_gid; 55 | attr.st_mode = obj.st_mode; 56 | attr.st_atime = obj.st_atime; 57 | attr.st_mtime = obj.st_mtime; 58 | if (filename) { 59 | attr.filename = filename; 60 | } 61 | return attr; 62 | }, 63 | 64 | 65 | // internals... 66 | 67 | 68 | _from_msg : function(msg, filename, longname) { 69 | var attr = this; 70 | attr._unpack(msg); 71 | if (filename) { 72 | attr.filename = filename; 73 | } 74 | if (longname) { 75 | attr.longname = longname; 76 | } 77 | return attr; 78 | }, 79 | 80 | _unpack : function(msg) { 81 | this._flags = msg.get_int(); 82 | if (this._flags & this.FLAG_SIZE) { 83 | this.st_size = msg.get_int64(); 84 | } 85 | if (this._flags & this.FLAG_UIDGID) { 86 | this.st_uid = msg.get_int(); 87 | this.st_gid = msg.get_int(); 88 | } 89 | if (this._flags & this.FLAG_PERMISSIONS) { 90 | this.st_mode = msg.get_int(); 91 | } 92 | if (this._flags & this.FLAG_AMTIME) { 93 | this.st_atime = msg.get_int(); 94 | this.st_mtime = msg.get_int(); 95 | } 96 | if (this._flags & this.FLAG_EXTENDED) { 97 | var count = msg.get_int(); 98 | for (var x = 0; x < count.length; ++x) { 99 | this.attr[msg.get_string()] = msg.get_string(); 100 | } 101 | } 102 | }, 103 | 104 | _pack : function(msg) { 105 | this._flags = 0; 106 | if (this.st_size) { 107 | this._flags |= this.FLAG_SIZE; 108 | } 109 | if (this.st_uid && this.st_gid) { 110 | this._flags |= this.FLAG_UIDGID; 111 | } 112 | if (this.st_mode) { 113 | this._flags |= this.FLAG_PERMISSIONS; 114 | } 115 | if (this.st_atime && this.st_mtime) { 116 | this._flags |= this.FLAG_AMTIME; 117 | } 118 | var i; 119 | for (i in this.attr) { // lamesauce :-/ 120 | break; 121 | } 122 | if (i) { 123 | this._flags |= this.FLAG_EXTENDED; 124 | } 125 | msg.add_int(this._flags); 126 | if (this._flags & this.FLAG_SIZE) { 127 | msg.add_int64(this.st_size); 128 | } 129 | if (this._flags & this.FLAG_UIDGID) { 130 | msg.add_int(this.st_uid); 131 | msg.add_int(this.st_gid); 132 | } 133 | if (this._flags & this.FLAG_PERMISSIONS) { 134 | msg.add_int(this.st_mode); 135 | } 136 | if (this._flags & this.FLAG_AMTIME) { 137 | // throw away any fractional seconds 138 | msg.add_int(this.st_atime); 139 | msg.add_int(this.st_mtime); 140 | } 141 | if (this._flags & this.FLAG_EXTENDED) { 142 | msg.add_int(this.attr.length); 143 | for (var key in this.attr) { 144 | msg.add_string(key); 145 | msg.add_string(this.attr[key]); 146 | } 147 | } 148 | }, 149 | 150 | _rwx : function(n, suid, sticky) { 151 | if (suid) { 152 | suid = 2; 153 | } 154 | var out = '-r'.charCodeAt(n >> 2) + '-w'.charCodeAt((n >> 1) & 1); 155 | if (sticky) { 156 | out += '-xTt'.charCodeAt(suid + (n & 1)); 157 | } else { 158 | out += '-xSs'.charCodeAt(suid + (n & 1)); 159 | } 160 | return out; 161 | }, 162 | 163 | toString : function() { 164 | // todo, implement if necessary 165 | } 166 | }; 167 | -------------------------------------------------------------------------------- /chrome/skin/default/bbs.css: -------------------------------------------------------------------------------- 1 | /*@font-face { 2 | font-family: "symmingliu"; 3 | src: url('chrome://bbsfox/skin/symmingliu.woff'); 4 | }*/ 5 | 6 | #BBSWindow { 7 | position:absolute; 8 | width:0px; 9 | height:0px; 10 | top:0px; 11 | left:0px; 12 | overflow:hidden; 13 | z-index:1; 14 | -moz-user-select: text; 15 | user-select: text; 16 | } 17 | 18 | .y { 19 | background-image:url("chrome://bbsfox/skin/link_line/http.bmp"); 20 | background-repeat: repeat-x; 21 | background-position: 0% 90%; 22 | } 23 | 24 | .bluFade { 25 | opacity: var(--blacklist); 26 | } 27 | 28 | .testElem { 29 | white-space: pre; 30 | left:-10000px; 31 | top:-10000px; 32 | position:absolute; 33 | overflow: hidden; 34 | } 35 | 36 | .main { 37 | font-family: MingLiu, monospace; 38 | margin-top:0px; 39 | margin-left:0px; 40 | margin-right:0px; 41 | margin-bottom:0px; 42 | } 43 | 44 | .linkurl { 45 | text-decoration:underline; 46 | color:#FF00FF; 47 | } 48 | 49 | a { 50 | background-image:url("chrome://bbsfox/skin/link_line/http.bmp"); 51 | background-repeat: repeat-x; 52 | background-position: 0% 90%; 53 | text-decoration:none; 54 | } 55 | 56 | a:link,a:visited,a:active,a:hover { 57 | background-position: 0% 90%; 58 | text-decoration:none; 59 | } 60 | 61 | @keyframes blinkBgColor { 62 | 0% {opacity: 1;} 63 | 50% {opacity: 1;} 64 | 51% {opacity: 0;} 65 | 100% {opacity: 0;} 66 | } 67 | 68 | .terminal_display { 69 | white-space: pre; 70 | cursor: text; 71 | position: absolute; 72 | color: #FFFFFF; 73 | pointer-events:none; 74 | margin-top:0.1%; 75 | -moz-user-select: none; 76 | user-select: none; 77 | animation: blinkBgColor 1s infinite linear; 78 | } 79 | 80 | img{background:white; color:black; padding:5px 5px;} 81 | body{color: white;background-color: var(--bbscolor-0);margin: 0px;overflow:hidden;} 82 | span [link="true"]{margin: 0px; background-image: inherit; background-repeat: inherit; background-position: inherit;} 83 | span{margin: 0px;} 84 | .drag{display: none; position: absolute; cursor: default; z-index: 11;} 85 | 86 | .symbolInput{ 87 | z-index: 3; 88 | left: 10px; 89 | top: 10px; 90 | background-color: #bbbbff; 91 | padding: 3px; 92 | border: 0px double #cccccc; 93 | border-radius: 8px; 94 | cursor: default; 95 | display: block; 96 | } 97 | 98 | .ansiColorTool{ 99 | z-index: 3; 100 | left: 10px; 101 | top: 10px; 102 | color: #000000; 103 | background-color: #ffff99; 104 | padding: 3px; 105 | border: 0px double #cccccc; 106 | border-radius: 8px; 107 | cursor: default; 108 | display: block; 109 | } 110 | 111 | .picViewer{ 112 | z-index: 5; 113 | left: 10px; 114 | top: 10px; 115 | background-color: #bbffbb; 116 | padding: 3px; 117 | border: 1px double #00ff00; 118 | cursor: default; 119 | } 120 | 121 | .closeWindowBtn { 122 | float: right; 123 | margin-top:0px; 124 | margin-left:0px; 125 | margin-right:0px; 126 | margin-bottom:0px; 127 | border: 0px; 128 | padding: 1px 1px; 129 | background-repeat: no-repeat; 130 | cursor: default; 131 | background-image: url("chrome://bbsfox/skin/window_icon/close.png"); 132 | } 133 | 134 | .closeWindowBtn:hover { 135 | background-image: url("chrome://bbsfox/skin/window_icon/close-h.png"); 136 | } 137 | 138 | .closeWindowBtn:active { 139 | background-image: url("chrome://bbsfox/skin/window_icon/close-a.png"); 140 | } 141 | 142 | #PicturePreviewInfo{ 143 | color : #fff; 144 | text-shadow: 0 0 1px #fff,0 0 2px #fff,0 0 3px #fff,0 0 4px #0000ff,0 0 7px #0000ff,0 0 8px #0000ff,0 0 10px #0000ff,0 0 15px #0000ff; 145 | } 146 | 147 | #PictureWindow { 148 | left: 10px; 149 | top: 10px; 150 | z-index: 3; 151 | background-color: #ffffff; 152 | padding: 3px; 153 | border:0px; 154 | border-radius:6px; 155 | cursor: default; 156 | } 157 | 158 | .floatWindowClientArea { 159 | background-color: #ffffff; 160 | margin-top:22px; 161 | margin-left:3px; 162 | margin-right:3px; 163 | margin-bottom:3px; 164 | border: 1px solid #000000; 165 | cursor: default; 166 | } 167 | 168 | .floatWindowClientArea4 { /*picturePreview*/ 169 | background-color: #ffffff; 170 | margin: 0px; 171 | padding: 0px; 172 | border: 0px solid #000000; 173 | cursor: default; 174 | position: relative; 175 | } 176 | 177 | .floatWindowClientArea5 { 178 | background-color: #bbffbb; 179 | margin: 0px; 180 | padding: 0px; 181 | border: 0px solid #000000; 182 | cursor: default; 183 | } 184 | 185 | .picturePreview {background:white; color:black; padding:0px;margin: 0px;} 186 | 187 | .sBtn{ 188 | font-family: "MingLiU, Osaka-Mono, monospace"; 189 | font-size: 12px; 190 | cursor: default; 191 | min-width: 26px; 192 | margin-top:2px; 193 | margin-left:2px; 194 | margin-right:2px; 195 | margin-bottom:2px; 196 | } 197 | 198 | .colorBtn{ 199 | border-radius: 0px; 200 | border-color: #FFF; 201 | border-width: 2px; 202 | border-style: solid; 203 | width: 26px; 204 | height: 22px; 205 | } 206 | 207 | .colorPreview{ 208 | width: 30px; 209 | height: 30px; 210 | color: #FFF; 211 | background: #000; 212 | margin: 2px 5px; 213 | padding: 5px; 214 | } 215 | -------------------------------------------------------------------------------- /chrome/content/prefs.json: -------------------------------------------------------------------------------- 1 | { 2 | "sitePrefs": { 3 | "ask": false, 4 | "AutoDbcsDetection": false, 5 | "HAlignCenter": true, 6 | "VAlignCenter": true, 7 | "LineFeed": true, 8 | "LoadUrlInBG": false, 9 | "DetectLink": true, 10 | "UseMouseBrowsing": false, 11 | "MouseBrowsingHighlight": true, 12 | "MouseBrowsingHandPointer": true, 13 | "UseMouseBrowsingEx": true, 14 | "MouseBrowseSendEnter": false, 15 | "EPWhenDropLink": false, 16 | "HokeyForCopy": true, 17 | "HokeyForPaste": true, 18 | "HokeyForSelectAll": true, 19 | "HokeyForMouseBrowsing": false, 20 | "HokeyForDownloadPost": false, 21 | "EnableHighlightWords": false, 22 | "DeleteSpaceWhenCopy": true, 23 | "MouseBrowseMenu": false, 24 | "OpenAllLinkMenu": false, 25 | "CopyHtmlMenu": false, 26 | "ScreenKeyboardMenu": false, 27 | "KeyWordTrackMenu": false, 28 | "HideBookMarkLinkMenu": true, 29 | "HideSendLinkMenu": true, 30 | "HideSendPageMenu": true, 31 | "DelayPasteMenu": false, 32 | "HideViewSourceMenu": true, 33 | "HideViewInfoMenu": true, 34 | "DownloadPostMenu": false, 35 | "FileIoMenu": false, 36 | "PreviewPictureMenu": false, 37 | "NotifyWhenBackground": true, 38 | "NotifyBySound": false, 39 | "NotifyByMessage": true, 40 | "HideInputBuffer": false, 41 | "DropToPaste": false, 42 | "EnablePicturePreview": false, 43 | "CtrlPicturePreview": false, 44 | "PicturePreviewInfo": false, 45 | "ClearCopiedSel": false, 46 | "HokeyForBgDisplay": false, 47 | "SwitchBgDisplayMenu": false, 48 | "Hokey2ForPaste": false, 49 | "DisplayBorder": false, 50 | "EasyReadingMenu": false, 51 | "HokeyForEasyReading": false, 52 | "EasyReadingWithImg": false, 53 | "EasyReadingWithVideo": false, 54 | "PushThreadMenu": false, 55 | "NotifyShowContent": false, 56 | "PreventNewTongWenAutoConv": true, 57 | "DownloadFullPost": true, 58 | "HideInspectMenu": true, 59 | "NotifyBlockByTime": true, 60 | "PicturePreviewClose": false, 61 | "OpenThreadUrlMenu": false, 62 | "HokeyOpenThreadUrl": false, 63 | "KeepFontAspectRatio": true, 64 | "KeyWordTrackCaseSensitive": true, 65 | "HokeyChangeColorTable": false, 66 | "ChangeColorTableMenu": false, 67 | "FixUnicodeDisplay": false, 68 | "HokeyForAnsiCopy": true, 69 | "AnsiCopyMenu": true, 70 | "EnableBlacklist": false, 71 | "BlacklistMenu": false, 72 | "AnsiColorToolMenu": false, 73 | "EnableNotification": true, 74 | 75 | "ScreenType": 0, 76 | "HighlightBG": 2, 77 | "bbsbox.width": 960, 78 | "bbsbox.height": 576, 79 | "EnterType": 0, 80 | "FontSize": 16, 81 | "AntiIdle.seconds": 0, 82 | "FGBGcolor": 0, 83 | "LineWrap": 0, 84 | "ReconnectTime": 20, 85 | "HotkeyCtrlW": 1, 86 | "HotkeyCtrlB": 1, 87 | "HotkeyCtrlL": 1, 88 | "HotkeyCtrlT": 1, 89 | "ScreenKeyboardAlpha": 15, 90 | "InputBufferSizeType": 1, 91 | "DefineInputBufferSize": 12, 92 | "PicturePreviewHeight": 150, 93 | "DownloadLineDelay": 300, 94 | "HotkeyDownloadType": 0, 95 | "MiddleButtonFunction": 0, 96 | "BackgroundType": 0, 97 | "BackgroundBrightness": 50, 98 | "MouseWheelFunc1": 0, 99 | "MouseWheelFunc2": 0, 100 | "MouseWheelFunc3": 0, 101 | "BorderColor": 15, 102 | "PushThreadLineLength": 54, 103 | "DisplayDelay": 10, 104 | "ClickAlertAction": 1, 105 | "ReconnectDelay": 2, 106 | "ReconnectCount": 200, 107 | "ReconnectType": 0, 108 | "SshProxyType": 0, 109 | "SshProxyPort": 22, 110 | "SshLoginType": 0, 111 | "TelnetProxyType": 0, 112 | "TelnetProxyPort": 23, 113 | "MouseBrowsingHlTime": 0, 114 | "bbsbox.col": 80, 115 | "bbsbox.row": 24, 116 | "AidAction": 0, 117 | "BlacklistAlpha": 80, 118 | 119 | "AntiIdle.string": "^[[A^[[B", 120 | "Escape.string": "^U", 121 | "TermType": "VT100", 122 | "Charset": "locale", 123 | "FontFace.string": "MingLiU,Osaka-Mono,monospace", 124 | "FontFaceEn.string": "", 125 | "PreLoginPrompt": "", 126 | "LoginPrompt": "", 127 | "PasswdPrompt": "", 128 | "PreLogin": "", 129 | "PostLogin": "", 130 | "BackgroundImageMD5": "", 131 | "AlertReplyString": "", 132 | "SshProxyHost": "", 133 | "TelnetProxyHost": "", 134 | "BlacklistedUserIds": "", 135 | "BBSColor01": "#000000", 136 | "BBSColor02": "#800000", 137 | "BBSColor03": "#008000", 138 | "BBSColor04": "#808000", 139 | "BBSColor05": "#000080", 140 | "BBSColor06": "#800080", 141 | "BBSColor07": "#008080", 142 | "BBSColor08": "#c0c0c0", 143 | "BBSColor09": "#808080", 144 | "BBSColor10": "#ff0000", 145 | "BBSColor11": "#00ff00", 146 | "BBSColor12": "#ffff00", 147 | "BBSColor13": "#0000ff", 148 | "BBSColor14": "#ff00ff", 149 | "BBSColor15": "#00ffff", 150 | "BBSColor16": "#ffffff", 151 | "HighlightWords": "" 152 | }, 153 | 154 | "globalPrefs": { 155 | "bbsfox2.DevVersion": false, 156 | "bbsfox1.SshSupport": false, 157 | "bbsfox2.DynamicRenderTest": false, 158 | "bbsfox1.Update": false, 159 | "bbsfox2.locale": "chrome://bbsfox/locale/bbsfox.properties" 160 | } 161 | } -------------------------------------------------------------------------------- /chrome/content/paramikojs/agent.js: -------------------------------------------------------------------------------- 1 | /* 2 | Client interface for using private keys from an SSH agent running on the 3 | local machine. If an SSH agent is running, this class can be used to 4 | connect to it and retreive L{PKey} objects which can be used when 5 | attempting to authenticate to remote SSH servers. 6 | 7 | Because the SSH agent protocol uses environment variables and unix-domain 8 | sockets, this probably doesn't work on Windows. It does work on most 9 | posix platforms though (Linux and MacOS X, for example). 10 | */ 11 | paramikojs.Agent = function () { 12 | /* 13 | Open a session with the local machine's SSH agent, if one is running. 14 | If no agent is running, initialization will succeed, but L{get_keys} 15 | will return an empty tuple. 16 | 17 | @raise SSHException: if an SSH agent is found, but speaks an 18 | incompatible protocol 19 | */ 20 | 21 | this.conn = null; 22 | this.keys = []; 23 | 24 | var userEnvironment = Cc["@mozilla.org/process/environment;1"].getService(Ci.nsIEnvironment); 25 | if (userEnvironment.exists('SSH_AUTH_SOCK') && sys.platform != 'win32') { 26 | var conn = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM); // todo, fixme, doesn't work right now :-/ 27 | var auth_sock = userEnvironment.get('SSH_AUTH_SOCK'); 28 | try { 29 | conn.connect(auth_sock); 30 | } catch(ex) { 31 | // probably a dangling env var: the ssh agent is gone 32 | return; 33 | } 34 | this.conn = conn; 35 | } else if (sys.platform == 'win32') { 36 | var win_pageant = new paramikojs.win_pageant(); 37 | if (win_pageant.can_talk_to_agent()) { 38 | this.conn = win_pageant.PageantConnection(); 39 | } else { 40 | return; 41 | } 42 | } else { 43 | // no agent support 44 | return; 45 | } 46 | 47 | var msg = this._send_message(String.fromCharCode(paramikojs.Agent.SSH2_AGENTC_REQUEST_IDENTITIES)); 48 | if (msg.ptype != paramikojs.Agent.SSH2_AGENT_IDENTITIES_ANSWER) { 49 | throw new paramikojs.ssh_exception.SSHException('could not get keys from ssh-agent'); 50 | } 51 | 52 | var max = msg.result.get_int(); 53 | for (var x = 0; x < max; ++x) { 54 | this.keys.push(new paramikojs.AgentKey(this, msg.result.get_string())); 55 | msg.result.get_string(); 56 | } 57 | } 58 | 59 | paramikojs.Agent.SSH2_AGENTC_REQUEST_IDENTITIES = 11; 60 | paramikojs.Agent.SSH2_AGENT_IDENTITIES_ANSWER = 12; 61 | paramikojs.Agent.SSH2_AGENTC_SIGN_REQUEST = 13; 62 | paramikojs.Agent.SSH2_AGENT_SIGN_RESPONSE = 14; 63 | 64 | paramikojs.Agent.prototype = { 65 | 66 | /* 67 | Close the SSH agent connection. 68 | */ 69 | close : function() { 70 | if (this.conn) { 71 | this.conn.close(); 72 | } 73 | this.conn = null; 74 | this.keys = []; 75 | }, 76 | 77 | /* 78 | Return the list of keys available through the SSH agent, if any. If 79 | no SSH agent was running (or it couldn't be contacted), an empty list 80 | will be returned. 81 | 82 | @return: a list of keys available on the SSH agent 83 | @rtype: tuple of L{AgentKey} 84 | */ 85 | get_keys : function() { 86 | return this.keys; 87 | }, 88 | 89 | _send_message : function(msg) { 90 | var msg = msg.toString(); 91 | this.conn.send(struct.pack('>I', msg.length) + msg); // TODO, fixme 92 | var l = this._read_all(4); 93 | msg = new paramikojs.Message(this._read_all(struct.unpack('>I', l)[0])); 94 | return { 'ptype': msg.get_byte().charCodeAt(0), 'result': msg }; 95 | }, 96 | 97 | _read_all : function(wanted) { 98 | var result = this.conn.recv(wanted); // TODO, fixme 99 | while (result.length < wanted) { 100 | if (result.length == 0) { 101 | throw new paramikojs.ssh_exception.SSHException('lost ssh-agent'); 102 | } 103 | var extra = this.conn.recv(wanted - result.length); 104 | if (extra.length == 0) { 105 | throw new paramikojs.ssh_exception.SSHException('lost ssh-agent'); 106 | } 107 | result += extra; 108 | } 109 | return result; 110 | } 111 | }; 112 | 113 | 114 | 115 | /* 116 | Private key held in a local SSH agent. This type of key can be used for 117 | authenticating to a remote server (signing). Most other key operations 118 | work as expected. 119 | */ 120 | paramikojs.AgentKey = function(agent, blob) { 121 | inherit(this, new paramikojs.PKey()); 122 | 123 | this.agent = agent; 124 | this.blob = blob; 125 | this.name = new paramikojs.Message(blob).get_string(); 126 | } 127 | 128 | paramikojs.AgentKey.prototype = { 129 | toString : function() { 130 | return this.blob; 131 | }, 132 | 133 | get_name : function() { 134 | return this.name; 135 | }, 136 | 137 | sign_ssh_data : function(rng, data, callback) { 138 | var msg = new paramikojs.Message(); 139 | msg.add_byte(String.fromCharCode(paramikojs.Agent.SSH2_AGENTC_SIGN_REQUEST)); 140 | msg.add_string(this.blob); 141 | msg.add_string(data); 142 | msg.add_int(0); 143 | var msg = this.agent._send_message(msg); 144 | if (msg.ptype != paramikojs.Agent.SSH2_AGENT_SIGN_RESPONSE) { 145 | throw new paramikojs.ssh_exception.SSHException('key cannot be used for signing'); 146 | } 147 | callback(msg.result.get_string()); 148 | } 149 | }; 150 | -------------------------------------------------------------------------------- /chrome/content/asciiTable.js: -------------------------------------------------------------------------------- 1 | asciiTable = new Object(); 2 | var a = asciiTable; 3 | a.h00='\x00'; 4 | a.h01='\x01'; 5 | a.h02='\x02'; 6 | a.h03='\x03'; 7 | a.h04='\x04'; 8 | a.h05='\x05'; 9 | a.h06='\x06'; 10 | a.h07='\x07'; 11 | a.h08='\x08'; 12 | a.h09='\x09'; 13 | a.h0a='\x0a'; 14 | a.h0b='\x0b'; 15 | a.h0c='\x0c'; 16 | a.h0d='\x0d'; 17 | a.h0e='\x0e'; 18 | a.h0f='\x0f'; 19 | 20 | a.h10='\x10'; 21 | a.h11='\x11'; 22 | a.h12='\x12'; 23 | a.h13='\x13'; 24 | a.h14='\x14'; 25 | a.h15='\x15'; 26 | a.h16='\x16'; 27 | a.h17='\x17'; 28 | a.h18='\x18'; 29 | a.h19='\x19'; 30 | a.h1a='\x1a'; 31 | a.h1b='\x1b'; 32 | a.h1c='\x1c'; 33 | a.h1d='\x1d'; 34 | a.h1e='\x1e'; 35 | a.h1f='\x1f'; 36 | 37 | a.h20='\x20'; 38 | a.h21='\x21'; 39 | a.h22='\x22'; 40 | a.h23='\x23'; 41 | a.h24='\x24'; 42 | a.h25='\x25'; 43 | a.h26='\x26'; 44 | a.h27='\x27'; 45 | a.h28='\x28'; 46 | a.h29='\x29'; 47 | a.h2a='\x2a'; 48 | a.h2b='\x2b'; 49 | a.h2c='\x2c'; 50 | a.h2d='\x2d'; 51 | a.h2e='\x2e'; 52 | a.h2f='\x2f'; 53 | 54 | a.h30='\x30'; 55 | a.h31='\x31'; 56 | a.h32='\x32'; 57 | a.h33='\x33'; 58 | a.h34='\x34'; 59 | a.h35='\x35'; 60 | a.h36='\x36'; 61 | a.h37='\x37'; 62 | a.h38='\x38'; 63 | a.h39='\x39'; 64 | a.h3a='\x3a'; 65 | a.h3b='\x3b'; 66 | a.h3c='\x3c'; 67 | a.h3d='\x3d'; 68 | a.h3e='\x3e'; 69 | a.h3f='\x3f'; 70 | 71 | a.h40='\x40'; 72 | a.h41='\x41'; 73 | a.h42='\x42'; 74 | a.h43='\x43'; 75 | a.h44='\x44'; 76 | a.h45='\x45'; 77 | a.h46='\x46'; 78 | a.h47='\x47'; 79 | a.h48='\x48'; 80 | a.h49='\x49'; 81 | a.h4a='\x4a'; 82 | a.h4b='\x4b'; 83 | a.h4c='\x4c'; 84 | a.h4d='\x4d'; 85 | a.h4e='\x4e'; 86 | a.h4f='\x4f'; 87 | 88 | a.h50='\x50'; 89 | a.h51='\x51'; 90 | a.h52='\x52'; 91 | a.h53='\x53'; 92 | a.h54='\x54'; 93 | a.h55='\x55'; 94 | a.h56='\x56'; 95 | a.h57='\x57'; 96 | a.h58='\x58'; 97 | a.h59='\x59'; 98 | a.h5a='\x5a'; 99 | a.h5b='\x5b'; 100 | a.h5c='\x5c'; 101 | a.h5d='\x5d'; 102 | a.h5e='\x5e'; 103 | a.h5f='\x5f'; 104 | 105 | a.h60='\x60'; 106 | a.h61='\x61'; 107 | a.h62='\x62'; 108 | a.h63='\x63'; 109 | a.h64='\x64'; 110 | a.h65='\x65'; 111 | a.h66='\x66'; 112 | a.h67='\x67'; 113 | a.h68='\x68'; 114 | a.h69='\x69'; 115 | a.h6a='\x6a'; 116 | a.h6b='\x6b'; 117 | a.h6c='\x6c'; 118 | a.h6d='\x6d'; 119 | a.h6e='\x6e'; 120 | a.h6f='\x6f'; 121 | 122 | a.h70='\x70'; 123 | a.h71='\x71'; 124 | a.h72='\x72'; 125 | a.h73='\x73'; 126 | a.h74='\x74'; 127 | a.h75='\x75'; 128 | a.h76='\x76'; 129 | a.h77='\x77'; 130 | a.h78='\x78'; 131 | a.h79='\x79'; 132 | a.h7a='\x7a'; 133 | a.h7b='\x7b'; 134 | a.h7c='\x7c'; 135 | a.h7d='\x7d'; 136 | a.h7e='\x7e'; 137 | a.h7f='\x7f'; 138 | 139 | a.h80='\x80'; 140 | a.h81='\x81'; 141 | a.h82='\x82'; 142 | a.h83='\x83'; 143 | a.h84='\x84'; 144 | a.h85='\x85'; 145 | a.h86='\x86'; 146 | a.h87='\x87'; 147 | a.h88='\x88'; 148 | a.h89='\x89'; 149 | a.h8a='\x8a'; 150 | a.h8b='\x8b'; 151 | a.h8c='\x8c'; 152 | a.h8d='\x8d'; 153 | a.h8e='\x8e'; 154 | a.h8f='\x8f'; 155 | 156 | a.h90='\x90'; 157 | a.h91='\x91'; 158 | a.h92='\x92'; 159 | a.h93='\x93'; 160 | a.h94='\x94'; 161 | a.h95='\x95'; 162 | a.h96='\x96'; 163 | a.h97='\x97'; 164 | a.h98='\x98'; 165 | a.h99='\x99'; 166 | a.h9a='\x9a'; 167 | a.h9b='\x9b'; 168 | a.h9c='\x9c'; 169 | a.h9d='\x9d'; 170 | a.h9e='\x9e'; 171 | a.h9f='\x9f'; 172 | 173 | a.ha0='\xa0'; 174 | a.ha1='\xa1'; 175 | a.ha2='\xa2'; 176 | a.ha3='\xa3'; 177 | a.ha4='\xa4'; 178 | a.ha5='\xa5'; 179 | a.ha6='\xa6'; 180 | a.ha7='\xa7'; 181 | a.ha8='\xa8'; 182 | a.ha9='\xa9'; 183 | a.haa='\xaa'; 184 | a.hab='\xab'; 185 | a.hac='\xac'; 186 | a.had='\xad'; 187 | a.hae='\xae'; 188 | a.haf='\xaf'; 189 | 190 | a.hb0='\xb0'; 191 | a.hb1='\xb1'; 192 | a.hb2='\xb2'; 193 | a.hb3='\xb3'; 194 | a.hb4='\xb4'; 195 | a.hb5='\xb5'; 196 | a.hb6='\xb6'; 197 | a.hb7='\xb7'; 198 | a.hb8='\xb8'; 199 | a.hb9='\xb9'; 200 | a.hba='\xba'; 201 | a.hbb='\xbb'; 202 | a.hbc='\xbc'; 203 | a.hbd='\xbd'; 204 | a.hbe='\xbe'; 205 | a.hbf='\xbf'; 206 | 207 | a.hc0='\xc0'; 208 | a.hc1='\xc1'; 209 | a.hc2='\xc2'; 210 | a.hc3='\xc3'; 211 | a.hc4='\xc4'; 212 | a.hc5='\xc5'; 213 | a.hc6='\xc6'; 214 | a.hc7='\xc7'; 215 | a.hc8='\xc8'; 216 | a.hc9='\xc9'; 217 | a.hca='\xca'; 218 | a.hcb='\xcb'; 219 | a.hcc='\xcc'; 220 | a.hcd='\xcd'; 221 | a.hce='\xce'; 222 | a.hcf='\xcf'; 223 | 224 | a.hd0='\xd0'; 225 | a.hd1='\xd1'; 226 | a.hd2='\xd2'; 227 | a.hd3='\xd3'; 228 | a.hd4='\xd4'; 229 | a.hd5='\xd5'; 230 | a.hd6='\xd6'; 231 | a.hd7='\xd7'; 232 | a.hd8='\xd8'; 233 | a.hd9='\xd9'; 234 | a.hda='\xda'; 235 | a.hdb='\xdb'; 236 | a.hdc='\xdc'; 237 | a.hdd='\xdd'; 238 | a.hde='\xde'; 239 | a.hdf='\xdf'; 240 | 241 | a.he0='\xe0'; 242 | a.he1='\xe1'; 243 | a.he2='\xe2'; 244 | a.he3='\xe3'; 245 | a.he4='\xe4'; 246 | a.he5='\xe5'; 247 | a.he6='\xe6'; 248 | a.he7='\xe7'; 249 | a.he8='\xe8'; 250 | a.he9='\xe9'; 251 | a.hea='\xea'; 252 | a.heb='\xeb'; 253 | a.hec='\xec'; 254 | a.hed='\xed'; 255 | a.hee='\xee'; 256 | a.hef='\xef'; 257 | 258 | a.hf0='\xf0'; 259 | a.hf1='\xf1'; 260 | a.hf2='\xf2'; 261 | a.hf3='\xf3'; 262 | a.hf4='\xf4'; 263 | a.hf5='\xf5'; 264 | a.hf6='\xf6'; 265 | a.hf7='\xf7'; 266 | a.hf8='\xf8'; 267 | a.hf9='\xf9'; 268 | a.hfa='\xfa'; 269 | a.hfb='\xfb'; 270 | a.hfc='\xfc'; 271 | a.hfd='\xfd'; 272 | a.hfe='\xfe'; 273 | a.hff='\xff'; 274 | -------------------------------------------------------------------------------- /chrome/content/picLoader/picLoader_ppt.js: -------------------------------------------------------------------------------- 1 | var EXPORTED_SYMBOLS = ["BBSPPTPicLoader"]; 2 | 3 | function BBSPPTPicLoader(listener, dp, xhr, htmlParser) { 4 | this.listener = listener; 5 | this.dp = dp;//new DOMParser(); 6 | this.Xhr = xhr; 7 | this.htmlParser = htmlParser; 8 | } 9 | 10 | BBSPPTPicLoader.prototype={ 11 | lastUrl: '', 12 | lastSuccessUrl: '', 13 | lastSuccessPic: '', 14 | regEx: /^http:\/\/ppt\.cc\/(.{4,6})$/i, 15 | codeBlockList: [], 16 | codeQueue: [], 17 | codePicture: [], 18 | maxBlock: 150, 19 | maxPicture: 100, 20 | pptUrl: 'http://ppt.cc/', 21 | pptUrlLength: 14, 22 | 23 | query: function(url, callback){ 24 | if(this.regEx.test(url)) 25 | { 26 | if(callback) { 27 | var xmlhttp = new this.Xhr(false, {UniUrl: url, LoaderAction: "query", callback: callback}, this.onPageResponse.bind(this)); 28 | xmlhttp.open(url); 29 | } 30 | return true; 31 | } 32 | return false; 33 | }, 34 | 35 | show: function(url, owner){ 36 | if(this.regEx.test(url)) 37 | { 38 | //var _this = this; 39 | var xmlhttp = new this.Xhr(false, {UniUrl: url, LoaderAction: "show", owner: owner}, this.onPageResponse.bind(this)); 40 | xmlhttp.open(url); 41 | return true; 42 | } 43 | return false; 44 | }, 45 | 46 | load: function(url){ 47 | //step 1: test url, must be http://ppt.cc/ 48 | //step 2: try to fetch web page. 49 | //step 3: check if it include 'plurkimg', get it's value. (http://ppt.cc/gFtO@.jpg) 50 | //step 4: set picture url to real image url (http://ppt.cc/gFtO@.jpg) 51 | //step 5: keep this result to reuse. 52 | if(this.listener && this.regEx.test(url)) 53 | { 54 | //we need block some url at here! 55 | var shortCode = url.substr(this.pptUrlLength); 56 | this.listener.cb_locate(); 57 | if(this.lastSuccessUrl==url) 58 | { 59 | this.listener.cb_load(this.lastSuccessUrl, this.lastSuccessPic); 60 | return true; 61 | } 62 | for(var i in this.codeBlockList) 63 | { 64 | if(this.codeBlockList[i] == shortCode) 65 | return false; 66 | } 67 | for(var i in this.codeQueue) 68 | { 69 | if(this.codeQueue[i] == shortCode) 70 | return false; 71 | } 72 | for(var i in this.codePicture) 73 | { 74 | if(this.codePicture[i].url == shortCode) 75 | { 76 | this.listener.cb_load(this.pptUrl + this.codePicture[i].url, this.pptUrl + this.codePicture[i].pic); 77 | return true; 78 | } 79 | } 80 | if(this.lastUrl!=url) 81 | { 82 | this.codeQueue.push(shortCode); 83 | this.lastUrl = url; 84 | var xmlhttp = new this.Xhr(false, {UniUrl: url, LoaderAction: "load", owner: null}, this.onPageResponse.bind(this)); 85 | xmlhttp.open(url); 86 | } 87 | return true; 88 | } 89 | return false; 90 | }, 91 | 92 | onPageResponse: function(info) { 93 | var shortCode = info.UniUrl.substr(this.pptUrlLength); 94 | if(info.LoaderAction=='load') { 95 | this.removeFromQueue(shortCode); 96 | } 97 | if(info.status == 200) 98 | { 99 | var doc = this.htmlParser(info.responseText); 100 | var plurkimg = null; 101 | var inputs = doc.getElementsByTagName('input'); 102 | for(var i=0;ithis.maxPicture) 117 | this.codePicture.shift(); 118 | if(info.UniUrl == this.lastUrl) 119 | { 120 | this.lastSuccessUrl = info.UniUrl; 121 | this.lastSuccessPic = plurkimg.value; 122 | this.listener.cb_load(this.lastSuccessUrl, this.lastSuccessPic); 123 | } 124 | } 125 | else if(info.LoaderAction=='show') 126 | { 127 | this.listener.cb_show(info.owner, plurkimg.value); 128 | } 129 | else if(info.LoaderAction=='query') 130 | { 131 | info.callback(plurkimg.value); 132 | } 133 | } 134 | else 135 | { 136 | this.codeBlockList.push(shortCode); 137 | if(this.codeBlockList.length>this.maxBlock) 138 | this.codeBlockList.shift(); 139 | } 140 | } 141 | else 142 | { 143 | this.codeBlockList.push(shortCode); 144 | if(this.codeBlockList.length>this.maxBlock) 145 | this.codeBlockList.shift(); 146 | if(info.LoaderAction=='query') 147 | info.callback(''); 148 | } 149 | }, 150 | 151 | removeFromQueue: function (code){ 152 | var temp = []; 153 | while(this.codeQueue.length){ 154 | var u = this.codeQueue.shift(); 155 | if(u != code) 156 | temp.push(u); 157 | } 158 | while(temp.length){ 159 | this.codeQueue.push(temp.shift()); 160 | } 161 | } 162 | }; 163 | -------------------------------------------------------------------------------- /chrome/content/picLoader/picLoader_imgur.js: -------------------------------------------------------------------------------- 1 | var EXPORTED_SYMBOLS = ["BBSImgurPicLoader"]; 2 | 3 | function BBSImgurPicLoader(listener, dp, xhr, htmlParser) { 4 | this.listener = listener; 5 | this.dp = dp;//new DOMParser(); 6 | this.Xhr = xhr; 7 | this.htmlParser = htmlParser; 8 | } 9 | 10 | BBSImgurPicLoader.prototype={ 11 | lastUrl: '', 12 | lastSuccessUrl: '', 13 | lastSuccessPic: '', 14 | regEx: /^https?:\/\/(?:m\.)?imgur\.com\/(\w{5,8})(?:\?tags)?/i, 15 | codeBlockList: [], 16 | codeQueue: [], 17 | codePicture: [], 18 | maxBlock: 150, 19 | maxPicture: 100, 20 | //imgurUrl: 'http://imgur.com/', 21 | 22 | query: function(url, callback){ 23 | if(this.regEx.test(url)) 24 | { 25 | if(callback) { 26 | var xmlhttp = new this.Xhr(false, {UniUrl: url, LoaderAction: "query", callback: callback}, this.onPageResponse.bind(this)); 27 | xmlhttp.open(url); 28 | } 29 | return true; 30 | } 31 | return false; 32 | }, 33 | 34 | show: function(url, owner){ 35 | if(this.regEx.test(url)) 36 | { 37 | var xmlhttp = new this.Xhr(false, {UniUrl: url, LoaderAction: "show", owner: owner}, this.onPageResponse.bind(this)); 38 | xmlhttp.open(url); 39 | return true; 40 | } 41 | return false; 42 | }, 43 | 44 | load: function(url){ 45 | //step 1: test url, must be http://imgur.com/ or https://imgur.com/ 46 | //step 2: try to fetch web page. 47 | //step 3: check if it include 'mainimg', get it's src. (//i.imgur.com/aIsFSPa.jpg) 48 | //step 4: set picture url to real image url (http://i.imgur.com/aIsFSPa.jpg) 49 | //step 5: keep this result to reuse. 50 | if(this.listener && this.regEx.test(url)) 51 | { 52 | //we need block some url at here! 53 | var strArr = url.split(this.regEx); 54 | if(strArr.length<3) 55 | return false; 56 | //var shortCode = strArr[3]; 57 | 58 | this.listener.cb_locate(); 59 | if(this.lastSuccessUrl==url) 60 | { 61 | this.listener.cb_load(this.lastSuccessUrl, this.lastSuccessPic); 62 | return true; 63 | } 64 | for(var i in this.codeBlockList) 65 | { 66 | if(this.codeBlockList[i] == url) 67 | return false; 68 | } 69 | for(var i in this.codeQueue) 70 | { 71 | if(this.codeQueue[i] == url) 72 | return false; 73 | } 74 | for(var i in this.codePicture) 75 | { 76 | if(this.codePicture[i].url == url) 77 | { 78 | this.listener.cb_load(this.codePicture[i].url, this.codePicture[i].pic); 79 | return true; 80 | } 81 | } 82 | if(this.lastUrl!=url) 83 | { 84 | this.codeQueue.push(url); 85 | this.lastUrl = url; 86 | var xmlhttp = new this.Xhr(false, {UniUrl: url, LoaderAction: "load", owner: null}, this.onPageResponse.bind(this)); 87 | xmlhttp.open(url); 88 | } 89 | return true; 90 | } 91 | return false; 92 | }, 93 | 94 | onPageResponse: function(info) { 95 | var strArr = this.regEx.exec(info.UniUrl); 96 | var shortCode = strArr[1]; 97 | if(info.LoaderAction=='load') { 98 | this.removeFromQueue(info.UniUrl); 99 | } 100 | if(info.status == 200) 101 | { 102 | var doc = this.htmlParser(info.responseText); 103 | var mainimg = null; 104 | var imgs = doc.getElementsByTagName('img'); 105 | for(var i=0;ithis.maxPicture) 120 | this.codePicture.shift(); 121 | if(info.UniUrl == this.lastUrl) 122 | { 123 | this.lastSuccessUrl = info.UniUrl; 124 | this.lastSuccessPic = picCode; 125 | this.listener.cb_load(this.lastSuccessUrl, this.lastSuccessPic); 126 | } 127 | } 128 | else if(info.LoaderAction=='show') 129 | { 130 | this.listener.cb_show(info.owner, 'https:' + mainimg.src); 131 | } 132 | else if(info.LoaderAction=='query') 133 | { 134 | info.callback('https:' + mainimg.src); 135 | } 136 | 137 | } 138 | else 139 | { 140 | this.codeBlockList.push(info.UniUrl); 141 | if(this.codeBlockList.length>this.maxBlock) 142 | this.codeBlockList.shift(); 143 | if(info.LoaderAction=='query') 144 | info.callback(''); 145 | } 146 | } 147 | else 148 | { 149 | this.codeBlockList.push(info.UniUrl); 150 | if(this.codeBlockList.length>this.maxBlock) 151 | this.codeBlockList.shift(); 152 | } 153 | }, 154 | 155 | removeFromQueue: function (code){ 156 | 157 | var temp = []; 158 | while(this.codeQueue.length){ 159 | var u = this.codeQueue.shift(); 160 | if(u != code) 161 | temp.push(u); 162 | } 163 | while(temp.length){ 164 | this.codeQueue.push(temp.shift()); 165 | } 166 | } 167 | }; 168 | -------------------------------------------------------------------------------- /chrome/content/paramikojs/kex_gex.js: -------------------------------------------------------------------------------- 1 | /* 2 | Variant on L{KexGroup1 } where the prime "p" and 3 | generator "g" are provided by the server. A bit more work is required on the 4 | client side, and a B{lot} more on the server side. 5 | */ 6 | 7 | paramikojs.KexGex = function(transport) { 8 | this.transport = transport; 9 | this.p = null; 10 | this.q = null; 11 | this.g = null; 12 | this.x = null; 13 | this.e = null; 14 | this.f = null; 15 | this.old_style = false; 16 | } 17 | 18 | 19 | paramikojs.KexGex._MSG_KEXDH_GEX_REQUEST_OLD = 30; 20 | paramikojs.KexGex._MSG_KEXDH_GEX_GROUP = 31; 21 | paramikojs.KexGex._MSG_KEXDH_GEX_INIT = 32; 22 | paramikojs.KexGex._MSG_KEXDH_GEX_REPLY = 33; 23 | paramikojs.KexGex._MSG_KEXDH_GEX_REQUEST = 34; 24 | 25 | paramikojs.KexGex.prototype = { 26 | name : 'diffie-hellman-group-exchange-sha1', 27 | min_bits : 1024, 28 | max_bits : 8192, 29 | preferred_bits : 2048, 30 | 31 | start_kex : function(_test_old_style) { 32 | if (this.transport.server_mode) { 33 | this.transport._expect_packet(paramikojs.KexGex._MSG_KEXDH_GEX_REQUEST, paramikojs.KexGex._MSG_KEXDH_GEX_REQUEST_OLD); 34 | return; 35 | } 36 | // request a bit range: we accept (min_bits) to (max_bits), but prefer 37 | // (preferred_bits). according to the spec, we shouldn't pull the 38 | // minimum up above 1024. 39 | var m = new paramikojs.Message(); 40 | if (_test_old_style) { 41 | // only used for unit tests: we shouldn't ever send this 42 | m.add_byte(String.fromCharCode(paramikojs.KexGex._MSG_KEXDH_GEX_REQUEST_OLD)); 43 | m.add_int(this.preferred_bits); 44 | this.old_style = true; 45 | } else { 46 | m.add_byte(String.fromCharCode(paramikojs.KexGex._MSG_KEXDH_GEX_REQUEST)); 47 | m.add_int(this.min_bits); 48 | m.add_int(this.preferred_bits); 49 | m.add_int(this.max_bits); 50 | } 51 | this.transport._send_message(m); 52 | this.transport._expect_packet(paramikojs.KexGex._MSG_KEXDH_GEX_GROUP); 53 | }, 54 | 55 | parse_next : function(ptype, m) { 56 | if (ptype == paramikojs.KexGex._MSG_KEXDH_GEX_GROUP) { 57 | return this._parse_kexdh_gex_group(m); 58 | } else if (ptype == paramikojs.KexGex._MSG_KEXDH_GEX_REPLY) { 59 | return this._parse_kexdh_gex_reply(m); 60 | } 61 | throw new paramikojs.ssh_exception.SSHException('KexGex asked to handle packet type ' + ptype); 62 | }, 63 | 64 | 65 | // internals... 66 | 67 | _generate_x : function() { 68 | // generate an "x" (1 < x < (p-1)/2). 69 | var one = BigInteger.ONE; 70 | var q = this.p.subtract(one); 71 | q = q.divide(new BigInteger("2", 10)); 72 | var qnorm = paramikojs.util.deflate_long(q, 0); 73 | var qhbyte = qnorm[0].charCodeAt(0); 74 | var bytes = qnorm.length; 75 | var qmask = 0xff; 76 | while (!(qhbyte & 0x80)) { 77 | qhbyte <<= 1; 78 | qmask >>= 1; 79 | } 80 | var x; 81 | while (true) { 82 | var x_bytes = this.transport.rng.read(bytes); 83 | x_bytes = String.fromCharCode(x_bytes[0].charCodeAt(0) & qmask) + x_bytes.substring(1); 84 | x = paramikojs.util.inflate_long(x_bytes, 1); 85 | if (x.compareTo(one) > 0 && q.compareTo(x) > 0) { 86 | break; 87 | } 88 | } 89 | this.x = x; 90 | }, 91 | 92 | _parse_kexdh_gex_group : function(m) { 93 | this.p = m.get_mpint(); 94 | this.g = m.get_mpint(); 95 | // reject if p's bit length < 1024 or > 8192 96 | var bitlen = paramikojs.util.bit_length(this.p); 97 | if (bitlen < 1024 || bitlen > 8192) { 98 | throw new paramikojs.ssh_exception.SSHException('Server-generated gex p (don\'t ask) is out of range (' + bitlen + ' bits)'); 99 | } 100 | if(ssh_console.debug) console.debug('Got server p (' + bitlen + ' bits)'); 101 | this._generate_x(); 102 | // now compute e = g^x mod p 103 | this.e = this.g.modPow(this.x, this.p); 104 | m = new paramikojs.Message(); 105 | m.add_byte(String.fromCharCode(paramikojs.KexGex._MSG_KEXDH_GEX_INIT)); 106 | m.add_mpint(this.e); 107 | this.transport._send_message(m); 108 | this.transport._expect_packet(paramikojs.KexGex._MSG_KEXDH_GEX_REPLY); 109 | }, 110 | 111 | _parse_kexdh_gex_reply : function(m) { 112 | var host_key = m.get_string(); 113 | this.f = m.get_mpint(); 114 | var sig = m.get_string(); 115 | var one = BigInteger.ONE; 116 | if (one.compareTo(this.f) > 0 || this.f.compareTo(this.p.subtract(one)) > 0) { 117 | throw new paramikojs.ssh_exception.SSHException('Server kex "f" is out of range'); 118 | } 119 | var K = this.f.modPow(this.x, this.p); 120 | // okay, build up the hash H of (V_C || V_S || I_C || I_S || K_S || min || n || max || p || g || e || f || K) 121 | var hm = new paramikojs.Message(); 122 | hm.add(this.transport.local_version, this.transport.remote_version, 123 | this.transport.local_kex_init, this.transport.remote_kex_init, 124 | host_key); 125 | if (!this.old_style) { 126 | hm.add_int(this.min_bits); 127 | } 128 | hm.add_int(this.preferred_bits); 129 | if (!this.old_style) { 130 | hm.add_int(this.max_bits); 131 | } 132 | hm.add_mpint(this.p); 133 | hm.add_mpint(this.g); 134 | hm.add_mpint(this.e); 135 | hm.add_mpint(this.f); 136 | hm.add_mpint(K); 137 | this.transport._set_K_H(K, new kryptos.hash.SHA(hm.toString()).digest()); 138 | this.transport._verify_key(host_key, sig); 139 | this.transport._activate_outbound(); 140 | } 141 | }; 142 | -------------------------------------------------------------------------------- /chrome/content/paramikojs/ssh_exception.js: -------------------------------------------------------------------------------- 1 | paramikojs.ssh_exception = {} 2 | 3 | /* 4 | Exception raised by failures in SSH2 protocol negotiation or logic errors. 5 | */ 6 | paramikojs.ssh_exception.SSHException = function(message) { 7 | this.message = message; 8 | this.custom = true; 9 | this.name = "SSHException"; 10 | }; 11 | 12 | paramikojs.ssh_exception.SSHException.prototype.toString = function () { 13 | return this.name + ': "' + this.message + '"'; 14 | } 15 | 16 | paramikojs.ssh_exception.WaitException = function(message) { 17 | var baseEx = new paramikojs.ssh_exception.SSHException(message); 18 | inherit(this, baseEx); 19 | this.toString = baseEx.toString; 20 | this.name = "WaitException"; 21 | } 22 | 23 | paramikojs.ssh_exception.CipherException = function(message) { 24 | var baseEx = new paramikojs.ssh_exception.SSHException(message); 25 | inherit(this, baseEx); 26 | this.toString = baseEx.toString; 27 | this.name = "CipherException"; 28 | } 29 | 30 | paramikojs.ssh_exception.EOFError = function(message) { 31 | var baseEx = new paramikojs.ssh_exception.SSHException(message); 32 | inherit(this, baseEx); 33 | this.toString = baseEx.toString; 34 | this.name = "EOFError"; 35 | } 36 | 37 | paramikojs.ssh_exception.IOError = function(message) { 38 | var baseEx = new paramikojs.ssh_exception.SSHException(message); 39 | inherit(this, baseEx); 40 | this.toString = baseEx.toString; 41 | this.name = "IOError"; 42 | } 43 | 44 | paramikojs.ssh_exception.SFTPError = function(message) { 45 | var baseEx = new paramikojs.ssh_exception.SSHException(message); 46 | inherit(this, baseEx); 47 | this.toString = baseEx.toString; 48 | this.name = "SFTPError"; 49 | } 50 | 51 | paramikojs.ssh_exception.UserRequestedDisconnect = function(message) { 52 | var baseEx = new paramikojs.ssh_exception.SSHException(message); 53 | inherit(this, baseEx); 54 | this.toString = baseEx.toString; 55 | this.name = "UserRequestedDisconnect"; 56 | } 57 | 58 | paramikojs.ssh_exception.IsPuttyKey = function(message, lines) { 59 | var baseEx = new paramikojs.ssh_exception.SSHException(message); 60 | inherit(this, baseEx); 61 | this.toString = baseEx.toString; 62 | this.name = "IsPuttyKey"; 63 | this.lines = lines; 64 | } 65 | 66 | paramikojs.ssh_exception.BERException = function(message) { 67 | var baseEx = new paramikojs.ssh_exception.SSHException(message); 68 | inherit(this, baseEx); 69 | this.toString = baseEx.toString; 70 | this.name = "BERException"; 71 | } 72 | 73 | paramikojs.ssh_exception.NeedRekeyException = function(message) { 74 | var baseEx = new paramikojs.ssh_exception.SSHException(message); 75 | inherit(this, baseEx); 76 | this.toString = baseEx.toString; 77 | this.name = "NeedRekeyException"; 78 | } 79 | 80 | /* 81 | Exception raised when authentication failed for some reason. It may be 82 | possible to retry with different credentials. (Other classes specify more 83 | specific reasons.) 84 | 85 | @since: 1.6 86 | */ 87 | paramikojs.ssh_exception.AuthenticationException = function(message) { 88 | var baseEx = new paramikojs.ssh_exception.SSHException(message); 89 | inherit(this, baseEx); 90 | this.toString = baseEx.toString; 91 | this.name = "AuthenticationException"; 92 | } 93 | 94 | /* 95 | Exception raised when a password is needed to unlock a private key file. 96 | */ 97 | paramikojs.ssh_exception.PasswordRequiredException = function(message) { 98 | var baseEx = new paramikojs.ssh_exception.SSHException(message); 99 | inherit(this, baseEx); 100 | this.toString = baseEx.toString; 101 | this.name = "PasswordRequiredException"; 102 | } 103 | 104 | /* 105 | Exception raised when an authentication type (like password) is used, but 106 | the server isn't allowing that type. (It may only allow public-key, for 107 | example.) 108 | 109 | @ivar allowed_types: list of allowed authentication types provided by the 110 | server (possible values are: C{"none"}, C{"password"}, and 111 | C{"publickey"}). 112 | @type allowed_types: list 113 | 114 | @since: 1.1 115 | */ 116 | paramikojs.ssh_exception.BadAuthenticationType = function(message, types) { 117 | var baseEx = new paramikojs.ssh_exception.SSHException(message); 118 | inherit(this, baseEx); 119 | this.toString = baseEx.toString; 120 | this.name = "BadAuthenticationType"; 121 | this.allowed_types = types; 122 | } 123 | 124 | paramikojs.ssh_exception.BadAuthenticationType.prototype.toString = function () { 125 | return this.name + ': "' + this.message + '"' + '(allowed_types=' + JSON.stringify(this.allowed_types) + ')'; 126 | } 127 | 128 | /* 129 | An internal exception thrown in the case of partial authentication. 130 | */ 131 | paramikojs.ssh_exception.PartialAuthentication = function(types) { 132 | var baseEx = new paramikojs.ssh_exception.SSHException('partial authentication'); 133 | inherit(this, baseEx); 134 | this.toString = baseEx.toString; 135 | this.name = "PartialAuthentication"; 136 | this.allowed_types = types; 137 | } 138 | 139 | /* 140 | Exception raised when an attempt to open a new L{Channel} fails. 141 | 142 | @ivar code: the error code returned by the server 143 | @type code: int 144 | 145 | @since: 1.6 146 | */ 147 | paramikojs.ssh_exception.ChannelException = function(code, text) { 148 | var baseEx = new paramikojs.ssh_exception.SSHException(text); 149 | inherit(this, baseEx); 150 | this.toString = baseEx.toString; 151 | this.name = "ChannelException"; 152 | this.code = code; 153 | } 154 | 155 | /* 156 | The host key given by the SSH server did not match what we were expecting. 157 | 158 | @ivar hostname: the hostname of the SSH server 159 | @type hostname: str 160 | @ivar key: the host key presented by the server 161 | @type key: L{PKey} 162 | @ivar expected_key: the host key expected 163 | @type expected_key: L{PKey} 164 | 165 | @since: 1.6 166 | */ 167 | paramikojs.ssh_exception.BadHostKeyException = function(hostname, got_key, expected_key) { 168 | var baseEx = new paramikojs.ssh_exception.SSHException('Host key for server ' + hostname + ' does not match!'); 169 | inherit(this, baseEx); 170 | this.toString = baseEx.toString; 171 | this.name = "BadHostKeyException"; 172 | this.hostname = hostname; 173 | this.key = got_key; 174 | this.expected_key = expected_key; 175 | } 176 | -------------------------------------------------------------------------------- /chrome/locale/en-US/help.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | BBSFox user manual 7 | 22 | 23 | 24 | 25 | Connect to site:
26 | For example, we want to connect site aaa.bbb.ccc.ddd
27 | Type telnet://aaa.bbb.ccc.ddd in Firefox URL bar to connect site. BBSFox use telnet default port 23 to make connection.
28 | If the site use specific port such as 8888, Type telnet://aaa.bbb.ccc.ddd:8888 in Firefox URL bar to connect site.
29 |
30 | General Hot Key:
31 | (Hotkey can be enable/disable in preference.)
32 | Ctrl + Shift + V (Paste)
33 | Ctrl + A (Select All)
34 | Select a preferred text and press Ctrl + C (Copy)
35 | Ctrl+D (Downlod post to system clipboard)
36 | Ctrl+E (Display/Hide BBS background image)
37 | Ctrl+M (Mouse browsing ON / OFF)
38 |
39 | Mouse Browsing:
40 | (Refer to the preference to enable the feature.)
41 | General page
42 | Page's left side = Arrow left(Go to the previous page)
43 | Page's other part = Enter (Click to access the article)
44 |
45 | While under the main board or the article list
46 | Refer to the following diagram:
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 | Red area = Home (First page)
55 | Green area = End (Last page)
56 | Blue area = Page Up (Page up)
57 | Yellow area = Page Down (Page down)
58 | Orange area = Arrow left (Go to the previous page)
59 | Purple area = Enter (Enter the board,/Read the article)
60 |
61 | While reading articles
62 | Refer to the following diagram:
63 |
64 |
65 |
66 |
67 |
68 |
69 | Green area = End (Last page)
70 | Blue area = Page Up (Page up)
71 | Yellow area = Page Down (Page down)
72 | Orange area = Arrow left(Go to previous page)
73 |
74 | Some notes about Mouse Browsing:
75 | While selecting a preferred text, mouse browsing would be blocked temporally.
76 | By single click, mouse browsing can be restored.
77 | While under mouse browsing, texts cannot be selected by double click (ignored automatically).For the concern that after the text is selected,
78 | the next click is ignored by the previous action.
79 | Use ctrl + M to switch ON/OFF mouse browsing temporarily for the sake of general operation.
80 | It is applied to all existing BBS windows for safety.
81 |
82 | Advanced Mouse Browsing:
83 | (Refer to the preference to enable the feature.)
84 | While under the article list or reading the article
85 | Top left corner of the page = Send command '=' (Go to the top of the thread.)
86 | The second/third line on the top left part of the page = Send command '[' (Go to the preceding article within the thread.)
87 | Top right corner of the page = Send command ']' (Go to the next article within the thread.)
88 | Bottom right corner of the page = Go to the last article within the thread.
89 | Bottom left corner of the page = Send command arrow left + Enter + End (Refresh the article.)
90 |
91 | Gestures:
92 | Create FireGestures script in the BBSFox preference page
93 | 94 | 95 | -------------------------------------------------------------------------------- /chrome/content/browserutils.js: -------------------------------------------------------------------------------- 1 | // Browser utilities, including preferences API access, site-depedent setting through Places API 2 | 3 | // From https://developer.mozilla.org/en/Code_snippets/Preferences 4 | function BBSFoxPrefListener(rootName, branchName, func, prefsHandler) { 5 | var prefService = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefService); 6 | var branch = prefService.getBranch(branchName); 7 | var rootBranch = prefService.getBranch(rootName); 8 | 9 | if(prefsHandler) { 10 | prefsHandler.branchName = branchName; 11 | } 12 | branch.QueryInterface(Ci.nsIPrefBranch); 13 | rootBranch.QueryInterface(Ci.nsIPrefBranch); 14 | 15 | this.register = function() { 16 | branch.addObserver("", this.branchObserve, false); 17 | branch.getChildList("", { }) 18 | .forEach(function (name) { func(branch, name); }); 19 | 20 | rootBranch.addObserver("DynamicRenderTest", this.rootObserve, false); 21 | rootBranch.getChildList("", { }) 22 | .forEach(function (name) { func(rootBranch, name); }); 23 | }; 24 | this.unregister = function unregister() { 25 | if (branch) 26 | branch.removeObserver("", this.branchObserve); 27 | 28 | if (rootBranch) 29 | rootBranch.removeObserver("DynamicRenderTest", this.rootObserve, false); 30 | }; 31 | this.branchObserve = { 32 | observe:function(subject, topic, data) { 33 | if (topic == "nsPref:changed") 34 | func(branch, data); 35 | }, 36 | }; 37 | this.rootObserve ={ 38 | observe:function(subject, topic, data) { 39 | if (topic == "nsPref:changed") 40 | func(rootBranch, data); 41 | } 42 | }; 43 | } 44 | 45 | function BBSFoxBrowserUtils() { 46 | // XXX: UNUSED AND UNTESTED 47 | this.__defineGetter__('_prefBranch', function() { 48 | delete this['_prefBranch']; 49 | return this['_prefBranch'] = Cc['@mozilla.org/preferences-service;1'].getService(Ci.nsIPrefService) 50 | .getBranch('extensions.bbsfox2.'); 51 | }); 52 | //this.__defineGetter__('_bookmarkService', function() { 53 | // delete this['_bookmarkService']; 54 | // return this['_bookmarkService'] = Cc['@mozilla.org/browser/nav-bookmarks-service;1'].getService(Ci.nsINavBookmarksService); 55 | //}); 56 | this.__defineGetter__('_ioService', function() { 57 | delete this['_ioService']; 58 | return this['_ioService'] = Cc['@mozilla.org/network/io-service;1'].getService(Ci.nsIIOService); 59 | }); 60 | //this.bookmarkID = null; 61 | this.isDefaultPref = true; 62 | this.siteAuthInfo = ''; 63 | this.siteAddr = null; 64 | } 65 | 66 | BBSFoxBrowserUtils.prototype = { 67 | 68 | findSiteTitle: function(url, port) { 69 | var url2 = url+":"+port; 70 | var siteIDs = this.getSubBranch('hostlist_').getChildList("", { }); 71 | var CiStr = Ci.nsISupportsString; 72 | //var availableIDs = new Array(); 73 | for(var i=0; i 15 ? '\\x' + code.toString(16) 36 | : '\\x0' + code.toString(16); 37 | i++; 38 | } else if(str.charAt(i+1) == '?') { 39 | result += '\\x7f'; 40 | i++; 41 | } 42 | break; 43 | case '"': 44 | result += '\\"'; 45 | break; 46 | default: 47 | result += str.charAt(i); 48 | } 49 | } 50 | return eval('"' + result + '"'); 51 | } 52 | */ 53 | 54 | // An alternative to the function with e v a l (); 55 | // Only support caret notations (^C, ^H, ^U, ^[, ^?, ...) 56 | // and hexadecimal notation (\x1b, \x7f, ...) 57 | // If you want to show \ and ^, use \\ and \^ respectively 58 | function UnEscapeStr(str) { 59 | var result = ''; 60 | for(var i=0; i str.length - 4) { 78 | result += '\\'; 79 | break; 80 | } 81 | var code = parseInt(str.substr(i+2, 2), 16); 82 | result += String.fromCharCode(code); 83 | i += 3; 84 | break; 85 | default: 86 | result += '\\'; 87 | } 88 | break; 89 | case '^': 90 | if(i == str.length-1) { // independent ^ at the end of the string 91 | result += '^'; 92 | break; 93 | } 94 | if('@' <= str.charAt(i+1) && str.charAt(i+1) <= '_') { 95 | var code = str.charCodeAt(i+1) - 64; 96 | result += String.fromCharCode(code); 97 | i++; 98 | } else if(str.charAt(i+1) == '?') { 99 | result += '\x7f'; 100 | i++; 101 | } else { 102 | result += '^'; 103 | } 104 | break; 105 | default: 106 | result += str.charAt(i); 107 | } 108 | } 109 | return result; 110 | } 111 | 112 | function ansiHalfColorConv(bufdata) { 113 | var str = ''; 114 | var regex = new RegExp('\x15\\[(([0-9]+)?;)+50m', 'g'); 115 | var result = null; 116 | var indices = []; 117 | while ((result = regex.exec(bufdata))) { 118 | indices.push(result.index + result[0].length - 4); 119 | } 120 | 121 | if (indices.length == 0) { 122 | return bufdata; 123 | } 124 | 125 | var curInd = 0; 126 | for (var i = 0; i < indices.length; ++i) { 127 | var ind = indices[i]; 128 | var preEscInd = bufdata.substring(curInd, ind).lastIndexOf('\x15') + curInd; 129 | str += bufdata.substring(curInd, preEscInd) + '\x00' + bufdata.substring(ind+4, ind+5) + bufdata.substring(preEscInd, ind) + 'm'; 130 | curInd = ind+5; 131 | } 132 | str += bufdata.substring(curInd); 133 | return str; 134 | }; 135 | 136 | // Wrap text within maxLen without hyphenating English words, 137 | // where the maxLen is generally the screen width. 138 | function wrapText(str, maxLen, enterChar) { 139 | // Divide string into non-hyphenated groups 140 | // classified as \r, \n, single full-width character, an English word, 141 | // and space characters in the beginning of original line. (indent) 142 | // Spaces next to a word group are merged into that group 143 | // to ensure the start of each wrapped line is a word. 144 | // FIXME: full-width punctuation marks aren't recognized 145 | var pattern = /\r|\n|([^\x00-\x7f][,.?!:;]?[\t ]*)|([\x00-\x08\x0b\x0c\x0e-\x1f\x21-\x7f]+[\t ]*)|[\t ]+/g; 146 | var splited = str.match(pattern); 147 | 148 | var result = ''; 149 | var len = 0; 150 | for(var i=0; i maxLen) { 161 | result += enterChar; 162 | len = 0; 163 | } 164 | result += splited[i]; 165 | len += grouplen; 166 | } 167 | return result; 168 | } 169 | 170 | function parseThreadForUserId (str) { 171 | var regex = new RegExp(/(?:(?:\d+)|(?: \u2605 )) [\u002bmMsSD*!=~ ](?:(?:[-X\d\* ]{2})|(?:\u7206))[\d ]\d\/\d{2} (\w+) +[\u9396\u25a1\u8f49\u25c6\u25c7R=]:?/g); 172 | var result = regex.exec(str); 173 | if (result && result.length == 2) { 174 | return result[1].toLowerCase(); 175 | } 176 | 177 | return null; 178 | } 179 | 180 | function parsePushthreadForUserId (str) { 181 | var regex = new RegExp(/[\u2192\u63a8\u5653] (\w+) *:.+ \d{2}\/\d{2} \d{2}:\d{2}/g); 182 | var result = regex.exec(str); 183 | if (result && result.length == 2) { 184 | return result[1].toLowerCase(); 185 | } 186 | 187 | return null; 188 | }; 189 | -------------------------------------------------------------------------------- /chrome/content/paramikojs/sftp.js: -------------------------------------------------------------------------------- 1 | paramikojs.BaseSFTP = function () { 2 | this.ultra_debug = false; 3 | } 4 | 5 | paramikojs.BaseSFTP.prototype = { 6 | CMD_INIT : 1, 7 | CMD_VERSION : 2, 8 | CMD_OPEN : 3, 9 | CMD_CLOSE : 4, 10 | CMD_READ : 5, 11 | CMD_WRITE : 6, 12 | CMD_LSTAT : 7, 13 | CMD_FSTAT : 8, 14 | CMD_SETSTAT : 9, 15 | CMD_FSETSTAT : 10, 16 | CMD_OPENDIR : 11, 17 | CMD_READDIR : 12, 18 | CMD_REMOVE : 13, 19 | CMD_MKDIR : 14, 20 | CMD_RMDIR : 15, 21 | CMD_REALPATH : 16, 22 | CMD_STAT : 17, 23 | CMD_RENAME : 18, 24 | CMD_READLINK : 19, 25 | CMD_SYMLINK : 20, 26 | 27 | CMD_STATUS : 101, 28 | CMD_HANDLE : 102, 29 | CMD_DATA : 103, 30 | CMD_NAME : 104, 31 | CMD_ATTRS : 105, 32 | 33 | CMD_EXTENDED : 200, 34 | CMD_EXTENDED_REPLY : 201, 35 | 36 | SFTP_OK : 0, 37 | SFTP_EOF : 1, 38 | SFTP_NO_SUCH_FILE : 2, 39 | SFTP_PERMISSION_DENIED : 3, 40 | SFTP_FAILURE : 4, 41 | SFTP_BAD_MESSAGE : 5, 42 | SFTP_NO_CONNECTION : 6, 43 | SFTP_CONNECTION_LOST : 7, 44 | SFTP_OP_UNSUPPORTED : 8, 45 | 46 | SFTP_DESC : [ 'Success', 47 | 'End of file', 48 | 'No such file', 49 | 'Permission denied', 50 | 'Failure', 51 | 'Bad message', 52 | 'No connection', 53 | 'Connection lost', 54 | 'Operation unsupported' ], 55 | 56 | SFTP_FLAG_READ : 0x1, 57 | SFTP_FLAG_WRITE : 0x2, 58 | SFTP_FLAG_APPEND : 0x4, 59 | SFTP_FLAG_CREATE : 0x8, 60 | SFTP_FLAG_TRUNC : 0x10, 61 | SFTP_FLAG_EXCL : 0x20, 62 | 63 | _VERSION : 3, 64 | 65 | 66 | // for debugging 67 | CMD_NAMES : { 68 | 1: 'init', 69 | 2: 'version', 70 | 3: 'open', 71 | 4: 'close', 72 | 5: 'read', 73 | 6: 'write', 74 | 7: 'lstat', 75 | 8: 'fstat', 76 | 9: 'setstat', 77 | 10: 'fsetstat', 78 | 11: 'opendir', 79 | 12: 'readdir', 80 | 13: 'remove', 81 | 14: 'mkdir', 82 | 15: 'rmdir', 83 | 16: 'realpath', 84 | 17: 'stat', 85 | 18: 'rename', 86 | 19: 'readlink', 87 | 20: 'symlink', 88 | 101: 'status', 89 | 102: 'handle', 90 | 103: 'data', 91 | 104: 'name', 92 | 105: 'attrs', 93 | 200: 'extended', 94 | 201: 'extended_reply' 95 | }, 96 | 97 | 98 | // internals... 99 | 100 | _send_version : function(callback) { 101 | var self = this; 102 | var send_packet_callback = function() { 103 | self._send_version_callback(callback); 104 | }; 105 | this._send_packet(this.CMD_INIT, struct.pack('>I', this._VERSION), send_packet_callback); 106 | }, 107 | 108 | _send_version_callback : function(callback) { 109 | try { 110 | var packet = this._read_packet(); 111 | } catch(ex) { 112 | if (ex instanceof paramikojs.ssh_exception.WaitException) { 113 | // waiting on socket 114 | var self = this; 115 | var wait_callback = function() { self._send_version_callback(callback) }; 116 | setTimeout(wait_callback, 10); 117 | return; 118 | } else { 119 | throw ex; 120 | } 121 | } 122 | 123 | if (packet[0] != this.CMD_VERSION) { 124 | throw 'Incompatible sftp protocol'; 125 | } 126 | var version = struct.unpack('>I', packet[1].substring(0, 4))[0]; 127 | // if version != _VERSION: 128 | // raise SFTPError('Incompatible sftp protocol') 129 | callback(version); 130 | }, 131 | 132 | _send_server_version : function() { 133 | // winscp will freak out if the server sends version info before the 134 | // client finishes sending INIT. 135 | var packet = this._read_packet(); 136 | if (t != this.CMD_INIT) { 137 | throw 'Incompatible sftp protocol'; 138 | } 139 | var version = struct.unpack('>I', packet[0].substring(0, 4))[0]; 140 | // advertise that we support "check-file" 141 | var extension_pairs = [ 'check-file', 'md5,sha1' ]; 142 | var msg = new paramikojs.Message(); 143 | msg.add_int(this._VERSION); 144 | msg.add(extension_pairs); 145 | this._send_packet(this.CMD_VERSION, msg.toString()); 146 | return version; 147 | }, 148 | 149 | _write_all : function(out, send_packet_callback) { 150 | while (out.length > 0) { 151 | try { 152 | var n = this.sock.send(out); 153 | } catch(ex) { 154 | if (ex instanceof paramikojs.ssh_exception.WaitException) { 155 | // waiting on window adjust 156 | var self = this; 157 | var wait_callback = function() { self._write_all(out, send_packet_callback) }; 158 | setTimeout(wait_callback, 10); 159 | return; 160 | } else { 161 | throw ex; 162 | } 163 | } 164 | if (n <= 0) { 165 | throw new paramikojs.ssh_exception.EOFError(); 166 | } 167 | if (n == out.length) { 168 | if (send_packet_callback) { 169 | send_packet_callback(); 170 | } 171 | return; 172 | } 173 | out = out.substring(n); 174 | } 175 | }, 176 | 177 | _read_all : function(n) { 178 | var out = this.sock.recv(n); 179 | if (out.length < n) { 180 | // waiting on socket 181 | this.sock.in_buffer = out + this.sock.in_buffer; // add data back into in_buffer 182 | throw new paramikojs.ssh_exception.WaitException("wait"); 183 | } 184 | return out; 185 | }, 186 | 187 | _send_packet : function(t, packet, send_packet_callback) { 188 | //self._log(DEBUG2, 'write: %s (len=%d)' % (CMD_NAMES.get(t, '0x%02x' % t), len(packet))) 189 | if(ssh_console.debug) console.debug('write: ' + this.CMD_NAMES[t] + '(len=' + packet.length + ')'); 190 | var out = struct.pack('>I', packet.length + 1) + String.fromCharCode(t) + packet; 191 | if (this.ultra_debug) { 192 | if(ssh_console.debug) console.debug(paramikojs.util.format_binary(out, 'OUT: ')); 193 | } 194 | this._write_all(out, send_packet_callback); 195 | }, 196 | 197 | _read_packet : function() { 198 | var x = this._read_all(4); 199 | // most sftp servers won't accept packets larger than about 32k, so 200 | // anything with the high byte set (> 16MB) is just garbage. 201 | if (x[0] != '\x00') { 202 | throw 'Garbage packet received'; 203 | } 204 | var size = struct.unpack('>I', x)[0]; 205 | try { 206 | var data = this._read_all(size); 207 | } catch(ex) { 208 | if (ex instanceof paramikojs.ssh_exception.WaitException) { 209 | // waiting on socket 210 | this.sock.in_buffer = x + this.sock.in_buffer; // add header back into in_buffer 211 | throw new paramikojs.ssh_exception.WaitException("wait"); // rethrow exception 212 | } else { 213 | throw ex; 214 | } 215 | } 216 | if (this.ultra_debug) { 217 | if(ssh_console.debug) console.debug(paramikojs.util.format_binary(data, 'IN: ')); 218 | } 219 | if (size > 0) { 220 | var t = data[0].charCodeAt(0); 221 | if(ssh_console.debug) console.debug('read: ' + this.CMD_NAMES[t] + '(len=' + (data.length - 1) + ')'); 222 | return [t, data.substring(1)]; 223 | } 224 | return [0, '']; 225 | } 226 | }; 227 | --------------------------------------------------------------------------------