├── 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 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/chrome/content/paramikojs/readme.md:
--------------------------------------------------------------------------------
1 | # paramikojs
2 |
3 | ## About
4 |
5 | `paramikojs` is a javascript port of [paramiko](http://www.lag.net/paramiko/). It powers the [fireftp](https://github.com/mimecuvalo/fireftp) and [firessh](https://github.com/mimecuvalo/firessh) projects. However, some caution should be taken if reusing the code as not all code paths have been tested (in python, yes, but not in the translated javascript). So, coder beware!
6 |
7 | ## Getting Started
8 |
9 | `paramikojs` doesn't work out of the box. You should check out the [fireftp](https://github.com/mimecuvalo/fireftp) or [firessh](https://github.com/mimecuvalo/firessh) projects for working examples on how to get something working. In particular, look at [ssh2.js](https://github.com/mimecuvalo/fireftp/blob/master/src/content/js/connection/ssh2.js) as a basic start to see how it glues together.
10 |
11 | ## Note!
12 |
13 | Before you ask, **no** this doesn't work on regular web pages. Being able to make an SSH connection only works currently in the context of a Firefox add-on which gives provides extra libraries/permissions (i.e. ahem, sockets)
14 |
--------------------------------------------------------------------------------
/data/js/context-menu/trackDel.js:
--------------------------------------------------------------------------------
1 | self.on("context", function (node) {
2 | if(!window.bbsfox) {
3 | return false;
4 | }
5 |
6 | if(window.bbsfox.prefs.keyWordTrackMenu) {
7 | let selstr = window.getSelection().toString().replace('\r\n','\n');
8 | let strArray = selstr.split('\n');
9 | let prefs = window.bbsfox.prefs;
10 | let highlightWords_raw = prefs.highlightWords_local;
11 | let highlightWords_lowCase = prefs.highlightWords_local.join('\n').toLowerCase().split('\n');
12 |
13 | selstr = window.bbsfox.trim_both(strArray[0]);
14 | if(selstr != '') {
15 | let findflag = false;
16 | if(prefs.keyWordTrackCaseSensitive) {
17 | findflag = (highlightWords_raw.indexOf(selstr) !== -1);
18 | }
19 | else {
20 | findflag = (highlightWords_lowCase.indexOf(selstr.toLowerCase()) !== -1);
21 | }
22 | return findflag;
23 | }
24 | return false;
25 | }
26 | else {
27 | return false;
28 | }
29 | });
30 |
31 | self.on("click", function(node, data) {
32 | //self.postMessage();
33 | window.bbsfox.overlaycmd.exec({command:"doDelTrack"});
34 | });
35 |
--------------------------------------------------------------------------------
/data/js/context-menu/trackAdd.js:
--------------------------------------------------------------------------------
1 | self.on("context", function (node) {
2 | if(!window.bbsfox) {
3 | return false;
4 | }
5 |
6 | if(window.bbsfox.prefs.keyWordTrackMenu) {
7 | let selstr = window.getSelection().toString().replace('\r\n','\n');
8 | let strArray = selstr.split('\n');
9 | let prefs = window.bbsfox.prefs;
10 | let highlightWords_raw = prefs.highlightWords_local;
11 | let highlightWords_lowCase = prefs.highlightWords_local.join('\n').toLowerCase().split('\n');
12 |
13 | selstr = window.bbsfox.trim_both(strArray[0]);
14 | if(selstr != '') {
15 | let findflag = false;
16 | if(prefs.keyWordTrackCaseSensitive) {
17 | findflag = (highlightWords_raw.indexOf(selstr) !== -1);
18 | }
19 | else {
20 | findflag = (highlightWords_lowCase.indexOf(selstr.toLowerCase()) !== -1);
21 | }
22 | return !findflag;
23 | }
24 | return false;
25 | }
26 | else {
27 | return false;
28 | }
29 | });
30 |
31 | self.on("click", function(node, data) {
32 | //self.postMessage();
33 | window.bbsfox.overlaycmd.exec({command:"doAddTrack"});
34 | });
35 |
--------------------------------------------------------------------------------
/chrome/content/paramikojs/kryptos/Random/LICENSE.txt:
--------------------------------------------------------------------------------
1 | # Written in 2008 by Dwayne C. Litzenberger
2 | #
3 | # ===================================================================
4 | # The contents of this directory are dedicated to the public domain. To
5 | # the extent that dedication to the public domain is not available,
6 | # everyone is granted a worldwide, perpetual, royalty-free,
7 | # non-exclusive license to exercise all rights associated with the
8 | # contents of this file for any purpose whatsoever.
9 | # No rights are reserved.
10 | #
11 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
12 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
13 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
14 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
15 | # BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
16 | # ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
17 | # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
18 | # SOFTWARE.
19 | # ===================================================================
20 |
--------------------------------------------------------------------------------
/chrome/content/paramikojs/kex_group14.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2013 Torsten Landschoff
3 |
4 | Standard SSH key exchange ("kex" if you wanna sound cool). Diffie-Hellman of
5 | 2048 bit key halves, using a known "p" prime and "g" generator.
6 | */
7 |
8 | paramikojs.KexGroup14 = function(transport) {
9 | inherit(this, new paramikojs.KexGroup1(transport));
10 |
11 | this.P = paramikojs.KexGroup14.P;
12 | this.G = paramikojs.KexGroup14.G;
13 | }
14 |
15 | // http://tools.ietf.org/html/rfc3526#section-3
16 | paramikojs.KexGroup14.P = new BigInteger("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF", 16);
17 | paramikojs.KexGroup14.G = new BigInteger("2", 10);
18 |
19 | paramikojs.KexGroup14.prototype = {
20 | name : 'diffie-hellman-group14-sha1'
21 | };
22 |
--------------------------------------------------------------------------------
/chrome/content/paramikojs/license.txt:
--------------------------------------------------------------------------------
1 | paramikojs is a port of the paramiko library: http://www.lag.net/paramiko/
2 |
3 | The Initial Developer of the Original Code is Robey Pointer
4 | Portions created by the Initial Developer are Copyright (C) 2011
5 | the Initial Developer. All Rights Reserved.
6 |
7 | Contributor(s):
8 | Robey Pointer (original author)
9 |
10 | Mime Cuvalo (translator, python -> javascript)
11 |
12 | This library is free software; you can redistribute it and/or
13 | modify it under the terms of the GNU Lesser General Public
14 | License as published by the Free Software Foundation; either
15 | version 2.1 of the License, or (at your option) any later version.
16 |
17 | This library is distributed in the hope that it will be useful,
18 | but WITHOUT ANY WARRANTY; without even the implied warranty of
19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 | Lesser General Public License for more details.
21 |
22 | You should have received a copy of the GNU Lesser General Public
23 | License along with this library; if not, write to the Free Software
24 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25 | You may also obtain a copy of the License at http://www.gnu.org/licenses/lgpl-2.1.html
26 |
--------------------------------------------------------------------------------
/data/js/optionsDlg.js:
--------------------------------------------------------------------------------
1 | var self = require('sdk/self');
2 | var data = self.data;
3 | var workers = require('sdk/content/worker');
4 | var tabs = require('sdk/tabs');
5 | var _ = require('sdk/l10n').get;
6 |
7 | var optionsDlg = {
8 |
9 | open: function(filePath) {
10 | if(!this.win) {
11 | this.win = require('sdk/window/utils').openDialog({
12 | features: Object.keys({
13 | minimizable: true,
14 | chrome: true,
15 | //toolbar: true,
16 | titlebar: true,
17 | alwaysRaised: true,
18 | centerscreen: true
19 | //private: true
20 | }).join() + ',width=740,height=230',
21 | name: _('openPrefsTab_title')
22 | });
23 | this.win.addEventListener('load', function () {
24 | //tabs.activeTab.on('ready', function (tab) {
25 | tabs.activeTab.on('load', function (tab) {
26 | this.worker = tab.attach({
27 | contentScriptFile: data.url('js/optionsDlg-cs.js')
28 | });
29 | this.win.document.title = _('openPrefsTab_title');
30 | //this.worker.port.emit('setData', {
31 | //});
32 | }.bind(this));
33 |
34 | tabs.activeTab.url = filePath;
35 | }.bind(this), false);
36 | }
37 | }
38 | };
39 |
40 | exports.optionsDlg = optionsDlg;
41 |
--------------------------------------------------------------------------------
/data/js/content-script.js:
--------------------------------------------------------------------------------
1 | // console.log("load content-script");
2 | function sendCommand(message, async){
3 | self.port.emit("bbsfox@ettoolong:bbsfox-coreCommand", message);
4 | }
5 | sendCommand({command: "contentScriptReady"}, true);
6 |
7 | self.port.on("bbsfox@ettoolong:bbsfox-overlayCommand", data => {
8 | if(window.bbsfox) {
9 | window.bbsfox.overlaycmd.exec(data);
10 | }
11 | });
12 |
13 | //socket data & event - start
14 | self.port.on("bbsfox@ettoolong:bbsfox-connect", () => {
15 | if(window.bbsfox) {
16 | window.bbsfox.conn.onStartRequest();
17 | }
18 | });
19 | self.port.on("bbsfox@ettoolong:bbsfox-disconnect", msg => {
20 | if(window.bbsfox) {
21 | window.bbsfox.conn.onStopRequest(msg.status);
22 | }
23 | });
24 | self.port.on("bbsfox@ettoolong:bbsfox-data", msg => {
25 | if(window.bbsfox) {
26 | window.bbsfox.conn.onDataAvailable(msg.data);
27 | }
28 | });
29 | //socket data & event - end
30 |
31 | self.port.on("detach", function() {
32 | // cleanup();
33 | if(window.bbsfox) {
34 | window.bbsfox.overlaycmd.exec({command: "unload"});
35 | }
36 | });
37 |
38 | if(window.bbsfox) {
39 | window.bbsfox.setContentScript(sendCommand, true);
40 | }
41 | else {
42 | document.body.addEventListener("bbsfoxReady", event => {
43 | window.bbsfox.setContentScript(sendCommand, true);
44 | });
45 | }
46 |
--------------------------------------------------------------------------------
/data/js/bbsfox-api.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const tabs = require("sdk/tabs");
4 | const apiKeys = [
5 | "checkFireGestureKey", "doPageUp", "doPageDown",
6 | "doEnd", "doHome", "doArrowLeft",
7 | "doArrowUp", "doArrowRight", "doArrowDown",
8 | "doCopy", "doCopyAnsi", "doPaste",
9 | "doSelectAll", "doOpenAllLink", "switchMouseBrowsing",
10 | "switchBgDisplay", "easyReading", "pushThread",
11 | "openThreadUrl", "changeColorTable", "doDownloadPost",
12 | "doLoadFile", "switchSymbolInput", "switchAnsiColorTool",
13 | "previewPicture", "closePictureViewer", "sendCodeStr"
14 | ];
15 | const urlCheck = /(^(telnet|ssh):\/\/)/i;
16 |
17 | let callback = null;
18 |
19 | const setCallback = (cb) => {
20 | callback = cb;
21 | }
22 |
23 | const setBBSCmdEx = (commandSet) => {
24 | //console.log(commandSet);
25 | if(commandSet.command && apiKeys.indexOf(commandSet.command) !== -1 ) { //only allow command that list in apiKeys
26 | if(callback)
27 | callback(commandSet);
28 | }
29 | };
30 |
31 | const setBBSCmd = (command) => {
32 | setBBSCmdEx({command: command});
33 | };
34 |
35 | const isBBSPage = () => {
36 | return urlCheck.test(tabs.activeTab.url);
37 | };
38 |
39 | exports.setAPICallback = setCallback;
40 | exports.bbsfoxAPI = {setBBSCmdEx: setBBSCmdEx,
41 | setBBSCmd: setBBSCmd,
42 | isBBSPage: isBBSPage};
43 |
--------------------------------------------------------------------------------
/data/js/context-menu/blacklistAdd.js:
--------------------------------------------------------------------------------
1 | self.on("context", function (node) {
2 | if(!window.bbsfox) {
3 | return false;
4 | }
5 | //TODO: bbsfox.buf.PageState always == 0, if mouse browsering == false
6 | let bbsfox = window.bbsfox;
7 | let prefs = bbsfox.prefs;
8 | if(!window.getSelection().isCollapsed && prefs.enableBlacklist && prefs.blacklistMenu) {
9 | //check blacklist id
10 | let selstr = window.getSelection().toString().toLowerCase();
11 | if(selstr && selstr.indexOf('\n') == -1) {
12 | selstr = selstr.replace(/^\s+|\s+$/g,'');
13 | let userid = '';
14 | let selection = bbsfox.view.getSelectionColRow();
15 | //if(selection.start.row)
16 | let rowText = bbsfox.buf.getRowText(selection.start.row, 0, bbsfox.buf.cols);
17 | if (bbsfox.buf.PageState === 3 && bbsfox.isPTT()) {
18 | userid = parsePushthreadForUserId(rowText);//
19 | }
20 | else if (bbsfox.buf.PageState === 2) {
21 | userid = parseThreadForUserId(rowText);//
22 | }
23 | if (userid && selstr == userid) {
24 | if( prefs.blacklistedUserIds.indexOf(userid) === -1 ) {
25 | //not in blacklist, show item 'add to blacklist'
26 | return true;
27 | }
28 | }
29 | }
30 | }
31 | return false;
32 | });
33 |
34 | self.on("click", function(node, data) {
35 | window.bbsfox.overlaycmd.exec({command:"addToBlacklist"});
36 | });
37 |
--------------------------------------------------------------------------------
/data/js/context-menu/blacklistDel.js:
--------------------------------------------------------------------------------
1 | self.on("context", function (node) {
2 | if(!window.bbsfox) {
3 | return false;
4 | }
5 | //TODO: bbsfox.buf.PageState always == 0, if mouse browsering == false
6 | let bbsfox = window.bbsfox;
7 | let prefs = bbsfox.prefs;
8 | if(!window.getSelection().isCollapsed && prefs.enableBlacklist && prefs.blacklistMenu) {
9 | //check blacklist id
10 | let selstr = window.getSelection().toString().toLowerCase();
11 | if(selstr && selstr.indexOf('\n') == -1) {
12 | selstr = selstr.replace(/^\s+|\s+$/g,'');
13 | let userid = '';
14 | let selection = bbsfox.view.getSelectionColRow();
15 | //if(selection.start.row)
16 | let rowText = bbsfox.buf.getRowText(selection.start.row, 0, bbsfox.buf.cols);
17 | if (bbsfox.buf.PageState === 3 && bbsfox.isPTT()) {
18 | userid = parsePushthreadForUserId(rowText);//
19 | }
20 | else if (bbsfox.buf.PageState === 2) {
21 | userid = parseThreadForUserId(rowText);//
22 | }
23 | if (userid && selstr == userid) {
24 | if( prefs.blacklistedUserIds.indexOf(userid) !== -1 ) {
25 | //not in blacklist, show item 'add to blacklist'
26 | return true;
27 | }
28 | }
29 | }
30 | }
31 | return false;
32 | });
33 |
34 | self.on("click", function(node, data) {
35 | window.bbsfox.overlaycmd.exec({command:"removeFromBlacklist"});
36 | });
37 |
--------------------------------------------------------------------------------
/chrome/locale/zh-TW/bbsfox.properties:
--------------------------------------------------------------------------------
1 | mouseBrowse=滑鼠瀏覽
2 | mouseBrowseOff=停用滑鼠瀏覽
3 | mouseBrowseOn=啟用滑鼠瀏覽
4 | messageNotify=訊息通知
5 | alert_down_finish=下載完成
6 | alert_down_terminate=下載中止
7 | extensions.bbsfox2.locale=big5
8 | delayPasteFinish=延遲貼上完成
9 | delayPasteStop=延遲貼上被中止
10 | fontTestResult1=適合作為中文及英文BBS字型。
11 | fontTestResult2=僅英文為等寬字型,只適合作為英文BBS字型。
12 | fontTestResult3=非等寬字型,不適合作為BBS字型。
13 | fontTestResult4=可作為中文及英文BBS字型,但部份符號可能導致畫面亂掉,不建議使用。
14 | fontTestResult5=適合作為英文BBS字型。
15 | fontTestResult6=不適合作為英文BBS字型。
16 | recoverwarning=將會以備份檔蓋過目前 BBSFox 的所有設定,你確定要這麼做嗎?
17 | delsitewarning=確定要刪除站台 "%S" 的設定嗎?
18 | delsitetitle=刪除站台
19 | symbolList0=一般常用符號
20 | symbolList1=線框
21 | symbolList2=填色方塊
22 | symbolList3=線段
23 | symbolList4=特殊圖形符號
24 | symbolList5=左右括號
25 | symbolList6=上下括號
26 | symbolList7=希臘字母
27 | symbolList8=注音符號
28 | symbolList9=數學符號
29 | symbolList10=日文平假名
30 | symbolList11=日文片假名
31 | foreground=前景色
32 | background=背景色
33 | blink=閃爍
34 | sendAnsiColorCode=送出 ANSI 色碼
35 | sendForegroundColorCode=只送出前景色彩
36 | sendBackgroundColorCode=只送出背景色彩
37 | sendResetColorCode=送出色彩還原碼
38 | preview=預覽文字
39 | copyUrl=複製網址
40 | SearchText=搜尋「%S」
41 | noThreadUrl=本看板目前不提供文章網址
42 | errorConn=無法連線,請再試。
43 | sftpCacheTitle=添加密鑰到暫存嗎?
44 | sftpCache=在註冊表中沒有伺服器主機密鑰的緩存。\n你不能保證這台伺服器是你所認為的那台電腦。\n\n該伺服器 RSA2 密鑰的指紋是:\n%S\n\n如果你信任該主機,按”是”把密鑰加到緩存並繼續連線。\n如果你只想連接一次,而不要把密鑰加到緩存,按”否”。\n如果你不信任該主機,按”取消”放棄連線。
45 | defaultSite=預設值
46 | addBlacklist=將 %S 加入站台設定: %S 的黑名單嗎?
47 | removeBlacklist=將 %S 從站台設定: %S 的黑名單中移除嗎?
48 |
--------------------------------------------------------------------------------
/chrome/content/paramikojs/kryptos/PublicKey/DSA.js:
--------------------------------------------------------------------------------
1 | kryptos.publicKey.DSA = function() {
2 |
3 | }
4 |
5 | kryptos.publicKey.DSA.prototype = {
6 | construct : function(y, g, p, q, x) {
7 | this.y = y;
8 | this.g = g;
9 | this.p = p;
10 | this.q = q;
11 | this.x = x;
12 |
13 | return this;
14 | },
15 |
16 | sign : function(m, k) {
17 | // SECURITY TODO - We _should_ be computing SHA1(m), but we don't because that's the API.
18 | var one = BigInteger.ONE;
19 | if (!(k.compareTo(one) > 0 && this.q.compareTo(k) > 0)) {
20 | throw "k is not between 2 and q-1";
21 | }
22 | var inv_k = k.modInverse(this.q); // Compute k**-1 mod q
23 | var r = this.g.modPow(k, this.p).mod(this.q); // r = (g**k mod p) mod q
24 | var s = inv_k.multiply(m.add(this.x.multiply(r))).mod(this.q);
25 | return [r, s];
26 | },
27 |
28 | verify : function(m, sig) {
29 | var r = sig[0];
30 | var s = sig[1];
31 | var zero = BigInteger.ZERO;
32 | // SECURITY TODO - We _should_ be computing SHA1(m), but we don't because that's the API.
33 | if (!(r.compareTo(zero) > 0 && this.q.compareTo(r) > 0) || !(s.compareTo(zero) > 0 && this.q.compareTo(s) > 0)) {
34 | return false;
35 | }
36 | var w = s.modInverse(this.q);
37 | var u1 = m.multiply(w).mod(this.q);
38 | var u2 = r.multiply(w).mod(this.q);
39 | var v = this.g.modPow(u1, this.p).multiply(this.y.modPow(u2, this.p)).mod(this.p).mod(this.q);
40 | return v.equals(r);
41 | },
42 |
43 | generate : function() {
44 | alert('NOT_IMPLEMENTED');
45 | }
46 | };
47 |
--------------------------------------------------------------------------------
/chrome/content/pushThread.xul:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/chrome/content/addSite.js:
--------------------------------------------------------------------------------
1 | function setAcceptBtn(enable) {
2 | document.getElementById("bbsfox-addSite").setAttribute("buttondisabledaccept", !enable);
3 | }
4 |
5 | function btnCancelClick() {
6 | return false;
7 | }
8 |
9 | function btnOkClick() {
10 | let retVals = window.arguments[0];
11 | retVals.sitename = document.getElementById("siteName").value;
12 | retVals.siteaddr = document.getElementById("siteAddr").value.toLowerCase();
13 | return true;
14 | }
15 |
16 | function checkValue() {
17 | //if site already exists, disable ok button
18 | let sn = document.getElementById("siteName").value;
19 | let sa = document.getElementById("siteAddr").value;
20 | if(sn === "" || sa === "") {
21 | setAcceptBtn(false);
22 | return;
23 | }
24 |
25 | let url = sa.toLowerCase();
26 | let url2;
27 | let addEnabled = (url.length > 0 && url.charCodeAt(url.length-1) !== 46 );
28 |
29 | if(addEnabled) {
30 | let splits = url.split(/:/g);
31 | if(splits.length === 1) {
32 | url2 = url.replace(/\./g, "");
33 | if(url2.match(/\W/))
34 | addEnabled = false;
35 | }
36 | else if(splits.length === 2) {
37 | if(splits[0] === "" || splits[1] === "") {
38 | addEnabled = false;
39 | }
40 | else {
41 | url2 = splits[0].replace(/\./g, "");
42 | if(url2.match(/\W/))
43 | addEnabled = false;
44 | if(splits[1].match(/\D/))
45 | addEnabled = false;
46 | }
47 | }
48 | else {
49 | addEnabled = false;
50 | }
51 | }
52 |
53 | if(addEnabled) { //check exists
54 | let existSite = window.arguments[1];
55 | addEnabled = !(existSite.includes(url));
56 | }
57 | setAcceptBtn(addEnabled);
58 | }
59 |
--------------------------------------------------------------------------------
/data/js/bbsfox-prefs.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const {Cu, Cc, Ci} = require("chrome");
4 |
5 | const initDefaultPrefs = data => {
6 | let bbsfoxPrefs = JSON.parse(data.load("chrome://bbsfox/content/prefs.json"));
7 | //default site setting
8 | let defaultPrefs = Cc["@mozilla.org/preferences-service;1"].
9 | getService(Ci.nsIPrefService).
10 | getDefaultBranch("extensions.bbsfox2.");
11 | for(let i in bbsfoxPrefs.sitePrefs) {
12 | let value = bbsfoxPrefs.sitePrefs[i];
13 | if( typeof value === "boolean") {
14 | defaultPrefs.setBoolPref("host_default." + i, value);
15 | }
16 | else if( typeof value === "number") {
17 | defaultPrefs.setIntPref("host_default." + i, value);
18 | }
19 | else if( typeof value === "string"){
20 | let nsIString = Cc["@mozilla.org/supports-string;1"].createInstance(Ci.nsISupportsString);
21 | nsIString.data = value;
22 | defaultPrefs.setComplexValue("host_default." + i, Ci.nsISupportsString, nsIString);
23 | }
24 | }
25 |
26 | //global setting
27 | let globalPrefs = Cc["@mozilla.org/preferences-service;1"].
28 | getService(Ci.nsIPrefService).
29 | getDefaultBranch("extensions.");
30 |
31 | for(let i in bbsfoxPrefs.globalPrefs) {
32 | let value = bbsfoxPrefs.globalPrefs[i];
33 | if( typeof value === "boolean") {
34 | globalPrefs.setBoolPref(i, value);
35 | }
36 | else if( typeof value === "number") {
37 | globalPrefs.setIntPref(i, value);
38 | }
39 | else if( typeof value === "string"){
40 | let nsIString = Cc["@mozilla.org/supports-string;1"].createInstance(Ci.nsISupportsString);
41 | nsIString.data = value;
42 | globalPrefs.setComplexValue(i, Ci.nsISupportsString, nsIString);
43 | }
44 | }
45 | }
46 | exports.initDefaultPrefs = initDefaultPrefs;
47 |
--------------------------------------------------------------------------------
/chrome/content/mainpage.js:
--------------------------------------------------------------------------------
1 | //this javascript file ONLY for telnet.htm. Because we remove all inline javascript code from 'telnet.htm' and 'ssh.htm'.
2 | var bbsfox;
3 |
4 | function startup() {
5 | document.title = document.location.host;
6 | bbsfox=new BBSFox();
7 | var browserutils = new BBSFoxBrowserUtils();
8 | document.title = browserutils.findSiteTitle(document.location.hostname, document.location.port ? document.location.port : BBSFOX_DEFAULT_PORT); //try to find site title.
9 | bbsfox.isDefaultPref = browserutils.isDefaultPref;
10 | bbsfox.siteAuthInfo = browserutils.siteAuthInfo;
11 | bbsfox.prefListener = browserutils.prefListener(function(branch, name) {
12 | bbsfox.prefs.onPrefChange(bbsfox, branch, name);
13 | }, bbsfox.prefs);
14 | if(bbsfox.prefs.preventNewTongWenAutoConv)
15 | {
16 | var tongwen = document.getElementById("tongwen_font");
17 | if (tongwen != null)
18 | tongwen.parentNode.removeChild(tongwen);
19 | }
20 | bbsfox.setInputAreaFocus();
21 | resize();
22 | //bbsfox.connect();//document.location.host
23 |
24 | var evt = new CustomEvent("bbsfoxReady", { bubbles: false, detail: '' });
25 | document.body.dispatchEvent(evt);
26 |
27 | }
28 |
29 | function release() {
30 | //document.getElementById('t').disabled="disabled";
31 | if(bbsfox) {
32 | bbsfox.prefListener.unregister();
33 | bbsfox.close();
34 | bbsfox=null;
35 | }
36 | window.removeEventListener('load', startup, true);
37 | window.removeEventListener('unload', release, true);
38 | window.removeEventListener('resize', resize, false);
39 | }
40 |
41 | function resize() {
42 | if(bbsfox)
43 | bbsfox.view.fontResize();
44 | }
45 |
46 | window.addEventListener('load', startup, true);
47 | window.addEventListener('unload', release, true);
48 | window.addEventListener('resize', resize, false);
49 |
--------------------------------------------------------------------------------
/data/js/bbsfox-about.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | let {components, Cc, Ci, Cm, Cr} = require("chrome");
3 |
4 | //reference: https://developer.mozilla.org/en-US/docs/Custom_about:_URLs
5 |
6 | Cm.QueryInterface(Ci.nsIComponentRegistrar);
7 |
8 | function AboutCustom() {}
9 | AboutCustom.prototype = Object.freeze({
10 | classDescription: 'BBSFox Preferences',
11 | contractID: '@mozilla.org/network/protocol/about;1?what=bbsfox',
12 | classID: components.ID('{be8771f0-2dbb-11e5-a2cb-0800200c9a66}'),
13 | QueryInterface: function QueryInterface(iid){
14 | if (iid.equals(Ci.nsIAboutModule))
15 | return this;
16 | else
17 | throw Cr.NS_ERROR_NO_INTERFACE;
18 | },
19 |
20 | getURIFlags: function(aURI) {
21 | return Ci.nsIAboutModule.ALLOW_SCRIPT;
22 | },
23 |
24 | newChannel: function(aURI, aSecurity_or_aLoadInfo) {
25 | if (! (aURI.spec === 'about:bbsfox') )
26 | return;
27 |
28 | let ios = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
29 | let uri = ios.newURI("chrome://bbsfox/content/options.xul", null, null);
30 | let channel = ios.newChannelFromURIWithLoadInfo(uri, aSecurity_or_aLoadInfo);
31 | channel.originalURI = aURI;
32 | return channel;
33 | }
34 | });
35 |
36 | function BBSFoxAboutFactory() {
37 | let component = AboutCustom;
38 | this.createInstance = function(outer, iid) {
39 | if (outer) {
40 | throw Cr.NS_ERROR_NO_AGGREGATION;
41 | }
42 | return new component();
43 | };
44 | this.register = function() {
45 | Cm.registerFactory(component.prototype.classID, component.prototype.classDescription, component.prototype.contractID, this);
46 | };
47 | this.unregister = function() {
48 | Cm.unregisterFactory(component.prototype.classID, this);
49 | }
50 | Object.freeze(this);
51 | this.register();
52 | }
53 |
54 | exports.Page = BBSFoxAboutFactory;
55 |
--------------------------------------------------------------------------------
/chrome/locale/en-US/bbsfox.properties:
--------------------------------------------------------------------------------
1 | mouseBrowse=Mouse Browsing
2 | mouseBrowseOff=Disable Mouse Browsing
3 | mouseBrowseOn=Enable Mouse Browsing
4 | messageNotify=Message Notify
5 | alert_down_finish=Download finished
6 | alert_down_terminate=Download terminated
7 | extensions.bbsfox2.locale=big5
8 | delayPasteFinish=Delay Paste Finished
9 | delayPasteStop=Delay Paste interrupted
10 | fontTestResult1=This font can use in Chinese and English BBS
11 | fontTestResult2=This font can use in English BBS
12 | fontTestResult3=This font can't use in BBS
13 | fontTestResult4=This font can use in Chinese and English BBS, but some symbol support not good, not proposed
14 | fontTestResult5=This font can use in English BBS
15 | fontTestResult6=This is not monospaced font, not proposed
16 | recoverwarning=This will replace all of your current BBSFox setting with the backup. Are you sure?
17 | delsitewarning=Are you sure want to delete site "%S" settings?
18 | delsitetitle=Delete site
19 | symbolList0=General Symbol
20 | symbolList1=Line Border
21 | symbolList2=Block
22 | symbolList3=Line
23 | symbolList4=Special Symbol
24 | symbolList5=Open/Close Bracket(Left/Right)
25 | symbolList6=Open/Close Bracket(Up/Down)
26 | symbolList7=Greek Alphabets
27 | symbolList8=Mandarin Phonetic Symbols
28 | symbolList9=Mathematical Symbols
29 | symbolList10=Hiragana
30 | symbolList11=Katakana
31 | foreground=Foreground
32 | background=Background
33 | blink=Blink
34 | sendAnsiColorCode=Send ANSI color code
35 | sendForegroundColorCode=Send foreground only
36 | sendBackgroundColorCode=Send background only
37 | sendResetColorCode=Send color reset code
38 | preview=PreviewText
39 | copyUrl=Copy URL
40 | SearchText=Search "%S"
41 | noThreadUrl=This borad not provide thread url
42 | errorConn=Unable to make a connection. Please try again.
43 | sftpCacheTitle=Add key to cache?
44 | sftpCache=The server's host key is not cached in the registry.\nYou have no guarantee that the server is the computer you think it is.\n\nThe server's rsa2 key fingerprint is:\n%S\n\nIf you trust this host, press "Yes" to add the key to the cache and carry on connecting.\nIf you want to carry on connecting just once, without adding the key to the cache, press "No".\nIf you do not trust this host, press "Cancel" to abandon the connection.
45 | defaultSite=default
46 | addBlacklist=Add %S to blacklist of site: %S ?
47 | removeBlacklist=Remove %S from blacklist of site: %S ?
48 |
--------------------------------------------------------------------------------
/bootstrap.js:
--------------------------------------------------------------------------------
1 | /* This Source Code Form is subject to the terms of the Mozilla Public
2 | * License, v. 2.0. If a copy of the MPL was not distributed with this
3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 | "use strict";
5 |
6 | const { utils: Cu, classes: Cc, interfaces: Ci } = Components;
7 | const rootURI = __SCRIPT_URI_SPEC__.replace("bootstrap.js", "");
8 | const COMMONJS_URI = "resource://gre/modules/commonjs";
9 | const { require } = Cu.import(COMMONJS_URI + "/toolkit/require.js", {});
10 | const { Bootstrap } = require(COMMONJS_URI + "/sdk/addon/bootstrap.js");
11 | var { startup: startupBS, shutdown: shutdownBS, install, uninstall } = new Bootstrap(rootURI);
12 | var enable = false;
13 | var addonBaseUrl = null;
14 |
15 | function unload() {
16 | //unload frame-script, unregister telnet protocol handler
17 | let globalMM = Cc["@mozilla.org/globalmessagemanager;1"].getService(Ci.nsIMessageBroadcaster);
18 | globalMM.removeDelayedFrameScript(addonBaseUrl + "data/js/frame-script.js");
19 | globalMM.removeMessageListener("bbsfox@ettoolong:bbsfox-globalCommand", exec);
20 | }
21 |
22 | function exec(msg) {
23 | switch(msg.data.name) {
24 | case "addonBaseUrl":
25 | return addonBaseUrl;
26 | case "unload":
27 | if(enable) {
28 | enable = false;
29 | return unload();
30 | }
31 | default:
32 | }
33 | }
34 |
35 | //reference: https://github.com/mozilla/pdf.js/blob/master/extensions/firefox/bootstrap.js
36 | function startup(aData, aReason) {
37 | addonBaseUrl = aData.resourceURI.spec;
38 | enable = true;
39 | startupBS(aData, aReason);
40 | //load frame-script, register telnet protocol handler
41 | let globalMM = Cc["@mozilla.org/globalmessagemanager;1"].getService(Ci.nsIFrameScriptLoader);
42 | globalMM.addMessageListener("bbsfox@ettoolong:bbsfox-globalCommand", exec);
43 | globalMM.loadFrameScript(addonBaseUrl + "data/js/frame-script.js", true);
44 | globalMM.broadcastAsyncMessage("bbsfox@ettoolong:bbsfox-globalCommand", {name:"load"});
45 | }
46 |
47 | function shutdown(aData, aReason) {
48 | shutdownBS(aData, aReason);
49 | if (aReason == APP_SHUTDOWN)
50 | return;
51 | let globalMM = Cc["@mozilla.org/globalmessagemanager;1"].getService(Ci.nsIMessageBroadcaster);
52 | // send message. it's time to unload frame-script.
53 | globalMM.broadcastAsyncMessage("bbsfox@ettoolong:bbsfox-globalCommand", {name:"unload"});
54 | }
55 |
--------------------------------------------------------------------------------
/chrome/content/pushThread.js:
--------------------------------------------------------------------------------
1 | var BBSPushThread = {
2 | lineLength : 54,
3 |
4 | init: function () {
5 | var retVals = window.arguments[0];
6 | if(retVals.pushText)
7 | document.getElementById("pushThreadText").value = retVals.pushText;
8 | this.lineLength = retVals.lineLength;
9 | this.setPreview();
10 | return true;
11 | },
12 |
13 | finish: function () {
14 | return true;
15 | },
16 |
17 | onSendAllText: function () {
18 | var retVals = window.arguments[0];
19 | var retVals2 = window.arguments[1];
20 | var strArray = document.getElementById("textPreview").value.split('\n');
21 | pushtype = document.getElementById("PushthreadType").value;
22 | for(var i=0;i this.lineLength)
59 | {
60 | preText = preview.value;
61 | if(preview.value.length)
62 | preview.value += ("\n" + tempText);
63 | else
64 | preview.value+=tempText;
65 | tempText = text[i];
66 | tempTextLen = nextLen
67 | }
68 | else
69 | {
70 | tempTextLen += nextLen;
71 | tempText+=text[i];
72 | }
73 | }
74 | if(preview.value.length)
75 | preview.value += ("\n" + tempText);
76 | else
77 | preview.value+=tempText;
78 |
79 | return true;
80 | }
81 | };
82 |
--------------------------------------------------------------------------------
/chrome/content/highlighter.js:
--------------------------------------------------------------------------------
1 | //reference:
2 | //https://github.com/mozilla-services/services-central-legacy/blob/master/toolkit/content/widgets/findbar.xml
3 |
4 | function Highlighter(bbscore) {
5 | this.nsISelectionController = Ci.nsISelectionController;
6 | this._findSelection = this.nsISelectionController.SELECTION_FIND;
7 | }
8 |
9 | Highlighter.prototype={
10 | highlight: function (text, caseSensitive) {
11 | this._highlightDoc(true, text, caseSensitive);
12 | },
13 |
14 | clean: function () {
15 | this._highlightDoc(false);
16 | },
17 |
18 | _getSelectionController: function (aWindow) {
19 | if (!aWindow.innerWidth || !aWindow.innerHeight)
20 | return null;
21 |
22 | var docShell = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
23 | .getInterface(Ci.nsIWebNavigation)
24 | .QueryInterface(Ci.nsIDocShell);
25 | var controller = docShell.QueryInterface(Ci.nsIInterfaceRequestor)
26 | .getInterface(Ci.nsISelectionDisplay)
27 | .QueryInterface(Ci.nsISelectionController);
28 | return controller;
29 | },
30 |
31 | _highlightDoc: function (aHighlight, aWord, caseSensitive) {
32 | var doc = document;
33 | var textFound = false;
34 |
35 | var controller = this._getSelectionController(window);
36 | if (!controller) {
37 | // Without the selection controller,
38 | // we are unable to (un)highlight any matches
39 | return textFound;
40 | }
41 |
42 | if (!doc || !(doc instanceof HTMLDocument))
43 | return textFound;
44 |
45 | if (aHighlight) {
46 | var searchRange = doc.createRange();
47 | searchRange.selectNodeContents(doc.body);
48 | var startPt = searchRange.cloneRange();
49 | startPt.collapse(true);
50 | var endPt = searchRange.cloneRange();
51 | endPt.collapse(false);
52 | var retRange = null;
53 | var finder = Cc["@mozilla.org/embedcomp/rangefind;1"].createInstance()
54 | .QueryInterface(Ci.nsIFind);
55 | finder.caseSensitive = caseSensitive;//this._shouldBeCaseSensitive(aWord);
56 | while ((retRange = finder.Find(aWord, searchRange, startPt, endPt))) {
57 | this._highlight(retRange, controller);
58 | startPt = retRange.cloneRange();
59 | startPt.collapse(false);
60 | textFound = true;
61 | }
62 | } else {
63 | // First, attempt to remove highlighting from main document
64 | var sel = controller.getSelection(this._findSelection);
65 | sel.removeAllRanges();
66 | // Next, check our editor cache, for editors belonging to this document
67 | return true;
68 | }
69 | return textFound;
70 | },
71 |
72 | _highlight: function (aRange, aController) {
73 | var controller = aController;
74 | var findSelection = controller.getSelection(this._findSelection);
75 | findSelection.addRange(aRange);
76 | }
77 | };
78 |
--------------------------------------------------------------------------------
/chrome/content/paramikojs/kryptos/Random/_UserFriendlyRNG.js:
--------------------------------------------------------------------------------
1 | kryptos.random.Random = function () {
2 | this._fa = new kryptos.random.Fortuna.FortunaAccumulator();
3 | this._ec = new kryptos.random._EntropyCollector(this._fa);
4 | this.reinit();
5 | }
6 |
7 | kryptos.random.Random.prototype = {
8 | reinit : function() {
9 | /*
10 | Initialize the random number generator and seed it with entropy from
11 | the operating system.
12 | */
13 | this._ec.reinit();
14 | },
15 |
16 | flush : function(s) {
17 | // pass
18 | },
19 |
20 | // Return N bytes from the RNG.
21 | read : function(N, dontFlush) {
22 | // Collect some entropy and feed it to Fortuna
23 | this._ec.collect(dontFlush);
24 |
25 | // Ask Fortuna to generate some bytes
26 | var retval = this._fa.random_data(N);
27 |
28 | // Return the random data.
29 | return retval;
30 | }
31 | };
32 |
33 |
34 | kryptos.random._EntropySource = function(accumulator, src_num) {
35 | this._fortuna = accumulator;
36 | this._src_num = src_num;
37 | this._pool_num = 0;
38 | }
39 |
40 | kryptos.random._EntropySource.prototype = {
41 | feed : function(data) {
42 | this._fortuna.add_random_event(this._src_num, this._pool_num, data);
43 | this._pool_num = (this._pool_num + 1) & 31;
44 | }
45 | };
46 |
47 | kryptos.random._EntropyCollector = function(accumulator) {
48 | this._osrng = new kryptos.random.OSRNG.BrowserRNG();
49 | this._osrng_es = new kryptos.random._EntropySource(accumulator, 255);
50 | this._time_es = new kryptos.random._EntropySource(accumulator, 254);
51 | this._time2_es = new kryptos.random._EntropySource(accumulator, 253);
52 |
53 | this.previousMilliseconds = new Date().getMilliseconds();
54 | }
55 |
56 | kryptos.random._EntropyCollector.prototype = {
57 | reinit : function() {
58 | // Add 256 bits to each of the 32 pools, twice. (For a total of 16384
59 | // bits collected from the operating system.)
60 | for (var i = 0; i < 2; ++i) {
61 | var block = this._osrng.read(32*32);
62 | for (var p = 0; p < 32; ++p) {
63 | this._osrng_es.feed(block.substring(p*32,(p+1)*32));
64 | }
65 | block = null;
66 | }
67 | this._osrng.flush();
68 | },
69 |
70 | collect : function(dontFlush) {
71 | // Collect 64 bits of entropy from the operating system and feed it to Fortuna.
72 | this._osrng_es.feed(this._osrng.read(8, dontFlush));
73 |
74 | // Add the fractional part of date
75 | var t = new Date().getMilliseconds() * Math.random() / 1000;
76 | this._time_es.feed(struct.pack("@I", parseInt(Math.pow(2, 30) * (t - Math.floor(t)))));
77 |
78 | // Add another fractional part of date
79 | var newMilliseconds = new Date().getMilliseconds();
80 | t = ((this.previousMilliseconds + newMilliseconds) % 1000) * Math.random() / 1000;
81 | this.previousMilliseconds = newMilliseconds;
82 | this._time2_es.feed(struct.pack("@I", parseInt(Math.pow(2, 30) * (t - Math.floor(t)))));
83 | }
84 | };
85 |
--------------------------------------------------------------------------------
/chrome/content/ansiFile.js:
--------------------------------------------------------------------------------
1 | function AnsiFile(ansiColor) {
2 | this.ansi = ansiColor;
3 | this.listener = ansiColor.listener;
4 | }
5 |
6 | AnsiFile.prototype = {
7 | doPasteFileData: function(data) {
8 | //TODO: remove clipboard operation, paste data directly
9 | //FIXME: load file with different charset
10 | let text = this.ansi.convertStringToUTF8(data);
11 | //this.ansi.ansiClipboard(text);
12 | this.ansi.paste(text);
13 | },
14 |
15 | savePage: function(saveMode) {
16 | //FIXME: save file with different charset
17 | let downloadArticle = this.listener.robot.downloadArticle;
18 | downloadArticle.finishCallback( data => {
19 | this.saveFile(data, saveMode);
20 | });
21 | downloadArticle.startDownloadEx(saveMode);
22 | },
23 |
24 | openTab: function() {
25 | let downloadArticle = this.listener.robot.downloadArticle;
26 | downloadArticle.finishCallback( data => {
27 | bbsfox.sendCoreCommand({command: "openEasyReadingTab", htmlData: data});
28 | });
29 | downloadArticle.startDownloadEx(2);
30 | },
31 |
32 | loadFile: function() {
33 | let nsIFilePicker = Ci.nsIFilePicker;
34 | bbsfox.sendCoreCommand({command: "openFilepicker",
35 | title: null,
36 | mode: nsIFilePicker.modeOpen,
37 | appendFilters: [nsIFilePicker.filterAll],
38 | postCommand: "doPasteFileData"});
39 | },
40 |
41 | saveFile: function(data, saveMode) {
42 | let nsIFilePicker = Ci.nsIFilePicker;
43 | let defaultExtension = "";
44 | let defaultString = "";
45 | let appendFilters = [];
46 | let convertUTF8 = false;
47 | let utf8BOM = false;
48 |
49 | if(saveMode == 0) {
50 | if(this.listener.prefs.deleteSpaceWhenCopy) {
51 | data = data.replace(/[ \t\f]+$/gm, "");
52 | }
53 | convertUTF8 = true;
54 | utf8BOM = true;
55 | defaultExtension = "txt";
56 | defaultString = "newtext";
57 | appendFilters.push(nsIFilePicker.filterAll);
58 | }
59 | else if(saveMode == 1) {
60 | defaultExtension = "ans";
61 | defaultString = "newansi";
62 | appendFilters.push(nsIFilePicker.filterAll);
63 | }
64 | else {//if(saveMode == 2)
65 | convertUTF8 = true;
66 | defaultExtension = "html";
67 | defaultString = "newhtml";
68 | appendFilters.push(nsIFilePicker.filterHTML);
69 | }
70 |
71 | bbsfox.sendCoreCommand({command: "openFilepicker",
72 | title: null,
73 | mode: nsIFilePicker.modeSave,
74 | defaultExtension:defaultExtension,
75 | defaultString: defaultString,
76 | appendFilters: appendFilters,
77 | saveData: data,
78 | convertUTF8: convertUTF8,
79 | utf8BOM: utf8BOM});
80 | }
81 | };
82 |
--------------------------------------------------------------------------------
/chrome/content/bbsbackground.js:
--------------------------------------------------------------------------------
1 | function BBSBackground(listener) {
2 | this.bbscore = listener;
3 | this.prefs = listener.prefs;
4 | this.BackgroundMD5='';
5 | this.DisplayBackground = false;
6 | this.BBSBg = document.getElementById('BBSBackgroundImage');
7 | this.key = 0;
8 | }
9 |
10 | BBSBackground.prototype = {
11 |
12 | ResetBackground: function(backgroundType, md5) {
13 | this.key++;
14 | if(backgroundType!=0 && md5!='') {
15 | let fileName;
16 |
17 | if(this.bbscore.isDefaultPref) {
18 | fileName = "_bg.default";
19 | }
20 | else {
21 | let url = this.bbscore.siteAuthInfo;
22 | url = url.replace(/:/g, '~');
23 | fileName = "_bg."+url;
24 | }
25 |
26 | //if(file exists)
27 | {
28 | this.BBSBg.style.backgroundImage='url(resource://bbsfox2/'+fileName+'?' + this.key + ')';
29 | //this.BBSBg.style.backgroundImage='url(resource://bbsfox2/bbsfoxBg/'+fileName+')';
30 | if(backgroundType==4) {
31 | this.BBSBg.style.backgroundSize='100% 100%';
32 | this.BBSBg.style.backgroundPosition='left top';
33 | this.BBSBg.style.backgroundRepeat='no-repeat';
34 | }
35 | else if(backgroundType==3) {
36 | this.BBSBg.style.backgroundSize='cover';
37 | this.BBSBg.style.backgroundPosition='left top';
38 | this.BBSBg.style.backgroundRepeat='no-repeat';
39 | }
40 | else if(backgroundType==2) {
41 | this.BBSBg.style.backgroundSize='auto auto';
42 | this.BBSBg.style.backgroundPosition='center center';
43 | this.BBSBg.style.backgroundRepeat='no-repeat';
44 | }
45 | else if(backgroundType==1) {
46 | this.BBSBg.style.backgroundSize='auto auto';
47 | this.BBSBg.style.backgroundPosition='center center';
48 | this.BBSBg.style.backgroundRepeat='repeat';
49 | }
50 | }
51 | /*
52 | else {
53 | console.log('file not exists');
54 | backgroundType=0;
55 | }
56 | */
57 | //try to load picture, if load fail, set backgroundType = 0;
58 | }
59 | if(backgroundType==0) {
60 | this.BBSBg.style.display='none';
61 | this.prefs.enableBackground = false;
62 | this.DisplayBackground=true;
63 | this.BackgroundMD5='';
64 | }
65 | else {
66 | this.BBSBg.style.display='block';
67 | this.prefs.enableBackground = true;
68 | this.DisplayBackground=true;
69 | }
70 | },
71 |
72 | SwitchBgDisplay: function() {
73 | if(this.DisplayBackground) {
74 | this.DisplayBackground = false;
75 | this.BBSBg.style.display='none';
76 | }
77 | else {
78 | this.DisplayBackground = true;
79 | this.BBSBg.style.display='block';
80 | }
81 | },
82 |
83 | SetBrightness: function(brightness) {
84 | if(brightness == 100)// no alpha
85 | this.BBSBg.style.opacity = '1';
86 | else
87 | this.BBSBg.style.opacity = '0.' + (brightness);
88 | },
89 |
90 | SetSize: function(w, h) {
91 | this.BBSBg.style.height = h;
92 | this.BBSBg.style.width = w;
93 | }
94 |
95 | };
96 |
--------------------------------------------------------------------------------
/chrome/content/extPicLoader.js:
--------------------------------------------------------------------------------
1 | function BBSFoxHttpReq(redirection, info, callback) {
2 | this.info = info;
3 | this.callback = callback;
4 | this.xmlhttp = new XMLHttpRequest();
5 | this.redirection = redirection;
6 | }
7 |
8 | BBSFoxHttpReq.prototype={
9 | open: function(url){
10 | var _this = this;
11 | this.xmlhttp.onreadystatechange = function() {_this.onPageResponse(this);};
12 | this.xmlhttp.open("GET",url,true);
13 | if(!this.redirection)
14 | this.xmlhttp.channel.QueryInterface(Ci.nsIHttpChannel).redirectionLimit = 0;
15 | this.xmlhttp.send(null);
16 | },
17 | onPageResponse: function(xmlhttp) {
18 | try
19 | {
20 | if(xmlhttp.readyState ==4)
21 | {
22 | this.info.status = xmlhttp.status;
23 | this.info.responseText = xmlhttp.responseText;
24 | this.callback(this.info);
25 | }
26 | }
27 | catch(e)
28 | {
29 | this.info.err = 'err';
30 | this.callback(this.info);
31 | //alert('err');
32 | }
33 | }
34 | };
35 |
36 | function ExtPicLoader(listener) {
37 | this.bbscore = listener;
38 | Cu.import("chrome://bbsfox/content/picLoader/picLoader_ppt.js");
39 | Cu.import("chrome://bbsfox/content/picLoader/picLoader_imgur.js");
40 | this.dp = new DOMParser();
41 |
42 | //https://developer.mozilla.org/en-US/Add-ons/Code_snippets/HTML_to_DOM
43 | var htmlParser = function (aHTMLString){
44 | var html = document.implementation.createDocument("http://www.w3.org/1999/xhtml", "html", null),
45 | body = document.createElementNS("http://www.w3.org/1999/xhtml", "body");
46 | html.documentElement.appendChild(body);
47 | body.appendChild(Cc["@mozilla.org/feed-unescapehtml;1"].getService(Ci.nsIScriptableUnescapeHTML).parseFragment(aHTMLString, false, null, body));
48 | return body;
49 | };
50 | this.pptPicLoader = new BBSPPTPicLoader(this, this.dp, BBSFoxHttpReq, htmlParser);
51 | this.imgurPicLoader = new BBSImgurPicLoader(this, this.dp, BBSFoxHttpReq, htmlParser);
52 | }
53 |
54 | ExtPicLoader.prototype={
55 | setCallback: function(action, cb){
56 | if(action == "load")
57 | this.loadCB = cb;
58 | else if(action == "show")
59 | this.showCB = cb;
60 | else if(action == "locate")
61 | this.locateCB = cb;
62 | },
63 |
64 | query: function(url, callback){
65 | if( this.imgurPicLoader.query(url, callback) ) return true;
66 | if( this.pptPicLoader.query(url, callback) ) return true;
67 | return false;
68 | },
69 |
70 | show: function(url, owner){
71 | if( this.imgurPicLoader.show(url, owner) ) return true;
72 | if( this.pptPicLoader.show(url, owner) ) return true;
73 | return false;
74 | },
75 |
76 | load: function(url, cb){
77 | if( this.imgurPicLoader.load(url, cb) ) return true;
78 | if( this.pptPicLoader.load(url, cb) ) return true;
79 | return false;
80 | },
81 |
82 | cb_locate: function(){
83 | this.locateCB(this.bbscore.view.tempPicX, this.bbscore.view.tempPicY);
84 | },
85 |
86 | cb_load: function(linkUrl, picUrl){
87 | this.loadCB(linkUrl, picUrl);
88 | },
89 |
90 | cb_show: function(owner, url){
91 | this.showCB(owner, url);
92 | }
93 |
94 | };
95 |
--------------------------------------------------------------------------------
/chrome/content/aidhandler.js:
--------------------------------------------------------------------------------
1 | function Aidhandler() {
2 |
3 | }
4 |
5 | Aidhandler.prototype={
6 | aid_base64_table: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_",
7 |
8 | repeat: function (str_in, count) {
9 | if (str_in == null) {
10 | throw new TypeError('can\'t convert null to object');
11 | }
12 | var str = '' + str_in;
13 | count = +count;
14 | if (count != count) {
15 | count = 0;
16 | }
17 | if (count < 0) {
18 | throw new RangeError('repeat count must be non-negative');
19 | }
20 | if (count == Infinity) {
21 | throw new RangeError('repeat count must be less than infinity');
22 | }
23 | count = Math.floor(count);
24 | if (str.length == 0 || count == 0) {
25 | return '';
26 | }
27 | // Ensuring count is a 31-bit integer allows us to heavily optimize the
28 | // main part. But anyway, most current (august 2014) browsers can't handle
29 | // strings 1 << 28 chars or longer, so:
30 | if (str.length * count >= 1 << 28) {
31 | throw new RangeError('repeat count must not overflow maximum string size');
32 | }
33 | var rpt = '';
34 | for (;;) {
35 | if ((count & 1) == 1) {
36 | rpt += str;
37 | }
38 | count >>>= 1;
39 | if (count == 0) {
40 | break;
41 | }
42 | str += str;
43 | }
44 | return rpt;
45 | },
46 |
47 | rjust: function (str, width, padding) {
48 | padding = (padding || " ").substr(0, 1);
49 | if (str.length < width) {
50 | //return padding.repeat(width - str.length) + str;
51 | return this.repeat(padding, width - str.length) + str;
52 | }
53 | else {
54 | return str;
55 | }
56 | },
57 |
58 | aidc2aidu: function (aidc) {
59 | var aidu = 0;
60 | for (var i = 0; i < aidc.length; i++) {
61 | var ch = aidc.charAt(i);
62 | var v = this.aid_base64_table.indexOf(ch);
63 | aidu = aidu * Math.pow(2, 6); // aidu <<= 6
64 | aidu = aidu - (aidu & 0x3f) + ((aidu & 0x3f) | (v & 0x3f)); // aidu |= (v & 0x3f);
65 | }
66 | return aidu;
67 | },
68 |
69 | aidu2fn: function (aidu) {
70 | var type = ((aidu / Math.pow(2, 44)) & 0xf); // type = ((aidu >> 44) & 0xf);
71 | var v1 = ((aidu / Math.pow(2, 12)) & 0xffffffff); // v1 = ((aidu >> 12) & 0xffffffff);
72 | var v2 = (aidu & 0xfff);
73 | var tmps = (type == 0 ? "M" : "G") + "." + v1.toString(10) + ".A." + v2.toString(16).toUpperCase();
74 | var filename = this.rjust(tmps, 3, "0");
75 | return filename;
76 | },
77 |
78 | buildUrl: function(boardName, fileName) {
79 | var protocol = 'https:';
80 | var hostname = 'www.ptt.cc';
81 | var port = ':443';
82 | var url = protocol + "//" + hostname + port + "/bbs/" + boardName + "/" + fileName + ".html";
83 | return url;
84 | },
85 |
86 | pttArticleUrlFromAidc: function (aidc, boardName) {
87 | // aidc should match [0-9a-zA-Z_\-]{8}
88 | var aidu = this.aidc2aidu(aidc);
89 | var fileName = this.aidu2fn(aidu);
90 | var articleUrl = this.buildUrl(boardName, fileName);
91 | //console.log("aidc =", aidc, "boardName =", boardName);
92 | return articleUrl;
93 | },
94 |
95 | };
96 |
--------------------------------------------------------------------------------
/chrome/content/paramikojs/common.js:
--------------------------------------------------------------------------------
1 | function paramikojs() { }
2 | paramikojs = {
3 | MSG_DISCONNECT : 1,
4 | MSG_IGNORE : 2,
5 | MSG_UNIMPLEMENTED : 3,
6 | MSG_DEBUG : 4,
7 | MSG_SERVICE_REQUEST : 5,
8 | MSG_SERVICE_ACCEPT : 6,
9 |
10 | MSG_KEXINIT : 20,
11 | MSG_NEWKEYS : 21,
12 |
13 | MSG_USERAUTH_REQUEST : 50,
14 | MSG_USERAUTH_FAILURE : 51,
15 | MSG_USERAUTH_SUCCESS : 52,
16 | MSG_USERAUTH_BANNER : 53,
17 |
18 | MSG_USERAUTH_PK_OK : 60,
19 |
20 | MSG_USERAUTH_INFO_REQUEST : 60,
21 | MSG_USERAUTH_INFO_RESPONSE : 61,
22 |
23 | MSG_GLOBAL_REQUEST : 80,
24 | MSG_REQUEST_SUCCESS : 81,
25 | MSG_REQUEST_FAILURE : 82,
26 |
27 | MSG_CHANNEL_OPEN : 90,
28 | MSG_CHANNEL_OPEN_SUCCESS : 91,
29 | MSG_CHANNEL_OPEN_FAILURE : 92,
30 | MSG_CHANNEL_WINDOW_ADJUST : 93,
31 | MSG_CHANNEL_DATA : 94,
32 | MSG_CHANNEL_EXTENDED_DATA : 95,
33 | MSG_CHANNEL_EOF : 96,
34 | MSG_CHANNEL_CLOSE : 97,
35 | MSG_CHANNEL_REQUEST : 98,
36 | MSG_CHANNEL_SUCCESS : 99,
37 | MSG_CHANNEL_FAILURE : 100,
38 |
39 | // for debugging:
40 | MSG_NAMES : {
41 | 1: 'disconnect',
42 | 2: 'ignore',
43 | 3: 'unimplemented',
44 | 4: 'debug',
45 | 5: 'service-request',
46 | 6: 'service-accept',
47 | 20: 'kexinit',
48 | 21: 'newkeys',
49 | 30: 'kex30',
50 | 31: 'kex31',
51 | 32: 'kex32',
52 | 33: 'kex33',
53 | 34: 'kex34',
54 | 50: 'userauth-request',
55 | 51: 'userauth-failure',
56 | 52: 'userauth-success',
57 | 53: 'userauth--banner',
58 | 60: 'userauth-60(pk-ok/info-request)',
59 | 61: 'userauth-info-response',
60 | 80: 'global-request',
61 | 81: 'request-success',
62 | 82: 'request-failure',
63 | 90: 'channel-open',
64 | 91: 'channel-open-success',
65 | 92: 'channel-open-failure',
66 | 93: 'channel-window-adjust',
67 | 94: 'channel-data',
68 | 95: 'channel-extended-data',
69 | 96: 'channel-eof',
70 | 97: 'channel-close',
71 | 98: 'channel-request',
72 | 99: 'channel-success',
73 | 100: 'channel-failure'
74 | },
75 |
76 | // authentication request return codes:
77 | AUTH_SUCCESSFUL : 0,
78 | AUTH_PARTIALLY_SUCCESSFUL : 1,
79 | AUTH_FAILED : 2,
80 |
81 | // channel request failed reasons:
82 | OPEN_SUCCEEDED : 0,
83 | OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED : 1,
84 | OPEN_FAILED_CONNECT_FAILED : 2,
85 | OPEN_FAILED_UNKNOWN_CHANNEL_TYPE : 3,
86 | OPEN_FAILED_RESOURCE_SHORTAGE : 4,
87 |
88 | CONNECTION_FAILED_CODE : {
89 | 1: 'Administratively prohibited',
90 | 2: 'Connect failed',
91 | 3: 'Unknown channel type',
92 | 4: 'Resource shortage'
93 | },
94 |
95 | DISCONNECT_SERVICE_NOT_AVAILABLE : 7,
96 | DISCONNECT_AUTH_CANCELLED_BY_USER : 13,
97 | DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE : 14
98 | };
99 |
100 | function inherit(derived, base) {
101 | for (property in base) {
102 | if (!derived[property]) {
103 | derived[property] = base[property];
104 | }
105 | }
106 | }
107 |
108 | var logging = {
109 | DEBUG : 10,
110 | INFO : 20,
111 | WARNING : 30,
112 | ERROR : 40,
113 | CRITICAL : 50,
114 |
115 | log : function(level, msg) {
116 | /* Override this as desired. */
117 | }
118 | };
119 | DEBUG = logging.DEBUG;
120 | INFO = logging.INFO;
121 | WARNING = logging.WARNING;
122 | ERROR = logging.ERROR;
123 | CRITICAL = logging.CRITICAL;
124 |
125 | var ssh_console = {
126 | log: false,
127 | info: false,
128 | debug: false,
129 | error: false,
130 | warn: false
131 | };
132 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "title": "BBSFox",
3 | "name": "bbsfox",
4 | "id": "{86095750-AD15-46d8-BF32-C0789F7E6A32}",
5 | "version": "5.0.24",
6 | "description": "Telnet client extension specifically designed for BBS browsing.",
7 | "main": "data/js/addon-script.js",
8 | "author": "ettoolong@hotmail.com",
9 | "homepage": "https://addons.mozilla.org/zh-TW/firefox/user/ett-chung/",
10 | "engines": {
11 | "firefox": ">=51.0"
12 | },
13 | "license": "MIT",
14 | "keywords": [
15 | "jetpack"
16 | ],
17 | "permissions":{
18 | "multiprocess": true,
19 | "private-browsing": true
20 | },
21 | "icon": "resource://86095750-AD15-46d8-BF32-C0789F7E6A32/data/img/logo/logo.png",
22 | "icon64": "resource://86095750-AD15-46d8-BF32-C0789F7E6A32/data/img/logo/logo.png",
23 | "preferences": [{
24 | "type": "control",
25 | "label": "Preferences",
26 | "name": "openPrefsTab",
27 | "title": "Preferences"
28 | },
29 | {
30 | "type": "control",
31 | "label": "User Manual",
32 | "name": "openUserManual",
33 | "title": "User Manual"
34 | },
35 | {
36 | "type": "control",
37 | "label": "Report Bug",
38 | "name": "reportBug",
39 | "title": "Report Bug"
40 | }],
41 | "translators":[
42 | "pc102880(forum.moztw.org)",
43 | "u881831(forum.moztw.org)"
44 | ],
45 | "contributors":[
46 | "PCMan (forum.moztw.org)",
47 | "u881831 (forum.moztw.org)",
48 | "pc102880 (forum.moztw.org)",
49 | "筆筆 (forum.moztw.org)",
50 | "homegoyes (forum.moztw.org)",
51 | "Velociraptor (forum.moztw.org)",
52 | "gejiod (forum.moztw.org)",
53 | "orange (forum.moztw.org)",
54 | "alex301 (forum.moztw.org)",
55 | "JoJos (forum.moztw.org)",
56 | "TC_player (forum.moztw.org)",
57 | "happyday (forum.moztw.org)",
58 | "capcomfan2010 (forum.moztw.org)",
59 | "chenlarry124 (forum.moztw.org)",
60 | "Kill (forum.moztw.org)",
61 | "ryan0805 (forum.moztw.org)",
62 | "waytin (forum.moztw.org)",
63 | "54fu0 (forum.moztw.org)",
64 | "tonyxfg (forum.moztw.org)",
65 | "tanchen (forum.moztw.org)",
66 | "jonnysun (forum.moztw.org)",
67 | "bot3700 (forum.moztw.org)",
68 | "duolin (forum.moztw.org)",
69 | "bowei12 (forum.moztw.org)",
70 | "holic3x (forum.moztw.org)",
71 | "浩 (forum.moztw.org)",
72 | "akuma (forum.moztw.org)",
73 | "shyangs (forum.moztw.org)",
74 | "dada234234 (forum.moztw.org)",
75 | "david7928 (forum.moztw.org)",
76 | "spreee (forum.moztw.org)",
77 | "Coopoo (forum.moztw.org)",
78 | "hyk (forum.moztw.org)",
79 | "mmis1000 (forum.moztw.org)",
80 | "adam (forum.moztw.org)",
81 | "house_chiu (forum.moztw.org)",
82 | "kk7system (forum.moztw.org)",
83 | "Treant (ptt.cc)",
84 | "maplemeowcat (ptt.cc)",
85 | "abatw (ptt.cc)",
86 | "fljh90047 (ptt.cc)",
87 | "MARGHT (ptt.cc)",
88 | "mybaby520 (ptt.cc)",
89 | "poxazrt (ptt.cc)",
90 | "Mysterioux (ptt.cc)",
91 | "iamchucky (ptt.cc)",
92 | "yukitowu (ptt.cc)",
93 | "WFXX (ptt.cc)",
94 | "vanjr (ptt.cc)",
95 | "mayuyu (ptt.cc)",
96 | "orange0319 (ptt.cc)",
97 | "doom3 (ptt.cc)",
98 | "dudeboy (ptt.cc)",
99 | "natsugo (ptt.cc)",
100 | "topgunguy (ptt.cc)",
101 | "exam1 (bbs.gamer.com.tw)",
102 | "zendic (bbs.gamer.com.tw)",
103 | "a11221 (bbs.gamer.com.tw)",
104 | "tottoko (bbs.gamer.com.tw)",
105 | "icearea (bbs.gamer.com.tw)",
106 | "legnaleurc (github.com)",
107 | "polar2031 (github.com)",
108 | "ngoo5tsong5sik (github.com)"
109 | ]
110 | }
111 |
--------------------------------------------------------------------------------
/chrome/content/alertService.js:
--------------------------------------------------------------------------------
1 | function AlertService(core, view, buf, conn) {
2 | this.core = core;
3 | this.view = view;
4 | this.conn = conn;
5 | this.prefs = core.prefs;
6 | this.buf = buf;
7 | this.tempX = 0;
8 | this.tempY = 0;
9 | this.checkCur = 0;//0 = unknow, 1 = check, 2 = don't check.
10 | }
11 |
12 | AlertService.prototype={
13 | alertTimer : null,
14 | lastMsgTime : 0,
15 | alert: function(blockByTime, showMsg, playSound, msg, clickAlertAction) {
16 | if(this.checkCur==0)
17 | {
18 | if(this.core.isPTT())
19 | this.checkCur = 1;
20 | else
21 | this.checkCur = 2;
22 | }
23 |
24 | if(!showMsg && !playSound)
25 | return;
26 | if(msg!=""){
27 | var execAlert = true;
28 | if(blockByTime)
29 | {
30 | var timeN = new Date();
31 | var timeT = Math.floor(timeN.getTime()/1000);
32 | if(this.lastMsgTime != timeT)
33 | this.lastMsgTime = timeT;
34 | else
35 | execAlert = false;
36 | }
37 | if(execAlert)
38 | {
39 | if(playSound)
40 | this.beep(msg);
41 | if(showMsg)
42 | this.showPopups(document.title, msg, this.prefs.clickAlertAction);
43 | }
44 | }
45 | else{
46 | this.cancelAlertTimer();
47 | var _this=this;
48 | this.tempX = this.buf.cur_x;
49 | this.tempY = this.buf.cur_y;
50 | var func=function() {
51 | if((_this.buf.cur_y==_this.buf.rows-1 || _this.buf.cur_y==_this.buf.rows-2) && (_this.tempX != _this.buf.cur_x || _this.tempY != _this.buf.cur_y || _this.checkCur==2) ){
52 | _this.tempX = 0;
53 | _this.tempY = 0;
54 | var msg = _this.getMsg(_this.buf.cur_y);
55 | var column = msg.replace(/^ +/,"").split(" ");
56 | var summary = document.title + " - " + column.shift();
57 | var body = column.join(" ");
58 | if(playSound)
59 | _this.beep(msg);
60 | if(showMsg)
61 | _this.showPopups(summary, body, _this.prefs.clickAlertAction);
62 | }
63 | else{
64 | //don't notify
65 | //alert('_this.tempX = '+_this.tempX+", _this.tempY = " + _this.tempY);
66 | }
67 | };
68 | this.alertTimer = setTimer(false, func, 200);
69 | }
70 | },
71 |
72 | cancelAlertTimer: function() {
73 | if(this.alertTimer)
74 | {
75 | this.alertTimer.cancel();
76 | this.alertTimer=null;
77 | }
78 | },
79 |
80 | getMsg: function(row) {
81 | var text = this.buf.getRowText(row, 0, this.buf.cols);
82 | return text.replace(/ +$/,"");
83 | },
84 |
85 | beep: function(msg) {
86 | this.core.sendCoreCommand({command: "fireNotifySound"}, true);
87 | //FIXME: support custum sound:
88 | //https://developer.mozilla.org/en/nsISound#play()
89 | },
90 |
91 | showPopups: function(caption, message, clickAlertAction) {
92 | this.core.sendCoreCommand({command: "showNotifyMessage",
93 | imageUrl: "chrome://bbsfox/skin/logo/logo.png",
94 | title: caption,
95 | text: message,
96 | replyString: clickAlertAction==2 ? this.prefs.alertReplyString : null,
97 | textClickable: (clickAlertAction==1 || clickAlertAction==2) });
98 | }
99 | };
100 |
--------------------------------------------------------------------------------
/chrome/content/paramikojs/kryptos/Random/Fortuna/FortunaGenerator.js:
--------------------------------------------------------------------------------
1 | kryptos.random.Fortuna.FortunaGenerator = {};
2 |
3 | kryptos.random.Fortuna.FortunaGenerator.AESGenerator = function() {
4 | /*
5 | The Fortuna "generator"
6 |
7 | This is used internally by the Fortuna PRNG to generate arbitrary amounts
8 | of pseudorandom data from a smaller amount of seed data.
9 |
10 | The output is generated by running AES-256 in counter mode and re-keying
11 | after every mebibyte (2**16 blocks) of output.
12 | */
13 |
14 | this.counter = new paramikojs.util.Counter(this.block_size * 8, 0);
15 | this.key = null;
16 |
17 | // Set some helper constants
18 | this.block_size_shift = 4; // exact_log2(this.block_size);
19 |
20 | this.blocks_per_key = 2; // exact_div(this.key_size, this.block_size);
21 |
22 | this.max_bytes_per_request = this.max_blocks_per_request * this.block_size;
23 | }
24 |
25 | kryptos.random.Fortuna.FortunaGenerator.AESGenerator.prototype = {
26 | block_size : 16, // output block size in octets (128 bits)
27 | key_size : 32, // key size in octets (256 bits)
28 |
29 | // Because of the birthday paradox, we expect to find approximately one
30 | // collision for every 2**64 blocks of output from a real random source.
31 | // However, this code generates pseudorandom data by running AES in
32 | // counter mode, so there will be no collisions until the counter
33 | // (theoretically) wraps around at 2**128 blocks. Thus, in order to prevent
34 | // Fortuna's pseudorandom output from deviating perceptibly from a true
35 | // random source, Ferguson and Schneier specify a limit of 2**16 blocks
36 | // without rekeying.
37 | max_blocks_per_request : Math.pow(2, 16), // Allow no more than this number of blocks per _pseudo_random_data request
38 |
39 | _four_kiblocks_of_zeros : new Array(16 * 4096 + 1).join("\0"), // 16 == block_size
40 |
41 | reseed : function(seed) {
42 | if (!this.key) {
43 | this.key = new Array(this.key_size + 1).join("\0");
44 | }
45 | this._set_key(new kryptos.random.Fortuna.SHAd256(this.key + seed).digest());
46 | this.counter.call(); // increment counter
47 | },
48 |
49 | pseudo_random_data : function(bytes) {
50 | var num_full_blocks = bytes >> 20;
51 | var remainder = bytes & ((1<<20)-1);
52 |
53 | var retval = [];
54 | for (var i = 0; i < num_full_blocks; ++i) {
55 | retval.push(this._pseudo_random_data(1<<20));
56 | }
57 | retval.push(this._pseudo_random_data(remainder));
58 |
59 | return retval.join("");
60 | },
61 |
62 | _set_key : function(key) {
63 | this.key = key;
64 | this._cipher = new kryptos.cipher.AES(key, kryptos.cipher.AES.MODE_CTR, 0, this.counter);
65 | },
66 |
67 | _pseudo_random_data : function(bytes) {
68 | var num_blocks = Math.ceil(1.0 * bytes / this.block_size_shift); // num_blocks = ceil(bytes / self.block_size)
69 |
70 | // Compute the output
71 | var retval = this._generate_blocks(num_blocks).substring(0, bytes);
72 |
73 | // Switch to a new key to avoid later compromises of this output (i.e.
74 | // state compromise extension attacks)
75 | this._set_key(this._generate_blocks(this.blocks_per_key));
76 |
77 | return retval;
78 | },
79 |
80 | _generate_blocks : function(num_blocks) {
81 | var retval = [];
82 | for (var i = 0; i < num_blocks >> 12; ++i) { // xrange(num_blocks / 4096)
83 | retval.push(this._cipher.encrypt(this._four_kiblocks_of_zeros));
84 | }
85 | var remaining_bytes = (num_blocks & 4095) << this.block_size_shift; // (num_blocks % 4095) * self.block_size
86 | retval.push(this._cipher.encrypt(this._four_kiblocks_of_zeros.substring(0, remaining_bytes)));
87 | return retval.join("");
88 | }
89 | };
90 |
--------------------------------------------------------------------------------
/chrome/content/paramikojs/ber.js:
--------------------------------------------------------------------------------
1 | paramikojs.BER = function (content) {
2 | this.content = content;
3 | this.idx = 0;
4 | }
5 |
6 | paramikojs.BER.prototype = {
7 | toString : function() {
8 | return this.content;
9 | },
10 |
11 | decode : function() {
12 | return this.decode_next();
13 | },
14 |
15 | decode_next : function() {
16 | if (this.idx >= this.content.length) {
17 | return null;
18 | }
19 | var ident = this.content[this.idx].charCodeAt(0);
20 | var t;
21 | this.idx += 1;
22 | if ((ident & 31) == 31) {
23 | // identifier > 30
24 | ident = 0;
25 | while (this.idx < this.content.length) {
26 | t = this.content[this.idx].charCodeAt(0);
27 | this.idx += 1;
28 | ident = (ident << 7) | (t & 0x7f);
29 | if (!(t & 0x80)) {
30 | break;
31 | }
32 | }
33 | }
34 | if (this.idx >= this.content.length) {
35 | return null;
36 | }
37 | // now fetch length
38 | var size = this.content[this.idx].charCodeAt(0);
39 | this.idx += 1;
40 | if (size & 0x80) {
41 | // more complimicated...
42 | // FIXME: theoretically should handle indefinite-length (0x80)
43 | t = size & 0x7f;
44 | if (this.idx + t > this.content.length) {
45 | return null;
46 | }
47 | size = paramikojs.util.inflate_long(this.content.substring(this.idx, this.idx + t), true).intValue();
48 | this.idx += t;
49 | }
50 | if (this.idx + size > this.content.length) {
51 | // can't fit
52 | return null;
53 | }
54 | var data = this.content.substring(this.idx, this.idx + size);
55 | this.idx += size;
56 | // now switch on id
57 | if (ident == 0x30) {
58 | // sequence
59 | return this.decode_sequence(data);
60 | } else if (ident == 2) {
61 | // int
62 | return paramikojs.util.inflate_long(data);
63 | } else {
64 | // 1: boolean (00 false, otherwise true)
65 | throw new paramikojs.ssh_exception.BERException('Unknown ber encoding type ' + ident + ' (robey is lazy)');
66 | }
67 | },
68 |
69 | decode_sequence : function(data) {
70 | var out = [];
71 | var b = new paramikojs.BER(data);
72 | while (true) {
73 | var x = b.decode_next();
74 | if (!x) {
75 | break;
76 | }
77 | out.push(x);
78 | }
79 | return out;
80 | },
81 |
82 | encode_tlv : function(ident, val) {
83 | // no need to support ident > 31 here
84 | this.content += String.fromCharCode(ident);
85 | if (val.length > 0x7f) {
86 | var lenstr = paramikojs.util.deflate_long(val.length);
87 | this.content += String.fromCharCode(0x80 + lenstr.length) + lenstr;
88 | } else {
89 | this.content += String.fromCharCode(val.length);
90 | }
91 | this.content += val;
92 | },
93 |
94 | encode : function(x) {
95 | if (typeof x == "boolean") {
96 | if (x) {
97 | this.encode_tlv(1, '\xff');
98 | } else {
99 | this.encode_tlv(1, '\x00');
100 | }
101 | } else if (typeof x == "number") {
102 | this.encode_tlv(2, paramikojs.util.deflate_long(x));
103 | } else if (typeof x == "string") {
104 | this.encode_tlv(4, x);
105 | } else if (x instanceof Array) {
106 | this.encode_tlv(0x30, this.encode_sequence(x));
107 | } else {
108 | throw new paramikojs.ssh_exception.BERException('Unknown type for encoding: ' + typeof x);
109 | }
110 | },
111 |
112 | encode_sequence : function(data) {
113 | var b = new paramikojs.BER();
114 | for (var x = 0; x < data.length; ++x) {
115 | b.encode(data[x]);
116 | }
117 | return str(b);
118 | }
119 | };
120 |
--------------------------------------------------------------------------------
/chrome/content/paramikojs/python_shim.js:
--------------------------------------------------------------------------------
1 | var binascii = {
2 | hexlify : function(str, padding) {
3 | var result = "";
4 | padding = padding || '';
5 | for (var x = 0; x < str.length; ++x) {
6 | var c = str.charCodeAt(x).toString(16);
7 | result += (c.length == 1 ? '0' : '') + c + padding;
8 | }
9 | return result;
10 | },
11 |
12 | unhexlify : function(str) {
13 | var result = "";
14 | for (var x = 0; x < str.length; x += 2) {
15 | result += String.fromCharCode(parseInt(str.charAt(x) + str.charAt(x + 1), 16));
16 | }
17 | return result;
18 | }
19 | };
20 |
21 | var base64 = {
22 | encodestring : function(input) {
23 | return window.btoa(input);
24 | },
25 |
26 | decodestring : function(input) {
27 | return window.atob(input);
28 | }
29 | };
30 |
31 | /*
32 | This is a dumbed down version of the python function only doing a couple formats and big-endian only currently.
33 | todo: allow for unlimited arguments
34 | */
35 | var struct = {
36 | pack : function(fmt, v) {
37 | var type = fmt[1];
38 | var result = "";
39 | switch (type) {
40 | case 'Q':
41 | var ff = new BigInteger('ff', 16);
42 | result += String.fromCharCode(v.shiftRight(56).and(ff));
43 | result += String.fromCharCode(v.shiftRight(48).and(ff));
44 | result += String.fromCharCode(v.shiftRight(40).and(ff));
45 | result += String.fromCharCode(v.shiftRight(32).and(ff));
46 | result += String.fromCharCode(v.shiftRight(24).and(ff));
47 | result += String.fromCharCode(v.shiftRight(16).and(ff));
48 | result += String.fromCharCode(v.shiftRight(8).and(ff));
49 | result += String.fromCharCode(v.and(ff));
50 | break;
51 | case 'I':
52 | result += String.fromCharCode(v >>> 24 & 0xff);
53 | result += String.fromCharCode(v >>> 16 & 0xff);
54 | result += String.fromCharCode(v >>> 8 & 0xff);
55 | // fall through
56 | case 'B':
57 | result += String.fromCharCode(v & 0xff);
58 | break;
59 | }
60 |
61 | return result;
62 | },
63 |
64 | unpack : function(fmt, str) {
65 | var type = fmt[1];
66 | var result = [];
67 | var index = 0;
68 | var v = 0;
69 | switch (type) {
70 | case 'Q':
71 | v = new BigInteger("0", 10);
72 |
73 | v = v.add(new BigInteger(str.charCodeAt(0).toString(), 10).shiftLeft(56));
74 | v = v.add(new BigInteger(str.charCodeAt(1).toString(), 10).shiftLeft(48));
75 | v = v.add(new BigInteger(str.charCodeAt(2).toString(), 10).shiftLeft(40));
76 | v = v.add(new BigInteger(str.charCodeAt(3).toString(), 10).shiftLeft(32));
77 | v = v.add(new BigInteger(str.charCodeAt(4).toString(), 10).shiftLeft(24));
78 | v = v.add(new BigInteger(str.charCodeAt(5).toString(), 10).shiftLeft(16));
79 | v = v.add(new BigInteger(str.charCodeAt(6).toString(), 10).shiftLeft(8));
80 | v = v.add(new BigInteger(str.charCodeAt(7).toString(), 10).shiftLeft(0));
81 | result.push(v);
82 | break;
83 | case 'I':
84 | v += str.charCodeAt(0) << 24 >>> 0;
85 | v += str.charCodeAt(1) << 16 >>> 0;
86 | v += str.charCodeAt(2) << 8 >>> 0;
87 | index += 3;
88 | // fall through
89 | case 'B':
90 | v += str.charCodeAt(0 + index) << 0 >>> 0;
91 | result.push(v);
92 | break;
93 | }
94 |
95 | return result;
96 | }
97 | };
98 |
99 | var sys = {
100 | 'browser' : typeof window !== 'undefined' ? (navigator.userAgent.toLowerCase().indexOf('chrome') != -1 ? 'chrome' : 'mozilla') : 'server',
101 | 'platform' : typeof window !== 'undefined' ? (navigator.platform.toLowerCase().indexOf('linux') != -1 ? 'linux' :
102 | (navigator.platform.toLowerCase().indexOf('mac') != -1 ? 'darwin' : 'win32')) : 'server'
103 | };
104 |
--------------------------------------------------------------------------------
/chrome/content/paramikojs/win_pageant.js:
--------------------------------------------------------------------------------
1 | // For reviewer:
2 | // These code from another Firefox Add-on: FireSSH
3 | // See: https://addons.mozilla.org/zh-tw/firefox/addon/firessh/
4 | // source code: firessh/chrome/firessh.jar/content/js/connection/paramikojs/win_pageant.js
5 | //
6 | // about paramikojs: https://github.com/mimecuvalo/paramikojs
7 | paramikojs.win_pageant = function() {
8 |
9 | };
10 |
11 | paramikojs.win_pageant.prototype = {
12 | _AGENT_COPYDATA_ID : 0x804e50ba,
13 | _AGENT_MAX_MSGLEN : 8192,
14 | // Note: The WM_COPYDATA value is pulled from win32con, as a workaround
15 | // so we do not have to import this huge library just for this one variable.
16 | win32con_WM_COPYDATA : 74,
17 |
18 | _get_pageant_window_object : function() {
19 | return ctypes.windll.user32.FindWindowA('Pageant', 'Pageant'); // todo fixme
20 | },
21 |
22 | /*
23 | Check to see if there is a "Pageant" agent we can talk to.
24 |
25 | This checks both if we have the required libraries (win32all or ctypes)
26 | and if there is a Pageant currently running.
27 | */
28 | can_talk_to_agent : function() {
29 | if (this._get_pageant_window_object()) {
30 | return true;
31 | }
32 | return false;
33 | },
34 |
35 | _query_pageant : function(msg) {
36 | var hwnd = _get_pageant_window_object(); // todo fixme this whole thing!
37 | if (!hwnd) {
38 | // Raise a failure to connect exception, pageant isn't running anymore!
39 | return null;
40 | }
41 |
42 | // Write our pageant request string into the file (pageant will read this to determine what to do)
43 | var filename = tempfile.mktemp('.pag'); // todo fixme
44 | var map_filename = os.path.basename(filename); // todo fixme
45 |
46 | var f = open(filename, 'w+b'); // todo fixme
47 | f.write(msg);
48 | // Ensure the rest of the file is empty, otherwise pageant will read this
49 | f.write('\0' * (this._AGENT_MAX_MSGLEN - msg.length));
50 | // Create the shared file map that pageant will use to read from
51 | var pymap = mmap.mmap(f.fileno(), this._AGENT_MAX_MSGLEN, tagname=map_filename, access=mmap.ACCESS_WRITE);
52 | try {
53 | // Create an array buffer containing the mapped filename
54 | var char_buffer = array.array("c", map_filename + '\0');
55 | char_buffer_address, char_buffer_size = char_buffer.buffer_info();
56 | // Create a string to use for the SendMessage function call
57 | cds = struct.pack("LLP", this._AGENT_COPYDATA_ID, char_buffer_size, char_buffer_address);
58 |
59 | _buf = array.array('B', cds);
60 | _addr, _size = _buf.buffer_info();
61 | response = ctypes.windll.user32.SendMessageA(hwnd, win32con_WM_COPYDATA, _size, _addr);
62 |
63 | if (response > 0) {
64 | datalen = pymap.read(4);
65 | retlen = struct.unpack('>I', datalen)[0];
66 | return datalen + pymap.read(retlen);
67 | }
68 | return null;
69 | } catch(ex) {
70 | } finally {
71 | pymap.close();
72 | f.close();
73 | // Remove the file, it was temporary only
74 | os.unlink(filename);
75 | }
76 | },
77 |
78 | /*
79 | Mock "connection" to an agent which roughly approximates the behavior of
80 | a unix local-domain socket (as used by Agent). Requests are sent to the
81 | pageant daemon via special Windows magick, and responses are buffered back
82 | for subsequent reads.
83 | */
84 | PageantConnection : {
85 | response : null,
86 |
87 | send : function(data) {
88 | this._response = paramikojs.win_pageant._query_pageant(data);
89 | },
90 |
91 | recv : function(n) {
92 | if (!this._response) {
93 | return '';
94 | }
95 | ret = this._response.substring(0, n);
96 | this._response = this._response.substring(n);
97 | if (this._response == '') {
98 | this._response = null;
99 | }
100 | return ret;
101 | },
102 |
103 | close : function() {}
104 | }
105 | };
106 |
107 |
108 |
--------------------------------------------------------------------------------
/chrome/content/paramikojs/kex_group1.js:
--------------------------------------------------------------------------------
1 | /*
2 | Standard SSH key exchange ("kex" if you wanna sound cool). Diffie-Hellman of
3 | 1024 bit key halves, using a known "p" prime and "g" generator.
4 | */
5 |
6 | paramikojs.KexGroup1 = function(transport) {
7 | this.transport = transport;
8 | this.x = new BigInteger("0", 10);
9 | this.e = new BigInteger("0", 10);
10 | this.f = new BigInteger("0", 10);
11 |
12 | this.P = paramikojs.KexGroup1.P;
13 | this.G = paramikojs.KexGroup1.G;
14 | }
15 |
16 | paramikojs.KexGroup1._MSG_KEXDH_INIT = 30;
17 | paramikojs.KexGroup1._MSG_KEXDH_REPLY = 31;
18 |
19 | // draft-ietf-secsh-transport-09.txt, page 17
20 | paramikojs.KexGroup1.P = new BigInteger("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF", 16);
21 | paramikojs.KexGroup1.G = new BigInteger("2", 10);
22 |
23 | paramikojs.KexGroup1.prototype = {
24 | name : 'diffie-hellman-group1-sha1',
25 |
26 | start_kex : function() {
27 | this._generate_x();
28 | if (this.transport.server_mode) {
29 | // compute f = g^x mod p, but don't send it yet
30 | this.f = this.G.modPow(this.x, this.P);
31 | this.transport._expect_packet(paramikojs.KexGroup1._MSG_KEXDH_INIT);
32 | return;
33 | }
34 | // compute e = g^x mod p (where g=2), and send it
35 | this.e = this.G.modPow(this.x, this.P);
36 | var m = new paramikojs.Message();
37 | m.add_byte(String.fromCharCode(paramikojs.KexGroup1._MSG_KEXDH_INIT));
38 | m.add_mpint(this.e);
39 | this.transport._send_message(m);
40 | this.transport._expect_packet(paramikojs.KexGroup1._MSG_KEXDH_REPLY);
41 | },
42 |
43 | parse_next : function(ptype, m) {
44 | if (this.transport.server_mode && ptype == paramikojs.KexGroup1._MSG_KEXDH_INIT) {
45 | return this._parse_kexdh_init(m);
46 | } else if (!this.transport.server_mode && ptype == paramikojs.KexGroup1._MSG_KEXDH_REPLY) {
47 | return this._parse_kexdh_reply(m);
48 | }
49 | throw new paramikojs.ssh_exception.SSHException('KexGroup1 asked to handle packet type ' + ptype);
50 | },
51 |
52 |
53 | // internals...
54 |
55 | _generate_x : function() {
56 | // generate an "x" (1 < x < q), where q is (p-1)/2.
57 | // p is a 128-byte (1024-bit) number, where the first 64 bits are 1.
58 | // therefore q can be approximated as a 2^1023. we drop the subset of
59 | // potential x where the first 63 bits are 1, because some of those will be
60 | // larger than q (but this is a tiny tiny subset of potential x).
61 | var x_bytes;
62 | while (true) {
63 | x_bytes = this.transport.rng.read(128);
64 | x_bytes = String.fromCharCode(x_bytes[0].charCodeAt(0) & 0x7f) + x_bytes.substring(1);
65 | if (x_bytes.substring(0, 8) != '\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF' && x_bytes.substring(0, 8) != '\x00\x00\x00\x00\x00\x00\x00\x00') {
66 | break;
67 | }
68 | }
69 | this.x = paramikojs.util.inflate_long(x_bytes, false);
70 | },
71 |
72 | _parse_kexdh_reply : function(m) {
73 | // client mode
74 | var host_key = m.get_string();
75 | this.f = m.get_mpint();
76 | var one = BigInteger.ONE;
77 | if (one.compareTo(this.f) > 0 || this.f.compareTo(this.P.subtract(one)) > 0) {
78 | throw new paramikojs.ssh_exception.SSHException('Server kex "f" is out of range');
79 | }
80 | var sig = m.get_string();
81 | var K = this.f.modPow(this.x, this.P);
82 | // okay, build up the hash H of (V_C || V_S || I_C || I_S || K_S || e || f || K)
83 | var hm = new paramikojs.Message();
84 | hm.add(this.transport.local_version, this.transport.remote_version,
85 | this.transport.local_kex_init, this.transport.remote_kex_init);
86 | hm.add_string(host_key);
87 | hm.add_mpint(this.e);
88 | hm.add_mpint(this.f);
89 | hm.add_mpint(K);
90 | this.transport._set_K_H(K, new kryptos.hash.SHA(hm.toString()).digest());
91 | this.transport._verify_key(host_key, sig);
92 | this.transport._activate_outbound();
93 | }
94 |
95 | };
96 |
--------------------------------------------------------------------------------
/chrome/content/paramikojs/kryptos/Random/Fortuna/FortunaAccumulator.js:
--------------------------------------------------------------------------------
1 | kryptos.random.Fortuna.FortunaPool = function() {
2 | /*
3 | Fortuna pool type
4 |
5 | This object acts like a hash object, with the following differences:
6 |
7 | - It keeps a count (the .length attribute) of the number of bytes that
8 | have been added to the pool
9 | - It supports a .reset() method for in-place reinitialization
10 | - The method to add bytes to the pool is .append(), not .update().
11 | */
12 | this.reset();
13 | }
14 |
15 | kryptos.random.Fortuna.FortunaPool.prototype = {
16 | digest_size : kryptos.random.Fortuna.SHAd256.digest_size,
17 |
18 | append : function(data) {
19 | this._h.update(data);
20 | this.length += data.length;
21 | },
22 |
23 | digest : function() {
24 | return this._h.digest();
25 | },
26 |
27 | reset : function() {
28 | this._h = new kryptos.random.Fortuna.SHAd256();
29 | this.length = 0;
30 | }
31 | };
32 |
33 |
34 | kryptos.random.Fortuna.which_pools = function(r) {
35 | /*
36 | Return a list of pools indexes (in range(32)) that are to be included during reseed number r.
37 |
38 | According to _Practical Cryptography_, chapter 10.5.2 "Pools":
39 |
40 | "Pool P_i is included if 2**i is a divisor of r. Thus P_0 is used
41 | every reseed, P_1 every other reseed, P_2 every fourth reseed, etc."
42 | */
43 | // This is a separate function so that it can be unit-tested.
44 |
45 | var retval = [];
46 | var mask = 0;
47 | for (var i = 0; i < 32; ++i) {
48 | // "Pool P_i is included if 2**i is a divisor of [reseed_count]"
49 | if ((r & mask) == 0) {
50 | retval.push(i);
51 | } else {
52 | break; // optimization. once this fails, it always fails
53 | }
54 | mask = (mask << 1) | 1;
55 | }
56 | return retval;
57 | }
58 |
59 |
60 | kryptos.random.Fortuna.FortunaAccumulator = function() {
61 | this.reseed_count = 0;
62 | this.generator = new kryptos.random.Fortuna.FortunaGenerator.AESGenerator();
63 | this.last_reseed = null;
64 |
65 | // Initialize 32 FortunaPool instances.
66 | // NB: This is _not_ equivalent to [FortunaPool()]*32, which would give
67 | // us 32 references to the _same_ FortunaPool instance (and cause the
68 | // assertion below to fail).
69 | this.pools = [];
70 | for (var i = 0; i < 32; ++i) { // 32 pools
71 | this.pools.push(new kryptos.random.Fortuna.FortunaPool());
72 | }
73 | }
74 |
75 | kryptos.random.Fortuna.FortunaAccumulator.prototype = {
76 | min_pool_size : 64, // TODO: explain why
77 | reseed_interval : 0.100, // 100 ms TODO: explain why
78 |
79 | random_data : function(bytes) {
80 | var current_time = new Date();
81 | if (this.last_reseed > current_time) {
82 | // warnings.warn("Clock rewind detected. Resetting last_reseed.", ClockRewindWarning)
83 | this.last_reseed = null;
84 | }
85 | if (this.pools[0].length >= this.min_pool_size &&
86 | (!this.last_reseed ||
87 | current_time > this.last_reseed + this.reseed_interval)) {
88 | this._reseed(current_time);
89 | }
90 | // The following should fail if we haven't seeded the pool yet.
91 | return this.generator.pseudo_random_data(bytes);
92 | },
93 |
94 | _reseed : function(current_time) {
95 | if (!current_time) {
96 | current_time = new Date();
97 | }
98 | var seed = [];
99 | this.reseed_count += 1;
100 | this.last_reseed = current_time;
101 | var which_pools = kryptos.random.Fortuna.which_pools(this.reseed_count);
102 | for (var i = 0; i < which_pools.length; ++i) {
103 | seed.push(this.pools[i].digest());
104 | this.pools[i].reset();
105 | }
106 |
107 | seed = seed.join("");
108 | this.generator.reseed(seed);
109 | },
110 |
111 | add_random_event : function(source_number, pool_number, data) {
112 | this.pools[pool_number].append(String.fromCharCode(source_number));
113 | this.pools[pool_number].append(String.fromCharCode(data.length));
114 | this.pools[pool_number].append(data);
115 | }
116 | };
117 |
--------------------------------------------------------------------------------
/chrome/content/paramikojs/kryptos/Cipher/ARC4.js:
--------------------------------------------------------------------------------
1 | // Copyright 2005 The Closure Library Authors. All Rights Reserved.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS-IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | /**
16 | * @fileoverview ARC4 streamcipher implementation. A description of the
17 | * algorithm can be found at:
18 | * http://www.mozilla.org/projects/security/pki/nss/draft-kaukonen-cipher-arcfour-03.txt.
19 | *
20 | * Usage:
21 | *
22 | * var arc4 = new goog.crypt.Arc4();
23 | * arc4.setKey(key);
24 | * arc4.discard(1536);
25 | * arc4.crypt(bytes);
26 | *
27 | *
28 | * Note: For converting between strings and byte arrays, goog.crypt.base64 may
29 | * be useful.
30 | *
31 | */
32 |
33 | goog = {};
34 | goog.crypt = {};
35 |
36 |
37 | /**
38 | * ARC4 streamcipher implementation.
39 | * @constructor
40 | */
41 | goog.crypt.Arc4 = function() {
42 | /**
43 | * A permutation of all 256 possible bytes.
44 | * @type {Array.}
45 | * @private
46 | */
47 | this.state_ = [];
48 |
49 | /**
50 | * 8 bit index pointer into this.state_.
51 | * @type {number}
52 | * @private
53 | */
54 | this.index1_ = 0;
55 |
56 | /**
57 | * 8 bit index pointer into this.state_.
58 | * @type {number}
59 | * @private
60 | */
61 | this.index2_ = 0;
62 | };
63 |
64 |
65 | /**
66 | * Initialize the cipher for use with new key.
67 | * @param {Array.} key A byte array containing the key.
68 | * @param {number=} opt_length Indicates # of bytes to take from the key.
69 | */
70 | goog.crypt.Arc4.prototype.setKey = function(key, opt_length) {
71 | if (!opt_length) {
72 | opt_length = key.length;
73 | }
74 |
75 | var state = this.state_;
76 |
77 | for (var i = 0; i < 256; ++i) {
78 | state[i] = i;
79 | }
80 |
81 | var j = 0;
82 | for (var i = 0; i < 256; ++i) {
83 | j = (j + state[i] + key[i % opt_length]) & 255;
84 |
85 | var tmp = state[i];
86 | state[i] = state[j];
87 | state[j] = tmp;
88 | }
89 |
90 | this.index1_ = 0;
91 | this.index2_ = 0;
92 | };
93 |
94 |
95 | /**
96 | * Discards n bytes of the keystream.
97 | * These days 1536 is considered a decent amount to drop to get the key state
98 | * warmed-up enough for secure usage. This is not done in the constructor to
99 | * preserve efficiency for use cases that do not need this.
100 | * @param {number} n Number of bytes to disregard from the stream.
101 | */
102 | goog.crypt.Arc4.prototype.discard = function(n) {
103 | var devnul = new Array(n);
104 | this.crypt(devnul);
105 | };
106 |
107 |
108 | /**
109 | * En- or decrypt (same operation for streamciphers like ARC4)
110 | * @param {Array.} data The data to be xor-ed in place.
111 | * @param {number=} opt_length The number of bytes to crypt.
112 | */
113 | goog.crypt.Arc4.prototype.crypt = function(data, opt_length) {
114 | if (!opt_length) {
115 | opt_length = data.length;
116 | }
117 |
118 | var i = this.index1_;
119 | var j = this.index2_;
120 | var state = this.state_;
121 |
122 | for (var n = 0; n < opt_length; ++n) {
123 | i = (i + 1) & 255;
124 | j = (j + state[i]) & 255;
125 |
126 | var tmp = state[i];
127 | state[i] = state[j];
128 | state[j] = tmp;
129 |
130 | data[n] ^= state[(state[i] + state[j]) & 255];
131 | }
132 |
133 | this.index1_ = i;
134 | this.index2_ = j;
135 | };
136 |
137 |
138 | kryptos.cipher.ARC4 = function(key) {
139 | this.cipher = new goog.crypt.Arc4();
140 | this.cipher.setKey(kryptos.toByteArray(key));
141 | }
142 |
143 | kryptos.cipher.ARC4.prototype = {
144 | encrypt : function(data) {
145 | var data = kryptos.toByteArray(data);
146 | this.cipher.crypt(data);
147 | return kryptos.fromByteArray(data);
148 | },
149 |
150 | decrypt : function(data) {
151 | return this.encrypt(data);
152 | }
153 | };
154 |
--------------------------------------------------------------------------------
/chrome/content/telnet.html:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
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 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
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 |
--------------------------------------------------------------------------------