├── .gitignore ├── BlobBuilder.js ├── CNAME ├── COPYING ├── FileSaver.js ├── README.md ├── about.htm ├── ace ├── ace.js ├── ext-static_highlight.js ├── ext-textarea.js ├── keybinding-emacs.js ├── keybinding-vim.js ├── mode-javascript.js ├── mode-python.js └── theme-chrome.js ├── builtin.js ├── contextmenu ├── arrow_s.png ├── jquery.contextmenu.css ├── jquery.contextmenu.js └── jquery.hoverintent.js ├── drop.js ├── favicon.ico ├── icebuddha.png ├── index.htm ├── jqtree ├── jqtree.css ├── tree.jquery.js ├── treeDownTriangleBlack.png └── treeRightTriangleBlack.png ├── jquery-1.8.2.min.js ├── jquery-ui.js ├── jquery.cookie.js ├── jquery.hotkeys.js ├── jquery.js ├── jquery.min.js ├── jquery.scrollTo.min.js ├── parse_scripts ├── example_extractMiniDukeFile.py ├── fileparser.py ├── gif.py ├── icebuddha │ └── __init__.py ├── mach_o.py ├── pe.py └── unknown.py ├── peg.min.js ├── projects.htm ├── skulpt.js ├── slopfinder.htm ├── slopfinder.js ├── slopfinder.png ├── style.css ├── summit_route_logo.png ├── test_data ├── bytes.data ├── high_bytes.data ├── icebuddha.gif ├── putty.exe └── sample_1.gif ├── tutorial.png └── waypoints.min.js /.gitignore: -------------------------------------------------------------------------------- 1 | .metadata 2 | -------------------------------------------------------------------------------- /BlobBuilder.js: -------------------------------------------------------------------------------- 1 | /* BlobBuilder.js 2 | * A BlobBuilder implementation. 3 | * 2012-04-21 4 | * 5 | * By Eli Grey, http://eligrey.com 6 | * License: X11/MIT 7 | * See LICENSE.md 8 | */ 9 | 10 | /*global self, unescape */ 11 | /*jslint bitwise: true, regexp: true, confusion: true, es5: true, vars: true, white: true, 12 | plusplus: true */ 13 | 14 | /*! @source http://purl.eligrey.com/github/BlobBuilder.js/blob/master/BlobBuilder.js */ 15 | 16 | var BlobBuilder = BlobBuilder || self.WebKitBlobBuilder || self.MozBlobBuilder || self.MSBlobBuilder || (function(view) { 17 | "use strict"; 18 | var 19 | get_class = function(object) { 20 | return Object.prototype.toString.call(object).match(/^\[object\s(.*)\]$/)[1]; 21 | } 22 | , FakeBlobBuilder = function(){ 23 | this.data = []; 24 | } 25 | , FakeBlob = function(data, type, encoding) { 26 | this.data = data; 27 | this.size = data.length; 28 | this.type = type; 29 | this.encoding = encoding; 30 | } 31 | , FBB_proto = FakeBlobBuilder.prototype 32 | , FB_proto = FakeBlob.prototype 33 | , FileReaderSync = view.FileReaderSync 34 | , FileException = function(type) { 35 | this.code = this[this.name = type]; 36 | } 37 | , file_ex_codes = ( 38 | "NOT_FOUND_ERR SECURITY_ERR ABORT_ERR NOT_READABLE_ERR ENCODING_ERR " 39 | + "NO_MODIFICATION_ALLOWED_ERR INVALID_STATE_ERR SYNTAX_ERR" 40 | ).split(" ") 41 | , file_ex_code = file_ex_codes.length 42 | , realURL = view.URL || view.webkitURL || view 43 | , real_create_object_URL = realURL.createObjectURL 44 | , real_revoke_object_URL = realURL.revokeObjectURL 45 | , URL = realURL 46 | , btoa = view.btoa 47 | , atob = view.atob 48 | , can_apply_typed_arrays = false 49 | , can_apply_typed_arrays_test = function(pass) { 50 | can_apply_typed_arrays = !pass; 51 | } 52 | 53 | , ArrayBuffer = view.ArrayBuffer 54 | , Uint8Array = view.Uint8Array 55 | ; 56 | FakeBlobBuilder.fake = FB_proto.fake = true; 57 | while (file_ex_code--) { 58 | FileException.prototype[file_ex_codes[file_ex_code]] = file_ex_code + 1; 59 | } 60 | try { 61 | if (Uint8Array) { 62 | can_apply_typed_arrays_test.apply(0, new Uint8Array(1)); 63 | } 64 | } catch (ex) {} 65 | if (!realURL.createObjectURL) { 66 | URL = view.URL = {}; 67 | } 68 | URL.createObjectURL = function(blob) { 69 | var 70 | type = blob.type 71 | , data_URI_header 72 | ; 73 | if (type === null) { 74 | type = "application/octet-stream"; 75 | } 76 | if (blob instanceof FakeBlob) { 77 | data_URI_header = "data:" + type; 78 | if (blob.encoding === "base64") { 79 | return data_URI_header + ";base64," + blob.data; 80 | } else if (blob.encoding === "URI") { 81 | return data_URI_header + "," + decodeURIComponent(blob.data); 82 | } if (btoa) { 83 | return data_URI_header + ";base64," + btoa(blob.data); 84 | } else { 85 | return data_URI_header + "," + encodeURIComponent(blob.data); 86 | } 87 | } else if (real_create_object_url) { 88 | return real_create_object_url.call(realURL, blob); 89 | } 90 | }; 91 | URL.revokeObjectURL = function(object_url) { 92 | if (object_url.substring(0, 5) !== "data:" && real_revoke_object_url) { 93 | real_revoke_object_url.call(realURL, object_url); 94 | } 95 | }; 96 | FBB_proto.append = function(data/*, endings*/) { 97 | var bb = this.data; 98 | // decode data to a binary string 99 | if (Uint8Array && data instanceof ArrayBuffer) { 100 | if (can_apply_typed_arrays) { 101 | bb.push(String.fromCharCode.apply(String, new Uint8Array(data))); 102 | } else { 103 | var 104 | str = "" 105 | , buf = new Uint8Array(data) 106 | , i = 0 107 | , buf_len = buf.length 108 | ; 109 | for (; i < buf_len; i++) { 110 | str += String.fromCharCode(buf[i]); 111 | } 112 | } 113 | } else if (get_class(data) === "Blob" || get_class(data) === "File") { 114 | if (FileReaderSync) { 115 | var fr = new FileReaderSync; 116 | bb.push(fr.readAsBinaryString(data)); 117 | } else { 118 | // async FileReader won't work as BlobBuilder is sync 119 | throw new FileException("NOT_READABLE_ERR"); 120 | } 121 | } else if (data instanceof FakeBlob) { 122 | if (data.encoding === "base64" && atob) { 123 | bb.push(atob(data.data)); 124 | } else if (data.encoding === "URI") { 125 | bb.push(decodeURIComponent(data.data)); 126 | } else if (data.encoding === "raw") { 127 | bb.push(data.data); 128 | } 129 | } else { 130 | if (typeof data !== "string") { 131 | data += ""; // convert unsupported types to strings 132 | } 133 | // decode UTF-16 to binary string 134 | bb.push(unescape(encodeURIComponent(data))); 135 | } 136 | }; 137 | FBB_proto.getBlob = function(type) { 138 | if (!arguments.length) { 139 | type = null; 140 | } 141 | return new FakeBlob(this.data.join(""), type, "raw"); 142 | }; 143 | FBB_proto.toString = function() { 144 | return "[object BlobBuilder]"; 145 | }; 146 | FB_proto.slice = function(start, end, type) { 147 | var args = arguments.length; 148 | if (args < 3) { 149 | type = null; 150 | } 151 | return new FakeBlob( 152 | this.data.slice(start, args > 1 ? end : this.data.length) 153 | , type 154 | , this.encoding 155 | ); 156 | }; 157 | FB_proto.toString = function() { 158 | return "[object Blob]"; 159 | }; 160 | return FakeBlobBuilder; 161 | }(self)); -------------------------------------------------------------------------------- /CNAME: -------------------------------------------------------------------------------- 1 | icebuddha.com 2 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Scott Piper 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /FileSaver.js: -------------------------------------------------------------------------------- 1 | /* FileSaver.js 2 | * A saveAs() FileSaver implementation. 3 | * 2012-12-11 4 | * 5 | * By Eli Grey, http://eligrey.com 6 | * License: X11/MIT 7 | * See LICENSE.md 8 | */ 9 | 10 | /*global self */ 11 | /*jslint bitwise: true, regexp: true, confusion: true, es5: true, vars: true, white: true, 12 | plusplus: true */ 13 | 14 | /*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */ 15 | 16 | var saveAs = saveAs 17 | || (navigator.msSaveOrOpenBlob && navigator.msSaveOrOpenBlob.bind(navigator)) 18 | || (function(view) { 19 | "use strict"; 20 | var 21 | doc = view.document 22 | // only get URL when necessary in case BlobBuilder.js hasn't overridden it yet 23 | , get_URL = function() { 24 | return view.URL || view.webkitURL || view; 25 | } 26 | , URL = view.URL || view.webkitURL || view 27 | , save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a") 28 | , can_use_save_link = "download" in save_link 29 | , click = function(node) { 30 | var event = doc.createEvent("MouseEvents"); 31 | event.initMouseEvent( 32 | "click", true, false, view, 0, 0, 0, 0, 0 33 | , false, false, false, false, 0, null 34 | ); 35 | return node.dispatchEvent(event); // false if event was cancelled 36 | } 37 | , webkit_req_fs = view.webkitRequestFileSystem 38 | , req_fs = view.requestFileSystem || webkit_req_fs || view.mozRequestFileSystem 39 | , throw_outside = function (ex) { 40 | (view.setImmediate || view.setTimeout)(function() { 41 | throw ex; 42 | }, 0); 43 | } 44 | , force_saveable_type = "application/octet-stream" 45 | , fs_min_size = 0 46 | , deletion_queue = [] 47 | , process_deletion_queue = function() { 48 | var i = deletion_queue.length; 49 | while (i--) { 50 | var file = deletion_queue[i]; 51 | if (typeof file === "string") { // file is an object URL 52 | URL.revokeObjectURL(file); 53 | } else { // file is a File 54 | file.remove(); 55 | } 56 | } 57 | deletion_queue.length = 0; // clear queue 58 | } 59 | , dispatch = function(filesaver, event_types, event) { 60 | event_types = [].concat(event_types); 61 | var i = event_types.length; 62 | while (i--) { 63 | var listener = filesaver["on" + event_types[i]]; 64 | if (typeof listener === "function") { 65 | try { 66 | listener.call(filesaver, event || filesaver); 67 | } catch (ex) { 68 | throw_outside(ex); 69 | } 70 | } 71 | } 72 | } 73 | , FileSaver = function(blob, name) { 74 | // First try a.download, then web filesystem, then object URLs 75 | var 76 | filesaver = this 77 | , type = blob.type 78 | , blob_changed = false 79 | , object_url 80 | , target_view 81 | , get_object_url = function() { 82 | var object_url = get_URL().createObjectURL(blob); 83 | deletion_queue.push(object_url); 84 | return object_url; 85 | } 86 | , dispatch_all = function() { 87 | dispatch(filesaver, "writestart progress write writeend".split(" ")); 88 | } 89 | // on any filesys errors revert to saving with object URLs 90 | , fs_error = function() { 91 | // don't create more object URLs than needed 92 | if (blob_changed || !object_url) { 93 | object_url = get_object_url(blob); 94 | } 95 | target_view.location.href = object_url; 96 | filesaver.readyState = filesaver.DONE; 97 | dispatch_all(); 98 | } 99 | , abortable = function(func) { 100 | return function() { 101 | if (filesaver.readyState !== filesaver.DONE) { 102 | return func.apply(this, arguments); 103 | } 104 | }; 105 | } 106 | , create_if_not_found = {create: true, exclusive: false} 107 | , slice 108 | ; 109 | filesaver.readyState = filesaver.INIT; 110 | if (!name) { 111 | name = "download"; 112 | } 113 | if (can_use_save_link) { 114 | object_url = get_object_url(blob); 115 | save_link.href = object_url; 116 | save_link.download = name; 117 | if (click(save_link)) { 118 | filesaver.readyState = filesaver.DONE; 119 | dispatch_all(); 120 | return; 121 | } 122 | } 123 | // Object and web filesystem URLs have a problem saving in Google Chrome when 124 | // viewed in a tab, so I force save with application/octet-stream 125 | // http://code.google.com/p/chromium/issues/detail?id=91158 126 | if (view.chrome && type && type !== force_saveable_type) { 127 | slice = blob.slice || blob.webkitSlice; 128 | blob = slice.call(blob, 0, blob.size, force_saveable_type); 129 | blob_changed = true; 130 | } 131 | // Since I can't be sure that the guessed media type will trigger a download 132 | // in WebKit, I append .download to the filename. 133 | // https://bugs.webkit.org/show_bug.cgi?id=65440 134 | if (webkit_req_fs && name !== "download") { 135 | name += ".download"; 136 | } 137 | if (type === force_saveable_type || webkit_req_fs) { 138 | target_view = view; 139 | } else { 140 | target_view = view.open(); 141 | } 142 | if (!req_fs) { 143 | fs_error(); 144 | return; 145 | } 146 | fs_min_size += blob.size; 147 | req_fs(view.TEMPORARY, fs_min_size, abortable(function(fs) { 148 | fs.root.getDirectory("saved", create_if_not_found, abortable(function(dir) { 149 | var save = function() { 150 | dir.getFile(name, create_if_not_found, abortable(function(file) { 151 | file.createWriter(abortable(function(writer) { 152 | writer.onwriteend = function(event) { 153 | target_view.location.href = file.toURL(); 154 | deletion_queue.push(file); 155 | filesaver.readyState = filesaver.DONE; 156 | dispatch(filesaver, "writeend", event); 157 | }; 158 | writer.onerror = function() { 159 | var error = writer.error; 160 | if (error.code !== error.ABORT_ERR) { 161 | fs_error(); 162 | } 163 | }; 164 | "writestart progress write abort".split(" ").forEach(function(event) { 165 | writer["on" + event] = filesaver["on" + event]; 166 | }); 167 | writer.write(blob); 168 | filesaver.abort = function() { 169 | writer.abort(); 170 | filesaver.readyState = filesaver.DONE; 171 | }; 172 | filesaver.readyState = filesaver.WRITING; 173 | }), fs_error); 174 | }), fs_error); 175 | }; 176 | dir.getFile(name, {create: false}, abortable(function(file) { 177 | // delete file if it already exists 178 | file.remove(); 179 | save(); 180 | }), abortable(function(ex) { 181 | if (ex.code === ex.NOT_FOUND_ERR) { 182 | save(); 183 | } else { 184 | fs_error(); 185 | } 186 | })); 187 | }), fs_error); 188 | }), fs_error); 189 | } 190 | , FS_proto = FileSaver.prototype 191 | , saveAs = function(blob, name) { 192 | return new FileSaver(blob, name); 193 | } 194 | ; 195 | FS_proto.abort = function() { 196 | var filesaver = this; 197 | filesaver.readyState = filesaver.DONE; 198 | dispatch(filesaver, "abort"); 199 | }; 200 | FS_proto.readyState = FS_proto.INIT = 0; 201 | FS_proto.WRITING = 1; 202 | FS_proto.DONE = 2; 203 | 204 | FS_proto.error = 205 | FS_proto.onwritestart = 206 | FS_proto.onprogress = 207 | FS_proto.onwrite = 208 | FS_proto.onabort = 209 | FS_proto.onerror = 210 | FS_proto.onwriteend = 211 | null; 212 | 213 | view.addEventListener("unload", process_deletion_queue, false); 214 | return saveAs; 215 | }(self)); -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Summary 2 | ======= 3 | IceBuddha a hex-viewer and generic binary file parser done via static web pages and with in-browser python-to-javascript translation for the parse scripts. 4 | 5 | Try it out 6 | - http://0xdabbad00.github.io/icebuddha/ 7 | - http://icebuddha.com 8 | 9 | Contact 10 | ------- 11 | IceBuddha was developed by [@0xdabbad00](https://twitter.com/0xdabbad00) (Scott Piper) from [Summmit Route](https://SummitRoute.com) 12 | 13 | License 14 | ------- 15 | MIT License 16 | 17 | 18 | Thank you 19 | ========= 20 | Special thanks to the following projects/people for making this site possible: 21 | - [skulpt](http://www.skulpt.org/) In-browser Python to JavaScript compiler. This project is insane. (MIT license) 22 | - [jqTree](http://mbraak.github.io/jqTree/) Allows me to show my tree view of the parsed data. (Apache license) 23 | - [jQuery.ScrollTo](http://flesler.blogspot.com/2007/10/jqueryscrollto.html) Makes the browser scroll. (MIT and GPL licenses) 24 | - [Waypoints](http://imakewebthings.com/jquery-waypoints/) Causes events to occur when you scroll. (MIT and GPL licenses) 25 | - [ACE editor](http://ace.c9.io/#nav=about) Code-editor. (BSD license) 26 | - [FileSaver.js](https://github.com/eligrey/FileSaver.js) and [BlobBuilder.js](https://github.com/eligrey/BlobBuilder.js), which I use to have the user download files from their browser (MIT/X11 license). 27 | -------------------------------------------------------------------------------- /about.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | Ice Buddha 4 | 5 | 6 | 7 | 8 |
9 | 12 | 13 |
14 |
15 |

Motive

16 | The goal of IceBuddha is to become a general purpose binary file parser to help me learn some things and try out some ideas. I'm doing this because I think it's an interesting idea, and with no goal of financial gain (just street cred). 17 | 18 |

19 | 20 |

Contact me

21 | Email me at 0xdabbad00 – at – gmail.com or read what I'm up to on my main site 0xdabbad00.com. 22 | 23 |

Thank you!

24 | Thanks to the following projects/people for making this site possible: 25 |
jqTree (Apache license) Allows me to show my tree view of the parsed data. 26 |
jQuery.ScrollTo (MIT and GPL licenses) Makes the browser scroll. 27 |
Waypoints (MIT and GPL licenses) Causes events to occur when you scroll. 28 |
ACE editor (BSD license?) Code-editor. 29 |
Eli Grey for FileSaver.js and BlobBuilder.js, which I use to download files (MIT/X11 license). 30 |
skulpt (MIT license) In-browser Python to JavaScript compiler. 31 | 32 |
PEG.js (MIT license) No longer used, but still appreciate them for it I was using it. 33 | 34 | 35 |

Thanks in advance

36 | Bruno for writing my auto-complete code in his answer to my question on stackoverflow. 37 | 38 | 39 |

Privacy Policy

40 | I don't collect any data. Everything is happening locally, client side on your system. It's all javascript and html, so I invite you to not only review my code on github, but host this site locally. Or better yet, fork it and send me fixes/features! Most of the site should work by just downloading it and browsing to it on your local hard-drive, even without a web server (some code does currently grab files from my server but I'm trying to figure out a smarter way to handle that). I host this site on amazon EC2 because most free hosting tracks users. I believe strongly in privacy, and frankly I'm too stupid to know how to profit from your use of this site. 41 | 42 |

I do want to eventually incorporate some wiki capabilities into this site which will mean some server side code, but I still will refrain from sending home any data you are not specifically requesting my server receive. 43 |

44 |
45 | 46 | 49 |
50 | 51 | 52 | -------------------------------------------------------------------------------- /ace/ext-static_highlight.js: -------------------------------------------------------------------------------- 1 | ace.define("ace/ext/static_highlight",["require","exports","module","ace/edit_session","ace/layer/text"],function(e,t,n){var r=e("../edit_session").EditSession,i=e("../layer/text").Text,s=".ace_editor {font-family: 'Monaco', 'Menlo', 'Droid Sans Mono', 'Courier New', monospace;font-size: 12px;}.ace_editor .ace_gutter { width: 25px !important;display: block;float: left;text-align: right; padding: 0 3px 0 0; margin-right: 3px;}.ace_line { clear: both; }*.ace_gutter-cell {-moz-user-select: -moz-none;-khtml-user-select: none;-webkit-user-select: none;user-select: none;}";t.render=function(e,t,n,o,u){o=parseInt(o||1,10);var a=new r("");a.setMode(t),a.setUseWorker(!1);var f=new i(document.createElement("div"));f.setSession(a),f.config={characterWidth:10,lineHeight:20},a.setValue(e);var l=[],c=a.getLength();for(var h=0;h"),u||l.push(""+(h+o)+""),f.$renderLine(l,h,!0,!1),l.push("");var p="
:code
".replace(/:cssClass/,n.cssClass).replace(/:code/,l.join(""));return f.destroy(),{css:s+n.cssText,html:p}}}) -------------------------------------------------------------------------------- /ace/ext-textarea.js: -------------------------------------------------------------------------------- 1 | ace.define("ace/ext/textarea",["require","exports","module","ace/lib/event","ace/lib/useragent","ace/lib/net","ace/ace","ace/theme/textmate","ace/mode/text"],function(e,t,n){function a(e,t){for(var n in t)e.style[n]=t[n]}function f(e,t){if(e.type!="textarea")throw"Textarea required!";var n=e.parentNode,i=document.createElement("div"),s=function(){var t="position:relative;";["margin-top","margin-left","margin-right","margin-bottom"].forEach(function(n){t+=n+":"+u(e,i,n)+";"});var n=u(e,i,"width")||e.clientWidth+"px",r=u(e,i,"height")||e.clientHeight+"px";t+="height:"+r+";width:"+n+";",t+="display:inline-block;",i.setAttribute("style",t)};r.addListener(window,"resize",s),s(),e.nextSibling?n.insertBefore(i,e.nextSibling):n.appendChild(i);while(n!==document){if(n.tagName.toUpperCase()==="FORM"){var o=n.onsubmit;n.onsubmit=function(n){e.innerHTML=t(),e.value=t(),o&&o.call(this,n)};break}n=n.parentNode}return i}function l(t,n,r){s.loadScript(t,function(){e([n],r)})}function c(n,r,i,s,o,u){function c(e){return e=="true"}var a=n.getSession(),f=n.renderer;u=u||l,n.setDisplaySettings=function(e){e==null&&(e=i.style.display=="none"),i.style.display=e?"block":"none"},n.setOption=function(t,i){if(o[t]==i)return;switch(t){case"gutter":f.setShowGutter(c(i));break;case"mode":i!="text"?u("mode-"+i+".js","ace/mode/"+i,function(){var t=e("../mode/"+i).Mode;a.setMode(new t)}):a.setMode(new(e("../mode/text").Mode));break;case"theme":i!="textmate"?u("theme-"+i+".js","ace/theme/"+i,function(){n.setTheme("ace/theme/"+i)}):n.setTheme("ace/theme/textmate");break;case"fontSize":r.style.fontSize=i;break;case"softWrap":switch(i){case"off":a.setUseWrapMode(!1),f.setPrintMarginColumn(80);break;case"40":a.setUseWrapMode(!0),a.setWrapLimitRange(40,40),f.setPrintMarginColumn(40);break;case"80":a.setUseWrapMode(!0),a.setWrapLimitRange(80,80),f.setPrintMarginColumn(80);break;case"free":a.setUseWrapMode(!0),a.setWrapLimitRange(null,null),f.setPrintMarginColumn(80)}break;case"useSoftTabs":a.setUseSoftTabs(c(i));break;case"showPrintMargin":f.setShowPrintMargin(c(i));break;case"showInvisibles":n.setShowInvisibles(c(i))}o[t]=i},n.getOption=function(e){return o[e]},n.getOptions=function(){return o};for(var h in t.options)n.setOption(h,t.options[h]);return n}function h(e,t,n,i){function f(e,t,n,r){e.push("")}var s={"true":!0,"false":!1},o={mode:"Mode:",gutter:"Display Gutter:",theme:"Theme:",fontSize:"Font Size:",softWrap:"Soft Wrap:",showPrintMargin:"Show Print Margin:",useSoftTabs:"Use Soft Tabs:",showInvisibles:"Show Invisibles"},u={mode:{text:"Plain",javascript:"JavaScript",xml:"XML",html:"HTML",css:"CSS",scss:"SCSS",python:"Python",php:"PHP",java:"Java",ruby:"Ruby",c_cpp:"C/C++",coffee:"CoffeeScript",json:"json",perl:"Perl",clojure:"Clojure",ocaml:"OCaml",csharp:"C#",haxe:"haXe",svg:"SVG",textile:"Textile",groovy:"Groovy",liquid:"Liquid",Scala:"Scala"},theme:{clouds:"Clouds",clouds_midnight:"Clouds Midnight",cobalt:"Cobalt",crimson_editor:"Crimson Editor",dawn:"Dawn",eclipse:"Eclipse",idle_fingers:"Idle Fingers",kr_theme:"Kr Theme",merbivore:"Merbivore",merbivore_soft:"Merbivore Soft",mono_industrial:"Mono Industrial",monokai:"Monokai",pastel_on_dark:"Pastel On Dark",solarized_dark:"Solarized Dark",solarized_light:"Solarized Light",textmate:"Textmate",twilight:"Twilight",vibrant_ink:"Vibrant Ink"},gutter:s,fontSize:{"10px":"10px","11px":"11px","12px":"12px","14px":"14px","16px":"16px"},softWrap:{off:"Off",40:"40",80:"80",free:"Free"},showPrintMargin:s,useSoftTabs:s,showInvisibles:s},a=[];a.push("");for(var l in i)a.push(""),a.push("");a.push("
SettingValue
",o[l],""),f(a,l,u[l],i[l]),a.push("
"),e.innerHTML=a.join("");var c=e.getElementsByTagName("select");for(var h=0;h30&&this.$data.shift()},get:function(){return this.$data[this.$data.length-1]||""},pop:function(){return this.$data.length>1&&this.$data.pop(),this.get()},rotate:function(){return this.$data.unshift(this.$data.pop()),this.get()}}}) -------------------------------------------------------------------------------- /ace/keybinding-vim.js: -------------------------------------------------------------------------------- 1 | ace.define("ace/keyboard/vim",["require","exports","module","ace/keyboard/vim/commands","ace/keyboard/vim/maps/util","ace/lib/useragent"],function(e,t,n){var r=e("./vim/commands"),i=r.coreCommands,s=e("./vim/maps/util"),o=e("../lib/useragent"),u={i:{command:i.start},I:{command:i.startBeginning},a:{command:i.append},A:{command:i.appendEnd},"ctrl-f":{command:"gotopagedown"},"ctrl-b":{command:"gotopageup"}};t.handler={handleMacRepeat:function(e,t,n){if(t==-1)e.inputChar=n,e.lastEvent="input";else if(e.inputChar&&e.$lastHash==t&&e.$lastKey==n){if(e.lastEvent=="input")e.lastEvent="input1";else if(e.lastEvent=="input1")return!0}else e.$lastHash=t,e.$lastKey=n,e.lastEvent="keypress"},handleKeyboard:function(e,t,n,s,a){if(t!=0&&(n==""||n=="\0"))return null;t==1&&(n="ctrl-"+n);if(n=="esc"&&t==0||n=="ctrl-[")return{command:i.stop};if(e.state=="start"){o.isMac&&this.handleMacRepeat(e,t,n)&&(t=-1,n=e.inputChar);if(t==-1||t==1)return r.inputBuffer.idle&&u[n]?u[n]:{command:{exec:function(e){r.inputBuffer.push(e,n)}}};if(n.length==1&&(t==0||t==4))return{command:"null",passEvent:!0};if(n=="esc"&&t==0)return{command:i.stop}}else if(n=="ctrl-w")return{command:"removewordleft"}},attach:function(e){e.on("click",t.onCursorMove),s.currentMode!=="insert"&&r.coreCommands.stop.exec(e),e.$vimModeHandler=this},detach:function(e){e.removeListener("click",t.onCursorMove),s.noMode(e),s.currentMode="normal"},actions:r.actions,getStatusText:function(){return s.currentMode=="insert"?"INSERT":s.onVisualMode?(s.onVisualLineMode?"VISUAL LINE ":"VISUAL ")+r.inputBuffer.status:r.inputBuffer.status}},t.onCursorMove=function(e){r.onCursorMove(e.editor,e),t.onCursorMove.scheduled=!1}}),ace.define("ace/keyboard/vim/commands",["require","exports","module","ace/keyboard/vim/maps/util","ace/keyboard/vim/maps/motions","ace/keyboard/vim/maps/operators","ace/keyboard/vim/maps/aliases","ace/keyboard/vim/registers"],function(e,t,n){"never use strict";function g(e){m.previous={action:{action:{fn:e}}}}var r=e("./maps/util"),i=e("./maps/motions"),s=e("./maps/operators"),o=e("./maps/aliases"),u=e("./registers"),a=1,f=2,l=3,c=4,h=8,p=function(t,n,r){while(0t.$size.scrollerHeight&&(i=t.$size.scrollerHeight/2),t.scrollTop>r-i&&t.session.setScrollTop(r-i),t.scrollTop+t.$size.scrollerHeight0&&e.navigateLeft()),e.setOverwrite(!0),e.keyBinding.$data.buffer="",e.keyBinding.$data.state="start",this.onVisualMode=!1,this.onVisualLineMode=!1,e._emit("changeStatus"),e.commands.recording?(e.commands.toggleRecording(e),e.commands.macro):[]},visualMode:function(e,t){if(this.onVisualLineMode&&t||this.onVisualMode&&!t){this.normalMode(e);return}e.setStyle("insert-mode"),e.unsetStyle("normal-mode"),e._emit("changeStatus"),t?this.onVisualLineMode=!0:(this.onVisualMode=!0,this.onVisualLineMode=!1)},getRightNthChar:function(e,t,n,r){var i=e.getSession().getLine(t.row),s=i.substr(t.column+1).split(n);return r~!@#$%^&*|+=\[\]{}`~?]/,u=/[.\/\\()\"'-:,.;<>~!@#$%^&*|+=\[\]{}`~?]/,a=/\s/,f=function(e,t){var n=e.selection;this.range=n.getRange(),t=t||n.selectionLead,this.row=t.row,this.col=t.column;var r=e.session.getLine(this.row),i=e.session.getLength();this.ch=r[this.col]||"\n",this.skippedLines=0,this.next=function(){return this.ch=r[++this.col]||this.handleNewLine(1),this.ch},this.prev=function(){return this.ch=r[--this.col]||this.handleNewLine(-1),this.ch},this.peek=function(t){var n=r[this.col+t];return n?n:t==-1?"\n":this.col==r.length-1?"\n":e.session.getLine(this.row+1)[0]||"\n"},this.handleNewLine=function(t){if(t==1)return this.col==r.length?"\n":this.row==i-1?"":(this.col=0,this.row++,r=e.session.getLine(this.row),this.skippedLines++,r[0]||"\n");if(t==-1)return this.row===0?"":(this.row--,r=e.session.getLine(this.row),this.col=r.length,this.skippedLines--,"\n")},this.debug=function(){console.log(r.substring(0,this.col)+"|"+this.ch+"'"+this.col+"'"+r.substr(this.col+1))}},l=e("../../../search").Search,c=new l,p=e("../../../range").Range;n.exports={w:new s(function(e){var t=new f(e);if(t.ch&&u.test(t.ch))while(t.ch&&u.test(t.ch))t.next();else while(t.ch&&!o.test(t.ch))t.next();while(t.ch&&a.test(t.ch)&&t.skippedLines<2)t.next();return t.skippedLines==2&&t.prev(),{column:t.col,row:t.row}}),W:new s(function(e){var t=new f(e);while(t.ch&&(!a.test(t.ch)||!!a.test(t.peek(1)))&&t.skippedLines<2)t.next();return t.skippedLines==2?t.prev():t.next(),{column:t.col,row:t.row}}),b:new s(function(e){var t=new f(e);t.prev();while(t.ch&&a.test(t.ch)&&t.skippedLines>-2)t.prev();if(t.ch&&u.test(t.ch))while(t.ch&&u.test(t.ch))t.prev();else while(t.ch&&!o.test(t.ch))t.prev();return t.ch&&t.next(),{column:t.col,row:t.row}}),B:new s(function(e){var t=new f(e);t.prev();while(t.ch&&(!!a.test(t.ch)||!a.test(t.peek(-1)))&&t.skippedLines>-2)t.prev();return t.skippedLines==-2&&t.next(),{column:t.col,row:t.row}}),e:new s(function(e){var t=new f(e);t.next();while(t.ch&&a.test(t.ch))t.next();if(t.ch&&u.test(t.ch))while(t.ch&&u.test(t.ch))t.next();else while(t.ch&&!o.test(t.ch))t.next();return t.ch&&t.prev(),{column:t.col,row:t.row}}),E:new s(function(e){var t=new f(e);t.next();while(t.ch&&(!!a.test(t.ch)||!a.test(t.peek(1))))t.next();return{column:t.col,row:t.row}}),l:{nav:function(e){e.navigateRight()},sel:function(e){var t=e.getCursorPosition(),n=t.column,r=e.session.getLine(t.row).length;r&&n!==r&&e.selection.selectRight()}},h:{nav:function(e){var t=e.getCursorPosition();t.column>0&&e.navigateLeft()},sel:function(e){var t=e.getCursorPosition();t.column>0&&e.selection.selectLeft()}},H:{nav:function(e){var t=e.renderer.getScrollTopRow();e.moveCursorTo(t)},sel:function(e){var t=e.renderer.getScrollTopRow();e.selection.selectTo(t)}},M:{nav:function(e){var t=e.renderer.getScrollTopRow(),n=e.renderer.getScrollBottomRow(),r=t+(n-t)/2;e.moveCursorTo(r)},sel:function(e){var t=e.renderer.getScrollTopRow(),n=e.renderer.getScrollBottomRow(),r=t+(n-t)/2;e.selection.selectTo(r)}},L:{nav:function(e){var t=e.renderer.getScrollBottomRow();e.moveCursorTo(t)},sel:function(e){var t=e.renderer.getScrollBottomRow();e.selection.selectTo(t)}},k:{nav:function(e){e.navigateUp()},sel:function(e){e.selection.selectUp()}},j:{nav:function(e){e.navigateDown()},sel:function(e){e.selection.selectDown()}},i:{param:!0,sel:function(e,t,n,r){switch(r){case"w":e.selection.selectWord();break;case"W":e.selection.selectAWord();break;case"(":case"{":case"[":var i=e.getCursorPosition(),s=e.session.$findClosingBracket(r,i,/paren/);if(!s)return;var o=e.session.$findOpeningBracket(e.session.$brackets[r],i,/paren/);if(!o)return;o.column++,e.selection.setSelectionRange(p.fromPoints(o,s));break;case"'":case'"':case"/":var s=h(e,r,1);if(!s)return;var o=h(e,r,-1);if(!o)return;e.selection.setSelectionRange(p.fromPoints(o.end,s.start))}}},a:{param:!0,sel:function(e,t,n,r){switch(r){case"w":e.selection.selectAWord();break;case"W":e.selection.selectAWord();break;case"(":case"{":case"[":var i=e.getCursorPosition(),s=e.session.$findClosingBracket(r,i,/paren/);if(!s)return;var o=e.session.$findOpeningBracket(e.session.$brackets[r],i,/paren/);if(!o)return;s.column++,e.selection.setSelectionRange(p.fromPoints(o,s));break;case"'":case'"':case"/":var s=h(e,r,1);if(!s)return;var o=h(e,r,-1);if(!o)return;s.column++,e.selection.setSelectionRange(p.fromPoints(o.start,s.end))}}},f:new s({param:!0,handlesCount:!0,getPos:function(e,t,n,i,s){var o=e.getCursorPosition(),u=r.getRightNthChar(e,o,i,n||1);if(typeof u=="number")return o.column+=u+(s?2:1),o}}),F:new s({param:!0,handlesCount:!0,getPos:function(e,t,n,i,s){var o=e.getCursorPosition(),u=r.getLeftNthChar(e,o,i,n||1);if(typeof u=="number")return o.column-=u+1,o}}),t:new s({param:!0,handlesCount:!0,getPos:function(e,t,n,i,s){var o=e.getCursorPosition(),u=r.getRightNthChar(e,o,i,n||1);if(typeof u=="number")return o.column+=u+(s?1:0),o}}),T:new s({param:!0,handlesCount:!0,getPos:function(e,t,n,i,s){var o=e.getCursorPosition(),u=r.getLeftNthChar(e,o,i,n||1);if(typeof u=="number")return o.column-=u,o}}),"^":{nav:function(e){e.navigateLineStart()},sel:function(e){e.selection.selectLineStart()}},$:{nav:function(e){e.navigateLineEnd()},sel:function(e){e.selection.selectLineEnd()}},0:new s(function(e){return{row:e.selection.lead.row,column:0}}),G:{nav:function(e,t,n,r){!n&&n!==0&&(n=e.session.getLength()),e.gotoLine(n)},sel:function(e,t,n,r){!n&&n!==0&&(n=e.session.getLength()),e.selection.selectTo(n,0)}},g:{param:!0,nav:function(e,t,n,r){switch(r){case"m":console.log("Middle line");break;case"e":console.log("End of prev word");break;case"g":e.gotoLine(n||0);case"u":e.gotoLine(n||0);case"U":e.gotoLine(n||0)}},sel:function(e,t,n,r){switch(r){case"m":console.log("Middle line");break;case"e":console.log("End of prev word");break;case"g":e.selection.selectTo(n||0,0)}}},o:{nav:function(e,t,n,i){n=n||1;var s="";while(00?(e.navigateUp(),e.navigateLineEnd(),e.insert(o)):(e.session.insert({row:0,column:0},o),e.navigateUp()),r.insertMode(e))}},"%":new s(function(e){var t=/[\[\]{}()]/g,n=e.getCursorPosition(),r=e.session.getLine(n.row)[n.column];if(!t.test(r)){var i=h(e,t);if(!i)return;n=i.start}var s=e.session.findMatchingBracket({row:n.row,column:n.column+1});return s}),"{":new s(function(e){var t=e.session,n=t.selection.lead.row;while(n>0&&!/\S/.test(t.getLine(n)))n--;while(/\S/.test(t.getLine(n)))n--;return{column:0,row:n}}),"}":new s(function(e){var t=e.session,n=t.getLength(),r=t.selection.lead.row;while(r":{selFn:function(e,t,n,i){n=n||1;for(var s=0;s":var i=e.getCursorPosition();e.selection.selectLine();for(var s=0;s=|<<=|>>=|>>>=|<>|<|>|!|&&|\|\||\?\:|\*=|%=|\+=|\-=|&=|\^=|\b(?:in|instanceof|new|delete|typeof|void)/,next:"regex_allowed"},{token:"punctuation.operator",regex:/\?|\:|\,|\;|\./,next:"regex_allowed"},{token:"paren.lparen",regex:/[\[({]/,next:"regex_allowed"},{token:"paren.rparen",regex:/[\])}]/},{token:"keyword.operator",regex:/\/=?/,next:"regex_allowed"},{token:"comment",regex:/^#!.*$/},{token:"text",regex:/\s+/}],regex_allowed:[i.getStartRule("doc-start"),{token:"comment",merge:!0,regex:"\\/\\*",next:"comment_regex_allowed"},{token:"comment",regex:"\\/\\/.*$"},{token:"string.regexp",regex:"\\/",next:"regex",merge:!0},{token:"text",regex:"\\s+"},{token:"empty",regex:"",next:"start"}],regex:[{token:"regexp.keyword.operator",regex:"\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)"},{token:"string.regexp",regex:"/\\w*",next:"start",merge:!0},{token:"invalid",regex:/\{\d+,?(?:\d+)?}[+*]|[+*$^?][+*]|[$^][?]|\?{3,}/},{token:"constant.language.escape",regex:/\(\?[:=!]|\)|{\d+,?(?:\d+)?}|{,\d+}|[+*]\?|[(|)$^+*?]/},{token:"string.regexp",regex:/{|[^{\[\/\\(|)$^+*?]+/,merge:!0},{token:"constant.language.escape",regex:/\[\^?/,next:"regex_character_class",merge:!0},{token:"empty",regex:"",next:"start"}],regex_character_class:[{token:"regexp.keyword.operator",regex:"\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)"},{token:"constant.language.escape",regex:"]",next:"regex",merge:!0},{token:"constant.language.escape",regex:"-"},{token:"string.regexp.charachterclass",regex:/[^\]\-\\]+/,merge:!0},{token:"empty",regex:"",next:"start"}],function_arguments:[{token:"variable.parameter",regex:n},{token:"punctuation.operator",regex:"[, ]+",merge:!0},{token:"punctuation.operator",regex:"$",merge:!0},{token:"empty",regex:"",next:"start"}],comment_regex_allowed:[{token:"comment",regex:".*?\\*\\/",merge:!0,next:"regex_allowed"},{token:"comment",merge:!0,regex:".+"}],comment:[{token:"comment",regex:".*?\\*\\/",merge:!0,next:"start"},{token:"comment",merge:!0,regex:".+"}],qqstring:[{token:"constant.language.escape",regex:r},{token:"string",regex:'[^"\\\\]+',merge:!0},{token:"string",regex:"\\\\$",next:"qqstring",merge:!0},{token:"string",regex:'"|$',next:"start",merge:!0}],qstring:[{token:"constant.language.escape",regex:r},{token:"string",regex:"[^'\\\\]+",merge:!0},{token:"string",regex:"\\\\$",next:"qstring",merge:!0},{token:"string",regex:"'|$",next:"start",merge:!0}]},this.embedRules(i,"doc-",[i.getEndRule("start")])};r.inherits(o,s),t.JavaScriptHighlightRules=o}),ace.define("ace/mode/doc_comment_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=function(){this.$rules={start:[{token:"comment.doc.tag",regex:"@[\\w\\d_]+"},{token:"comment.doc",merge:!0,regex:"\\s+"},{token:"comment.doc",merge:!0,regex:"TODO"},{token:"comment.doc",merge:!0,regex:"[^@\\*]+"},{token:"comment.doc",merge:!0,regex:"."}]}};r.inherits(s,i),s.getStartRule=function(e){return{token:"comment.doc",merge:!0,regex:"\\/\\*(?=\\*)",next:e}},s.getEndRule=function(e){return{token:"comment.doc",merge:!0,regex:"\\*\\/",next:e}},t.DocCommentHighlightRules=s}),ace.define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(e,t,n){var r=e("../range").Range,i=function(){};(function(){this.checkOutdent=function(e,t){return/^\s+$/.test(e)?/^\s*\}/.test(t):!1},this.autoOutdent=function(e,t){var n=e.getLine(t),i=n.match(/^(\s*\})/);if(!i)return 0;var s=i[1].length,o=e.findMatchingBracket({row:t,column:s});if(!o||o.row==t)return 0;var u=this.$getIndent(e.getLine(o.row));e.replace(new r(t,0,t,s-1),u)},this.$getIndent=function(e){var t=e.match(/^(\s+)/);return t?t[1]:""}}).call(i.prototype),t.MatchingBraceOutdent=i}),ace.define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/token_iterator"],function(e,t,n){var r=e("../../lib/oop"),i=e("../behaviour").Behaviour,s=e("../../token_iterator").TokenIterator,o=0,u=-1,a="",f=function(){f.isSaneInsertion=function(e,t){var n=e.getCursorPosition(),r=new s(t,n.row,n.column);if(!this.$matchTokenType(r.getCurrentToken()||"text",["text","paren.rparen"])){r=new s(t,n.row,n.column+1);if(!this.$matchTokenType(r.getCurrentToken()||"text",["text","paren.rparen"]))return!1}return r.stepForward(),r.getCurrentTokenRow()!==n.row||this.$matchTokenType(r.getCurrentToken()||"text",["text","comment","paren.rparen"])},f.$matchTokenType=function(e,t){return t.indexOf(e.type||e)>-1},f.recordAutoInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isAutoInsertedClosing(r,i,a[0])||(o=0),u=r.row,a=n+i.substr(r.column),o++},f.isAutoInsertedClosing=function(e,t,n){return o>0&&e.row===u&&n===a[0]&&t.substr(e.column)===a},f.popAutoInsertedClosing=function(){a=a.substr(1),o--},this.add("braces","insertion",function(e,t,n,r,i){if(i=="{"){var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==""&&o!=="{")return{text:"{"+o+"}",selection:!1};if(f.isSaneInsertion(n,r))return f.recordAutoInsert(n,r,"}"),{text:"{}",selection:[1,1]}}else if(i=="}"){var u=n.getCursorPosition(),a=r.doc.getLine(u.row),l=a.substring(u.column,u.column+1);if(l=="}"){var c=r.$findOpeningBracket("}",{column:u.column+1,row:u.row});if(c!==null&&f.isAutoInsertedClosing(u,a,i))return f.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}else if(i=="\n"||i=="\r\n"){var u=n.getCursorPosition(),a=r.doc.getLine(u.row),l=a.substring(u.column,u.column+1);if(l=="}"){var h=r.findMatchingBracket({row:u.row,column:u.column+1});if(!h)return null;var p=this.getNextLineIndent(e,a.substring(0,a.length-1),r.getTabString()),d=this.$getIndent(r.doc.getLine(h.row));return{text:"\n"+p+"\n"+d,selection:[1,p.length,1,p.length]}}}}),this.add("braces","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="{"){var o=r.doc.getLine(i.start.row),u=o.substring(i.end.column,i.end.column+1);if(u=="}")return i.end.column++,i}}),this.add("parens","insertion",function(e,t,n,r,i){if(i=="("){var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!=="")return{text:"("+o+")",selection:!1};if(f.isSaneInsertion(n,r))return f.recordAutoInsert(n,r,")"),{text:"()",selection:[1,1]}}else if(i==")"){var u=n.getCursorPosition(),a=r.doc.getLine(u.row),l=a.substring(u.column,u.column+1);if(l==")"){var c=r.$findOpeningBracket(")",{column:u.column+1,row:u.row});if(c!==null&&f.isAutoInsertedClosing(u,a,i))return f.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("parens","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="("){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==")")return i.end.column++,i}}),this.add("brackets","insertion",function(e,t,n,r,i){if(i=="["){var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!=="")return{text:"["+o+"]",selection:!1};if(f.isSaneInsertion(n,r))return f.recordAutoInsert(n,r,"]"),{text:"[]",selection:[1,1]}}else if(i=="]"){var u=n.getCursorPosition(),a=r.doc.getLine(u.row),l=a.substring(u.column,u.column+1);if(l=="]"){var c=r.$findOpeningBracket("]",{column:u.column+1,row:u.row});if(c!==null&&f.isAutoInsertedClosing(u,a,i))return f.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("brackets","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="["){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u=="]")return i.end.column++,i}}),this.add("string_dquotes","insertion",function(e,t,n,r,i){if(i=='"'||i=="'"){var s=i,o=n.getSelectionRange(),u=r.doc.getTextRange(o);if(u!=="")return{text:s+u+s,selection:!1};var a=n.getCursorPosition(),f=r.doc.getLine(a.row),l=f.substring(a.column-1,a.column);if(l=="\\")return null;var c=r.getTokens(o.start.row),h=0,p,d=-1;for(var v=0;vo.start.column)break;h+=c[v].value.length}if(!p||d<0&&p.type!=="comment"&&(p.type!=="string"||o.start.column!==p.value.length+h-1&&p.value.lastIndexOf(s)===p.value.length-1))return{text:s+s,selection:[1,1]};if(p&&p.type==="string"){var m=f.substring(a.column,a.column+1);if(m==s)return{text:"",selection:[1,1]}}}}),this.add("string_dquotes","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&(s=='"'||s=="'")){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u=='"')return i.end.column++,i}})};r.inherits(f,i),t.CstyleBehaviour=f}),ace.define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(e,t,n){var r=e("../../lib/oop"),i=e("../../range").Range,s=e("./fold_mode").FoldMode,o=t.FoldMode=function(){};r.inherits(o,s),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(e,t,n){var r=e.getLine(n),i=r.match(this.foldingStartMarker);if(i){var s=i.index;return i[1]?this.openingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s+i[0].length,1)}if(t!=="markbeginend")return;var i=r.match(this.foldingStopMarker);if(i){var s=i.index+i[0].length;return i[1]?this.closingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s,-1)}}}.call(o.prototype)}) -------------------------------------------------------------------------------- /ace/mode-python.js: -------------------------------------------------------------------------------- 1 | ace.define("ace/mode/python",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/python_highlight_rules","ace/mode/folding/pythonic","ace/range"],function(e,t,n){var r=e("../lib/oop"),i=e("./text").Mode,s=e("../tokenizer").Tokenizer,o=e("./python_highlight_rules").PythonHighlightRules,u=e("./folding/pythonic").FoldMode,a=e("../range").Range,f=function(){this.$tokenizer=new s((new o).getRules()),this.foldingRules=new u("\\:")};r.inherits(f,i),function(){this.toggleCommentLines=function(e,t,n,r){var i=!0,s=/^(\s*)#/;for(var o=n;o<=r;o++)if(!s.test(t.getLine(o))){i=!1;break}if(i){var u=new a(0,0,0,0);for(var o=n;o<=r;o++){var f=t.getLine(o),l=f.match(s);u.start.row=o,u.end.row=o,u.end.column=l[0].length,t.replace(u,l[1])}}else t.indentRows(n,r,"#")},this.getNextLineIndent=function(e,t,n){var r=this.$getIndent(t),i=this.$tokenizer.getLineTokens(t,e),s=i.tokens;if(s.length&&s[s.length-1].type=="comment")return r;if(e=="start"){var o=t.match(/^.*[\{\(\[\:]\s*$/);o&&(r+=n)}return r};var e={pass:1,"return":1,raise:1,"break":1,"continue":1};this.checkOutdent=function(t,n,r){if(r!=="\r\n"&&r!=="\r"&&r!=="\n")return!1;var i=this.$tokenizer.getLineTokens(n.trim(),t).tokens;if(!i)return!1;do var s=i.pop();while(s&&(s.type=="comment"||s.type=="text"&&s.value.match(/^\s+$/)));return s?s.type=="keyword"&&e[s.value]:!1},this.autoOutdent=function(e,t,n){n+=1;var r=this.$getIndent(t.getLine(n)),i=t.getTabString();r.slice(-i.length)==i&&t.remove(new a(n,r.length-i.length,n,r.length))}}.call(f.prototype),t.Mode=f}),ace.define("ace/mode/python_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=function(){var e="and|as|assert|break|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|not|or|pass|print|raise|return|try|while|with|yield",t="True|False|None|NotImplemented|Ellipsis|__debug__",n="abs|divmod|input|open|staticmethod|all|enumerate|int|ord|str|any|eval|isinstance|pow|sum|basestring|execfile|issubclass|print|super|binfile|iter|property|tuple|bool|filter|len|range|type|bytearray|float|list|raw_input|unichr|callable|format|locals|reduce|unicode|chr|frozenset|long|reload|vars|classmethod|getattr|map|repr|xrange|cmp|globals|max|reversed|zip|compile|hasattr|memoryview|round|__import__|complex|hash|min|set|apply|delattr|help|next|setattr|buffer|dict|hex|object|slice|coerce|dir|id|oct|sorted|intern",r=this.createKeywordMapper({"invalid.deprecated":"debugger","support.function":n,"constant.language":t,keyword:e},"identifier"),i="(?:r|u|ur|R|U|UR|Ur|uR)?",s="(?:(?:[1-9]\\d*)|(?:0))",o="(?:0[oO]?[0-7]+)",u="(?:0[xX][\\dA-Fa-f]+)",a="(?:0[bB][01]+)",f="(?:"+s+"|"+o+"|"+u+"|"+a+")",l="(?:[eE][+-]?\\d+)",c="(?:\\.\\d+)",h="(?:\\d+)",p="(?:(?:"+h+"?"+c+")|(?:"+h+"\\.))",d="(?:(?:"+p+"|"+h+")"+l+")",v="(?:"+d+"|"+p+")";this.$rules={start:[{token:"comment",regex:"#.*$"},{token:"string",regex:i+'"{3}(?:[^\\\\]|\\\\.)*?"{3}'},{token:"string",merge:!0,regex:i+'"{3}.*$',next:"qqstring"},{token:"string",regex:i+'"(?:[^\\\\]|\\\\.)*?"'},{token:"string",regex:i+"'{3}(?:[^\\\\]|\\\\.)*?'{3}"},{token:"string",merge:!0,regex:i+"'{3}.*$",next:"qstring"},{token:"string",regex:i+"'(?:[^\\\\]|\\\\.)*?'"},{token:"constant.numeric",regex:"(?:"+v+"|\\d+)[jJ]\\b"},{token:"constant.numeric",regex:v},{token:"constant.numeric",regex:f+"[lL]\\b"},{token:"constant.numeric",regex:f+"\\b"},{token:r,regex:"[a-zA-Z_$][a-zA-Z0-9_$]*\\b"},{token:"keyword.operator",regex:"\\+|\\-|\\*|\\*\\*|\\/|\\/\\/|%|<<|>>|&|\\||\\^|~|<|>|<=|=>|==|!=|<>|="},{token:"paren.lparen",regex:"[\\[\\(\\{]"},{token:"paren.rparen",regex:"[\\]\\)\\}]"},{token:"text",regex:"\\s+"}],qqstring:[{token:"string",regex:'(?:[^\\\\]|\\\\.)*?"{3}',next:"start"},{token:"string",merge:!0,regex:".+"}],qstring:[{token:"string",regex:"(?:[^\\\\]|\\\\.)*?'{3}",next:"start"},{token:"string",merge:!0,regex:".+"}]}};r.inherits(s,i),t.PythonHighlightRules=s}),ace.define("ace/mode/folding/pythonic",["require","exports","module","ace/lib/oop","ace/mode/folding/fold_mode"],function(e,t,n){var r=e("../../lib/oop"),i=e("./fold_mode").FoldMode,s=t.FoldMode=function(e){this.foldingStartMarker=new RegExp("([\\[{])(?:\\s*)$|("+e+")(?:\\s*)(?:#.*)?$")};r.inherits(s,i),function(){this.getFoldWidgetRange=function(e,t,n){var r=e.getLine(n),i=r.match(this.foldingStartMarker);if(i)return i[1]?this.openingBracketBlock(e,i[1],n,i.index):i[2]?this.indentationBlock(e,n,i.index+i[2].length):this.indentationBlock(e,n)}}.call(s.prototype)}) -------------------------------------------------------------------------------- /ace/theme-chrome.js: -------------------------------------------------------------------------------- 1 | ace.define("ace/theme/chrome",["require","exports","module","ace/lib/dom"],function(e,t,n){t.isDark=!1,t.cssClass="ace-chrome",t.cssText='.ace-chrome .ace_gutter {background: #ebebeb;color: #333;overflow : hidden;}.ace-chrome .ace_print-margin {width: 1px;background: #e8e8e8;}.ace-chrome .ace_scroller {background-color: #FFFFFF;}.ace-chrome .ace_cursor {border-left: 2px solid black;}.ace-chrome .ace_overwrite-cursors .ace_cursor {border-left: 0px;border-bottom: 1px solid black;}.ace-chrome .ace_invisible {color: rgb(191, 191, 191);}.ace-chrome .ace_constant.ace_buildin {color: rgb(88, 72, 246);}.ace-chrome .ace_constant.ace_language {color: rgb(88, 92, 246);}.ace-chrome .ace_constant.ace_library {color: rgb(6, 150, 14);}.ace-chrome .ace_invalid {background-color: rgb(153, 0, 0);color: white;}.ace-chrome .ace_fold {}.ace-chrome .ace_support.ace_function {color: rgb(60, 76, 114);}.ace-chrome .ace_support.ace_constant {color: rgb(6, 150, 14);}.ace-chrome .ace_support.ace_type,.ace-chrome .ace_support.ace_class.ace-chrome .ace_support.ace_other {color: rgb(109, 121, 222);}.ace-chrome .ace_variable.ace_parameter {font-style:italic;color:#FD971F;}.ace-chrome .ace_keyword.ace_operator {color: rgb(104, 118, 135);}.ace-chrome .ace_comment {color: #236e24;}.ace-chrome .ace_comment.ace_doc {color: #236e24;}.ace-chrome .ace_comment.ace_doc.ace_tag {color: #236e24;}.ace-chrome .ace_constant.ace_numeric {color: rgb(0, 0, 205);}.ace-chrome .ace_variable {color: rgb(49, 132, 149);}.ace-chrome .ace_xml-pe {color: rgb(104, 104, 91);}.ace-chrome .ace_entity.ace_name.ace_function {color: #0000A2;}.ace-chrome .ace_markup.ace_heading {color: rgb(12, 7, 255);}.ace-chrome .ace_markup.ace_list {color:rgb(185, 6, 144);}.ace-chrome .ace_marker-layer .ace_selection {background: rgb(181, 213, 255);}.ace-chrome .ace_marker-layer .ace_step {background: rgb(252, 255, 0);}.ace-chrome .ace_marker-layer .ace_stack {background: rgb(164, 229, 101);}.ace-chrome .ace_marker-layer .ace_bracket {margin: -1px 0 0 -1px;border: 1px solid rgb(192, 192, 192);}.ace-chrome .ace_marker-layer .ace_active-line {background: rgba(0, 0, 0, 0.07);}.ace-chrome .ace_gutter-active-line {background-color : #dcdcdc;}.ace-chrome .ace_marker-layer .ace_selected-word {background: rgb(250, 250, 255);border: 1px solid rgb(200, 200, 250);}.ace-chrome .ace_storage,.ace-chrome .ace_keyword,.ace-chrome .ace_meta.ace_tag {color: rgb(147, 15, 128);}.ace-chrome .ace_string.ace_regex {color: rgb(255, 0, 0)}.ace-chrome .ace_string {color: #1A1AA6;}.ace-chrome .ace_entity.ace_other.ace_attribute-name {color: #994409;}.ace-chrome .ace_indent-guide {background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4////f4bLly//BwAmVgd1/w11/gAAAABJRU5ErkJggg==") right repeat-y;}';var r=e("../lib/dom");r.importCssString(t.cssText,t.cssClass)}) -------------------------------------------------------------------------------- /contextmenu/arrow_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xdabbad00/icebuddha/6ebfbeb2a2ceda9a4b15f2f7fe203522ef3e8113/contextmenu/arrow_s.png -------------------------------------------------------------------------------- /contextmenu/jquery.contextmenu.css: -------------------------------------------------------------------------------- 1 | .uctxMenu { 2 | position: absolute; 3 | z-index: 99999; 4 | border: solid 1px #979797; 5 | background: #f1f1f1; 6 | padding: 2px 0; 7 | margin: 0; 8 | top: 0; 9 | left: 0; 10 | display: none; 11 | font-family: Arial, Helvetica, sans-serif; 12 | -moz-box-shadow: 3px 3px 5px rgba(0,0,0,.3); 13 | -webkit-box-shadow: 3px 3px 5px rgba(0,0,0,.3); 14 | box-shadow: 3px 3px 5px rgba(0,0,0,.3); 15 | } 16 | .uctxMenu ul { 17 | list-style: none; 18 | padding: 0; 19 | margin: 0; 20 | } 21 | .uctxMenu li { 22 | margin: 1px 2px; 23 | padding: 1px; 24 | color : #333; 25 | } 26 | .uctxMenu a { 27 | text-decoration: none; 28 | color: #333; 29 | display: block; 30 | line-height: 20px; 31 | height: 20px; 32 | outline: none; 33 | padding: 1px 1px 1px 1px; 34 | margin-left: 0px; 35 | border-left: 1px solid #e3e3e3; 36 | margin-top: -1px; 37 | margin-bottom: -3px; 38 | } 39 | 40 | #content .uctxMenu a {color: #333;} 41 | 42 | .uctxMenu img { 43 | float: left; 44 | margin-top: 2px; 45 | margin-left: 6px; 46 | } 47 | .uctxMenu li.separator a { 48 | border-top: 1px solid #e3e3e3; 49 | margin-top: -4px; 50 | padding-top: 5px; 51 | } 52 | .uctxMenu li.separator, .uctxMenu li.separator.hover { 53 | margin-top: 5px; 54 | } 55 | .uctxMenu li.hover { 56 | background-color: #e2ecf5; 57 | -moz-border-radius: 2px; 58 | border-radius: 3px; 59 | border: 1px solid #acd8e5; 60 | padding: 0; 61 | margin: 1px 2px; 62 | background: -moz-linear-gradient(100% 100% 90deg, #e8f2fe, #daebf3); 63 | background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#daebf3), to(#e8f2fe)); 64 | background: -webkit-linear-gradient(#e8f2fe, #daebf3); 65 | background: -o-linear-gradient(#e8f2fe, #daebf3); 66 | } 67 | .uctxMenu li.disabled { 68 | color: #999; 69 | } 70 | .uctxMenu li span { 71 | background-image: url('arrow_s.png'); 72 | background-position: center; 73 | background-repeat: no-repeat; 74 | width: 10px; 75 | height: 20px; 76 | float: right; 77 | } 78 | .uctxMenu li ul { 79 | margin-top: -2px; 80 | left: 180px; 81 | position: absolute; 82 | width: 180px; 83 | border: solid 1px #979797; 84 | background: #f1f1f1; 85 | display: none; 86 | top: 0; 87 | padding: 2px 0; 88 | margin: 0; 89 | -moz-box-shadow: 3px 3px 5px rgba(0,0,0,.3); 90 | -webkit-box-shadow: 3px 3px 5px rgba(0,0,0,.3); 91 | box-shadow: 3px 3px 5px rgba(0,0,0,.3); 92 | } -------------------------------------------------------------------------------- /contextmenu/jquery.contextmenu.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * jQuery ContextMenu 3 | * http://www.userdot.net/#!/jquery 4 | * 5 | * Copyright 2011, UserDot www.userdot.net 6 | * Licensed under the GPL Version 3 license. 7 | * Version 1.0.0 8 | * 9 | */ 10 | (function($) { 11 | var classes = { 12 | popupDiv : 'uctxMenu', 13 | separator : 'separator', 14 | hover : 'hover', 15 | disabled : 'disabled' 16 | }, 17 | defaults = { 18 | menu : null, 19 | mouseButton : 'right', 20 | isMenu : true, 21 | minWidth : 120, 22 | maxWidth : 0, 23 | delay : 500, 24 | keyboard : true, 25 | hoverIntent : true, 26 | onSelect : function(item) {}, 27 | onLoad : function() {}, 28 | onShow : function() {}, 29 | onHide : function() {} 30 | }, 31 | menus = [], 32 | target, 33 | methods = { 34 | init : function(options) { 35 | options = $.extend({}, defaults, options); 36 | if (!options.menu) { 37 | return false; 38 | } 39 | var $menu; 40 | if ((typeof(options.menu) === 'object') && (options.menu.constructor.toString().match(/array/i) !== null || options.menu.length)) { 41 | $menu = $('
').append(buildMenu(options.menu)); 42 | $('body').append($menu); 43 | $menu.data('uctxDynamic', true); 44 | } 45 | else { 46 | $menu = $(document.getElementById(options.menu)); 47 | $menu.data('uctxDynamic', false); 48 | $menu.data('uctxOriginal', $menu.clone()); 49 | } 50 | return this.each(function() { 51 | var $this = $(this), 52 | eventNamespace; 53 | if (!$this.data('uctxMenu')) { 54 | eventNamespace = "uctxContext-" + (new Date().getTime()); 55 | $this.data('uctxEventNamespace', eventNamespace) 56 | .data('uctxOptions', options) 57 | .data('uctxMenu', $menu) 58 | .data('uctxEnable', true); 59 | $menu.data('isMenu', options.isMenu); 60 | if (! $menu.data('uctxOwners')) { 61 | $menu.data('uctxOwners', []); 62 | } 63 | $menu.data('uctxOwners').push($this); 64 | menus.push($menu); 65 | if (options.isMenu) { 66 | methods.refresh.call($this); 67 | } 68 | else { 69 | $menu.hide(); 70 | $menu.css({ 71 | 'position' : 'absolute', 72 | 'z-index' : 99999 73 | }); 74 | } 75 | $this.bind((((options.mouseButton === 'right') ? 'contextmenu' : 'click') + '.' + eventNamespace), function(e){ 76 | target = $(e.target); 77 | 78 | if (! $this.data('uctxEnable')) { 79 | return true; 80 | } 81 | methods.show.apply($this, [e.pageX, e.pageY, options.showAnimation]); 82 | if (options.isMenu && options.keyboard) { 83 | $(window).bind('keydown.' + eventNamespace, function(even){ 84 | var $currentItem; 85 | switch (event.keyCode) { 86 | case 27: 87 | $(document).trigger('click.' + eventNamespace); 88 | break; 89 | case 40: 90 | if ($menu.find('li.' + classes.hover).length === 0) { 91 | $menu.find('li:not(.disabled):first').addClass(classes.hover); 92 | } 93 | else { 94 | $currentItem = $menu.find('li.' + classes.hover + ':last'); 95 | $currentItem.parent().find('li.' + classes.hover).removeClass(classes.hover).nextAll('li:not(.disabled)').eq(0).addClass(classes.hover); 96 | if ($currentItem.parent().find('li.' + classes.hover).length === 0) { 97 | $currentItem.parent().find('li:not(.disabled):first').addClass(classes.hover); 98 | } 99 | } 100 | return false; 101 | case 38: 102 | if ($menu.find('li.' + classes.hover).length === 0) { 103 | $menu.find('li:not(.disabled):first').nextAll().eq(-1).addClass(classes.hover); 104 | } 105 | else { 106 | $currentItem = $menu.find('li.' + classes.hover + ':last'); 107 | $currentItem.parent().find('li.' + classes.hover).removeClass(classes.hover).prevAll('LI:not(.disabled)').eq(0).addClass(classes.hover); 108 | if ($currentItem.parent().find('li.' + classes.hover).length === 0) { 109 | $currentItem.parent().find('li:first').nextAll().eq(-1).addClass(classes.hover); 110 | } 111 | } 112 | return false; 113 | case 39: 114 | if ($menu.find('li.' + classes.hover + ' ul').length > 0) { 115 | $menu.find('li.' + classes.hover + ':last').find('ul:first').show().offset(forceViewport({ 116 | top: $menu.find('li.' + classes.hover + ':last').offset().top 117 | }, $menu.find('li.' + classes.hover + ':last').find('ul:first'))); 118 | $menu.find('li.' + classes.hover + ':last ul:first li:not(.disabled):first').addClass(classes.hover); 119 | } 120 | return false; 121 | case 37: 122 | if (!$menu.find('li.' + classes.hover + ':last').parent().parent().hasClass(classes.popupDiv)) { 123 | $menu.find('li.' + classes.hover + ':last').removeClass(classes.hover).parent().hide(); 124 | } 125 | return false; 126 | } 127 | return true; 128 | }); 129 | } 130 | else { 131 | if (options.keyboard) { 132 | $(window).bind('keydown.' + eventNamespace, function(even){ 133 | if (event.keyCode === 27) { 134 | $(document).trigger('click.' + eventNamespace); 135 | } 136 | }); 137 | } 138 | } 139 | $('li', $menu).each(function() { 140 | $(this).click(function() { 141 | if (!$(this).hasClass(classes.disabled)) { 142 | options.onSelect.call(this, { 143 | id : $(this).attr('id'), 144 | action : $('a:first', this).attr('href').substr(1), 145 | target: target 146 | }); 147 | } 148 | }); 149 | }); 150 | $(document).bind('click.' + eventNamespace, function(e){ 151 | $(window).unbind('keydown.' + eventNamespace); 152 | $(document).unbind('click.' + eventNamespace); 153 | $('li', $menu).unbind('click'); 154 | methods.hide.call(); 155 | }); 156 | options.onShow.call(this); 157 | return false; 158 | }); 159 | } 160 | options.onLoad.call(this); 161 | }); 162 | }, 163 | refresh : function(options) { 164 | var opts; 165 | return this.each(function() { 166 | var $this = $(this), 167 | $menu = $this.data('uctxMenu'), 168 | calculatedWidth, 169 | $widthTest; 170 | if ($this.data('uctxMenu').data('isMenu')) { 171 | opts = $.extend($this.data('uctxOptions'), options); 172 | if (opts.hoverIntent && ! $.fn.hoverIntent) { 173 | opts.hoverIntent = false; 174 | } 175 | $menu.removeClass(classes.popupDiv); 176 | $('li', $menu).removeClass(classes.hover); 177 | $('span', $menu).remove(); 178 | $menu.addClass(classes.popupDiv); 179 | $widthTest = $('
').addClass(classes.popupDiv).appendTo('body'); 180 | $('ul', $menu).each(function() { 181 | $widthTest.html(''); 182 | calculatedWidth = 0; 183 | $widthTest.html($(this).html()); 184 | calculatedWidth = $widthTest.width() + 16; 185 | if (calculatedWidth < opts.minWidth) { 186 | calculatedWidth = opts.minWidth; 187 | } 188 | if (calculatedWidth > opts.maxWidth && opts.maxWidth > 0){ 189 | calculatedWidth = opts.maxWidth; 190 | } 191 | $(this).width(calculatedWidth); 192 | $(this).children('li').children('ul').css('left', calculatedWidth); 193 | }); 194 | $widthTest.remove(); 195 | $('li:has(ul)', $menu).each(function(){ 196 | if (! $(this).hasClass(classes.disabled)) { 197 | $('a:first', this).append($('')); 198 | if (opts.hoverIntent) { 199 | $(this).hoverIntent({ 200 | over : function() { 201 | $('ul:first', this).show().offset(forceViewport({ 202 | top: $(this).offset().top 203 | }, $('ul:first',this))); 204 | }, 205 | out : function() { 206 | $('ul:first', this).hide(); 207 | }, 208 | timeout : opts.delay 209 | }); 210 | } 211 | else { 212 | $(this).hover(function() { 213 | $('ul:first', this).show().offset(forceViewport({ 214 | top: $(this).offset().top 215 | }, $(this).find('ul:first'))); 216 | }, function() { 217 | $('ul:first', this).hide(); 218 | }); 219 | } 220 | } 221 | }); 222 | $('li', $menu).each(function() { 223 | $(this).click(function() { 224 | if ($('ul', this).length < 1) { 225 | $('li', $menu).unbind('click'); 226 | $menu.hide(); 227 | } 228 | return false; 229 | }); 230 | $(this).hover(function() { 231 | $(this).parent().find('li.' + classes.hover).removeClass(classes.hover); 232 | $(this).addClass(classes.hover); 233 | }, function() { 234 | $(this).removeClass(classes.hover); 235 | }); 236 | }); 237 | } 238 | }); 239 | }, 240 | restore : function() { 241 | return this.each(function() { 242 | var $this = $(this), 243 | $menu = $this.data('uctxMenu'); 244 | $this.unbind('.' + $this.data('uctxEventNamespace')); 245 | $(window).unbind('keydown.' + $this.data('uctxEventNamespace')); 246 | $(document).unbind('click.' + $this.data('uctxEventNamespace')); 247 | $.each($menu.data('uctxOwners'), function(index) { 248 | if ($this[0] === this) { 249 | $menu.data('uctxOwners').splice(index, 1); 250 | } 251 | }); 252 | if ($menu.data('uctxOwners').length < 1) { 253 | $.each(menus, function(index) { 254 | if ($menu[0] === this) { 255 | menus.splice(index, 1); 256 | } 257 | }); 258 | if ($menu.data('uctxDynamic')) { 259 | $menu.remove(); 260 | } 261 | else { 262 | $menu.removeClass(classes.popupDiv); 263 | $menu.replaceWith($menu.data('uctxOriginal')); 264 | } 265 | } 266 | $this.removeData('uctxEventNamespace'); 267 | $this.removeData('uctxMenu'); 268 | $this.removeData('uctxOptions'); 269 | $this.removeData('uctxEnable'); 270 | }); 271 | }, 272 | show : function(x, y) { 273 | if (!x || !y) { 274 | $.error('The position for the menu has not been specified'); 275 | return false; 276 | } 277 | var $menu = $(this).first().data('uctxMenu'); 278 | methods.hide.apply(this); 279 | $menu.show(); 280 | $menu.data('uctxMenu', $(this)); 281 | $menu.offset(forceViewport({ 282 | top : y, 283 | left: x 284 | }, $menu, true)); 285 | return this; 286 | }, 287 | hide : function() { 288 | $.each(menus, function() { 289 | $('.' + classes.hover, this).removeClass(classes.hover); 290 | $('ul:first ul', this).hide(); 291 | if ($(this).data('uctxMenu')) { 292 | $(this).data('uctxMenu').data('uctxOptions').onHide.call($(this).data('uctxMenu')); 293 | $(this).removeData('uctxMenu'); 294 | } 295 | $(this).hide(); 296 | }); 297 | return this; 298 | }, 299 | disable : function(item) { 300 | if (item) { 301 | var $menu = $(this).data('uctxMenu'); 302 | if (item.charAt(0) === '#') { 303 | $('li' + item.replace(/ /g,'_'), $menu).addClass(classes.disabled); 304 | } 305 | else { 306 | $('a[href="' + item + '"]', $menu).parent().addClass(classes.disabled); 307 | } 308 | } 309 | else { 310 | $(this).data('uctxEnable', false); 311 | } 312 | return this; 313 | }, 314 | enable : function(item) { 315 | if (item) { 316 | var $menu = $(this).data('uctxMenu'); 317 | if (item.charAt(0) === '#') { 318 | $('li' + item.replace(/ /g,'_'), $menu).removeClass(classes.disabled); 319 | } 320 | else { 321 | $('a[href="' + item + '"]', $menu).parent().removeClass(classes.disabled); 322 | } 323 | } 324 | else { 325 | $(this).data('uctxEnable', true); 326 | $('li', this).each(function() { 327 | $(this).removeClass(classes.disabled); 328 | }); 329 | } 330 | return this; 331 | } 332 | }, 333 | forceViewport = function(position, o, mouse) { 334 | if (position.top) { 335 | if ((position.top + o.height() - $(window).scrollTop()) > $(window).height()) { 336 | if (mouse) { 337 | position.top = position.top - o.height(); 338 | } 339 | else { 340 | position.top = $(window).height() + $(window).scrollTop() - o.height(); 341 | } 342 | } 343 | if (position.top < $(window).scrollTop()) { 344 | position.top = $(window).scrollTop(); 345 | } 346 | } 347 | if (position.left) { 348 | if ((position.left + o.width() - $(window).scrollLeft() > $(window).width())) { 349 | position.left = $(window).width() - o.width() + $(window).scrollLeft(); 350 | } 351 | if (position.left < $(window).scrollLeft()) { 352 | position.left = $(window).scrollLeft(); 353 | } 354 | } 355 | return position; 356 | }, 357 | buildMenu = function(children) { 358 | var ul = $('
    '), entry, item, li; 359 | if (children) { 360 | for (entry in children) { 361 | item = children[entry]; 362 | li = $('
  • ').attr('id' , item.id.replace(/ /g,'_')).append($('').attr('href', item.action?('#' + item.action):'#').text(item.text)); 363 | if (item.image) { 364 | li.prepend($('').attr('src', item.image)); 365 | } 366 | if (item.separator) { 367 | li.addClass(classes.separator); 368 | } 369 | ul.append( li ); 370 | if (item.children) { 371 | li.append(buildMenu(item.children)); 372 | } 373 | } 374 | } 375 | return ul; 376 | }; 377 | $.fn.contextMenu = function(method) { 378 | if (methods[method]) { 379 | return methods[ method ].apply(this, Array.prototype.slice.call(arguments, 1)); 380 | } 381 | else if (typeof method === 'object' || ! method) { 382 | return methods.init.apply(this, arguments); 383 | } 384 | else { 385 | $.error('Method ' + method + ' does not exist on jQuery.contextmenu'); 386 | return this; 387 | } 388 | }; 389 | })(jQuery); 390 | 391 | -------------------------------------------------------------------------------- /contextmenu/jquery.hoverintent.js: -------------------------------------------------------------------------------- 1 | /** 2 | * hoverIntent r5 // 2007.03.27 // jQuery 1.1.2+ 3 | * 4 | * 5 | * @param f onMouseOver function || An object with configuration options 6 | * @param g onMouseOut function || Nothing (use configuration options object) 7 | * @author Brian Cherne 8 | */ 9 | (function($){$.fn.hoverIntent=function(f,g){var cfg={sensitivity:7,interval:100,timeout:0};cfg=$.extend(cfg,g?{over:f,out:g}:f);var cX,cY,pX,pY;var track=function(ev){cX=ev.pageX;cY=ev.pageY;};var compare=function(ev,ob){ob.hoverIntent_t=clearTimeout(ob.hoverIntent_t);if((Math.abs(pX-cX)+Math.abs(pY-cY)) 2 | 3 | Ice Buddha 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 26 | 27 |
    28 | 31 | 32 |
    33 |
    34 | 35 |
    36 | 37 |
    38 | 39 |
    40 | 44 | 45 |
    46 | Drop file here 47 |
    48 | 49 |
    50 | Fork me on GitHub 51 |

    52 | 53 | 54 |

    55 |

    Check out Summit Route for end-point protection. 56 |
    57 | 58 | 59 | 60 | 61 |

    62 | 63 |

    About

    64 | IceBuddha is an open-source (MIT license) hex viewer and generic binary file parser that runs in the browser. 65 |

    66 | See an example. 67 | 68 |

    69 |

    Why?

    70 | I wanted to test the limits of what was possible in the browser from a static site. Because all the files are static (no database, and no server-side functionality) IceBuddha is hosted on github pages. 71 | 72 |

    Ridiculous things IceBuddha does

    73 |
      74 |
    1. "Submitted" files are not uploaded anywhere. Everything happens in your browser locally. 75 |
      If you're concerned, you can clone and host this project locally by running it in a simple web server, 76 | such as using "python -m SimpleHTTPServer" in the folder you clone the repo to. 77 |
    2. Files are parsed via >Python scripts that define the structure of the files. 78 | The python is converted to Javascript in your browser via the skulpt library. 79 | By clicking on the "Parse as" tab when you drop a file, you can see this Python code. 80 | You can then edit it, and your file will parsed again immediately using your new code. 81 | Again, this is all happening entirely in your browser without hitting the server. 82 |
    3. You can take your python parse scripts, and run them directly on files to generate JSON data, without using your browser, as explained here 83 |
    84 |

    Similar projects/products

    85 | 010 editor: Windows & Mac (commercial), odd format for binary templates to parse files, but looks similar to C structs and is often referenced. 86 |
    Synalize It!: Mac only (commercial); XML based grammar format which means limited capability for more advanced binary file formats. 87 |

    88 |

    File parsing

    89 | IceBuddha can parse a few of the main structures in the following file types: 90 |
      91 |
    1. PE files (.exe, .dll, .sys) 92 |
    2. GIF image files 93 |
    3. Mach-O (Mac OS X files) 94 |
    95 |

    Expanding and adding your own file parsing

    96 | File types are automatically identified in drop.js via the function "ChooseParseScript". Look at pe.py to see an example of how files are parsed. 97 |
      98 |
    1. Change the PE in the line ib = icebuddha.IceBuddha(filedata, "PE") to be name of your file type. 99 |
    2. The line imageDosHeader = ib.parse(0, "IMAGE_DOS_HEADER", """ creates a structure at offset 0 with name IMAGE_DOS_HEADER. 100 | Then the next lines in that file describe what is in that structure. 101 |
    3. Known variable types are: 102 |
        103 |
      1. BYTE, CHAR, and anything unknown: 1 byte 104 |
      2. WORD: 2 bytes 105 |
      3. DWORD: 4 bytes 106 |
      4. ULONGLONG: 8 bytes 107 |
      108 | You can also create arrays such as WORD e_res2[10]; 109 |
    4. ib is the root object, so we then append imageDosHeader to that. Later we append objects to imageDosHeader 110 |
    5. The line e_lfanew = imageDosHeader.getInt("e_lfanew") gets the value of PE.IMAGE_DOS_HEADER.e_lfanew in the file it parses, and sets the variable e_lfanew which is then used as the offset in the next line. 111 |
    6. Usually you can specify an offset simply by using something like imageNtHeader.end() to specify the end of the previous object. 112 |
    7. To describe a bit field, you can look at what I did for dllCharacteristics. 113 |
    8. Finally, you just need to return everything with the lines return ib.getParseTree() and parser = Parse() 114 |
    9. You can have loops, other functions, and other logic in your code, as shown in gif.py. 115 |
    10. You can also describe what a value means as shown with the function setMeaningFromConstants in the file mach_o.py 116 |
    11. You can set the endianness as shown with setBigEndian in the file mach_o.py 117 |
    118 | 119 |

    120 |

    Project status

    121 | IceBuddha is mostly abandoned (last update on 2014-11-13). It does a lot of stuff, but a lot of things are impossible for a webapp based on static files (ex. saving files). 122 |

    This was my first javascript project. The codebase is not pretty. 123 | 124 |

    125 | 126 |
    127 | 128 | 131 |
    132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | -------------------------------------------------------------------------------- /jqtree/jqtree.css: -------------------------------------------------------------------------------- 1 | ul.tree { 2 | margin-left: 12px; 3 | } 4 | 5 | ul.tree, 6 | ul.tree ul { 7 | list-style: none outside; 8 | margin-bottom: 0; 9 | } 10 | 11 | ul.tree ul { 12 | display: block; 13 | margin-left: 12px; 14 | margin-right: 0; 15 | } 16 | 17 | ul.tree li.closed > ul { 18 | display: none; 19 | } 20 | 21 | ul.tree li { 22 | clear: both; 23 | } 24 | 25 | ul.tree .toggler { 26 | background: url(treeDownTriangleBlack.png) no-repeat 0 50%; 27 | width: 12px; 28 | display: block; 29 | position: absolute; 30 | left: -12px; 31 | text-indent: -9999px; 32 | border-bottom: none; 33 | } 34 | 35 | ul.tree div { 36 | cursor: pointer; 37 | } 38 | 39 | ul.tree .title { 40 | /* color: #1C4257; */ 41 | font-family: monospace, monospace; 42 | vertical-align: middle; 43 | } 44 | 45 | ul.tree li.folder { 46 | margin-bottom: 4px; 47 | } 48 | 49 | ul.tree li.folder.closed { 50 | margin-bottom: 1px; 51 | } 52 | 53 | ul.tree li.folder .title { 54 | margin-left: 0; 55 | } 56 | 57 | ul.tree .toggler.closed { 58 | background-image: url(treeRightTriangleBlack.png); 59 | } 60 | 61 | span.tree-dragging { 62 | color: #fff; 63 | background: #000; 64 | opacity: 0.6; 65 | cursor: pointer; 66 | padding: 2px 8px; 67 | } 68 | 69 | ul.tree li.ghost { 70 | position: relative; 71 | z-index: 10; 72 | margin-right: 10px; 73 | } 74 | 75 | ul.tree li.ghost span { 76 | display: block; 77 | } 78 | 79 | ul.tree li.ghost span.circle { 80 | background: url(circle.png) no-repeat; 81 | height: 8px; 82 | width: 8px; 83 | position: absolute; 84 | top: -4px; 85 | left: 2px; 86 | } 87 | 88 | ul.tree li.ghost span.line { 89 | background-color: #0000ff; 90 | height: 2px; 91 | padding: 0; 92 | position: absolute; 93 | top: -1px; 94 | left: 10px; 95 | width: 100%; 96 | } 97 | 98 | ul.tree li.ghost.inside { 99 | margin-left: 48px; 100 | } 101 | 102 | ul.tree span.tree-hit { 103 | position: absolute; 104 | display: block; 105 | } 106 | 107 | ul.tree span.border { 108 | position: absolute; 109 | display: block; 110 | left: -2px; 111 | top: 0; 112 | border: solid 2px #0000ff; 113 | -webkit-border-radius: 6px; 114 | -moz-border-radius: 6px; 115 | border-radius: 6px; 116 | margin: 0; 117 | } 118 | 119 | ul.tree div { 120 | width: 100%; 121 | position: relative; 122 | } 123 | 124 | ul.tree li.selected > div, 125 | ul.tree li.selected > div:hover { 126 | background-color: #97BDD6; 127 | background: -webkit-gradient(linear, left top, left bottom, from(#BEE0F5), to(#89AFCA)); 128 | background: -moz-linear-gradient(top, #BEE0F5, #89AFCA); 129 | text-shadow: 0 1px 0 rgba(255, 255, 255, 0.7); 130 | } 131 | 132 | ul.tree .moving > div .title { 133 | outline: dashed 1px #0000ff; 134 | } 135 | -------------------------------------------------------------------------------- /jqtree/tree.jquery.js: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | Copyright 2012 Marco Braak 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | (function() { 19 | var $, BorderDropHint, DragElement, FolderElement, GhostDropHint, Json, Node, NodeElement, Position, indexOf, toJson, 20 | __hasProp = Object.prototype.hasOwnProperty, 21 | __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor; child.__super__ = parent.prototype; return child; }; 22 | 23 | this.Tree = {}; 24 | 25 | $ = this.jQuery; 26 | 27 | indexOf = function(array, item) { 28 | var i, value, _len; 29 | if (array.indexOf) { 30 | return array.indexOf(item); 31 | } else { 32 | for (i = 0, _len = array.length; i < _len; i++) { 33 | value = array[i]; 34 | if (value === item) return i; 35 | } 36 | return -1; 37 | } 38 | }; 39 | 40 | this.Tree.indexOf = indexOf; 41 | 42 | Json = {}; 43 | 44 | Json.escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g; 45 | 46 | Json.meta = { 47 | '\b': '\\b', 48 | '\t': '\\t', 49 | '\n': '\\n', 50 | '\f': '\\f', 51 | '\r': '\\r', 52 | '"': '\\"', 53 | '\\': '\\\\' 54 | }; 55 | 56 | Json.quote = function(string) { 57 | Json.escapable.lastIndex = 0; 58 | if (Json.escapable.test(string)) { 59 | return '"' + string.replace(Json.escapable, function(a) { 60 | var c; 61 | c = Json.meta[a]; 62 | return (type(c === 'string') ? c : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4)); 63 | }) + '"'; 64 | } else { 65 | return '"' + string + '"'; 66 | } 67 | }; 68 | 69 | Json.str = function(key, holder) { 70 | var i, k, partial, v, value, _len; 71 | value = holder[key]; 72 | if (value && typeof value === 'object' && value.toJSON === 'function') { 73 | value = value.toJSON(key); 74 | } 75 | switch (typeof value) { 76 | case 'string': 77 | return Json.quote(value); 78 | case 'number': 79 | if (isFinite(value)) { 80 | return String(value); 81 | } else { 82 | return 'null'; 83 | } 84 | case 'boolean': 85 | case 'null': 86 | return String(value); 87 | case 'object': 88 | if (!value) return 'null'; 89 | partial = []; 90 | if (Object.prototype.toString.apply(value) === '[object Array]') { 91 | for (i = 0, _len = value.length; i < _len; i++) { 92 | v = value[i]; 93 | partial[i] = Json.str(i, value) || 'null'; 94 | } 95 | return (partial.length === 0 ? '[]' : '[' + partial.join(',') + ']'); 96 | } 97 | for (k in value) { 98 | if (Object.prototype.hasOwnProperty.call(value, k)) { 99 | v = Json.str(k, value); 100 | if (v) partial.push(Json.quote(k) + ':' + v); 101 | } 102 | } 103 | return (partial.length === 0 ? '{}' : '{' + partial.join(',') + '}'); 104 | } 105 | }; 106 | 107 | toJson = function(value) { 108 | return Json.str('', { 109 | '': value 110 | }); 111 | }; 112 | 113 | this.Tree.toJson = toJson; 114 | 115 | Position = { 116 | getName: function(position) { 117 | if (position === Position.BEFORE) { 118 | return 'before'; 119 | } else if (position === Position.AFTER) { 120 | return 'after'; 121 | } else if (position === Position.INSIDE) { 122 | return 'inside'; 123 | } else { 124 | return 'none'; 125 | } 126 | } 127 | }; 128 | 129 | Position.BEFORE = 1; 130 | 131 | Position.AFTER = 2; 132 | 133 | Position.INSIDE = 3; 134 | 135 | Position.NONE = 4; 136 | 137 | this.Tree.Position = Position; 138 | 139 | Node = (function() { 140 | 141 | function Node(name) { 142 | this.init(name); 143 | } 144 | 145 | Node.prototype.init = function(name) { 146 | this.name = name; 147 | this.children = []; 148 | return this.parent = null; 149 | }; 150 | 151 | Node.prototype.initFromData = function(data) { 152 | var addChildren, addNode, 153 | _this = this; 154 | addNode = function(node_data) { 155 | return $.each(node_data, function(key, value) { 156 | if (key === 'children') { 157 | addChildren(value); 158 | } else if (key === 'label') { 159 | _this['name'] = value; 160 | } else { 161 | _this[key] = value; 162 | } 163 | return true; 164 | }); 165 | }; 166 | addChildren = function(children_data) { 167 | var child, node, _i, _len, _results; 168 | _results = []; 169 | for (_i = 0, _len = children_data.length; _i < _len; _i++) { 170 | child = children_data[_i]; 171 | node = new Node(); 172 | node.initFromData(child); 173 | _results.push(_this.addChild(node)); 174 | } 175 | return _results; 176 | }; 177 | return addNode(data); 178 | }; 179 | 180 | /* 181 | Create tree from data. 182 | 183 | Structure of data is: 184 | [ 185 | { 186 | label: 'node1', 187 | children: [ 188 | { label: 'child1' }, 189 | { label: 'child2' } 190 | ] 191 | }, 192 | { 193 | label: 'node2' 194 | } 195 | ] 196 | */ 197 | 198 | Node.prototype.loadFromData = function(data) { 199 | var node, o, _i, _len, _results, 200 | _this = this; 201 | this.children = []; 202 | _results = []; 203 | for (_i = 0, _len = data.length; _i < _len; _i++) { 204 | o = data[_i]; 205 | mylabel = o.label; 206 | 207 | if (o.children != []) { 208 | var ws = ""; 209 | for (var ws_i = 0; ws_i < 14; ws_i++) { 210 | ws += " "; 211 | } 212 | mylabel = convertToHexWord(o.offset)+ws + mylabel 213 | } 214 | 215 | if (o.comment != "") { 216 | mylabel += " /* "+o.comment+" */"; 217 | } 218 | node = new Node(mylabel); 219 | $.each(o, function(key, value) { 220 | node[key] = value; 221 | return true; 222 | }); 223 | this.addChild(node); 224 | if (o.children) { 225 | _results.push(node.loadFromData(o.children)); 226 | } else { 227 | _results.push(void 0); 228 | } 229 | } 230 | return _results; 231 | }; 232 | 233 | /* 234 | Add child. 235 | 236 | tree.addChild( 237 | new Node('child1') 238 | ); 239 | */ 240 | 241 | Node.prototype.addChild = function(node) { 242 | this.children.push(node); 243 | return node.parent = this; 244 | }; 245 | 246 | /* 247 | Add child at position. Index starts at 0. 248 | 249 | tree.addChildAtPosition( 250 | new Node('abc'), 251 | 1 252 | ); 253 | */ 254 | 255 | Node.prototype.addChildAtPosition = function(node, index) { 256 | this.children.splice(index, 0, node); 257 | return node.parent = this; 258 | }; 259 | 260 | /* 261 | Remove child. 262 | 263 | tree.removeChile(tree.children[0]); 264 | */ 265 | 266 | Node.prototype.removeChild = function(node) { 267 | return this.children.splice(this.getChildIndex(node), 1); 268 | }; 269 | 270 | /* 271 | Get child index. 272 | 273 | var index = getChildIndex(node); 274 | */ 275 | 276 | Node.prototype.getChildIndex = function(node) { 277 | return $.inArray(node, this.children); 278 | }; 279 | 280 | 281 | /* 282 | Compress children 283 | */ 284 | Node.prototype.compressChildren = function() { 285 | this.iterate(function(node, level) { 286 | if (node.hasChildren()) { 287 | new FolderElement(node).close(); 288 | } 289 | }); 290 | }; 291 | 292 | /* 293 | Expand children 294 | */ 295 | Node.prototype.expandChildren = function() { 296 | this.iterate(function(node, level) { 297 | if (node.hasChildren()) { 298 | new FolderElement(node).open(); 299 | } 300 | }); 301 | }; 302 | 303 | /* 304 | Does the tree have children? 305 | 306 | if (tree.hasChildren()) { 307 | // 308 | } 309 | */ 310 | 311 | Node.prototype.hasChildren = function() { 312 | return this.children.length !== 0; 313 | }; 314 | 315 | /* 316 | Iterate over all the nodes in the tree. 317 | 318 | Calls callback with (node, level). 319 | 320 | The callback must return true to continue the iteration on current node. 321 | 322 | tree.iterate( 323 | function(node, level) { 324 | console.log(node.name); 325 | 326 | // stop iteration after level 2 327 | return (level <= 2); 328 | } 329 | ); 330 | */ 331 | 332 | Node.prototype.iterate = function(callback) { 333 | var _iterate, 334 | _this = this; 335 | _iterate = function(level) { 336 | var child, result, _i, _len, _ref, _results; 337 | _ref = _this.children; 338 | _results = []; 339 | for (_i = 0, _len = _ref.length; _i < _len; _i++) { 340 | child = _ref[_i]; 341 | result = callback(child, level); 342 | if (_this.hasChildren() && result) { 343 | _results.push(child.iterate(callback, level + 1)); 344 | } else { 345 | _results.push(void 0); 346 | } 347 | } 348 | return _results; 349 | }; 350 | return _iterate(0); 351 | }; 352 | 353 | /* 354 | Move node relative to another node. 355 | 356 | Argument position: Position.BEFORE, Position.AFTER or Position.Inside 357 | 358 | // move node1 after node2 359 | tree.moveNode(node1, node2, Position.AFTER); 360 | */ 361 | 362 | Node.prototype.moveNode = function(moved_node, target_node, position) { 363 | moved_node.parent.removeChild(moved_node); 364 | if (position === Position.AFTER) { 365 | return target_node.parent.addChildAtPosition(moved_node, target_node.parent.getChildIndex(target_node) + 1); 366 | } else if (position === Position.BEFORE) { 367 | return target_node.parent.addChildAtPosition(moved_node, target_node.parent.getChildIndex(target_node)); 368 | } else if (position === Position.INSIDE) { 369 | return target_node.addChildAtPosition(moved_node, 0); 370 | } 371 | }; 372 | 373 | /* 374 | Get the tree as data. 375 | */ 376 | 377 | Node.prototype.getData = function() { 378 | var getDataFromNodes, 379 | _this = this; 380 | getDataFromNodes = function(nodes) { 381 | var data, k, node, tmp_node, v, _i, _len; 382 | data = []; 383 | for (_i = 0, _len = nodes.length; _i < _len; _i++) { 384 | node = nodes[_i]; 385 | tmp_node = {}; 386 | for (k in node) { 387 | v = node[k]; 388 | if ((k !== 'parent' && k !== 'children' && k !== 'element') && Object.prototype.hasOwnProperty.call(node, k)) { 389 | tmp_node[k] = v; 390 | } 391 | } 392 | if (node.hasChildren()) { 393 | tmp_node.children = getDataFromNodes(node.children); 394 | } 395 | data.push(tmp_node); 396 | } 397 | return data; 398 | }; 399 | return getDataFromNodes(this.children); 400 | }; 401 | 402 | return Node; 403 | 404 | })(); 405 | 406 | this.Tree.Tree = Node; 407 | 408 | $.widget("ui.tree", $.ui.mouse, { 409 | widgetEventPrefix: "tree", 410 | options: { 411 | autoOpen: false, 412 | saveState: false, 413 | dragAndDrop: false, 414 | selectable: false, 415 | onCanSelectNode: null, 416 | onSetStateFromStorage: null, 417 | onGetStateFromStorage: null, 418 | onCreateLi: null, 419 | onIsMoveHandle: null, 420 | onCanMove: null, 421 | onCanMoveTo: null 422 | }, 423 | _create: function() { 424 | this._initTree(this.options.data); 425 | this.element.click($.proxy(this._click, this)); 426 | this.element.bind('contextmenu', $.proxy(this._contextmenu, this)); 427 | this._mouseInit(); 428 | this.hovered_area = null; 429 | this.$ghost = null; 430 | return this.hit_areas = []; 431 | }, 432 | destroy: function() { 433 | this.element.empty(); 434 | this.element.unbind(); 435 | this.tree = null; 436 | this._mouseDestroy(); 437 | return $.Widget.prototype.destroy.call(this); 438 | }, 439 | getTree: function() { 440 | return this.tree; 441 | }, 442 | toJson: function() { 443 | return toJson(this.tree.getData()); 444 | }, 445 | addNode: function(data) { 446 | var n; 447 | n = new Node(); 448 | n.initFromData(data); 449 | this.getTree().addChild(n); 450 | this.element.empty(); 451 | return this._createDomElements(this.getTree()); 452 | }, 453 | toggle: function(node, on_finished) { 454 | if (node.hasChildren()) new FolderElement(node).toggle(on_finished); 455 | if (this.options.saveState) return this._saveState(); 456 | }, 457 | openNode: function(node, on_finished, skip_slide) { 458 | if (node.hasChildren()) { 459 | return new FolderElement(node).open(on_finished, skip_slide); 460 | } 461 | }, 462 | selectNode: function(node, must_open_parents) { 463 | var parent; 464 | if (this.options.selectable) { 465 | if (this.selected_node) { 466 | this._getNodeElementForNode(this.selected_node).deselect(); 467 | } 468 | this._getNodeElementForNode(node).select(); 469 | this.selected_node = node; 470 | if (must_open_parents) { 471 | parent = this.selected_node.parent; 472 | while (parent) { 473 | if (!parent.is_open) this.openNode(parent, null, true); 474 | parent = parent.parent; 475 | } 476 | } 477 | if (this.options.saveState) return this._saveState(); 478 | } 479 | }, 480 | getSelectedNode: function() { 481 | return this.selected_node || false; 482 | }, 483 | loadData: function(data) { 484 | return this._initTree(data); 485 | }, 486 | _initTree: function(data) { 487 | var node_element; 488 | this.tree = new Node(); 489 | this.tree.loadFromData(data); 490 | this.selected_node = null; 491 | this._openNodes(); 492 | this._createDomElements(this.tree); 493 | if (this.selected_node) { 494 | node_element = this._getNodeElementForNode(this.selected_node); 495 | if (node_element) return node_element.select(); 496 | } 497 | }, 498 | _getState: function() { 499 | var open_nodes, selected_node, 500 | _this = this; 501 | open_nodes = []; 502 | this.tree.iterate(function(node) { 503 | if (node.is_open && node.id && node.hasChildren()) { 504 | open_nodes.push(node.id); 505 | } 506 | return true; 507 | }); 508 | selected_node = ''; 509 | if (this.selected_node) selected_node = this.selected_node.id; 510 | return toJson({ 511 | open_nodes: open_nodes, 512 | selected_node: selected_node 513 | }); 514 | }, 515 | _setState: function(state) { 516 | var data, open_nodes, selected_node_id, 517 | _this = this; 518 | data = $.parseJSON(state); 519 | open_nodes = data.open_nodes; 520 | selected_node_id = data.selected_node; 521 | return this.tree.iterate(function(node) { 522 | if (node.id && node.hasChildren() && (indexOf(open_nodes, node.id) >= 0)) { 523 | node.is_open = true; 524 | } 525 | if (selected_node_id && (node.id === selected_node_id)) { 526 | _this.selected_node = node; 527 | } 528 | return true; 529 | }); 530 | }, 531 | _saveState: function() { 532 | if (this.options.onSetStateFromStorage) { 533 | return this.options.onSetStateFromStorage(this._getState()); 534 | } else { 535 | if ($.cookie) { 536 | return $.cookie(this._getCookieName(), this._getState(), { 537 | path: '/' 538 | }); 539 | } 540 | } 541 | }, 542 | _restoreState: function() { 543 | var state; 544 | if (this.options.onGetStateFromStorage) { 545 | state = this.options.onGetStateFromStorage(); 546 | } else { 547 | if ($.cookie) { 548 | state = $.cookie(this._getCookieName(), { 549 | path: '/' 550 | }); 551 | } else { 552 | state = null; 553 | } 554 | } 555 | if (!state) { 556 | return false; 557 | } else { 558 | this._setState(state); 559 | return true; 560 | } 561 | }, 562 | _getCookieName: function() { 563 | if (typeof this.options.saveState === 'string') { 564 | return this.options.saveState; 565 | } else { 566 | return 'tree'; 567 | } 568 | }, 569 | _createDomElements: function(tree) { 570 | var createFolderLi, createLi, createNodeLi, createUl, doCreateDomElements, 571 | _this = this; 572 | createUl = function(depth, is_open) { 573 | var class_string; 574 | if (depth) { 575 | class_string = ''; 576 | } else { 577 | class_string = ' class="tree"'; 578 | } 579 | return $("
"); 580 | }; 581 | createLi = function(node) { 582 | var $li; 583 | if (node.hasChildren()) { 584 | $li = createFolderLi(node); 585 | } else { 586 | $li = createNodeLi(node); 587 | } 588 | if (_this.options.onCreateLi) _this.options.onCreateLi(node, $li); 589 | return $li; 590 | }; 591 | createNodeLi = function(node) { 592 | // 593 | // Node data display 594 | // 595 | var interpretation = ""; 596 | if (node.interpretation != "") { 597 | interpretation = "
         "+node.interpretation; 598 | } 599 | 600 | // Make hexData specific length 601 | var maxDataDisplaySize = 4; 602 | var hexData=node.hexData; 603 | var fillNeeded = maxDataDisplaySize*3+1 - hexData.length; 604 | for(var i=0; i 0) { 609 | comment = " " + comment; 610 | } 611 | 612 | return $("
  • " + convertToHexWord(node.offset) 613 | + " " + hexData 614 | + node.label 615 | + comment 616 | + interpretation+"
  • "); 617 | 618 | }; 619 | createFolderLi = function(node) { 620 | var button_class, folder_class, getButtonClass, getFolderClass; 621 | getButtonClass = function() { 622 | var classes; 623 | classes = ['toggler']; 624 | if (!node.is_open) classes.push('closed'); 625 | return classes.join(' '); 626 | }; 627 | getFolderClass = function() { 628 | var classes; 629 | classes = ['folder']; 630 | if (!node.is_open) classes.push('closed'); 631 | return classes.join(' '); 632 | }; 633 | button_class = getButtonClass(); 634 | folder_class = getFolderClass(); 635 | return $("
  • »" + node.name + "
  • "); 636 | }; 637 | doCreateDomElements = function($element, children, depth, is_open) { 638 | var $li, $ul, child, _i, _len, _results; 639 | $ul = createUl(depth, is_open); 640 | $element.append($ul); 641 | _results = []; 642 | for (_i = 0, _len = children.length; _i < _len; _i++) { 643 | child = children[_i]; 644 | $li = createLi(child); 645 | $ul.append($li); 646 | child.element = $li[0]; 647 | $li.data('node', child); 648 | if (child.hasChildren()) { 649 | _results.push(doCreateDomElements($li, child.children, depth + 1, child.is_open)); 650 | } else { 651 | _results.push(void 0); 652 | } 653 | } 654 | return _results; 655 | }; 656 | this.element.empty(); 657 | return doCreateDomElements(this.element, tree.children, 0, true); 658 | }, 659 | _click: function(e) { 660 | var $target, event, node, node_element; 661 | if (e.ctrlKey) return; 662 | $target = $(e.target); 663 | if ($target.is('.toggler')) { 664 | node_element = this._getNodeElement($target); 665 | if (node_element && node_element.node.hasChildren()) { 666 | node_element.toggle(); 667 | if (this.options.saveState) this._saveState(); 668 | e.preventDefault(); 669 | return e.stopPropagation(); 670 | } 671 | } else if ($target.is('div') || $target.is('span')) { 672 | node = this._getNode($target); 673 | if (node) { 674 | if ((!this.options.onCanSelectNode) || this.options.onCanSelectNode(node)) { 675 | this.selectNode(node); 676 | event = $.Event('tree.click'); 677 | event.node = node; 678 | event.target = $target; 679 | return this.element.trigger(event); 680 | } 681 | } 682 | } 683 | }, 684 | _contextmenu: function(e) { 685 | var $div, event, node; 686 | $div = $(e.target).closest('ul.tree div'); 687 | if ($div.length) { 688 | node = this._getNode($div); 689 | if (node) { 690 | e.preventDefault(); 691 | e.stopPropagation(); 692 | event = $.Event('tree.contextmenu'); 693 | event.node = node; 694 | event.click_event = e; 695 | this.element.trigger(event); 696 | return false; 697 | } 698 | } 699 | }, 700 | _getNode: function($element) { 701 | var $li; 702 | $li = $element.closest('li'); 703 | if ($li.length === 0) { 704 | return null; 705 | } else { 706 | return $li.data('node'); 707 | } 708 | }, 709 | _getNodeElement: function($element) { 710 | var node; 711 | node = this._getNode($element); 712 | if (node) { 713 | return this._getNodeElementForNode(node); 714 | } else { 715 | return null; 716 | } 717 | }, 718 | _getNodeElementForNode: function(node) { 719 | if (node.hasChildren()) { 720 | return new FolderElement(node); 721 | } else { 722 | return new NodeElement(node); 723 | } 724 | }, 725 | _mouseCapture: function(event) { 726 | var $element, node_element; 727 | if (!this.options.dragAndDrop) return; 728 | $element = $(event.target); 729 | if (this.options.onIsMoveHandle && !this.options.onIsMoveHandle($element)) { 730 | return null; 731 | } 732 | node_element = this._getNodeElement($(event.target)); 733 | if (node_element && this.options.onCanMove) { 734 | if (!this.options.onCanMove(node_element.node)) node_element = null; 735 | } 736 | this.current_item = node_element; 737 | return this.current_item !== null; 738 | }, 739 | _mouseStart: function(event) { 740 | var offsetX, offsetY, _ref; 741 | if (!this.options.dragAndDrop) return; 742 | this._refreshHitAreas(); 743 | _ref = this._getOffsetFromEvent(event), offsetX = _ref[0], offsetY = _ref[1]; 744 | this.drag_element = new DragElement(this.current_item.node, offsetX, offsetY, this.element); 745 | this.current_item.$element.addClass('moving'); 746 | return true; 747 | }, 748 | _getOffsetFromEvent: function(event) { 749 | var element_offset; 750 | element_offset = $(event.target).offset(); 751 | return [event.pageX - element_offset.left, event.pageY - element_offset.top]; 752 | }, 753 | _mouseDrag: function(event) { 754 | var area, position_name; 755 | if (!this.options.dragAndDrop) return; 756 | this.drag_element.move(event.pageX, event.pageY); 757 | area = this.findHoveredArea(event.pageX, event.pageY); 758 | if (area && this.options.onCanMoveTo) { 759 | position_name = Position.getName(area.position); 760 | if (!this.options.onCanMoveTo(this.current_item.node, area.node, position_name)) { 761 | area = null; 762 | } 763 | } 764 | if (!area) { 765 | this._removeDropHint(); 766 | this._removeHover(); 767 | this._stopOpenFolderTimer(); 768 | } else { 769 | if (this.hovered_area !== area) { 770 | this.hovered_area = area; 771 | this._updateDropHint(); 772 | } 773 | } 774 | return true; 775 | }, 776 | _updateDropHint: function() { 777 | var node, node_element; 778 | this._stopOpenFolderTimer(); 779 | if (!this.hovered_area) return; 780 | node = this.hovered_area.node; 781 | if (node.hasChildren() && !node.is_open && this.hovered_area.position === Position.INSIDE) { 782 | this._startOpenFolderTimer(node); 783 | } 784 | this._removeDropHint(); 785 | node_element = this._getNodeElementForNode(this.hovered_area.node); 786 | return this.previous_ghost = node_element.addDropHint(this.hovered_area.position); 787 | }, 788 | _mouseStop: function() { 789 | if (!this.options.dragAndDrop) return; 790 | this._moveItem(); 791 | this._clear(); 792 | this._removeHover(); 793 | this._removeDropHint(); 794 | this._removeHitAreas(); 795 | this.current_item.$element.removeClass('moving'); 796 | return false; 797 | }, 798 | _mouseMove: function(event) { 799 | if ($.browser.msie && document.documentMode === 8 && !event.button) { 800 | event.button = 1; 801 | } 802 | return $.ui.mouse.prototype._mouseMove.call(this, event); 803 | }, 804 | _moveItem: function() { 805 | var event; 806 | if (this.hovered_area && this.hovered_area.position !== Position.NONE) { 807 | this.tree.moveNode(this.current_item.node, this.hovered_area.node, this.hovered_area.position); 808 | if (this.hovered_area.position === Position.INSIDE) { 809 | this.hovered_area.node.is_open = true; 810 | } 811 | event = $.Event('tree.move'); 812 | event.move_info = { 813 | moved_node: this.current_item.node, 814 | target_node: this.hovered_area.node, 815 | position: Position.getName(this.hovered_area.position) 816 | }; 817 | this.element.trigger(event); 818 | this.element.empty(); 819 | return this._createDomElements(this.tree); 820 | } 821 | }, 822 | _clear: function() { 823 | this.drag_element.remove(); 824 | return this.drag_element = null; 825 | }, 826 | _refreshHitAreas: function() { 827 | this._removeHitAreas(); 828 | return this._generateHitAreas(); 829 | }, 830 | _generateHitAreas: function() { 831 | var addPosition, getTop, groupPositions, handleAfterOpenFolder, handleClosedFolder, handleFirstNode, handleNode, handleOpenFolder, hit_areas, last_top, positions, 832 | _this = this; 833 | positions = []; 834 | last_top = 0; 835 | getTop = function($element) { 836 | return $element.offset().top; 837 | }; 838 | addPosition = function(node, position, top) { 839 | positions.push({ 840 | top: top, 841 | node: node, 842 | position: position 843 | }); 844 | return last_top = top; 845 | }; 846 | groupPositions = function(handle_group) { 847 | var group, position, previous_top, _i, _len; 848 | previous_top = -1; 849 | group = []; 850 | for (_i = 0, _len = positions.length; _i < _len; _i++) { 851 | position = positions[_i]; 852 | if (position.top !== previous_top) { 853 | if (group.length) handle_group(group, previous_top, position.top); 854 | previous_top = position.top; 855 | group = []; 856 | } 857 | group.push(position); 858 | } 859 | return handle_group(group, previous_top, _this.element.offset().top + _this.element.height()); 860 | }; 861 | handleNode = function(node, next_node, $element) { 862 | var top; 863 | top = getTop($element); 864 | if (node === _this.current_item.node) { 865 | addPosition(node, Position.NONE, top); 866 | } else { 867 | addPosition(node, Position.INSIDE, top); 868 | } 869 | if (next_node === _this.current_item.node || node === _this.current_item.node) { 870 | return addPosition(node, Position.NONE, top); 871 | } else { 872 | return addPosition(node, Position.AFTER, top); 873 | } 874 | }; 875 | handleOpenFolder = function(node, $element) { 876 | if (node === _this.current_item.node) return false; 877 | if (node.children[0] !== _this.current_item.node) { 878 | addPosition(node, Position.INSIDE, getTop($element)); 879 | } 880 | return true; 881 | }; 882 | handleAfterOpenFolder = function(node, next_node, $element) { 883 | if (node === _this.current_item.node || next_node === _this.current_item.node) { 884 | return addPosition(node, Position.NONE, last_top); 885 | } else { 886 | return addPosition(node, Position.AFTER, last_top); 887 | } 888 | }; 889 | handleClosedFolder = function(node, next_node, $element) { 890 | var top; 891 | top = getTop($element); 892 | if (node === _this.current_item.node) { 893 | return addPosition(node, Position.NONE, top); 894 | } else { 895 | addPosition(node, Position.INSIDE, top); 896 | if (next_node !== _this.current_item.node) { 897 | return addPosition(node, Position.AFTER, top); 898 | } 899 | } 900 | }; 901 | handleFirstNode = function(node, $element) { 902 | if (node !== _this.current_item.node) { 903 | return addPosition(node, Position.BEFORE, getTop($(node.element))); 904 | } 905 | }; 906 | this._iterateVisibleNodes(handleNode, handleOpenFolder, handleClosedFolder, handleAfterOpenFolder, handleFirstNode); 907 | hit_areas = []; 908 | groupPositions(function(positions_in_group, top, bottom) { 909 | var area_height, area_top, position, _i, _len, _results; 910 | area_height = (bottom - top) / positions_in_group.length; 911 | area_top = top; 912 | _results = []; 913 | for (_i = 0, _len = positions_in_group.length; _i < _len; _i++) { 914 | position = positions_in_group[_i]; 915 | hit_areas.push({ 916 | top: area_top, 917 | bottom: area_top + area_height, 918 | node: position.node, 919 | position: position.position 920 | }); 921 | _results.push(area_top += area_height); 922 | } 923 | return _results; 924 | }); 925 | return this.hit_areas = hit_areas; 926 | }, 927 | findHoveredArea: function(x, y) { 928 | var area, high, low, mid, tree_offset; 929 | tree_offset = this.element.offset(); 930 | if (x < tree_offset.left || y < tree_offset.top || x > (tree_offset.left + this.element.width()) || y > (tree_offset.top + this.element.height())) { 931 | return null; 932 | } 933 | low = 0; 934 | high = this.hit_areas.length; 935 | while (low < high) { 936 | mid = (low + high) >> 1; 937 | area = this.hit_areas[mid]; 938 | if (y < area.top) { 939 | high = mid; 940 | } else if (y > area.bottom) { 941 | low = mid + 1; 942 | } else { 943 | return area; 944 | } 945 | } 946 | return null; 947 | }, 948 | _iterateVisibleNodes: function(handle_node, handle_open_folder, handle_closed_folder, handle_after_open_folder, handle_first_node) { 949 | var is_first_node, iterate, 950 | _this = this; 951 | is_first_node = true; 952 | iterate = function(node, next_node) { 953 | var $element, child, children_length, i, must_iterate_inside, _len, _ref; 954 | must_iterate_inside = (node.is_open || !node.element) && node.hasChildren(); 955 | if (node.element) { 956 | $element = $(node.element); 957 | if (!$element.is(':visible')) return; 958 | if (is_first_node) { 959 | handle_first_node(node, $element); 960 | is_first_node = false; 961 | } 962 | if (!node.hasChildren()) { 963 | handle_node(node, next_node, $element); 964 | } else if (node.is_open) { 965 | if (!handle_open_folder(node, $element)) must_iterate_inside = false; 966 | } else { 967 | handle_closed_folder(node, next_node, $element); 968 | } 969 | } 970 | if (must_iterate_inside) { 971 | children_length = node.children.length; 972 | _ref = node.children; 973 | for (i = 0, _len = _ref.length; i < _len; i++) { 974 | child = _ref[i]; 975 | if (i === (children_length - 1)) { 976 | iterate(node.children[i], null); 977 | } else { 978 | iterate(node.children[i], node.children[i + 1]); 979 | } 980 | } 981 | if (node.is_open) { 982 | return handle_after_open_folder(node, next_node, $element); 983 | } 984 | } 985 | }; 986 | return iterate(this.tree); 987 | }, 988 | _removeHover: function() { 989 | return this.hovered_area = null; 990 | }, 991 | _removeDropHint: function() { 992 | if (this.previous_ghost) return this.previous_ghost.remove(); 993 | }, 994 | _removeHitAreas: function() { 995 | return this.hit_areas = []; 996 | }, 997 | _openNodes: function() { 998 | var max_level; 999 | if (this.options.saveState) if (this._restoreState()) return; 1000 | if (this.options.autoOpen === false) { 1001 | return; 1002 | } else if (this.options.autoOpen === true) { 1003 | max_level = -1; 1004 | } else { 1005 | max_level = parseInt(this.options.autoOpen); 1006 | } 1007 | return this.tree.iterate(function(node, level) { 1008 | node.is_open = true; 1009 | return level !== max_level; 1010 | }); 1011 | }, 1012 | _startOpenFolderTimer: function(folder) { 1013 | var openFolder, 1014 | _this = this; 1015 | openFolder = function() { 1016 | return _this._getNodeElementForNode(folder).open(function() { 1017 | _this._refreshHitAreas(); 1018 | return _this._updateDropHint(); 1019 | }); 1020 | }; 1021 | return this.open_folder_timer = setTimeout(openFolder, 500); 1022 | }, 1023 | _stopOpenFolderTimer: function() { 1024 | if (this.open_folder_timer) { 1025 | clearTimeout(this.open_folder_timer); 1026 | return this.open_folder_timer = null; 1027 | } 1028 | } 1029 | }); 1030 | 1031 | GhostDropHint = (function() { 1032 | 1033 | function GhostDropHint(node, $element, position) { 1034 | this.$element = $element; 1035 | this.node = node; 1036 | this.$ghost = $('
  • '); 1037 | if (position === Position.AFTER) { 1038 | this.moveAfter(); 1039 | } else if (position === Position.BEFORE) { 1040 | this.moveBefore(); 1041 | } else if (position === Position.INSIDE) { 1042 | if (node.hasChildren() && node.is_open) { 1043 | this.moveInsideOpenFolder(); 1044 | } else { 1045 | this.moveInside(); 1046 | } 1047 | } 1048 | } 1049 | 1050 | GhostDropHint.prototype.remove = function() { 1051 | return this.$ghost.remove(); 1052 | }; 1053 | 1054 | GhostDropHint.prototype.moveAfter = function() { 1055 | return this.$element.after(this.$ghost); 1056 | }; 1057 | 1058 | GhostDropHint.prototype.moveBefore = function() { 1059 | return this.$element.before(this.$ghost); 1060 | }; 1061 | 1062 | GhostDropHint.prototype.moveInsideOpenFolder = function() { 1063 | return $(this.node.children[0].element).before(this.$ghost); 1064 | }; 1065 | 1066 | GhostDropHint.prototype.moveInside = function() { 1067 | this.$element.after(this.$ghost); 1068 | return this.$ghost.addClass('inside'); 1069 | }; 1070 | 1071 | return GhostDropHint; 1072 | 1073 | })(); 1074 | 1075 | BorderDropHint = (function() { 1076 | 1077 | function BorderDropHint($element) { 1078 | var $div, width; 1079 | $div = $element.children('div'); 1080 | width = $element.width() - 4; 1081 | this.$hint = $(''); 1082 | $div.append(this.$hint); 1083 | this.$hint.css({ 1084 | width: width, 1085 | height: $div.height() - 4 1086 | }); 1087 | } 1088 | 1089 | BorderDropHint.prototype.remove = function() { 1090 | return this.$hint.remove(); 1091 | }; 1092 | 1093 | return BorderDropHint; 1094 | 1095 | })(); 1096 | 1097 | NodeElement = (function() { 1098 | 1099 | function NodeElement(node) { 1100 | this.init(node); 1101 | } 1102 | 1103 | NodeElement.prototype.init = function(node) { 1104 | this.node = node; 1105 | return this.$element = $(node.element); 1106 | }; 1107 | 1108 | NodeElement.prototype.getUl = function() { 1109 | return this.$element.children('ul:first'); 1110 | }; 1111 | 1112 | NodeElement.prototype.getSpan = function() { 1113 | return this.$element.children('div').find('span.title'); 1114 | }; 1115 | 1116 | NodeElement.prototype.getLi = function() { 1117 | return this.$element; 1118 | }; 1119 | 1120 | NodeElement.prototype.addDropHint = function(position) { 1121 | if (position === Position.INSIDE) { 1122 | return new BorderDropHint(this.$element); 1123 | } else { 1124 | return new GhostDropHint(this.node, this.$element, position); 1125 | } 1126 | }; 1127 | 1128 | NodeElement.prototype.select = function() { 1129 | return this.getLi().addClass('selected'); 1130 | }; 1131 | 1132 | NodeElement.prototype.deselect = function() { 1133 | return this.getLi().removeClass('selected'); 1134 | }; 1135 | 1136 | return NodeElement; 1137 | 1138 | })(); 1139 | 1140 | FolderElement = (function(_super) { 1141 | 1142 | __extends(FolderElement, _super); 1143 | 1144 | function FolderElement() { 1145 | FolderElement.__super__.constructor.apply(this, arguments); 1146 | } 1147 | 1148 | FolderElement.prototype.toggle = function(on_finished) { 1149 | if (this.node.is_open) { 1150 | return this.close(on_finished); 1151 | } else { 1152 | return this.open(on_finished); 1153 | } 1154 | }; 1155 | 1156 | FolderElement.prototype.open = function(on_finished, skip_slide) { 1157 | var doOpen, 1158 | _this = this; 1159 | this.node.is_open = true; 1160 | this.getButton().removeClass('closed'); 1161 | doOpen = function() { 1162 | _this.getLi().removeClass('closed'); 1163 | if (on_finished) return on_finished(); 1164 | }; 1165 | if (skip_slide) { 1166 | this.getUl().show(); 1167 | return doOpen(); 1168 | } else { 1169 | return this.getUl().slideDown('fast', doOpen); 1170 | } 1171 | }; 1172 | 1173 | FolderElement.prototype.close = function(on_finished) { 1174 | var _this = this; 1175 | this.node.is_open = false; 1176 | this.getButton().addClass('closed'); 1177 | return this.getUl().slideUp('fast', function() { 1178 | _this.getLi().addClass('closed'); 1179 | if (on_finished) return on_finished(); 1180 | }); 1181 | }; 1182 | 1183 | FolderElement.prototype.getButton = function() { 1184 | return this.$element.children('div').find('a.toggler'); 1185 | }; 1186 | 1187 | FolderElement.prototype.addDropHint = function(position) { 1188 | if (!this.node.is_open && position === Position.INSIDE) { 1189 | return new BorderDropHint(this.$element); 1190 | } else { 1191 | return new GhostDropHint(this.node, this.$element, position); 1192 | } 1193 | }; 1194 | 1195 | return FolderElement; 1196 | 1197 | })(NodeElement); 1198 | 1199 | DragElement = (function() { 1200 | 1201 | function DragElement(node, offset_x, offset_y, $tree) { 1202 | this.offset_x = offset_x; 1203 | this.offset_y = offset_y; 1204 | this.$element = $("" + node.name + ""); 1205 | this.$element.css("position", "absolute"); 1206 | $tree.append(this.$element); 1207 | } 1208 | 1209 | DragElement.prototype.move = function(page_x, page_y) { 1210 | return this.$element.offset({ 1211 | left: page_x - this.offset_x, 1212 | top: page_y - this.offset_y 1213 | }); 1214 | }; 1215 | 1216 | DragElement.prototype.remove = function() { 1217 | return this.$element.remove(); 1218 | }; 1219 | 1220 | return DragElement; 1221 | 1222 | })(); 1223 | 1224 | this.Tree.Node = Node; 1225 | 1226 | }).call(this); 1227 | -------------------------------------------------------------------------------- /jqtree/treeDownTriangleBlack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xdabbad00/icebuddha/6ebfbeb2a2ceda9a4b15f2f7fe203522ef3e8113/jqtree/treeDownTriangleBlack.png -------------------------------------------------------------------------------- /jqtree/treeRightTriangleBlack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xdabbad00/icebuddha/6ebfbeb2a2ceda9a4b15f2f7fe203522ef3e8113/jqtree/treeRightTriangleBlack.png -------------------------------------------------------------------------------- /jquery.cookie.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * jQuery Cookie Plugin v1.4.1 3 | * https://github.com/carhartl/jquery-cookie 4 | * 5 | * Copyright 2013 Klaus Hartl 6 | * Released under the MIT license 7 | */ 8 | (function (factory) { 9 | if (typeof define === 'function' && define.amd) { 10 | // AMD 11 | define(['jquery'], factory); 12 | } else if (typeof exports === 'object') { 13 | // CommonJS 14 | factory(require('jquery')); 15 | } else { 16 | // Browser globals 17 | factory(jQuery); 18 | } 19 | }(function ($) { 20 | 21 | var pluses = /\+/g; 22 | 23 | function encode(s) { 24 | return config.raw ? s : encodeURIComponent(s); 25 | } 26 | 27 | function decode(s) { 28 | return config.raw ? s : decodeURIComponent(s); 29 | } 30 | 31 | function stringifyCookieValue(value) { 32 | return encode(config.json ? JSON.stringify(value) : String(value)); 33 | } 34 | 35 | function parseCookieValue(s) { 36 | if (s.indexOf('"') === 0) { 37 | // This is a quoted cookie as according to RFC2068, unescape... 38 | s = s.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\'); 39 | } 40 | 41 | try { 42 | // Replace server-side written pluses with spaces. 43 | // If we can't decode the cookie, ignore it, it's unusable. 44 | // If we can't parse the cookie, ignore it, it's unusable. 45 | s = decodeURIComponent(s.replace(pluses, ' ')); 46 | return config.json ? JSON.parse(s) : s; 47 | } catch(e) {} 48 | } 49 | 50 | function read(s, converter) { 51 | var value = config.raw ? s : parseCookieValue(s); 52 | return $.isFunction(converter) ? converter(value) : value; 53 | } 54 | 55 | var config = $.cookie = function (key, value, options) { 56 | 57 | // Write 58 | 59 | if (value !== undefined && !$.isFunction(value)) { 60 | options = $.extend({}, config.defaults, options); 61 | 62 | if (typeof options.expires === 'number') { 63 | var days = options.expires, t = options.expires = new Date(); 64 | t.setTime(+t + days * 864e+5); 65 | } 66 | 67 | return (document.cookie = [ 68 | encode(key), '=', stringifyCookieValue(value), 69 | options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE 70 | options.path ? '; path=' + options.path : '', 71 | options.domain ? '; domain=' + options.domain : '', 72 | options.secure ? '; secure' : '' 73 | ].join('')); 74 | } 75 | 76 | // Read 77 | 78 | var result = key ? undefined : {}; 79 | 80 | // To prevent the for loop in the first place assign an empty array 81 | // in case there are no cookies at all. Also prevents odd result when 82 | // calling $.cookie(). 83 | var cookies = document.cookie ? document.cookie.split('; ') : []; 84 | 85 | for (var i = 0, l = cookies.length; i < l; i++) { 86 | var parts = cookies[i].split('='); 87 | var name = decode(parts.shift()); 88 | var cookie = parts.join('='); 89 | 90 | if (key && key === name) { 91 | // If second argument (value) is a function it's a converter... 92 | result = read(cookie, value); 93 | break; 94 | } 95 | 96 | // Prevent storing a cookie that we couldn't decode. 97 | if (!key && (cookie = read(cookie)) !== undefined) { 98 | result[name] = cookie; 99 | } 100 | } 101 | 102 | return result; 103 | }; 104 | 105 | config.defaults = {}; 106 | 107 | $.removeCookie = function (key, options) { 108 | if ($.cookie(key) === undefined) { 109 | return false; 110 | } 111 | 112 | // Must not alter options, thus extending a fresh object... 113 | $.cookie(key, '', $.extend({}, options, { expires: -1 })); 114 | return !$.cookie(key); 115 | }; 116 | 117 | })); 118 | -------------------------------------------------------------------------------- /jquery.hotkeys.js: -------------------------------------------------------------------------------- 1 | /*jslint browser: true*/ 2 | /*jslint jquery: true*/ 3 | 4 | /* 5 | * jQuery Hotkeys Plugin 6 | * Copyright 2010, John Resig 7 | * Dual licensed under the MIT or GPL Version 2 licenses. 8 | * 9 | * Based upon the plugin by Tzury Bar Yochay: 10 | * http://github.com/tzuryby/hotkeys 11 | * 12 | * Original idea by: 13 | * Binny V A, http://www.openjs.com/scripts/events/keyboard_shortcuts/ 14 | */ 15 | 16 | /* 17 | * One small change is: now keys are passed by object { keys: '...' } 18 | * Might be useful, when you want to pass some other data to your handler 19 | */ 20 | 21 | (function(jQuery) { 22 | 23 | jQuery.hotkeys = { 24 | version: "0.8", 25 | 26 | specialKeys: { 27 | 8: "backspace", 28 | 9: "tab", 29 | 10: "return", 30 | 13: "return", 31 | 16: "shift", 32 | 17: "ctrl", 33 | 18: "alt", 34 | 19: "pause", 35 | 20: "capslock", 36 | 27: "esc", 37 | 32: "space", 38 | 33: "pageup", 39 | 34: "pagedown", 40 | 35: "end", 41 | 36: "home", 42 | 37: "left", 43 | 38: "up", 44 | 39: "right", 45 | 40: "down", 46 | 45: "insert", 47 | 46: "del", 48 | 59: ";", 49 | 61: "=", 50 | 96: "0", 51 | 97: "1", 52 | 98: "2", 53 | 99: "3", 54 | 100: "4", 55 | 101: "5", 56 | 102: "6", 57 | 103: "7", 58 | 104: "8", 59 | 105: "9", 60 | 106: "*", 61 | 107: "+", 62 | 109: "-", 63 | 110: ".", 64 | 111: "/", 65 | 112: "f1", 66 | 113: "f2", 67 | 114: "f3", 68 | 115: "f4", 69 | 116: "f5", 70 | 117: "f6", 71 | 118: "f7", 72 | 119: "f8", 73 | 120: "f9", 74 | 121: "f10", 75 | 122: "f11", 76 | 123: "f12", 77 | 144: "numlock", 78 | 145: "scroll", 79 | 173: "-", 80 | 186: ";", 81 | 187: "=", 82 | 188: ",", 83 | 189: "-", 84 | 190: ".", 85 | 191: "/", 86 | 192: "`", 87 | 219: "[", 88 | 220: "\\", 89 | 221: "]", 90 | 222: "'" 91 | }, 92 | 93 | shiftNums: { 94 | "`": "~", 95 | "1": "!", 96 | "2": "@", 97 | "3": "#", 98 | "4": "$", 99 | "5": "%", 100 | "6": "^", 101 | "7": "&", 102 | "8": "*", 103 | "9": "(", 104 | "0": ")", 105 | "-": "_", 106 | "=": "+", 107 | ";": ": ", 108 | "'": "\"", 109 | ",": "<", 110 | ".": ">", 111 | "/": "?", 112 | "\\": "|" 113 | }, 114 | 115 | // excludes: button, checkbox, file, hidden, image, password, radio, reset, search, submit, url 116 | textAcceptingInputTypes: [ 117 | "text", "password", "number", "email", "url", "range", "date", "month", "week", "time", "datetime", 118 | "datetime-local", "search", "color", "tel"], 119 | 120 | options: { 121 | filterTextInputs: true 122 | } 123 | }; 124 | 125 | function keyHandler(handleObj) { 126 | if (typeof handleObj.data === "string") { 127 | handleObj.data = { 128 | keys: handleObj.data 129 | }; 130 | } 131 | 132 | // Only care when a possible input has been specified 133 | if (!handleObj.data || !handleObj.data.keys || typeof handleObj.data.keys !== "string") { 134 | return; 135 | } 136 | 137 | var origHandler = handleObj.handler, 138 | keys = handleObj.data.keys.toLowerCase().split(" "); 139 | 140 | handleObj.handler = function(event) { 141 | // Don't fire in text-accepting inputs that we didn't directly bind to 142 | if (this !== event.target && (/textarea|select/i.test(event.target.nodeName) || 143 | (jQuery.hotkeys.options.filterTextInputs && 144 | jQuery.inArray(event.target.type, jQuery.hotkeys.textAcceptingInputTypes) > -1))) { 145 | return; 146 | } 147 | 148 | var special = event.type !== "keypress" && jQuery.hotkeys.specialKeys[event.which], 149 | character = String.fromCharCode(event.which).toLowerCase(), 150 | modif = "", 151 | possible = {}; 152 | 153 | jQuery.each(["alt", "ctrl", "shift"], function(index, specialKey) { 154 | 155 | if (event[specialKey + 'Key'] && special !== specialKey) { 156 | modif += specialKey + '+'; 157 | } 158 | }); 159 | 160 | // metaKey is triggered off ctrlKey erronously 161 | if (event.metaKey && !event.ctrlKey && special !== "meta") { 162 | modif += "meta+"; 163 | } 164 | 165 | if (event.metaKey && special !== "meta" && modif.indexOf("alt+ctrl+shift+") > -1) { 166 | modif = modif.replace("alt+ctrl+shift+", "hyper+"); 167 | } 168 | 169 | if (special) { 170 | possible[modif + special] = true; 171 | } 172 | else { 173 | possible[modif + character] = true; 174 | possible[modif + jQuery.hotkeys.shiftNums[character]] = true; 175 | 176 | // "$" can be triggered as "Shift+4" or "Shift+$" or just "$" 177 | if (modif === "shift+") { 178 | possible[jQuery.hotkeys.shiftNums[character]] = true; 179 | } 180 | } 181 | 182 | for (var i = 0, l = keys.length; i < l; i++) { 183 | if (possible[keys[i]]) { 184 | return origHandler.apply(this, arguments); 185 | } 186 | } 187 | }; 188 | } 189 | 190 | jQuery.each(["keydown", "keyup", "keypress"], function() { 191 | jQuery.event.special[this] = { 192 | add: keyHandler 193 | }; 194 | }); 195 | 196 | })(jQuery || this.jQuery || window.jQuery); 197 | -------------------------------------------------------------------------------- /jquery.scrollTo.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * jQuery.ScrollTo - Easy element scrolling using jQuery. 3 | * Copyright (c) 2007-2009 Ariel Flesler - aflesler(at)gmail(dot)com | http://flesler.blogspot.com 4 | * Dual licensed under MIT and GPL. 5 | * Date: 5/25/2009 6 | * @author Ariel Flesler 7 | * @version 1.4.2 8 | * 9 | * http://flesler.blogspot.com/2007/10/jqueryscrollto.html 10 | */ 11 | ;(function(d){var k=d.scrollTo=function(a,i,e){d(window).scrollTo(a,i,e)};k.defaults={axis:'xy',duration:parseFloat(d.fn.jquery)>=1.3?0:1};k.window=function(a){return d(window)._scrollable()};d.fn._scrollable=function(){return this.map(function(){var a=this,i=!a.nodeName||d.inArray(a.nodeName.toLowerCase(),['iframe','#document','html','body'])!=-1;if(!i)return a;var e=(a.contentWindow||a).document||a.ownerDocument||a;return d.browser.safari||e.compatMode=='BackCompat'?e.body:e.documentElement})};d.fn.scrollTo=function(n,j,b){if(typeof j=='object'){b=j;j=0}if(typeof b=='function')b={onAfter:b};if(n=='max')n=9e9;b=d.extend({},k.defaults,b);j=j||b.speed||b.duration;b.queue=b.queue&&b.axis.length>1;if(b.queue)j/=2;b.offset=p(b.offset);b.over=p(b.over);return this._scrollable().each(function(){var q=this,r=d(q),f=n,s,g={},u=r.is('html,body');switch(typeof f){case'number':case'string':if(/^([+-]=)?\d+(\.\d+)?(px|%)?$/.test(f)){f=p(f);break}f=d(f,this);case'object':if(f.is||f.style)s=(f=d(f)).offset()}d.each(b.axis.split(''),function(a,i){var e=i=='x'?'Left':'Top',h=e.toLowerCase(),c='scroll'+e,l=q[c],m=k.max(q,i);if(s){g[c]=s[h]+(u?0:l-r.offset()[h]);if(b.margin){g[c]-=parseInt(f.css('margin'+e))||0;g[c]-=parseInt(f.css('border'+e+'Width'))||0}g[c]+=b.offset[h]||0;if(b.over[h])g[c]+=f[i=='x'?'width':'height']()*b.over[h]}else{var o=f[h];g[c]=o.slice&&o.slice(-1)=='%'?parseFloat(o)/100*m:o}if(/^\d+$/.test(g[c]))g[c]=g[c]<=0?0:Math.min(g[c],m);if(!a&&b.queue){if(l!=g[c])t(b.onAfterFirst);delete g[c]}});t(b.onAfter);function t(a){r.animate(g,j,b.easing,a&&function(){a.call(this,n,b)})}}).end()};k.max=function(a,i){var e=i=='x'?'Width':'Height',h='scroll'+e;if(!d(a).is('html,body'))return a[h]-d(a)[e.toLowerCase()]();var c='client'+e,l=a.ownerDocument.documentElement,m=a.ownerDocument.body;return Math.max(l[h],m[h])-Math.min(l[c],m[c])};function p(a){return typeof a=='object'?a:{top:a,left:a}}})(jQuery); -------------------------------------------------------------------------------- /parse_scripts/example_extractMiniDukeFile.py: -------------------------------------------------------------------------------- 1 | import json 2 | import sys 3 | import os 4 | import fileparser 5 | 6 | filename = sys.argv[1] 7 | filetype = "gif" 8 | 9 | # Check if GIFTrailer is at the end of the file 10 | parsedData = fileparser.parseFile(filename, filetype) 11 | 12 | trailer = fileparser.findElement(parsedData, "GIFTrailer") 13 | trailerOffset = trailer['offset'] 14 | 15 | statinfo = os.stat(filename) 16 | extraDataSize = statinfo.st_size - trailerOffset + 1 17 | if (extraDataSize != 0): 18 | # Discrepency found! 19 | print "%d bytes found at end of file" % extraDataSize 20 | 21 | # Read file in 22 | with open(filename, "rb") as f: 23 | infile = f.read() 24 | 25 | # Extract key 26 | keybytes = [] 27 | for i in range(4): 28 | keybyte = ord(infile[trailerOffset+1+i]) 29 | keybytes.append(keybyte) 30 | 31 | # Key uses weird shifting operation to expand 4 bytes to 8 32 | key = [0 for x in range(8)] 33 | key[0] = keybytes[0] 34 | key[1] = ((keybytes[0] & 0xf) << 4) | (keybytes[3] >> 4) 35 | key[2] = keybytes[3] 36 | key[3] = ((keybytes[3] & 0xf) << 4) | (keybytes[2] >> 4) 37 | 38 | key[4] = keybytes[2] 39 | key[5] = ((keybytes[2] & 0xf) << 4) | (keybytes[1] >> 4) 40 | key[6] = keybytes[1] 41 | key[7] = ((keybytes[1] & 0xf) << 4) | (keybytes[0] >> 4) 42 | 43 | outfile = [] 44 | keybyte = 0 45 | for i in range(extraDataSize-6): 46 | bytein = ord(infile[trailerOffset + 1 + 4 + i]) 47 | outfile.append(bytein ^ key[keybyte]) 48 | keybyte = (keybyte + 1) % 8 49 | 50 | with open(filename+".infected", "wb") as f: 51 | f.write(bytearray(outfile)) 52 | 53 | print "Extracted file written to: %s" % (filename+".infected") 54 | 55 | 56 | -------------------------------------------------------------------------------- /parse_scripts/fileparser.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import sys 3 | import json 4 | import icebuddha 5 | from collections import OrderedDict 6 | 7 | def getStructured(json): 8 | result = [] 9 | for e in json: 10 | element = OrderedDict() 11 | element['label'] = e[0] 12 | element['size'] = e[1] 13 | element['data'] = e[2] 14 | element['offset'] = e[3] 15 | element['interpretation'] = e[5] 16 | element['children'] = getStructured(e[4]) 17 | result.append(element) 18 | return result 19 | 20 | def findElement(struct, needle): 21 | if isinstance(struct, list): 22 | for e in struct: 23 | result = findElement(e, needle) 24 | if result != None: 25 | return result 26 | return None 27 | 28 | if struct['label'] == needle: 29 | return struct 30 | for c in struct['children']: 31 | result = findElement(c, needle) 32 | if result != None: 33 | return result 34 | return None 35 | 36 | def parseFile(filename, filetype): 37 | if filetype == 'gif': 38 | import gif 39 | p = gif.Parser() 40 | elif filetype == 'pe': 41 | import pe 42 | p = pe.Parser() 43 | elif filetype == 'mach_o': 44 | import mach_o 45 | p = mach_o.Parser() 46 | else: 47 | print "Unknown file type" 48 | sys.exit(-1) 49 | 50 | with open(filename, "rb") as f: 51 | bytes = f.read() 52 | 53 | parsedJson = p.run(bytearray(bytes)) 54 | return getStructured(parsedJson) 55 | 56 | if __name__ == "__main__": 57 | argparser = argparse.ArgumentParser(description='IceBuddha parsing script') 58 | argparser.add_argument('-t','--type', help='File type [gif, pe, mach_o]', required=True) 59 | argparser.add_argument('files', metavar='files', type=str, nargs='+', 60 | help='files to parse') 61 | args = vars(argparser.parse_args()) 62 | 63 | for filename in args['files']: 64 | filetype = args['type'].lower() 65 | print json.dumps(parseFile(filename, filetype), indent=2) -------------------------------------------------------------------------------- /parse_scripts/gif.py: -------------------------------------------------------------------------------- 1 | """ GIF file parse script for IceBuddha.com 2 | """ 3 | import icebuddha 4 | 5 | __author__ = "0xdabbad00" 6 | __license__ = "Apache" 7 | 8 | 9 | class Parser: 10 | def run(self, data): 11 | filedata = data 12 | ib = icebuddha.IceBuddha(filedata, "GIF") 13 | 14 | RGB = """ 15 | BYTE R; 16 | BYTE G; 17 | BYTE B; 18 | """ 19 | 20 | gifHeader = ib.parse(0, "GIFHEADER", """ 21 | CHAR Signature[3]; 22 | CHAR Version[3]; 23 | """) 24 | if (gifHeader.findChild("Signature").getValue() != "GIF"): 25 | print "File is not a gif" 26 | return [] 27 | ib.append(gifHeader) 28 | 29 | lsd = ib.parse(gifHeader.end(), "LOGICAL_SCREEN_DESCRIPTOR", """ 30 | WORD Width; 31 | WORD Height; 32 | BYTE GlobalColorTable; 33 | BYTE BackgroundColorIndex; 34 | BYTE PixelAspectRatio; 35 | """) 36 | gct = lsd.findChild("GlobalColorTable") 37 | gct.parseBitField(""" 38 | BYTE SizeOfGlobalColorTable : 3; 39 | BYTE SortFlag : 1; 40 | BYTE ColorResolution : 3; 41 | BYTE GlobalColorTableFlag : 1; 42 | """) 43 | GlobalColorTableFlag = gct.getData() & 1 44 | 45 | if (GlobalColorTableFlag == 1): 46 | SizeOfGlobalColorTable = (gct.getData() & 7) 47 | SizeOfGlobalColorTable = 1 << (SizeOfGlobalColorTable + 1) 48 | ColorTable = ib.parse(lsd.end(), "ColorTable RGB[%d]" % SizeOfGlobalColorTable, "") 49 | for i in range(SizeOfGlobalColorTable): 50 | color = ib.parse(ColorTable.end(), "RGB /* " + str(i) + " */", RGB) 51 | ColorTable.append(color) 52 | lsd.append(ColorTable) 53 | ib.append(lsd) 54 | 55 | offset = lsd.end() 56 | Data = ib.parse(offset, "Data", "") 57 | while (not ib.isEqual(offset, [0x3B]) and offset < len(filedata)): 58 | if (ib.isEqual(offset, [0x2C])): 59 | imgDescriptor = ib.parse(offset, "IMAGE_DESCRIPTOR", """ 60 | BYTE ImageSeperator; 61 | WORD Left; 62 | WORD Top; 63 | WORD Width; 64 | WORD Height; 65 | BYTE PackedField; 66 | """) 67 | imgDescriptorPackedField = imgDescriptor.findChild("PackedField") 68 | imgDescriptorPackedField.parseBitField(""" 69 | BYTE SizeOfLocalColorTable : 3; 70 | BYTE Reserved : 2; 71 | BYTE SortFlag : 1; 72 | BYTE InterlaceFlag : 1; 73 | BYTE LocalColorTableFlag : 1; 74 | """) 75 | Data.append(imgDescriptor) 76 | 77 | LocalColorTableFlag = imgDescriptorPackedField.getData() & 1 78 | if (LocalColorTableFlag == 1): 79 | SizeOfLocalColorTable = (imgDescriptorPackedField.getData() & 7) 80 | SizeOfLocalColorTable = 1 << (SizeOfLocalColorTable + 1) 81 | ColorTable = ib.parse(imgDescriptor.end(), "ColorTable RGB[%d]" % SizeOfLocalColorTable, "") 82 | for i in range(SizeOfLocalColorTable): 83 | color = ib.parse(ColorTable.end(), "RGB /* " + str(i) + " */", RGB) 84 | ColorTable.append(color) 85 | Data.append(ColorTable) 86 | imgData = ib.parse(Data.end(), "IMAGE_DATA", "BYTE LZWMinimumCodeSize;") 87 | self.getDataSubBlocks(filedata, ib, imgData) 88 | Data.append(imgData) 89 | 90 | elif (ib.isEqual(offset, [0x21, 0xF9])): 91 | Data.append(ib.parse(offset, "GraphicsControlExtension", """ 92 | BYTE Introducer; /* Extension Introducer (always 21h) */ 93 | BYTE Label; /* Graphic Control Label (always F9h) */ 94 | BYTE BlockSize; /* Size of remaining fields (always 04h) */ 95 | BYTE Packed; /* Method of graphics disposal to use */ 96 | WORD DelayTime; /* Hundredths of seconds to wait */ 97 | BYTE ColorIndex; /* Transparent Color Index */ 98 | BYTE Terminator; /* Block Terminator (always 0) */ 99 | """)) 100 | # TODO Handle Packed field 101 | 102 | elif (ib.isEqual(offset, [0x21, 0xFE])): 103 | commentExtension = ib.parse(filedata, offset, "CommentExtension", """ 104 | BYTE ExtensionIntroducer; 105 | BYTE CommentLabel; 106 | """) 107 | self.getDataSubBlocks(filedata, ib, commentExtension) 108 | Data.append(commentExtension) 109 | 110 | elif (ib.isEqual(offset, [0x21, 0x01])): 111 | plainTextExtension = ib.parse(filedata, offset, "PlainTextExtension", """ 112 | BYTE Introducer; /* Extension Introducer (always 21h) */ 113 | BYTE Label; /* Extension Label (always 01h) */ 114 | BYTE BlockSize; /* Size of Extension Block (always 0Ch) */ 115 | WORD TextGridLeft; /* X position of text grid in pixels */ 116 | WORD TextGridTop; /* Y position of text grid in pixels */ 117 | WORD TextGridWidth; /* Width of the text grid in pixels */ 118 | WORD TextGridHeight; /* Height of the text grid in pixels */ 119 | BYTE CellWidth; /* Width of a grid cell in pixels */ 120 | BYTE CellHeight; /* Height of a grid cell in pixels */ 121 | BYTE TextFgColorIndex; /* Text foreground color index value */ 122 | BYTE TextBgColorIndex; /* Text background color index value */ 123 | BYTE PlainTextData; /* The Plain Text data */ 124 | BYTE Terminator; /* Block Terminator (always 0) */ 125 | """) 126 | # TODO Handle PlainTextData 127 | Data.append(plainTextExtension) 128 | 129 | elif (ib.isEqual(offset, [0xFF])): 130 | applicationExtension = ib.parse(filedata, offset, "ApplicationExtension", """ 131 | BYTE BlockSize; 132 | BYTE ApplicationIdentifier[8]; 133 | BYTE ApplicationAuthenticationCode[3]; 134 | """) 135 | Data.append(applicationExtension) 136 | else: 137 | print "Undefined data at %d" % offset 138 | break 139 | offset = Data.end() 140 | 141 | ib.append(Data) 142 | ib.append(ib.parse(Data.end(), "TRAILER", "BYTE GIFTrailer;")) 143 | 144 | return ib.getParseTree() 145 | 146 | def getDataSubBlocks(self, filedata, ib, struct): 147 | size = 1 148 | while (size != 0): 149 | size = filedata[struct.end()] 150 | subBlock = ib.parse(struct.end(), "SUBBLOCK", """ 151 | BYTE Size; 152 | BYTE Data[%d]; 153 | """ % size) 154 | struct.append(subBlock) 155 | 156 | parser = Parser() 157 | -------------------------------------------------------------------------------- /parse_scripts/icebuddha/__init__.py: -------------------------------------------------------------------------------- 1 | def intToHex(value, fill=8): 2 | if fill == 0: 3 | return "%X" % value 4 | if fill == 8: 5 | return "%0.8X" % value 6 | else: 7 | format = "%s0.%dX" % ("%", fill) 8 | return format % value 9 | 10 | 11 | def getBinary(value, varsize): 12 | str = "" 13 | for i in range(varsize): 14 | if (value & (1 << ((varsize-1) - i))) != 0: 15 | str += "1" 16 | else: 17 | str += "0" 18 | return str 19 | 20 | 21 | def getMask(value, varsize, mask): 22 | str = "" 23 | for i in range(varsize): 24 | if (mask & (1 << ((varsize-1) - i))) != 0: 25 | if (value & (1 << ((varsize-1) - i))) != 0: 26 | str += "1" 27 | else: 28 | str += "0" 29 | else: 30 | str += "." 31 | return str 32 | 33 | 34 | def nbsp(count): 35 | str = "" 36 | for i in range(count): 37 | str += ("%snbsp;" % chr(0x26)) 38 | return str 39 | 40 | 41 | def getString(filedata, offset, length): 42 | displayableAscii = ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", 43 | "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", 44 | " ", "!", "", "#", "$", "%", "", "", "(", ")", "*", "+", ",", "-", "", "", 45 | "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", ":", ";", "", "=", "", "?", 46 | "@", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", 47 | "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "[", "", "]", "^", "_", 48 | "", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", 49 | "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "{", "|", "}", "~", ""] 50 | str = "" 51 | for i in range(length): 52 | val = filedata[offset + i] 53 | if (val > 127): 54 | continue 55 | str += displayableAscii[val] 56 | return str 57 | 58 | class IceBuddha: 59 | def __init__(self, filedata, root): 60 | self.filedata = filedata 61 | self.root = Node(self, root, 0, 0) 62 | self.endian = self.getConst("LITTLE_ENDIAN") 63 | 64 | def getConst(self, name): 65 | # Hack due to skulpt not knowing about static variables 66 | if name == "LITTLE_ENDIAN": 67 | return 0 68 | elif name == "BIG_ENDIAN": 69 | return 1 70 | return 0 71 | 72 | def setBigEndian(self): 73 | self.endian = self.getConst("BIG_ENDIAN") 74 | 75 | def setLittleEndian(self): 76 | self.endian = self.getConst("LITTLE_ENDIAN") 77 | 78 | def getEndian(self): 79 | return self.endian 80 | 81 | def getParseTree(self): 82 | return [self.root.get()] 83 | 84 | def append(self, node): 85 | self.root.append(node) 86 | 87 | def isEqual(self, offset, arrayToCheck): 88 | for i in range(len(arrayToCheck)): 89 | if (self.filedata[offset + i] != arrayToCheck[i]): 90 | return False 91 | return True 92 | 93 | def parse(self, offset, structName, input, comment=""): 94 | struct = Node(self, structName, offset) 95 | struct.setComment(comment) 96 | for l in input.split('\n'): 97 | parts = l.split(';') 98 | if (len(parts) < 2): 99 | continue 100 | comment = parts[1] 101 | parts = parts[0].split() 102 | type = parts[0] 103 | ascii = False 104 | if (type == "BYTE"): 105 | size = 1 106 | if (type == "CHAR"): 107 | size = 1 108 | ascii = True 109 | elif (type == "WORD"): 110 | size = 2 111 | elif (type == "DWORD"): 112 | size = 4 113 | elif (type == "ULONGLONG"): 114 | size = 8 115 | else: 116 | size = 1 117 | 118 | name = parts[1] 119 | value = "" 120 | 121 | arrayParts = name.split('[') 122 | if len(arrayParts) > 1: 123 | arraySize = int((arrayParts[1].split(']'))[0]) 124 | size *= arraySize 125 | if ascii: 126 | value = getString(self.filedata, offset, size) 127 | n = Node(self, name, offset, size, comment, value) 128 | offset += size 129 | struct.append(n) 130 | return struct 131 | 132 | 133 | class Node: 134 | def __init__(self, ib, label="", offset=0, size=0, comment="", value=""): 135 | self.ib = ib 136 | self.filedata = ib.filedata 137 | self.offset = offset 138 | self.size = size 139 | 140 | self.label = label 141 | self.comment = comment 142 | self.children = [] 143 | self.value = value 144 | 145 | def setComment(self, comment): 146 | self.comment = comment 147 | 148 | def setValue(self, value): 149 | self.value = value 150 | 151 | def getValue(self): 152 | return self.value 153 | 154 | def getData(self): 155 | data = 0 156 | if self.ib.getEndian() == self.ib.getConst("LITTLE_ENDIAN"): 157 | for i in range(self.size): 158 | data = data << 8 159 | data |= self.filedata[self.offset+(self.size-1-i)] 160 | else: 161 | for i in range(self.size): 162 | data = data << 8 163 | data |= self.filedata[self.offset+(i)] 164 | return data 165 | 166 | def getBytes(self): 167 | data = [] 168 | if self.ib.getEndian() == self.ib.getConst("LITTLE_ENDIAN"): 169 | for i in range(self.size): 170 | data.append(self.filedata[self.offset+(self.size-1-i)]) 171 | else: 172 | for i in range(self.size): 173 | data.append(self.filedata[self.offset+(i)]) 174 | return data 175 | 176 | def get(self): 177 | childData = [] 178 | for c in self.children: 179 | childData.append(c.get()) 180 | 181 | return [self.label, self.size, self.comment, self.offset, 182 | childData, self.value] 183 | 184 | def findChild(self, childName): 185 | for c in self.children: 186 | name = c.label.split('[') 187 | name = name[0] 188 | if name == childName: 189 | return c 190 | print "Child %s not found" % childName 191 | return None 192 | 193 | def getInt(self, valueName=None): 194 | size = self.size 195 | offset = self.offset 196 | if valueName != None: 197 | c = self.findChild(valueName) 198 | size = c.size 199 | offset = c.offset 200 | 201 | if c is None: 202 | return 0 203 | return c.getData() 204 | 205 | c.getData() 206 | 207 | def start(self): 208 | return self.offset 209 | 210 | def end(self): 211 | return self.offset + self.size 212 | 213 | def append(self, child): 214 | self.children.append(child) 215 | self.size += child.size 216 | 217 | # TODO Put this somewhere else 218 | def isMatch(self, a1, a2): 219 | if (len(a1) != len(a2)): 220 | return False 221 | 222 | for i in range(len(a1)): 223 | if a1[i] != a2[i]: 224 | return False 225 | return True 226 | 227 | def setMeaningFromConstants(self, input): 228 | for l in input.split('\n'): 229 | parts = l.split('=') 230 | if (len(parts) < 2): 231 | continue 232 | name = parts[0].strip() 233 | value = int(parts[1].strip(), 0) 234 | 235 | # TODO Don't assume 4 bytes 236 | valueBytes = [value & 0xff, (value >> 8) & 0xff, (value >> 16) & 0xff, (value >> 24) & 0xff] 237 | selfBytes = self.getBytes() 238 | 239 | if self.isMatch(valueBytes, selfBytes): 240 | self.setValue(name) 241 | break 242 | 243 | 244 | def parseBitField(self, input): 245 | bitCount = 0 246 | varSize = self.size*8 247 | 248 | self.value = "%s%s" % (nbsp(2), getBinary(self.getData(), varSize)) 249 | for l in input.split('\n'): 250 | parts = l.split(';') 251 | if (len(parts) < 2): 252 | continue 253 | comment = parts[1] 254 | parts = parts[0].split(":") 255 | if (len(parts) < 2): 256 | continue 257 | size = int(parts[1]) 258 | if bitCount + size > self.size * 8: 259 | print "Bit field too large for %s" % self.label 260 | 261 | parts = parts[0].split() 262 | 263 | varType = parts[0] # Ignored 264 | name = parts[1] 265 | 266 | bitmask = 0 267 | for i in range(bitCount, bitCount + size): 268 | bitmask |= (1 << i) 269 | 270 | data = (bitmask & self.getData()) 271 | data = data >> bitCount 272 | 273 | value = "
    %s%s (%s) %s : %d %s" % (nbsp(11), 274 | getMask(bitmask & self.getData(), varSize, bitmask), 275 | intToHex(data, 0), 276 | name, 277 | size, 278 | comment) 279 | self.value += value 280 | bitCount += size 281 | -------------------------------------------------------------------------------- /parse_scripts/mach_o.py: -------------------------------------------------------------------------------- 1 | """ GIF file parse script for IceBuddha.com 2 | """ 3 | import icebuddha 4 | 5 | __author__ = "0xdabbad00" 6 | __license__ = "Apache" 7 | 8 | class Parser: 9 | def run(self, data): 10 | filedata = data 11 | ib = icebuddha.IceBuddha(filedata, "MACH_O") 12 | 13 | machHeader = ib.parse(0, "mach_header", """ 14 | DWORD magic; 15 | DWORD cputype; 16 | DWORD cpusubtype; 17 | DWORD filetype; 18 | DWORD ncmds; 19 | DWORD sizeofcmds; 20 | DWORD flags; 21 | """) 22 | 23 | magicElement = machHeader.findChild("magic") 24 | magicElement.setMeaningFromConstants(""" 25 | MACHO_32 = 0xFEEDFACE 26 | MACHO_64 = 0xFEEDFACF 27 | MACHO_FAT = 0xCAFEBABE 28 | MACHO_FAT_CIGAM = 0xBEBAFECA 29 | """); 30 | 31 | if magicElement.getValue() == "": 32 | ib.setBigEndian() 33 | magicElement.setMeaningFromConstants(""" 34 | MACHO_32 = 0xFEEDFACE 35 | MACHO_64 = 0xFEEDFACF 36 | """); 37 | if magicElement.getValue() == "": 38 | print "Unknown file format" 39 | return ib.getParseTree() 40 | 41 | cputype = machHeader.findChild("cputype") 42 | cputype.setMeaningFromConstants(""" 43 | CPU_TYPE_I386 = 0x7 44 | CPU_TYPE_X86_64 = 0x01000007 45 | CPU_TYPE_POWERPC = 0x12 46 | CPU_TYPE_POWERPC64 = 0x01000012 47 | CPU_TYPE_ARM = 0xC 48 | """); 49 | 50 | filetype = machHeader.findChild("filetype") 51 | filetype.setMeaningFromConstants(""" 52 | MACH_OBJECT = 0x1 53 | MACH_EXECUTE = 0x2 54 | MACH_FVMLIB = 0x3 55 | MACH_CORE = 0x4 56 | MACH_PRELOAD = 0x5 57 | MACH_DYLIB = 0x6 58 | MACH_DYLINKER = 0x7 59 | MACH_BUNDLE = 0x8 60 | MACH_DYLIB_STUB = 0x9 61 | MACH_DSYM = 0xA 62 | MACH_KEXT_BUNDLE = 0xB 63 | """); 64 | 65 | flags = machHeader.findChild("flags") 66 | flags.parseBitField(""" 67 | DWORD NOUNDEFS : 1; 68 | DWORD INCRLINK : 1; 69 | DWORD DYLDLINK : 1; 70 | DWORD BINDATLOAD : 1; 71 | DWORD PREBOUND : 1; 72 | DWORD SPLIT_SEGS : 1; 73 | DWORD LAZY_INIT : 1; 74 | DWORD TWOLEVEL : 1; 75 | DWORD FORCE_FLAT : 1; 76 | DWORD NOMULTIDEFS : 1; 77 | DWORD NOFIXPREBINDING : 1; 78 | DWORD PREBINDABLE : 1; 79 | DWORD ALLMODSBOUND : 1; 80 | DWORD SUBSECTIONS_VIA_SYMBOLS : 1; 81 | DWORD CANONICAL : 1; 82 | DWORD WEAK_DEFINES : 1; 83 | DWORD BINDS_TO_WEAK : 1; 84 | DWORD ALLOW_STACK_EXECUTION : 1; 85 | DWORD ROOT_SAFE : 1; 86 | DWORD SETUID_SAFE : 1; 87 | DWORD NO_REEXPORTED_DYLIBS : 1; 88 | DWORD PIE : 1; 89 | DWORD DEAD_STRIPPABLE_DYLIB : 1; 90 | DWORD HAS_TLV_DESCRIPTORS : 1; 91 | DWORD NO_HEAP_EXECUTION : 1; 92 | """); 93 | 94 | ib.append(machHeader) 95 | return ib.getParseTree() 96 | 97 | parser = Parser() 98 | -------------------------------------------------------------------------------- /parse_scripts/pe.py: -------------------------------------------------------------------------------- 1 | """ PE file parse script for IceBuddha.com 2 | """ 3 | import icebuddha 4 | 5 | __author__ = "0xdabbad00" 6 | __license__ = "Apache" 7 | 8 | 9 | class Parse: 10 | def run(self, data): 11 | filedata = data 12 | ib = icebuddha.IceBuddha(filedata, "PE") 13 | 14 | imageDosHeader = ib.parse(0, "IMAGE_DOS_HEADER", """ 15 | WORD e_magic; /* MZ Header signature */ 16 | WORD e_cblp; /* Bytes on last page of file */ 17 | WORD e_cp; /* Pages in file */ 18 | WORD e_crlc; /* Relocations */ 19 | WORD e_cparhdr; /* Size of header in paragraphs */ 20 | WORD e_minalloc; /* Minimum extra paragraphs needed */ 21 | WORD e_maxalloc; /* Maximum extra paragraphs needed */ 22 | WORD e_ss; /* Initial (relative) SS value */ 23 | WORD e_sp; /* Initial SP value */ 24 | WORD e_csum; /* Checksum */ 25 | WORD e_ip; /* Initial IP value */ 26 | WORD e_cs; /* Initial (relative) CS value */ 27 | WORD e_lfarlc; /* File address of relocation table */ 28 | WORD e_ovno; /* Overlay number */ 29 | WORD e_res[4]; /* Reserved words */ 30 | WORD e_oemid; /* OEM identifier (for e_oeminfo) */ 31 | WORD e_oeminfo; /* OEM information; e_oemid specific */ 32 | WORD e_res2[10]; /* Reserved words */ 33 | DWORD e_lfanew; /* Offset to extended header */ 34 | """) 35 | ib.append(imageDosHeader) 36 | 37 | e_lfanew = imageDosHeader.getInt("e_lfanew") 38 | imageNtHeader = ib.parse(e_lfanew, "IMAGE_NT_HEADER", """ 39 | DWORD Signature; 40 | """) 41 | 42 | imageFileHeader = ib.parse(imageNtHeader.end(), "IMAGE_FILE_HEADER", """ 43 | WORD Machine; 44 | WORD NumberOfSections; 45 | DWORD TimeDateStamp; 46 | DWORD PointerToSymbolTable; 47 | DWORD NumberOfSymbols; 48 | WORD SizeOfOptionalHeader; 49 | WORD Characteristics; 50 | """) 51 | imageNtHeader.append(imageFileHeader) 52 | 53 | # IMAGE_OPTIONAL_HEADER 54 | machine = imageFileHeader.getInt("Machine") 55 | imageOptionalHeader = [] 56 | if (machine == 0x014c): 57 | imageOptionalHeader = ib.parse(imageNtHeader.end(), "IMAGE_OPTIONAL_HEADER", """ 58 | WORD Magic; 59 | BYTE MajorLinkerVersion; 60 | BYTE MinorLinkerVersion; 61 | DWORD SizeOfCode; 62 | DWORD SizeOfInitializedData; 63 | DWORD SizeOfUninitializedData; 64 | DWORD AddressOfEntryPoint; 65 | DWORD BaseOfCode; 66 | DWORD BaseOfData; 67 | DWORD ImageBase; 68 | DWORD SectionAlignment; 69 | DWORD FileAlignment; 70 | WORD MajorOperatingSystemVersion; 71 | WORD MinorOperatingSystemVersion; 72 | WORD MajorImageVersion; 73 | WORD MinorImageVersion; 74 | WORD MajorSubsystemVersion; 75 | WORD MinorSubsystemVersion; 76 | DWORD Win32VersionValue; 77 | DWORD SizeOfImage; 78 | DWORD SizeOfHeaders; 79 | DWORD CheckSum; 80 | WORD Subsystem; 81 | WORD DllCharacteristics; 82 | DWORD SizeOfStackReserve; 83 | DWORD SizeOfStackCommit; 84 | DWORD SizeOfHeapReserve; 85 | DWORD SizeOfHeapCommit; 86 | DWORD LoaderFlags; 87 | DWORD NumberOfRvaAndSizes; 88 | """) 89 | elif (machine == 0x8664): 90 | imageOptionalHeader = ib.parse(imageNtHeader.end(), "IMAGE_OPTIONAL_HEADER64", """ 91 | WORD Magic; 92 | BYTE MajorLinkerVersion; 93 | BYTE MinorLinkerVersion; 94 | DWORD SizeOfCode; 95 | DWORD SizeOfInitializedData; 96 | DWORD SizeOfUninitializedData; 97 | DWORD AddressOfEntryPoint; 98 | DWORD BaseOfCode; 99 | ULONGLONG ImageBase; 100 | DWORD SectionAlignment; 101 | DWORD FileAlignment; 102 | WORD MajorOperatingSystemVersion; 103 | WORD MinorOperatingSystemVersion; 104 | WORD MajorImageVersion; 105 | WORD MinorImageVersion; 106 | WORD MajorSubsystemVersion; 107 | WORD MinorSubsystemVersion; 108 | DWORD Win32VersionValue; 109 | DWORD SizeOfImage; 110 | DWORD SizeOfHeaders; 111 | DWORD CheckSum; 112 | WORD Subsystem; 113 | WORD DllCharacteristics; 114 | ULONGLONG SizeOfStackReserve; 115 | ULONGLONG SizeOfStackCommit; 116 | ULONGLONG SizeOfHeapReserve; 117 | ULONGLONG SizeOfHeapCommit; 118 | DWORD LoaderFlags; 119 | DWORD NumberOfRvaAndSizes; 120 | """) 121 | else: 122 | print("ERROR: machine type unknown: %d" % machine) 123 | 124 | dllCharacteristics = imageOptionalHeader.findChild("DllCharacteristics") 125 | dllCharacteristics.parseBitField(""" 126 | WORD Reserved : 1; 127 | WORD Reserved : 1; 128 | WORD Reserved : 1; 129 | WORD Reserved : 1; 130 | WORD Reserved : 1; 131 | WORD Reserved : 1; 132 | WORD DYNAMIC_BASE : 1; 133 | WORD FORCE_INTEGRITY : 1; 134 | WORD NX_COMPAT : 1; 135 | WORD NO_ISOLATION : 1; 136 | WORD NO_SEH : 1; 137 | WORD NO_BIND : 1; 138 | WORD Reserved : 1; 139 | WORD WDM_DRIVER : 1; 140 | WORD Reserved : 1; 141 | WORD TERMINAL_SERVER_AWARE : 1; 142 | 143 | """) 144 | 145 | IMAGE_DATA_DIRECTORY = """ 146 | DWORD VirtualAddress; 147 | DWORD Size; 148 | """ 149 | imageOptionalHeader.append(ib.parse(imageOptionalHeader.end(), "IMAGE_DATA_DIRECTORY", IMAGE_DATA_DIRECTORY, "export table")) 150 | imageOptionalHeader.append(ib.parse(imageOptionalHeader.end(), "IMAGE_DATA_DIRECTORY", IMAGE_DATA_DIRECTORY, "import table")) 151 | 152 | imageNtHeader.append(imageOptionalHeader) 153 | ib.append(imageNtHeader) 154 | 155 | return ib.getParseTree() 156 | 157 | parser = Parse() 158 | -------------------------------------------------------------------------------- /parse_scripts/unknown.py: -------------------------------------------------------------------------------- 1 | """ Unknown file type parse script for IceBuddha.com 2 | """ 3 | import icebuddha 4 | 5 | __author__ = "0xdabbad00" 6 | __license__ = "Apache" 7 | 8 | class Parse: 9 | def run(self, data): 10 | filedata = data 11 | ib = icebuddha.IceBuddha(filedata, "Unknown") 12 | 13 | print("Unknown file type") 14 | # Try using something like the following 15 | # ib = icebuddha.IceBuddha(filedata, "myfile_type") 16 | # startStruct = ib.parse(0, "START_STRUCT", """ 17 | # WORD magic; /* Magic signature */ 18 | # DWORD length; 19 | # """) 20 | # 21 | # ib.append(startStruct); 22 | 23 | return ib.getParseTree() 24 | 25 | parser = Parse() 26 | -------------------------------------------------------------------------------- /projects.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | Ice Buddha 4 | 5 | 6 | 7 | 8 |
    9 | 12 | 13 |
    14 |

    IceBuddha

    15 | Main site. Generic binary file parser. 16 | 17 |

    SlopFinder

    18 | Checks for DEP/ASLR. 19 |
    20 | 21 | 24 |
    25 | 26 | 27 | -------------------------------------------------------------------------------- /slopfinder.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | Ice Buddha 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 24 | 25 |
    26 | 29 | 30 |
    31 |
    32 | 33 |
    34 |
    35 | 36 |
    37 | 41 |
    42 | Drop files here 43 |
    44 | 45 |
    46 |

    SlopFinder

    47 |

    Statically analyzes Windows executable files to look for use of DEP and ASLR. The lack of either indicates possible bad software development practices which pose security risks. 48 | 49 |

    These are free protections provided by Microsoft. Not taking advantage of them is foolish. 50 | 51 |

    To use, drag and drop Windows executables onto this page. If you use Chrome, you can drag and drop entire directories in C:\Program Files\. (Dropping your entire C:\ drive will crash your browser). 52 | 53 |

    54 |

    55 |
    56 | 57 |
    58 |


    For developers

    59 | Data Execution Prevention (DEP) can be turned on by compiling with any Visual Studio version since 2005 and ensure NXCOMPAT is on (default). 60 | 61 |

    Address Space Layout Randomization (ASLR) can be turned on by compiling with any Visual Studio version since 2005 and ensure DYNAMICBASE in on (default). 62 |

    63 | 64 |
    65 | 66 | 69 |
    70 | 71 | 72 | 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /slopfinder.js: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // Globals 3 | /////////////////////////////////////////////////////////////////////////////// 4 | var MAX_FILE_SIZE = 10*1024; // 10K 5 | var NUM_BYTES_TO_LOAD = 16*100; 6 | 7 | var files; 8 | var fileData; 9 | var numFilesRead = 0; 10 | var numFiles = 0; 11 | var filesOnly = false; 12 | 13 | /////////////////////////////////////////////////////////////////////////////// 14 | // Dialog message 15 | /////////////////////////////////////////////////////////////////////////////// 16 | function showDialog(str, title, okBtn) { 17 | $( "#dialog-message" ).html(str); 18 | 19 | if (okBtn) { 20 | $( "#dialog-message" ).dialog({ 21 | title: title, 22 | modal: true, 23 | disabled: false, 24 | 25 | buttons: { 26 | Ok: function() { 27 | $( this ).dialog( "close" ); 28 | } 29 | } 30 | }); 31 | } else { 32 | $( "#dialog-message" ).dialog({ 33 | title: title, 34 | modal: true, 35 | disabled: false 36 | }); 37 | } 38 | 39 | $( "#dialog-message" ).dialog( "enable" ); 40 | $( "#dialog-message" ).dialog( "open" ); 41 | } 42 | 43 | function removeDialog() { 44 | $( "#dialog-message" ).dialog( "close" ); 45 | } 46 | 47 | 48 | function showError(str) { 49 | $( "#dialog-message" ).html(""+str); 50 | 51 | $( "#dialog-message" ).dialog({ 52 | title: "Error", 53 | modal: true, 54 | disabled: false, 55 | 56 | buttons: { 57 | Ok: function() { 58 | $( this ).dialog( "close" ); 59 | } 60 | } 61 | }); 62 | 63 | $( "#dialog-message" ).dialog( "enable" ); 64 | $( "#dialog-message" ).dialog( "open" ); 65 | } 66 | 67 | /////////////////////////////////////////////////////////////////////////////// 68 | // File reading 69 | /////////////////////////////////////////////////////////////////////////////// 70 | function handleFinishedRead(evt, i) { 71 | if(evt.target.readyState == FileReader.DONE) { 72 | var length = evt.target.result.byteLength; 73 | var readBlock = new Uint8Array(evt.target.result, 0, length); 74 | doRead(readBlock, length, i); 75 | numFilesRead++; 76 | if (numFilesRead == numFiles) { 77 | displayResults(); 78 | } 79 | } 80 | } 81 | 82 | function displayResults() { 83 | var output = [""]; 84 | var executables = [""]; 85 | var unknownFiles = [""]; 86 | for (var i = 0; i < fileData.length; i++) { 87 | file = fileData[i]; 88 | if (file.type == 'exe') { 89 | style = ""; 90 | if (file.dep != "yes" || file.aslr != "yes") { 91 | style = "style=\"background: #FF5C5C\""; 92 | } 93 | executables.push(""+escape(file.name).replace(/%20/g, " ") + ""+file.dep+""+file.aslr+"\n"); 94 | } else { 95 | unknownFiles.push(escape(file.name).replace(/%20/g, " ") + "
    \n"); 96 | } 97 | } 98 | 99 | output.push("
    "); 100 | 101 | if (executables.length>1) { 102 | output.push(""+ 103 | ""+ 104 | "" 105 | + executables.join("") 106 | +"
    Executable nameDEP
    protection
    ASLR
    protection
    "); 107 | } else { 108 | output.push("No Windows executables found
    "); 109 | } 110 | if (unknownFiles.length>1) { 111 | output.push("
    Nonexecutables
    " + unknownFiles.join("")); 112 | } 113 | $('#analysis').html(output.join("")); 114 | removeDialog(); 115 | } 116 | 117 | 118 | function doRead(readBlock, length, i) { 119 | 120 | fileData[i].type = 'unknown'; 121 | // Check for MZ header 122 | if (readBlock[0] == 'M'.charCodeAt(0) && readBlock[1] == 'Z'.charCodeAt(0)) 123 | { 124 | fileData[i].type = 'exe'; 125 | fileData[i].dep = 'NO'; 126 | fileData[i].aslr = 'NO'; 127 | 128 | // Get to DllCharacteristics data 129 | offset = 0x3c; 130 | e_lfanew = ((readBlock[offset+3]<<24)>>>0) + 131 | ((readBlock[offset+2]<<16)>>>0) + 132 | ((readBlock[offset+1]<<8)>>>0) + 133 | (readBlock[offset+0]); 134 | sizeof_magic = 4; 135 | offset = e_lfanew + sizeof_magic; 136 | machine = 137 | ((readBlock[offset+1]<<8)>>>0) + 138 | (readBlock[offset+0]); 139 | 140 | var sizeof_IMAGE_FILE_HEADER = 20; 141 | var offset_in_IMAGE_OPTIONAL_HEADER; 142 | if (machine == 0x014c) { 143 | offset_in_IMAGE_OPTIONAL_HEADER = 0x46; 144 | } else if (machine == 0x8664) { 145 | offset_in_IMAGE_OPTIONAL_HEADER = 0x46; 146 | } else { 147 | fileData[i].error = "Unknown file type"; 148 | fileData[i].dep = 'ERROR'; 149 | fileData[i].aslr = 'ERROR'; 150 | } 151 | 152 | offset = e_lfanew + sizeof_magic + sizeof_IMAGE_FILE_HEADER + offset_in_IMAGE_OPTIONAL_HEADER; 153 | DllCharacteristics = ((readBlock[offset+1]<<8)>>>0) + 154 | (readBlock[offset+0]); 155 | 156 | if ((DllCharacteristics & 0x100) != 0) { 157 | fileData[i].dep = 'yes'; 158 | } 159 | if ((DllCharacteristics & 0x40) != 0) { 160 | fileData[i].aslr = 'yes'; 161 | } 162 | 163 | } 164 | } 165 | 166 | function handleFile(file, path) 167 | { 168 | var fileNum = numFiles; 169 | numFiles++; 170 | fileData[fileNum] = {}; 171 | fileData[fileNum].name = path; 172 | fileData[fileNum].type = ''; 173 | fileData[fileNum].error = ''; 174 | 175 | reader = new FileReader(); 176 | fileData[fileNum].reader = reader; 177 | reader.onloadend = function(evt) { handleFinishedRead(evt, fileNum); } 178 | readFile(reader, file); 179 | } 180 | 181 | function handleFileTree(entry, i) { 182 | var directoryReader = entry.createReader(); 183 | getAllEntries( 184 | directoryReader, 185 | readDirectory, 186 | appendIndentList(parentNode) 187 | ); 188 | } 189 | 190 | function readDirectory(entries) { 191 | for (i = 0; i < entries.length; i++) { 192 | (function(i) { 193 | if (entries[i].isDirectory) { 194 | var directoryReader = entries[i].createReader(); 195 | getAllEntries( 196 | directoryReader, 197 | readDirectory 198 | ); 199 | } else { 200 | entries[i].file(function(file) {handleFile(file, entries[i].fullPath);}, errorHandler); 201 | } 202 | })(i); 203 | } 204 | } 205 | 206 | function errorHandler(e) { 207 | console.log('FileSystem API error code: ' + e.code) 208 | } 209 | 210 | 211 | function getAllEntries(directoryReader, callback) { 212 | var entries = []; 213 | 214 | var readEntries = function () { 215 | directoryReader.readEntries(function (results) { 216 | if (!results.length) { 217 | entries.sort(); 218 | callback(entries); 219 | } else { 220 | entries = entries.concat(toArray(results)); 221 | readEntries(); 222 | } 223 | }, errorHandler); 224 | }; 225 | 226 | readEntries(); 227 | } 228 | 229 | function toArray(list) { 230 | return Array.prototype.slice.call(list || [], 0); 231 | } 232 | 233 | 234 | 235 | function handleFileSelect(evt) { 236 | showDialog("Loading files", "Loading"); 237 | evt.stopPropagation(); 238 | evt.preventDefault(); 239 | 240 | items = evt.dataTransfer.items; 241 | if ($.browser.webkit && (!items || !items[0] || !items[0].webkitGetAsEntry)) 242 | { 243 | alert("You should really upgrade your browser. This site needs at least Google Chrome 21 to handle dropped folders. You can still drop files though."); 244 | items = evt.dataTransfer.files; 245 | filesOnly = true; 246 | } else if ($.browser.mozilla) { 247 | items = evt.dataTransfer.files; 248 | filesOnly = true; 249 | } 250 | 251 | numFilesRead = 0; 252 | numFiles = 0; 253 | fileData = []; 254 | 255 | for (var i = 0; i < items.length; i++) { 256 | var entry = items[i]; 257 | if (filesOnly) { 258 | handleFile(entry, entry.name); 259 | } else { 260 | if (entry.getAsEntry){ //Standard HTML5 API 261 | entry = entry.getAsEntry(); 262 | } else if (entry.webkitGetAsEntry){ //WebKit implementation of HTML5 API. 263 | entry = entry.webkitGetAsEntry(); 264 | } 265 | if (entry.isFile){ 266 | handleFile(evt.dataTransfer.files[i], "/" + entry.name); 267 | } else if (entry.isDirectory){ 268 | var entries = []; 269 | entries[0] = evt.dataTransfer.items[i].webkitGetAsEntry(); 270 | readDirectory(entries); 271 | } else { 272 | alert("Error, unkown type given"); 273 | } 274 | } 275 | } 276 | 277 | if (numFiles == 0) { 278 | $( "#dialog-message" ).html("No files found"); 279 | } 280 | } 281 | 282 | function readFile(reader, file) { 283 | end = MAX_FILE_SIZE; 284 | var blob; 285 | if (file.slice) { 286 | blob = file.slice(0, end); 287 | } else if(file.webkitSlice) { 288 | blob = file.webkitSlice(0, end); 289 | } else if(file.mozSlice) { 290 | blob = file.mozSlice(0, end); 291 | } else { 292 | console.log("No file slicing possible in this browser"); 293 | return; 294 | } 295 | 296 | reader.readAsArrayBuffer(blob); 297 | } 298 | 299 | function handleDragOver(evt) { 300 | evt.stopPropagation(); 301 | evt.preventDefault(); 302 | evt.dataTransfer.dropEffect = 'copy'; 303 | } 304 | 305 | 306 | /////////////////////////////////////////////////////////////////////////////// 307 | // Main 308 | /////////////////////////////////////////////////////////////////////////////// 309 | 310 | if ($.browser.webkit) { 311 | $('#drop_zone').html('Drop files and folders here'); 312 | } 313 | 314 | $(function() { 315 | // Handler for when the page has loaded 316 | $( "#dialog-message" ).dialog({ autoOpen: false }); 317 | }); 318 | 319 | //Setup the dnd listeners. 320 | var dropZone = document.getElementById('container'); 321 | dropZone.addEventListener('dragover', handleDragOver, false); 322 | dropZone.addEventListener('drop', handleFileSelect, false); 323 | -------------------------------------------------------------------------------- /slopfinder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xdabbad00/icebuddha/6ebfbeb2a2ceda9a4b15f2f7fe203522ef3e8113/slopfinder.png -------------------------------------------------------------------------------- /style.css: -------------------------------------------------------------------------------- 1 | body { 2 | background:#D0D0D0; 3 | margin:0; 4 | padding:0; 5 | height:100%; /* needed for container min-height */ 6 | } 7 | 8 | body, th, td, .buttonstyle, textarea, input, ul, li { 9 | font-family: arial, Verdana; 10 | color: #303030; 11 | vertical-align: top; 12 | } 13 | 14 | #accordion th, #accordion td, #accordion .buttonstyle, #accordion textarea, #accordion input, #accordion ul, #accordion li { 15 | color: #444444; 16 | } 17 | 18 | body, th, td, .buttonstyle, textarea, input { 19 | font-size: 80%; 20 | } 21 | 22 | a:link, a:active, a:visited {color: #eee; text-decoration: none; } 23 | a:hover {color: #222; text-decoration: underline; } 24 | 25 | #content a:link, #content a:active, #content a:visited {color: #404040; text-decoration: underline; } 26 | #content a:hover {color: #000; text-decoration: underline; } 27 | 28 | #content .uctxMenu a:link, #content .uctxMenu a:active, #content .uctxMenu a:visited { 29 | color: #404040; text-decoration: none; 30 | } 31 | 32 | ul { 33 | margin:0px; 34 | padding:0px; 35 | list-style:none; 36 | } 37 | 38 | li { 39 | margin:0px; 40 | } 41 | 42 | h1, h2, h3 { 43 | padding: 1px; 44 | margin: 0px; 45 | } 46 | h2 { font-size: 110%;} 47 | h3 { font-size: 100%;} 48 | .ui-accordion h3.ui-accordion-header {padding: 0; padding-left: 2.2em;} 49 | .ui-accordion h3.ui-accordion-header-active {background: #CCC} 50 | .ui-accordion .ui-accordion-content {padding: 0;} 51 | 52 | .ui-state-active, .ui-widget-content { 53 | background:#f0f0f0; 54 | } 55 | 56 | .ui-helper-reset { line-height: 1;} 57 | 58 | div#parsetree { 59 | border: 1px solid #A0A0A0; 60 | 61 | padding: 3px; 62 | margin: 1px; 63 | 64 | overflow-y: scroll; 65 | overflow-x: auto; 66 | 67 | width: 650px; 68 | 69 | max-height: 300px; 70 | min-height: 300px; 71 | 72 | font-size: 12px; 73 | color: #505050; 74 | font-family: monospace, monospace; 75 | font-style: normal; 76 | } 77 | 78 | div#about { 79 | margin: 5px; 80 | } 81 | 82 | div#container { 83 | /*position:relative; /* needed for footer positioning*/ 84 | position:absolute; 85 | top: 0em; 86 | margin:0 125px; 87 | width:800px; 88 | background:#f0f0f0; 89 | 90 | height:auto !important; /* real browsers */ 91 | height:100%; /* IE6: treated as min-height*/ 92 | min-height:100%; /* real browsers */ 93 | } 94 | 95 | div#header { 96 | background:#666; 97 | color: #eee; 98 | padding: 5px; 99 | } 100 | 101 | 102 | div#subheader { 103 | background:#f0f0f0; 104 | padding: 0 0 0 1px; 105 | } 106 | 107 | div#drop_zone { 108 | border: 2px dashed #909090; 109 | -moz-border-radius: 15px; 110 | border-radius: 15px; 111 | width: 80%; 112 | 113 | margin: 10px; 114 | padding: 10px; 115 | 116 | /* Center */ 117 | margin-left: auto; 118 | margin-right: auto; 119 | 120 | text-align: center; 121 | 122 | font-size: 400%; 123 | color: #909090; 124 | 125 | background: #e0e0e0; 126 | 127 | box-shadow: rgba(0, 0, 0, 0.5) 0 0 6px 0 128 | } 129 | 130 | div#content { 131 | height: auto; 132 | padding:0px 0px 20px 0px; /* bottom padding for footer */ 133 | } 134 | 135 | div#footer { 136 | position:absolute; 137 | width:100%; 138 | bottom:0; /* stick to bottom */ 139 | height: 16px; 140 | background:#666; 141 | 142 | font-size: 12px; 143 | color: #B2B2B2; 144 | } 145 | 146 | #footer a:link, #footer a:active, #footer a:visited { 147 | color: #C9C9C9; 148 | text-decoration: underline; 149 | } 150 | 151 | a:hover { 152 | color: #aaa; 153 | text-decoration: underline; 154 | } 155 | 156 | #byte_content { 157 | border: 1px solid #A0A0A0; 158 | 159 | padding: 3px; 160 | margin: 1px; 161 | 162 | overflow-y: scroll; 163 | overflow-x: hidden; 164 | 165 | width: 650px; 166 | } 167 | 168 | .hex, .address, .ascii, .bytes, #byte_content, #addressCell, #hexCell, #asciiCell { 169 | font-family: monospace, monospace; 170 | max-height: 200px; 171 | font-style: normal; 172 | font-size: 13px; 173 | } 174 | 175 | #accordion .address, #accordion .ascii { 176 | color: #888; 177 | } 178 | 179 | i { 180 | font-style:normal; 181 | } 182 | 183 | .alt_row { 184 | /* background:#CFCFCF; */ 185 | background:#d8d8d8; 186 | } 187 | 188 | #value { 189 | padding:0px 0px 0px 5px; 190 | font-family: monospace, monospace; 191 | font-size: 12px; 192 | } 193 | 194 | textarea, input { 195 | text-decoration: none; 196 | border: 1px solid #D0D0D0; 197 | margin: 1px 0px 5px 2px; 198 | padding: 1px; 199 | } 200 | 201 | textarea:focus, input:focus, textarea:hover, input:hover { 202 | /* background-color: #FFFFCC; */ 203 | border: 1px solid #0099FF; 204 | } 205 | 206 | #goto { 207 | vertical-align:bottom; 208 | padding-right: 5px; 209 | } 210 | 211 | #gotoInput { 212 | width: 100%; 213 | } 214 | 215 | .InputError { 216 | background-color: #FFCCCC; 217 | } 218 | 219 | .parseTreeData { 220 | font-size: 12px; 221 | color: #505050; 222 | font-family: monospace, monospace; 223 | font-style: normal; 224 | } 225 | 226 | .comment { 227 | font-size: 10px; 228 | color: #505050; 229 | font-family: monospace, monospace; 230 | font-style: normal; 231 | } 232 | 233 | 234 | 235 | #strings { 236 | font-size: 12px; 237 | color: #505050; 238 | font-family: monospace, monospace; 239 | font-style: normal; 240 | max-height: 600px; 241 | white-space: nowrap; 242 | } 243 | 244 | .selected { 245 | background: #f99; 246 | } 247 | 248 | .hex::selection, .address::selection, .ascii::selection, td::selection { 249 | background: #fff2a8; 250 | } 251 | .hex::-moz-selection, .address::-moz-selection, .ascii::-moz-selection, td::-moz-selection { 252 | background: #fff2a8; 253 | } 254 | 255 | .hex:hover, .ascii:hover, .hovered { 256 | background: #a0a0a0 !important; 257 | } 258 | 259 | #editor { 260 | height: 500px; 261 | position: relative; 262 | border: 1px solid #DDD; 263 | border-radius: 4px; 264 | border-bottom-right-radius: 0px; 265 | margin-top: 5px; 266 | } 267 | 268 | 269 | .hash { 270 | font-family: monospace, monospace; 271 | font-style: normal; 272 | font-size: 12px; 273 | } 274 | 275 | .hash_match_found { 276 | background: #58FA58; 277 | } 278 | 279 | .hash_no_match_found { 280 | background: #FA5858; 281 | } 282 | 283 | .ui-dialog-titlebar .ui-widget-header .ui-corner-all .ui-helper-clearfix { 284 | padding-top: 0px; 285 | margin: 0px; 286 | } 287 | 288 | .ui-dialog .ui-dialog-content { 289 | font-family: arial, Verdana; 290 | padding-top: 0px; 291 | padding-left: 3px; 292 | padding-right: 0px; 293 | padding-bottom: 0px; 294 | margin: 0px; 295 | } 296 | 297 | .ui-dialog .ui-dialog-titlebar { 298 | font-family: arial, Verdana; 299 | padding: 0px 0px 0px 3px; 300 | margin: 0px; 301 | } 302 | 303 | .ui-dialog .ui-dialog-buttonpane button { 304 | margin: 0px; 305 | } 306 | 307 | .ui-button-text-only .ui-button-text { 308 | margin: 0px 0px 0px 0px; 309 | padding: 0px 5px 0px 5px; 310 | } 311 | 312 | .boxsizingBorder { 313 | -webkit-box-sizing: border-box; 314 | -moz-box-sizing: border-box; 315 | box-sizing: border-box; 316 | width:100%; 317 | min-width: 100%; 318 | max-width: 100%; 319 | margin: 0px 0px 0px 0px; 320 | } 321 | 322 | 323 | .hexColor0 { 324 | color: rgba(48, 48, 48, 0.1) !important; 325 | } 326 | 327 | .hexColorNonAscii { 328 | color: rgba(48, 48, 48, 0.5) !important; 329 | } 330 | 331 | .asciiPeriod { 332 | color: rgba(48, 48, 48, 0.4) !important; 333 | } 334 | 335 | .zeroline, .zeroline i.hex { 336 | height: 1px !important; 337 | font-size: 1px; 338 | letter-spacing: 6.6px; 339 | } 340 | -------------------------------------------------------------------------------- /summit_route_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xdabbad00/icebuddha/6ebfbeb2a2ceda9a4b15f2f7fe203522ef3e8113/summit_route_logo.png -------------------------------------------------------------------------------- /test_data/bytes.data: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xdabbad00/icebuddha/6ebfbeb2a2ceda9a4b15f2f7fe203522ef3e8113/test_data/bytes.data -------------------------------------------------------------------------------- /test_data/high_bytes.data: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xdabbad00/icebuddha/6ebfbeb2a2ceda9a4b15f2f7fe203522ef3e8113/test_data/high_bytes.data -------------------------------------------------------------------------------- /test_data/icebuddha.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xdabbad00/icebuddha/6ebfbeb2a2ceda9a4b15f2f7fe203522ef3e8113/test_data/icebuddha.gif -------------------------------------------------------------------------------- /test_data/putty.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xdabbad00/icebuddha/6ebfbeb2a2ceda9a4b15f2f7fe203522ef3e8113/test_data/putty.exe -------------------------------------------------------------------------------- /test_data/sample_1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xdabbad00/icebuddha/6ebfbeb2a2ceda9a4b15f2f7fe203522ef3e8113/test_data/sample_1.gif -------------------------------------------------------------------------------- /tutorial.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xdabbad00/icebuddha/6ebfbeb2a2ceda9a4b15f2f7fe203522ef3e8113/tutorial.png -------------------------------------------------------------------------------- /waypoints.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | jQuery Waypoints - v1.1.6 3 | Copyright (c) 2011-2012 Caleb Troughton 4 | Dual licensed under the MIT license and GPL license. 5 | https://github.com/imakewebthings/jquery-waypoints/blob/master/MIT-license.txt 6 | https://github.com/imakewebthings/jquery-waypoints/blob/master/GPL-license.txt 7 | */ 8 | (function($,k,m,i,d){var e=$(i),g="waypoint.reached",b=function(o,n){o.element.trigger(g,n);if(o.options.triggerOnce){o.element[k]("destroy")}},h=function(p,o){if(!o){return -1}var n=o.waypoints.length-1;while(n>=0&&o.waypoints[n].element[0]!==p[0]){n-=1}return n},f=[],l=function(n){$.extend(this,{element:$(n),oldScroll:0,waypoints:[],didScroll:false,didResize:false,doScroll:$.proxy(function(){var q=this.element.scrollTop(),p=q>this.oldScroll,s=this,r=$.grep(this.waypoints,function(u,t){return p?(u.offset>s.oldScroll&&u.offset<=q):(u.offset<=s.oldScroll&&u.offset>q)}),o=r.length;if(!this.oldScroll||!q){$[m]("refresh")}this.oldScroll=q;if(!o){return}if(!p){r.reverse()}$.each(r,function(u,t){if(t.options.continuous||u===o-1){b(t,[p?"down":"up"])}})},this)});$(n).bind("scroll.waypoints",$.proxy(function(){if(!this.didScroll){this.didScroll=true;i.setTimeout($.proxy(function(){this.doScroll();this.didScroll=false},this),$[m].settings.scrollThrottle)}},this)).bind("resize.waypoints",$.proxy(function(){if(!this.didResize){this.didResize=true;i.setTimeout($.proxy(function(){$[m]("refresh");this.didResize=false},this),$[m].settings.resizeThrottle)}},this));e.load($.proxy(function(){this.doScroll()},this))},j=function(n){var o=null;$.each(f,function(p,q){if(q.element[0]===n){o=q;return false}});return o},c={init:function(o,n){this.each(function(){var u=$.fn[k].defaults.context,q,t=$(this);if(n&&n.context){u=n.context}if(!$.isWindow(u)){u=t.closest(u)[0]}q=j(u);if(!q){q=new l(u);f.push(q)}var p=h(t,q),s=p<0?$.fn[k].defaults:q.waypoints[p].options,r=$.extend({},s,n);r.offset=r.offset==="bottom-in-view"?function(){var v=$.isWindow(u)?$[m]("viewportHeight"):$(u).height();return v-$(this).outerHeight()}:r.offset;if(p<0){q.waypoints.push({element:t,offset:null,options:r})}else{q.waypoints[p].options=r}if(o){t.bind(g,o)}if(n&&n.handler){t.bind(g,n.handler)}});$[m]("refresh");return this},remove:function(){return this.each(function(o,p){var n=$(p);$.each(f,function(r,s){var q=h(n,s);if(q>=0){s.waypoints.splice(q,1);if(!s.waypoints.length){s.element.unbind("scroll.waypoints resize.waypoints");f.splice(r,1)}}})})},destroy:function(){return this.unbind(g)[k]("remove")}},a={refresh:function(){$.each(f,function(r,s){var q=$.isWindow(s.element[0]),n=q?0:s.element.offset().top,p=q?$[m]("viewportHeight"):s.element.height(),o=q?0:s.element.scrollTop();$.each(s.waypoints,function(u,x){if(!x){return}var t=x.options.offset,w=x.offset;if(typeof x.options.offset==="function"){t=x.options.offset.apply(x.element)}else{if(typeof x.options.offset==="string"){var v=parseFloat(x.options.offset);t=x.options.offset.indexOf("%")?Math.ceil(p*(v/100)):v}}x.offset=x.element.offset().top-n+o-t;if(x.options.onlyOnScroll){return}if(w!==null&&s.oldScroll>w&&s.oldScroll<=x.offset){b(x,["up"])}else{if(w!==null&&s.oldScroll=x.offset){b(x,["down"])}else{if(!w&&o>x.offset){b(x,["down"])}}}});s.waypoints.sort(function(u,t){return u.offset-t.offset})})},viewportHeight:function(){return(i.innerHeight?i.innerHeight:e.height())},aggregate:function(){var n=$();$.each(f,function(o,p){$.each(p.waypoints,function(q,r){n=n.add(r.element)})});return n}};$.fn[k]=function(n){if(c[n]){return c[n].apply(this,Array.prototype.slice.call(arguments,1))}else{if(typeof n==="function"||!n){return c.init.apply(this,arguments)}else{if(typeof n==="object"){return c.init.apply(this,[null,n])}else{$.error("Method "+n+" does not exist on jQuery "+k)}}}};$.fn[k].defaults={continuous:true,offset:0,triggerOnce:false,context:i};$[m]=function(n){if(a[n]){return a[n].apply(this)}else{return a.aggregate()}};$[m].settings={resizeThrottle:200,scrollThrottle:100};e.load(function(){$[m]("refresh")})})(jQuery,"waypoint","waypoints",window); --------------------------------------------------------------------------------