1// LICENSE_CODE ZON ISC 2'use strict'; /*jslint node:true, browser:true*/ 3(function(){ 4var define; 5var is_node = typeof module=='object' && module.exports && module.children; 6if (!is_node) 7 define = self.define; 8else 9 define = require('./require_node.js').define(module, '../'); 10define([], function(){ 11var E = {}; 12E.un = {}; 13 14var html_escape_table = { 15 '&': '&', '<': '<', '>': '>', '"': '"', "'": '''}; 16E.html = function(html){ 17 return html.replace(/[&<>"']/g, function(m){ 18 return html_escape_table[m[0]]; }); 19}; 20 21E.sh = function(s_or_a, opt){ 22 opt=opt||{}; 23 var q = opt.perl_f_esc ? '\'' : '"'; 24 function single(s){ 25 s = ''+s; // supports also numbers 26 if (!s) 27 return q+q; 28 if (/^[a-z0-9_\-.\/:]+$/i.test(s)) 29 return s; 30 return q+s.replace(/([\\"`$])/g, '\\$1')+q; 31 } 32 if (!Array.isArray(s_or_a)) 33 return single(s_or_a); 34 var s = '', a = s_or_a; 35 for (var i=0; i<a.length; i++) 36 s += (i ? ' ' : '')+single(a[i]); 37 return s; 38}; 39 40E.un_sh = function(s, keep_esc){ 41 var state = {PARSE_STATE_INIT: 0, PARSE_STATE_NORMAL_ARG: 1, 42 PARSE_STATE_QUOTE_ARG: 2}, cur_state = state.PARSE_STATE_INIT; 43 var i, quote = 0, argv = [], a = ''; 44 for (i=0; i<s.length; i++) 45 { 46 var esc = 0; 47 a += s[i]; 48 if (s[i]=='\\' && s[1]) 49 { 50 if (!keep_esc) 51 a = a.slice(0, -1); 52 esc = 1; 53 i++; 54 a += s[i]; 55 } 56 switch (cur_state) 57 { 58 case state.PARSE_STATE_INIT: 59 switch (s[i]) 60 { 61 case '\r': case '\n': case ' ': case '\t': 62 if (!esc) 63 { 64 a = ''; 65 break; 66 } 67 /*jslint -W086*/ // fall through 68 case '"': case '\'': 69 if (!esc) 70 { 71 cur_state = state.PARSE_STATE_QUOTE_ARG; 72 if (!keep_esc) 73 a = a.slice(0, -1); 74 quote = s[i]; 75 break; 76 } 77 /*jslint -W086*/ // fall through 78 default: cur_state = state.PARSE_STATE_NORMAL_ARG; 79 } 80 break; 81 case state.PARSE_STATE_NORMAL_ARG: 82 switch (s[i]) 83 { 84 case '\r': case '\n': case ' ': case '\t': 85 if (!esc) 86 { 87 cur_state = state.PARSE_STATE_INIT; 88 a = a.slice(0, -1); 89 argv.push(a); 90 a = ''; 91 } 92 break; 93 case '"': case '\'': 94 if (!esc) 95 { 96 cur_state = state.PARSE_STATE_QUOTE_ARG; 97 quote = s[i]; 98 if (!keep_esc) 99 a = a.slice(0, -1); 100 } 101 break; 102 } 103 break; 104 case state.PARSE_STATE_QUOTE_ARG: 105 if (s[i]==quote && !esc) 106 { 107 cur_state = state.PARSE_STATE_NORMAL_ARG; 108 if (!keep_esc) 109 a = a.slice(0, -1); 110 } 111 break; 112 } 113 } 114 if (cur_state==state.PARSE_STATE_NORMAL_ARG) 115 { 116 cur_state = state.PARSE_STATE_INIT; 117 argv.push(a); 118 } 119 if (cur_state!=state.PARSE_STATE_INIT) 120 throw 'error parsing shell'; 121 return argv; 122}; 123 124E.regex = function(s){ return s.replace(/[[\]{}()*+?.\\^$|\/]/g, '\\$&'); }; 125 126E.uri_comp = function(s){ return encodeURIComponent(s).replace(/%20/g, '+'); }; 127 128var http_escape_chars = []; 129(function(){ 130 var i; 131 for (i=0; i<256; i++) 132 { 133 var c = String.fromCharCode(i); 134 http_escape_chars[i] = /^[a-zA-Z0-9_.~,\-]$/.test(c) ? c : 135 '%'+('0'+i.toString(16)).slice(-2); 136 } 137}()); 138E.encodeURIComponent_bin = function(s_or_b){ 139 // Browser does not have Buffer Object 140 var s = typeof Buffer!='undefined' && s_or_b instanceof Buffer ? 141 s_or_b.toString('binary') : ''+s_or_b; 142 var esc = ''; 143 // critical perf only for 0<=code<256: encodeURIComponent() will not be
144 // called in these cases 145 for (var i = 0; i < s.length; i++) 146 { 147 var code = s.charCodeAt(i); 148 // process surrogate utf8 chars (4 bytes) 149 if (0xd800<=code && code<=0xdfff) 150 esc += encodeURIComponent(s.substr(i++, 2)); 151 else 152 esc += http_escape_chars[code] || encodeURIComponent(s[i]); 153 } 154 return esc; 155}; 156 157E.qs = function(param, opt){ 158 opt = opt||{}; 159 var qs = opt.qs||''; 160 var sep = qs || opt.amp ? '&' : ''; 161 if (!param) 162 return qs; 163 var uri_comp = opt.space_plus===undefined || opt.space_plus ? E.uri_comp 164 : encodeURIComponent; 165 var uri_comp_val = opt.bin ? E.encodeURIComponent_bin : uri_comp; 166 for (var i in param) 167 { 168 var val = param[i]; 169 if (val===undefined) 170 continue; 171 var key = uri_comp(i); 172 qs += sep; 173 if (val===null) 174 qs += key; 175 else if (Array.isArray(val)) 176 { 177 if (!val.length) 178 continue; 179 qs += val.map(function(val){ return key+'='+uri_comp_val(val); }) 180 .join('&'); 181 } 182 else 183 qs += key+'='+uri_comp_val(val); 184 sep = '&'; 185 } 186 return qs; 187}; 188 189// uri(opt) 190// uri(uri, qs, hash) 191E.uri = function(uri, qs, hash){ 192 var opt; 193 if (typeof uri=='string') 194 opt = {uri: uri, _qs: qs, hash: hash}; 195 else 196 { 197 opt = Object.assign({}, uri); 198 opt._qs = opt.qs; 199 opt.qs = undefined; 200 } 201 uri = opt.uri; 202 qs = typeof opt._qs=='string' ? opt._qs : E.qs(opt._qs, opt); 203 hash = typeof opt.hash=='string' ? opt.hash : E.qs(opt.hash, opt); 204 if (qs) 205 { 206 if (!uri.includes('?')) 207 uri += '?'; 208 else if (uri[uri.length-1]!='?' && uri[uri.length-1]!='&') 209 uri += '&'; 210 } 211 else 212 qs = ''; 213 if (hash) 214 hash = '#'+hash; 215 else 216 hash = ''; 217 return uri+qs+hash; 218}; 219 220E.mailto_url = function(mail){ 221 return 'mailto:'+(mail.to||'')+'?' 222 +E.qs({cc: mail.cc, bcc: mail.bcc, subject: mail.subject, body: mail.body}, 223 {space_plus: false}); 224}; 225 226E.hide_email = function(mail){ 227 var sep = mail.includes('@') ? '@' : '%40'; 228 var parts = mail.split(sep); 229 var name = parts[0]||'', domain = parts[1]||''; 230 var h_name = name.length>3 ? name[0]+name[1]+'*'+name[name.length-1] : '*'; 231 var h_domain = domain[0]+'*'+domain.slice(domain.lastIndexOf('.')); 232 return h_name+sep+h_domain; 233}; 234 235E.parse = {}; // should this move to parse.js? 236E.parse.eat_token = function(s_obj, re){ 237 var match; 238 if (!(match = re.exec(s_obj.s))) 239 return match; 240 s_obj.s = s_obj.s.substr(match.index+match[0].length); 241 return match; 242}; 243 244E.parse.http_words = function(val){ 245 // Translation from perl: 246 // http://search.cpan.org/~gaas/HTTP-Message-6.06/lib/HTTP/Headers/Util.pm 247 var res = [], o = {s: val}, eat_token = E.parse.eat_token, match; 248 while (o.s) 249 { 250 // 'token' or parameter 'attribute' 251 if (match = eat_token(o, /^\s*(=*[^\s=;,]+)/)) 252 { 253 var v = match[1]; 254 // a quoted value 255 if (match = eat_token(o, /^\s*=\s*\"([^\"\\]*(?:\\.[^\"\\]*)*)\"/)) 256 res.push([v, match[1].replace(/\\(.)/, '$1')]); 257 // some unquoted value 258 else if (match = eat_token(o, /^\s*=\s*([^;,\s]*)/)) 259 res.push([v, match[1].replace(/\s+$/, '')]); 260 // no value, a lone token 261 else 262 res.push([v, null]); 263 } 264 else if (match = eat_token(o, /^\s*,/)); 265 else if ((match = eat_token(o, /^\s*;/)) || (match = eat_token(o, 266 /^\s+/))); 267 else 268 throw new Error('This should not happen: '+o.s); 269 } 270 return res; 271}; 272 273return E; }); }());
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.