From 779aaa764cb26f02da56e60bb903afc9442f5f1c Mon Sep 17 00:00:00 2001 From: Chris Xiong Date: Thu, 11 Oct 2018 18:39:34 +0800 Subject: Initial commit. --- generator/listrenderer.js | 68 ++++++++++++++++++ generator/main.js | 86 +++++++++++++++++++++++ generator/postrenderer.js | 161 ++++++++++++++++++++++++++++++++++++++++++ generator/scanner.js | 53 ++++++++++++++ generator/sha256.js | 174 ++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 542 insertions(+) create mode 100644 generator/listrenderer.js create mode 100644 generator/main.js create mode 100644 generator/postrenderer.js create mode 100644 generator/scanner.js create mode 100644 generator/sha256.js (limited to 'generator') diff --git a/generator/listrenderer.js b/generator/listrenderer.js new file mode 100644 index 0000000..fd58b3a --- /dev/null +++ b/generator/listrenderer.js @@ -0,0 +1,68 @@ +module.exports={ + render:function(outf,pginfo,posts){return _render(outf,pginfo,posts);}, + set_template:function(tmplf){return _set_template(tmplf);} +}; +const fs=require('fs'); +const jsdom=require('jsdom'); +const path=require('path'); +let template_file=''; +let tmplcont=''; + +function _set_template(tmplf) +{ + template_file=tmplf; + tmplcont=fs.readFileSync(template_file,'utf8'); +} + +async function _render(outf,pginfo,posts) +{ + const tr=new jsdom.JSDOM(tmplcont); + const trd=tr.window.document; + + const tags_list=trd.getElementById('tagslist'); + const posts_list=trd.getElementById('postslist'); + const atag_template=trd.getElementById('active_taglist_item_template'); + const tag_template=trd.getElementById('taglist_item_template'); + const pitm_template=trd.getElementById('post_item_template'); + + for(let i of pginfo.tags) + { + const newnode=(i==pginfo.atag?atag_template:tag_template).cloneNode(true); + newnode.id=''; + const a=newnode.querySelector('a'); + a.innerHTML=i; + a.href=`/blog/list/${i}`; + tags_list.appendChild(newnode); + } + + for(let i of posts) + { + let newnode=pitm_template.cloneNode(true); + newnode.id=''; + const mdate=new Date(i.mdate); + const mdstr=`${mdate.getFullYear()}-${(mdate.getMonth()+1+'').padStart(2,'0')}-${(mdate.getDate()+'').padStart(2,'0')}` + newnode.querySelector('#title').innerHTML=i.title; + newnode.querySelector('#title').href=`/blog/post/${i.file}.html`; + newnode.querySelector('#tags').innerHTML='#'+i.tags.split(',').join(' #'); + newnode.querySelector('#time').innerHTML=`${i.date}/${mdstr}`; + newnode.querySelector('#title').id= + newnode.querySelector('#tags').id= + newnode.querySelector('#time').id=''; + posts_list.appendChild(newnode); + } + + trd.getElementById('page').innerHTML=`${pginfo.cp+1}/${pginfo.pc}`; + trd.getElementById('prepage').href=pginfo.cp>0? + `/blog/list/${pginfo.atag?pginfo.atag+'/':''}${pginfo.cp-1}.html` + :'#'; + trd.getElementById('nexpage').href=pginfo.cp{console.log(`rendered: ${r}`);}) +} + +const listrenderer=require('./listrenderer'); +listrenderer.set_template(path.join(template_dir,'list_template')); + +const list_dir=path.join(dest_dir,'list'); +const ppp=posts_per_listpage; +ensure_dir(list_dir); +let pc=Math.floor(list.length/ppp)+(list.length%ppp!=0); +for(let i=0;i${el.innerHTML}`; + le.appendChild(e); + el.id='tocanch'+(tocid++); + el.classList.add('tvis'); + var che=null,i; + for(i=p+1;i["+(starting+i+1)+"]: "+s+"
"; + doc.getElementById("notediv").appendChild(span); + } + starting+=footnotes.length; + while(footnotes.length)footnotes[0].remove(); +} +async function encrypt(doc) +{ + let enid=0; + for(let i of doc.querySelectorAll('encrypted')) + { + const key=i.getAttribute('key'); + i.removeAttribute('key'); + const contu8=aes.utils.utf8.toBytes(i.innerHTML); + const conths=sha256.hash(aes.utils.hex.fromBytes(contu8),{msgFormat:'hex-bytes'}); + const keyu8=aes.utils.utf8.toBytes(key); + const saltu8=aes.utils.utf8.toBytes('hellwhymustiaddsalttothiscrap'); + const enckey=await new Promise( + (resolv,rej)=> + {scrypt(keyu8,saltu8,1024,16,2,32,(e,p,k)=>{e?rej(e):k?resolv(k):undefined;});} + ); + const ctr=new aes.ModeOfOperation.ctr(enckey); + const enccont=ctr.encrypt(contu8); + let encconts='';for(let i=0;ihere +to decrypt. `; + ++enid; + } +} +function _set_template(tmplf) +{ + template_file=tmplf; + tmplcont=fs.readFileSync(template_file,'utf8'); +} +async function _render(inf,outf,np,pp) +{ + const postcont=fs.readFileSync(inf,'utf8'); + const tr=new jsdom.JSDOM(tmplcont); + const trd=tr.window.document; + const cont=fs.readFileSync(inf,'utf8'); + const contsplit=cont.split('\n'); + const meta=contsplit.splice(0,4); + const preproc=meta[3].trim(); + trd.getElementById('title').innerHTML= + trd.getElementById('titleh').innerHTML=meta[0].trim(); + trd.getElementById('datetags').innerHTML=`${meta[1].trim()}
#${meta[2].split(',').join(' #')}`; + if(preproc.length) + { + const ppargs=preproc.split(' '); + const ppcmd=ppargs.splice(0,1); + const pp=spawn(ppcmd[0],ppargs,{maxBuffer:1048576}); + let out=''; + pp.stdout.setEncoding('utf8'); + pp.stdout.on('data',(d)=>{out+=d;}); + pp.stdin.write(contsplit.join('\n'),'utf8'); + const ppp=new Promise( + (resolv,rej)=> + { + pp.on('close',(r)=>{if(r)rej(r);resolv(out);}); + } + ); + pp.stdin.end(); + trd.getElementById('article').innerHTML=await ppp; + } + else + trd.getElementById('article').innerHTML=contsplit.join('\n'); + + //Encryption + await encrypt(trd); + + //TOC + const l=trd.getElementById('article').querySelectorAll('h2,h3,h4,h5,h6'); + const tocroot=trd.getElementById('tocroot'); + tocid=0; + headerlist=[]; + for(let i of l) + if(!i.classList.contains('notoc'))headerlist.push(i); + for(let i=0;i${tgs[i]}`; + trd.getElementById('tagslist').appendChild(l); + } + + //neighboring posts + if(pp)trd.getElementById('prevp').href=`${pp}.html`; + if(np)trd.getElementById('nextp').href=`${np}.html`; + + fs.writeFileSync(outf,trd.documentElement.outerHTML,'utf8'); + return outf; +} diff --git a/generator/scanner.js b/generator/scanner.js new file mode 100644 index 0000000..0817cdb --- /dev/null +++ b/generator/scanner.js @@ -0,0 +1,53 @@ +module.exports={ + scan:function(s,d){return _scan(s,d);}, + build_list_index:function(){return _build_list_index();} +}; +const fs=require('fs'); +const path=require('path'); +const list=[]; +const tags=[]; +function _scan(s,dst) +{ + list.splice(0); + d=fs.readdirSync(s).reverse(); + pdst=path.join(dst,'post'); + let poste=true; + try{ + st=fs.statSync(pdst); + if(!st.isDirectory)throw 'shit'; + }catch(e){poste=false;} + for(let i of d) + if(i.endsWith('.txt')) + { + const cont=fs.readFileSync(path.join(s,i),'utf8'); + const smodt=fs.statSync(path.join(s,i)).mtimeMs; + let dmodt=0; + try{ + dmodt=fs.statSync(path.join(pdst,i.substring(0,i.length-4)+'.html')).mtimeMs; + }catch(e){}; + contsplit=cont.split('\n'); + if(contsplit.length<4)continue; + if(contsplit[1].indexOf('WIP')!=-1)continue; + list.push({ + file:i.substring(0,i.length-4), + title:contsplit[0].trim(), + date:contsplit[1].trim(), + tags:contsplit[2].trim(), + mdate:smodt, + needsupdate:dmodt>> 0' to coerce Number 'n' to unsigned 32-bit integer + + switch (opt.msgFormat) { + default: // default is to convert string to UTF-8, as SHA only deals with byte-streams + case 'string': msg = utf8Encode(msg); break; + case 'hex-bytes':msg = hexBytesToString(msg); break; // mostly for running tests + } + + // constants [§4.2.2] + const K = [ + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 ]; + + // initial hash value [§5.3.3] + const H = [ + 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 ]; + + // PREPROCESSING [§6.2.1] + + msg += String.fromCharCode(0x80); // add trailing '1' bit (+ 0's padding) to string [§5.1.1] + + // convert string msg into 512-bit blocks (array of 16 32-bit integers) [§5.2.1] + const l = msg.length/4 + 2; // length (in 32-bit integers) of msg + ‘1’ + appended length + const N = Math.ceil(l/16); // number of 16-integer (512-bit) blocks required to hold 'l' ints + const M = new Array(N); // message M is N×16 array of 32-bit integers + + for (let i=0; i>> 32, but since JS converts + // bitwise-op args to 32 bits, we need to simulate this by arithmetic operators + const lenHi = ((msg.length-1)*8) / Math.pow(2, 32); + const lenLo = ((msg.length-1)*8) >>> 0; + M[N-1][14] = Math.floor(lenHi); + M[N-1][15] = lenLo; + + + // HASH COMPUTATION [§6.2.2] + + for (let i=0; i>> 0; + } + + // 2 - initialise working variables a, b, c, d, e, f, g, h with previous hash value + let a = H[0], b = H[1], c = H[2], d = H[3], e = H[4], f = H[5], g = H[6], h = H[7]; + + // 3 - main loop (note '>>> 0' for 'addition modulo 2^32') + for (let t=0; t<64; t++) { + const T1 = h + Sha256.Σ1(e) + Sha256.Ch(e, f, g) + K[t] + W[t]; + const T2 = Sha256.Σ0(a) + Sha256.Maj(a, b, c); + h = g; + g = f; + f = e; + e = (d + T1) >>> 0; + d = c; + c = b; + b = a; + a = (T1 + T2) >>> 0; + } + + // 4 - compute the new intermediate hash value (note '>>> 0' for 'addition modulo 2^32') + H[0] = (H[0]+a) >>> 0; + H[1] = (H[1]+b) >>> 0; + H[2] = (H[2]+c) >>> 0; + H[3] = (H[3]+d) >>> 0; + H[4] = (H[4]+e) >>> 0; + H[5] = (H[5]+f) >>> 0; + H[6] = (H[6]+g) >>> 0; + H[7] = (H[7]+h) >>> 0; + } + + // convert H0..H7 to hex strings (with leading zeros) + for (let h=0; h prev + String.fromCharCode(curr), ''); + } catch (e) { // no TextEncoder available? + return unescape(encodeURIComponent(str)); // monsur.hossa.in/2012/07/20/utf-8-in-javascript.html + } + } + + function hexBytesToString(hexStr) { // convert string of hex numbers to a string of chars (eg '616263' -> 'abc'). + const str = hexStr.replace(' ', ''); // allow space-separated groups + return str=='' ? '' : str.match(/.{2}/g).map(byte => String.fromCharCode(parseInt(byte, 16))).join(''); + } + } + + + + /** + * Rotates right (circular right shift) value x by n positions [§3.2.4]. + * @private + */ + static ROTR(n, x) { + return (x >>> n) | (x << (32-n)); + } + + + /** + * Logical functions [§4.1.2]. + * @private + */ + static Σ0(x) { return Sha256.ROTR(2, x) ^ Sha256.ROTR(13, x) ^ Sha256.ROTR(22, x); } + static Σ1(x) { return Sha256.ROTR(6, x) ^ Sha256.ROTR(11, x) ^ Sha256.ROTR(25, x); } + static σ0(x) { return Sha256.ROTR(7, x) ^ Sha256.ROTR(18, x) ^ (x>>>3); } + static σ1(x) { return Sha256.ROTR(17, x) ^ Sha256.ROTR(19, x) ^ (x>>>10); } + static Ch(x, y, z) { return (x & y) ^ (~x & z); } // 'choice' + static Maj(x, y, z) { return (x & y) ^ (x & z) ^ (y & z); } // 'majority' + +} + +module.exports.sha256 = Sha256; -- cgit v1.2.3