From 0ae868ac2d08675bc20c05a99e25f331b10724b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=96=9F=E9=85=8C=20=E9=B5=AC=E5=85=84?= Date: Tue, 31 May 2016 17:56:05 +0800 Subject: [PATCH] Initial commit --- array.js | 83 ++++++++++++++++++++++++++++++++++++ date.js | 66 +++++++++++++++++++++++++++++ form.js | 120 ++++++++++++++++++++++++++++++++++++++++++++++++++++ hash.js | 16 +++++++ loader.js | 23 ++++++++++ object.js | 61 ++++++++++++++++++++++++++ querystr.js | 19 +++++++++ random.js | 15 +++++++ string.js | 22 ++++++++++ 9 files changed, 425 insertions(+) create mode 100644 array.js create mode 100644 date.js create mode 100644 form.js create mode 100644 hash.js create mode 100644 loader.js create mode 100644 object.js create mode 100644 querystr.js create mode 100644 random.js create mode 100644 string.js diff --git a/array.js b/array.js new file mode 100644 index 0000000..b859fdb --- /dev/null +++ b/array.js @@ -0,0 +1,83 @@ +module.exports = { + array_col: function( arr, name ) + { + var colArr = []; + if( name === undefined ) + { + for( var i in arr ) + { + var o = arr[i]; + colArr.push( o[ Object.keys( o )[0] ] ); + } + } + else + { + for( var i in arr ) + { + colArr.push( arr[i][ name ] ); + } + } + return colArr; + } + + // join exclude + , joinx: function( glue, arr, exclude ) + { + var namedArr = false; + if( arr.length == 2 + && typeof( arr[0] ) == "string" + && typeof( arr[1] ) == "object" ) + { + namedArr = arr[0]; + arr = arr[1]; + } + + var exMatch = []; + if( typeof( exclude ) == "string" ) + { + exMatch.push( exclude ); + } + else if( typeof( exclude ) == "object" ) + { + exMatch.push( exclude[ namedArr ] ); + } + else if( typeof( exclude ) == "array" ) + { + if( namedArr ) + { + for( var i in exclude ) + { + exMatch.push( exclude[i][ namedArr ] ); + } + } + else + { + exMatch = exclude + } + } + + var gluedStr = ""; + if( namedArr ) + { + for( var i = 0, l = arr.length; i < l; i ++ ) + { + if( exMatch.indexOf( arr[i][ namedArr ] ) < 0 ) + { + gluedStr += arr[i][ namedArr ] + "+"; + } + } + } + else + { + for( var i = 0, l = arr.length; i < l; i ++ ) + { + if( exMatch.indexOf( arr[i] ) < 0 ) + { + gluedStr += arr[i] + "+"; + } + } + } + + return gluedStr.substr( 0, gluedStr.length - 1 ); + } +}; diff --git a/date.js b/date.js new file mode 100644 index 0000000..ff9a95b --- /dev/null +++ b/date.js @@ -0,0 +1,66 @@ +// Capital month +var CAP_MONTHS = [ false, false, false, true, false, true, false, false, true, false, true, false ]; +var MONTH_ABBR = [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ]; +var MONTH = [ + "January", "February", "March", "April" + , "May", "June", "July", "August" + , "September", "October", "November", "December" +]; +var DAY_ABBR = [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ]; +var DAY = [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ]; + +var getOrdinalSuffix = function(day) +{ + if (day < 4 || ( 20 < day && day < 24 )) { + if (day == 1 || day == 21) return "st"; + else if (day == 2 || day == 22) return "nd"; + else if (day == 3 || day == 23) return "rd"; + } + else if (day == 31) return "st"; + return "th"; +}; + +module.exports = { + date_pretty: function( dateObj, plain ) + { + return dateObj.getDate() + + ( plain ? "" : "" ) + + getOrdinalSuffix( dateObj.getDate() ) + + ( plain ? " " : " " ) + + MONTH[ dateObj.getMonth() ] + + ", " + + dateObj.getFullYear() + ; + } + , date_bMon: function( date ) { return MONTH[ date.getMonth() ]; } + , date_sDay: function( date ) { return DAY_ABBR[ date.getDay() ]; } + , date_short: function( date ) + { + // Rearrange the date format + var d = date.toDateString().split( " " ); + // ddd dd mmm yyyy + return d[2] + " " + d[1] + " " + d[3] + " " + d[0]; + } + , date_comment: function( date ) + { + var d = date.toDateString().split( " " ); + var t = date.toTimeString().split( ":" ); + var ampm = "AM"; + var h = Number( t[0] ); + if( 12 <= h ) + { + ampm = "PM"; + if( h != 12 ) h -= 12; + } + + // h:mm AM/PM dd mmm, yyyy + return h + ":" + t[1] + " " + ampm + + " " + d[1] + " " + d[3] + ", " + d[2] + " " + d[0]; + } + , date_tzISODate: function( date ) + { + var tzo = new Date().getTimezoneOffset() * 6e4; + var ndate = new Date( date.getTime() - tzo ); + return ndate.toISOString().split( "T" )[0]; + } +}; diff --git a/form.js b/form.js new file mode 100644 index 0000000..904e284 --- /dev/null +++ b/form.js @@ -0,0 +1,120 @@ +var cl = global.botanLoader; +var WebParam = cl.load( "botanss.utils.WebParam" ); +var ReadStream = require( "stream" ).Readable; + +var qstr = require( "./querystr.js" ); + +module.exports = { + form_multipart: function( boundary, request, handler ) + { + boundary = new Buffer( "--" + boundary ); + var delim = new Buffer( "0D0A0D0A", "hex" ); + var endBuff = new Buffer( "2D2D0D0A", "hex" ); + + var st = request.resultStream(); + var firstRead = true; + + var tarBuff = null; + var content = [[]]; + + var i = 0; + var ring = 0; + + st.addListener( "readable", function() + { + if( firstRead ) + { + firstRead = false; + var r = st.read( boundary.length, "hex" ); + if( !r.equals( boundary ) ) + throw new Error( "Invalid form input" ); + } + + // Read them byte by byte + while( ( r = st.read( 1, "hex" ) ) !== null ) + { + switch( ring ) + { + case 0: + tarRBuff = delim; + nextRing = 1; + break; + + case 1: + tarRBuff = boundary; + nextRing = 0; + break; + } + + if( tarBuff ) + { + content[ i ].push( tarBuff[0] ); + tarBuff = Buffer.concat([ tarBuff.slice( 1 ), r ]); + } + else + { + tarBuff = Buffer.concat([ r, st.read( tarRBuff.length - 1, "hex" ) ]); + } + + if( tarBuff.equals( tarRBuff ) ) + { + i ++; content[ i ] = []; + ring = nextRing; + tarBuff = null; + } + } + + } ); + + st.addListener( "end", function() + { + if( !tarBuff.equals( endBuff ) ) + { + throw new Error( "Invalid form data" ); + } + + content = content.map( ( v ) => new Buffer( v ) ); + + var item; + var formData = []; + + var l = content.length; + + for( var i = 0; i < l; i ++ ) + { + if( i % 2 == 0 ) + { + item = {}; + content[i].toString().split( "\r\n" ).forEach( + function( v ) + { + if( !v ) return; + v = v.split( ":" ); + item[ v[0] ] = new WebParam( v[1] ); + } ); + } + else + { + // the -2 is the last 0D0A + item.file = { + content: new ReadStream() + , size: content[i].length - 2 + }; + item.file.content._read = function(){}; + + setTimeout( + function() + { + this.f.push( this.c.slice( 0, -2 ) ); + this.f.push( null ); + }.bind({ f: item.file.content, c: content[i] }) + , 0 ); + + formData.push( item ); + } + } + + handler( formData ); + } ); + } +}; diff --git a/hash.js b/hash.js new file mode 100644 index 0000000..15eb3d3 --- /dev/null +++ b/hash.js @@ -0,0 +1,16 @@ +var crypto = require( "crypto" ); + +module.exports = { + md5: function( str ) + { + var md5 = crypto.createHash( "md5" ); + md5.update( str ); + return md5.digest( "hex" ); + } + , sha1: function( str ) + { + var sha1 = crypto.createHash( "sha1" ); + sha1.update( str ); + return sha1.digest( "hex" ); + } +}; diff --git a/loader.js b/loader.js new file mode 100644 index 0000000..7703d69 --- /dev/null +++ b/loader.js @@ -0,0 +1,23 @@ +var cl = global.botanLoader; + +var Loader = function() +{ + for( var i in arguments ) + { + this.use( arguments[i] ); + } +}; + +Loader.prototype.use = function() +{ + for( var i in arguments ) + { + var module = arguments[i]; + var m = require( "./" + module ); + + // Link all methods to this + for( var j in m ) this[ j ] = m[ j ]; + } +}; + +module.exports = Loader; diff --git a/object.js b/object.js new file mode 100644 index 0000000..ea202f8 --- /dev/null +++ b/object.js @@ -0,0 +1,61 @@ +var cloneObj = function( o ) +{ + if ( o == null || typeof o != "object" ) return o; + + var clone = {}; + + if ( o instanceof Date ) + { + clone = new Date(); + clone.setTime( o.getTime() ); + return clone; + } + + if ( o instanceof Array ) + { + clone = []; + + for ( var i = 0, l = o.length; i < l; i ++ ) + { + clone[i] = cloneObj( o[i] ); + } + + return clone; + } + + if ( o instanceof Object ) + { + for ( var p in o ) + { + o.hasOwnProperty( p ) + && ( clone[ p ] = cloneObj( o[ p ] ) ); + } + + return clone; + } + + throw new Error( "Can't clone object: " + o ); +}; + +var referenceObj = function() +{ + var l = arguments.length; + if( l == 0 ) return null; + + var ref = arguments[0]; + if( l == 1 ) return ref; + + var refd = {}; + for( var i = 1; i < l; i ++ ) + { + var prop = arguments[i]; + refd[ prop ] = ref[ prop ]; + } + + return refd; +}; + +module.exports = { + clone: cloneObj + , refObj: referenceObj +}; diff --git a/querystr.js b/querystr.js new file mode 100644 index 0000000..24d1699 --- /dev/null +++ b/querystr.js @@ -0,0 +1,19 @@ +var cl = global.botanLoader; +var CondStream = cl.load( "botanss.utils.CondStream" ); + +module.exports = { + queryStr: function( qstr ) + { + var qObj = {}; + + if( qstr instanceof CondStream ) qstr = qstr.toString(); + + qstr.split( "&" ).forEach( function( val ) + { + val = val.split( "=" ); + qObj[ val[0] ] = val[1] ? decodeURIComponent( val[1].replace( /\+/g, " " ) ) : ""; + } ); + + return qObj; + } +}; diff --git a/random.js b/random.js new file mode 100644 index 0000000..8fdcfc5 --- /dev/null +++ b/random.js @@ -0,0 +1,15 @@ +var lut = []; for ( var i=0; i<256; i++ ) { lut[i] = (i<16?'0':'')+(i).toString(16); } + +module.exports = { + uuid: function() + { + var d0 = Math.random()*0xffffffff|0; + var d1 = Math.random()*0xffffffff|0; + var d2 = Math.random()*0xffffffff|0; + var d3 = Math.random()*0xffffffff|0; + return lut[d0&0xff]+lut[d0>>8&0xff]+lut[d0>>16&0xff]+lut[d0>>24&0xff]+'-'+ + lut[d1&0xff]+lut[d1>>8&0xff]+'-'+lut[d1>>16&0x0f|0x40]+lut[d1>>24&0xff]+'-'+ + lut[d2&0x3f|0x80]+lut[d2>>8&0xff]+'-'+lut[d2>>16&0xff]+lut[d2>>24&0xff]+ + lut[d3&0xff]+lut[d3>>8&0xff]+lut[d3>>16&0xff]+lut[d3>>24&0xff]; + } +}; diff --git a/string.js b/string.js new file mode 100644 index 0000000..07b0e73 --- /dev/null +++ b/string.js @@ -0,0 +1,22 @@ +module.exports = { + encodeHtml: function ( str, br ) + { + str = ( str + "" ).replace(/&/g, "&") + .replace(//g, ">") + .replace(/"/g, """) + .replace(/'/g, "'") + ; + if( br ) str = str.replace( /\n/g, "
" ); + return str; + } + , http_str: function( str ) + { + if( str.match( "^https?://" ) ) + { + return str; + } + + return "http://" + str; + } +}