FrenchYeti/dexcalibur

View on GitHub
src/Utils.js

Summary

Maintainability
D
1 day
Test Coverage
const fs = require("fs");
const Process = require("child_process");
const Chalk = require("chalk");
const Path = require("path");
const crypto = require("crypto");

const _util_ = require('util');

const _stream_      = require('stream');
const _got_         = require("got");
//const {promisify}   = require('util');

const _exec_ = _util_.promisify(Process.exec);


//const TestHelper = require("./TestHelper.js");

const RE_REPLACE = /[-\/\\^$*+?.()|[\]{}]/g;
const CR = ""; //\n";

function checksum(str, algorithm, encoding) {
    return crypto
      .createHash(algorithm || 'md5')
      .update(str, 'utf8')
      .digest(encoding || 'hex')
  }

const NO_FLAG = 0x0;
const FLAG_CR = 0x1;
const FLAG_WS = 0x2;
const FLAG_TB = 0x4;

const PATTERNS = {};

PATTERNS[FLAG_CR] = new RegExp("^[\n]*$");
PATTERNS[FLAG_WS] = new RegExp("^[\s]*$");
PATTERNS[FLAG_TB] = new RegExp("^[\t]*$");
PATTERNS[FLAG_CR | FLAG_WS] = new RegExp("^[\n\s]*$");
PATTERNS[FLAG_CR | FLAG_TB] = new RegExp("^[\n\t]*$");
PATTERNS[FLAG_WS | FLAG_TB] = new RegExp("^[\s\t]*$");
PATTERNS[FLAG_WS | FLAG_CR | FLAG_TB] = new RegExp("^[\s\t\n]*$");

const Util = {
    ALPHA: 'abcdefghijklmnopqrstuvwxyz',
    ALPHANUM: 'abcdefghijklmnopqrstuvwxyz0123456789',
    FLAG_CR: FLAG_CR,
    FLAG_WS: FLAG_WS,
    FLAG_TB: FLAG_TB,
    NO_FLAG: NO_FLAG,
    /**
     * To encode
     */
    sha1_file: function(path){      
        return checksum(
            fs.readFileSync(path),
            'sha1'
        );
    },
    sha1_buffer: function(data){
        return checksum(
            data,
            'sha1'
        );
    },
    b64_encode: function(src){
        return Buffer.from(src).toString('base64');
    },
    b64_decode: function(src){
        return Buffer.from(src, 'base64').toString('ascii');
    },
    decodeURI: function(uri){
        return decodeURIComponent(uri);
    },
    encodeURI: function(uri){
        return encodeURIComponent(uri);
    },
    trim: function(str){
        if(! str instanceof String) console.error("trim() : the argument must be a string");

        while(str[0]!=undefined && (str[0]=="\t"||str[0]==" ")) 
            str=str.substr(1);

        while(str[str.length]!=undefined && (str[str.length]=="\t"||str[str.length]==" ")) 
            str=str.substr(0,str.length-1);

        return str;
    },
    // do  a deep copy of an object to a var
    deepCopy: function(src,dst){
        for(let k in src){
            if(src[k] instanceof Object)
                deepCopy(src[k],dst[k]);
            else
                dst[k]=src[k];
        }
    },
    forEachFileOf: function(path,callback,isDir=false){
        let dir=null, elemnt=null, ret = null, smali=[], stat=fs.lstatSync(path);

        if(isDir || stat.isDirectory()){
            dir=fs.readdirSync(path);
            for(let i in dir){
                elemnt = Path.join(path,dir[i]);
                if(fs.lstatSync(elemnt).isDirectory()){
                    this.forEachFileOf( elemnt, callback, true);
                }else{
                    // TODO : add additional test on file extension 
                    callback(elemnt, dir[i]);
                }
            }     
        }else{
            callback(path, Path.basename(path));
        }
    },
    count: function(list){
        let k=0;
        for(let j in list) k++;
        return k;
    },
    makeTable: function(array, fields){
        if(array.length == 0) return "";

        // filtre les colonnes
        let header = [], body=[], row={}, w=0, maxwidth={} ; 
        if(fields !== undefined){
            for(let i in array[0]){
                if(fields.indexOf(i)>-1){
                    header.push(i);
                    maxwidth[i] = i.length;   
                }
            }
        }else{
            for(let i in array[0]){
                header.push(i);
                maxwidth[i] = i.length;   
            }
        }
        
        // prepare le contenu
        for(let k=0; k<array.length; k++){
            row = [];
            for(let i in header){
                row[i] = array[k][header[i]]; 
                if(row[i] != null){
                    w = row[i].length - maxwidth[header[i]];
                    if(w > 0) maxwidth[header[i]] += w;   
                }
            }   
            body.push(row);
        }

        // dessine
        let width = 0, sep="",out="", isize=" Index  |".length,v="";
        for(let i in maxwidth) width += maxwidth[i]+7;

        sep = "+"+"-".repeat(isize+width+1)+"+\n";
        out = sep+"| Index  |"
        header.map(x=>{ out+="  "+x+(" ".repeat(maxwidth[x]-x.length+5))+"|"; });
        out += "\n"+sep;

        for(let k=0; k<body.length; k++){
            out+="| "+k+(" ".repeat(isize-2-(""+k).length))+"| ";
            for(let i in body[k]){
                //console.log(maxwidth[header[i]], body[k][i].length)
                v = (body[k][i] != undefined)?  body[k][i] : "";

                out += v+(" ".repeat(maxwidth[header[i]]-v.length+6))+"| "
            }
            out += "\n";
        }
        out += sep;
        
        return out;
    },
    msgBox: function(title,ctn){
        let header = "╔═══════════════════════════[ "+title+" ]═══════════════════════════════╗\n";
        let msg = "";

        for(let i in ctn){
            msg += "║ "+ctn[i]+" ".repeat(header.length-ctn[i].length-4)+"║\n";
        }
        
        console.log(header+msg+"╚"+"═".repeat(header.length-3)+"╝\n"); 
    },
    time: function(){
        return (new Date()).getTime();
    },
    RegExpEscape: function(val){
        return val.replace(RE_REPLACE,'\\$&');
    },
    escapeRE: function(data){
        // regexp replace ici
        while(data.indexOf(".")>-1) data.replace(".","<<>>");
        while(data.indexOf("<<>>")>-1) data.replace("<<>>","\\.");
        return data;
    },
    execSync: function(command,charset){
        var ret = null;
        
        if(process.env.DEXCALIBUR_TEST){
            ret = require('./TestHelper').execSync(command);
        }else{
            console.log(Chalk.bold.red("Execute command request : "+command));
            ret = Process.execSync(command);
        }

        return ret.toString(charset);
    },
    execAsync: async function(command){
        let ret;

        if(process.env.DEXCALIBUR_TEST){
            ret = await (require('./TestHelper').execAsync(command));
        }else{
            console.log(Chalk.bold.red("Execute command request : "+command));
            ret = await _exec_(command);
        }

        return ret;
    },
    randString: function(size, charset){
        let s="";
        while(s.length <= size){
            s += charset[parseInt(Math.random()*charset.length)];
        }
        return s;
    },
    isEmpty: function( pVar, pFlags=NO_FLAG){
        let f=null, p=null;
        switch(typeof pVar){
            case 'array':
                if(pFlags != null)
                    f = (pVar.length==0);
                else{
                    f = true;
                    for(let i=0; i<pVar.length; i++){
                        f &= Util.isEmpty(pVar[i], Util.FLAG_WS | Util.FLAG_CR);
                    }
                }
                break;
            case 'string':
                f = true;
                if(pFlags == Util.NO_FLAG)
                    f &= (pVar.length==0);
                else{
                    f &= PATTERNS[pFlags].test(pVar);
                }
                break;
            default: 
                f = undefined;
                break;
        }

        return f;
    },
    download(pRemoteURL, pLocalPath, pCallbacks, pMode=0o666, pEncoding='binary'){
        
        _stream_.pipeline(
            _got_.stream(pRemoteURL),
            fs.createWriteStream(pLocalPath, {
                flags: 'w+',
                mode: 0o777,
                encoding: 'binary' // binary
            }),
            (err)=>{
                if(pCallbacks.onSuccess != null)
                        pCallbacks.onSuccess(err);
            }
        );

    },
    recursiveRmDirSync: function(pPath){
        if (fs.existsSync(pPath)) {
          fs.readdirSync(pPath).forEach((file, index) => {
            const curPath = Path.join(pPath, file);
            if (fs.lstatSync(curPath).isDirectory()) { 
              Util.recursiveRmDirSync(curPath);
            } else {
              fs.unlinkSync(curPath);
            }
          });
          fs.rmdirSync(pPath);
        }
      },
    parseIPv4: function( pAddress, pHasPortNumber=false){
        const IPv4 = '(?<a>25[0–5]|2[0–4][0–9]|1[0-9]{2}|[0-9]{1,2})\.(?<b>25[0–5]|2[0–4][0–9]|1[0-9]{2}|[0-9]{1,2})\.(?<c>25[0–5]|2[0–4][0–9]|1[0-9]{2}|[0-9]{1,2})\.(?<d>25[0–5]|2[0–4][0–9]|1[0-9]{2}|[0-9]{1,2})';
        const PORT ='(?<port>[0-9]{1,5})' 

        if(pAddress == null) return { valid:false };

        let RE = new RegExp(IPv4 + (pHasPortNumber? ':'+PORT:''));
        let res = RE.exec(pAddress) ;

        if(res !== null && res.index==0 && pAddress==res[0]){

            if(res.groups.port > 65535) return false;

            return { valid:true, ip: `${res.groups.a}.${res.groups.b}.${res.groups.c}.${res.groups.d}`, port:res.groups.port };
        }else{
            return { valid:false };
        }
    },/*
    parseIPv6: function( pAddress, pHasPortNumber=false){
        const IPv6 =  '^((([0–9A-Fa-f]{1,4}:){7}[0–9A-Fa-f]{1,4})|(([0–9A-Fa-f]{1,4}:){6}:[0–9A-Fa-f]{1,4})|(([0–9A-Fa-f]{1,4}:){5}:([0–9A-Fa-f]{1,4}:)?[0–9A-Fa-f]{1,4})|(([0–9A-Fa-f]{1,4}:){4}:([0–9A-Fa-f]{1,4}:){0,2}[0–9A-Fa-f]{1,4})|(([0–9A-Fa-f]{1,4}:){3}:([0–9A-Fa-f]{1,4}:){0,3}[0–9A-Fa-f]{1,4})|(([0–9A-Fa-f]{1,4}:){2}:([0–9A-Fa-f]{1,4}:){0,4}[0–9A-Fa-f]{1,4})|(([0–9A-Fa-f]{1,4}:){6}((b((25[0–5])|(1d{2})|(2[0–4]d)|(d{1,2}))b).){3}(b((25[0–5])|(1d{2})|(2[0–4]d)|(d{1,2}))b))|(([0–9A-Fa-f]{1,4}:){0,5}:((b((25[0–5])|(1d{2})|(2[0–4]d)|(d{1,2}))b).){3}(b((25[0–5])|(1d{2})|(2[0–4]d)|(d{1,2}))b))|(::([0–9A-Fa-f]{1,4}:){0,5}((b((25[0–5])|(1d{2})|(2[0–4]d)|(d{1,2}))b).){3}(b((25[0–5])|(1d{2})|(2[0–4]d)|(d{1,2}))b))|([0–9A-Fa-f]{1,4}::([0–9A-Fa-f]{1,4}:){0,5}[0–9A-Fa-f]{1,4})|(::([0–9A-Fa-f]{1,4}:){0,6}[0–9A-Fa-f]{1,4})|(([0–9A-Fa-f]{1,4}:){1,7}:))';
        const PORT ='(?<port>[0-9]{1,5})' 

        if(pAddress == null) return { valid:false };

        let RE = new RegExp(IPv4 + (pHasPortNumber? ':'+PORT:''));

        
        let res = RE.exec(pAddress) ;

        console.log(pAddress,res);


        if(res !== null && res.index==0 && pAddress==res[0]){

            if(res.groups.port > 65535) return false;

            return { valid:true, ip: `${res.groups.a}.${res.groups.b}.${res.groups.c}.${res.groups.d}`, port:res.groups.port };
        }else{
            return { valid:false };
        }
    },
*/

};

module.exports = Util;