Thursday, January 26, 2012

Simple SHA Digest/Hash

import java.security.*

makeDigest = {String msg, int loops = 1, long t1 = (new Date()).getTime(), double q1 = Math.random() ->
    MessageDigest md = MessageDigest.getInstance("SHA")
    (Math.abs(loops) ?: 1).times {
        byte[] randm = {
            ByteArrayOutputStream byteOut = new ByteArrayOutputStream()
            DataOutputStream dataOut = new DataOutputStream(byteOut)
            dataOut.writeLong(t1)
            dataOut.writeDouble(q1)
            return byteOut.toByteArray()
        }()
        md.update(randm)
        md.update(msg.getBytes())
    }
    return md.digest()
}

String user = "admin"
String password = "s3cr3t"

int loops = 1
byte[] hash1 = makeDigest(user+password, loops, 0, 0) // not randomized
byte[] hash2 = makeDigest(user+password) // randomized
assert hash1 != hash2
println "$hash1\n$hash2"

Wednesday, January 25, 2012

File/Directory Traverse

//helpful file properties: http://groovy.codehaus.org/JN2015-Files
 
import groovy.io.FileType

def walkFiles = {filepath, filterOnly, onFind, onEnd = {} ->
    try {
        File f = new File(filepath)
        f.traverse([type:FileType.FILES, nameFilter:filterOnly], onFind)
        onEnd()
    }
    catch (FileNotFoundException e) { println "ERROR: invalid file/directory"}
}

def pf = { file ->
    if (file.name.contains("a"))
        println file.name
}

walkFiles("C:\\123", ~/.*\.ico/, pf)

Tuesday, January 24, 2012

FastMap and IdentityHashMap

@Grapes(
    @Grab(group='javolution', module='javolution', version='5.5.1')
)
import javolution.util.FastMap // also FastSet, FastList

Map labels1 = new FastMap().shared()
Map labels2 = [:] as IdentityHashMap // unsorted

100.times { i ->
    labels1[String.valueOf(i)] = i*i
    labels2[String.valueOf(i)] = i*i
}

assert labels1 == labels2.sort()

see http://javolution.org/target/site/apidocs/javolution/util/FastMap.html

Fibonacci

/**
 * Fibonacci series:
 * the sum of two elements defines the next
 */

int LIMIT = 1000

(a,b) = [0,1]
while (b < LIMIT) {
    print "$b "
    (a,b) = [b, a+b]
}

(source)

Thursday, December 29, 2011

ASCII Art

/**
 * Groovy ASCII Art. Converts an image into ASCII.
 * This doesn't work under the web console due to missing AWT classes.
 *
 * Author  : Cedric Champeau (http://twitter.com/CedricChampeau)
 * Updated : Steven Olsen (http://crazy4groovy.blogspot.com)
 */
import java.awt.color.ColorSpace as CS
import java.awt.geom.AffineTransform
import javax.imageio.ImageIO
import java.awt.image.*

String nl = System.getProperty("line.separator")
String slash = System.getProperty("file.separator")
def input = System.console().&readLine

def charset1 = /#@$&%*o=^|-:,'. / //16 chars
//def charset2 = /#@$&%*o=^|-:,'. / //16 chars
def charset2 = /ABCDEFGHIJKLMNOP/ //16 chars

/////////CLI///////////
def cli = new CliBuilder(usage:'asciiArt [options] [path/file/url]', header:'Options:')
cli.h    (longOpt:'help', 'print this message')
cli.bw    (longOpt:'blackWhiteText', 'set normal black/white text')
cli.ctxt(longOpt:'colourText', 'set html colour (text)')
cli.cbg    (longOpt:'colourBackground', 'set html colour (background)')
cli.ics    (longOpt:'isCharSequ', 'output char map in sequence')
cli.vf    (longOpt:'verifyFile', 'verify each file write with a confirmation message')
cli.r    (longOpt:'recursiveFiles', 'recursively iterate through all files in a directory')
cli.cm    (longOpt:'characterMapping', args:1, argName:'percent', 'set custom char map (16)')
cli.s    (longOpt:'scale', args:1, argName:'percentage', 'scale image resolution for output processing (default=40)')
cli.ext    (longOpt:'fileExtension', args:1, argName:'ext', 'name of file extension (default=txt or html)')
cli.incl(longOpt:'fileExtensionInclude', args:1, argName:'regex', 'regex -- name of file extensions to include (default=jpe?g|png|gif)')
cli.outDir    (longOpt:'outputDir', args:1, argName:'...\\dir\\', 'output into dir')
cli.outFile    (longOpt:'outputFile', args:1, argName:'...\\file', 'output into file')

def opt = cli.parse(args)

if (opt.h) {
    cli.usage(); return
}
/////////CLI///////////

List srcs
if (opt.arguments().size() >= 1)
    srcs = opt.arguments()
else
    srcs = [input('image file (local or http): ')] ?: ['http://gordondickens.com/images/groovy.png']

srcs = srcs.collect{ it.replaceAll('"','').split(',') }.flatten()

Set imgSrcList = [] as SortedSet
String filter = opt.incl ?: 'jpe?g|png|gif'
imgSrcList.metaClass.leftShift { if (it.split('\\.')[-1] ==~ "(${filter})") { delegate.add it } }

srcs.each { s ->
    boolean isRemote = s ==~ 'https?://.*'
    if (isRemote) {
        imgSrcList.add s // bypass meatclass filter with .add
        return
    }
    
    def f = new File(s)
    if (!f.directory == true && f.name.split('\\.')[-1] ==~ '(jpe?g|png)') {
        imgSrcList << s
        return
    }
    
    if (opt.r)
        f.eachFileRecurse { fi -> 
            imgSrcList << fi.path }
    else
        f.eachFile { fi -> 
            imgSrcList << fi.path }
}

boolean isMultiImg = (imgSrcList.size() > 1)

Boolean isCharSequGlobal = null // once set to true/false, val will always be used
imgSrcList.eachWithIndex { src, i ->
try {

println "** IMAGE ${i+1} of ${imgSrcList.size()}: $src ..."

boolean isRemote = src ==~ 'https?://.*'
def imgSrc = ImageIO.read( isRemote ? new URL(src) : new File(src))

def scale = opt.s ? opt.s.toBigDecimal() / 100 : 0.4G
String fileName = opt.outFile ?: opt.outDir ? '' : 'SCREEN'

boolean convert = true
while (convert) {
    ////////////INPUT START////////////
    scale *= 100 // reset scale to %
    scale = isMultiImg ? scale : (input("scale of ascii art (percentage) [${scale}]: ") ?: scale)
    scale = scale.toBigDecimal() / 100 // prep scale for usage
    boolean isHtmlColour = opt.bw ? false : (opt.ctxt ?: opt.cbg ?: (input('html colour chars? [y/N]: ').toLowerCase().contains('y') ? true : false) )
    boolean isBgColour = false
    if (isHtmlColour)
        isBgColour = opt.cbg ?: isMultiImg ? false : (input('set background colour? [y/N]: ').toLowerCase().contains('y') ? true : false)
    String charsMapping = opt.cm ?: isMultiImg ? '' : (input('custom char set? (16): ') ?: null)
    if (isHtmlColour && charsMapping && charsMapping.size() < 16 && !isMultiImg)
        println "WARNING: custom char set size is less than 16 (${charsMapping.size()})\n -- must be output in order!"
    boolean isCharSequ = isCharSequGlobal ?: false
    if (isHtmlColour && charsMapping && charsMapping.size() >= 1) {
        isCharSequ = opt.ics ?: isCharSequGlobal ?: (input('output custom chars in order? [Y/n]:').toLowerCase().contains('n') ? false : true)
        isCharSequGlobal = isCharSequ
    }
    if (isHtmlColour && charsMapping && charsMapping.size() < 16 && !isCharSequ)
        println "ERROR: custom char set REJECTED -- size is less than 16 (${charsMapping.size()}) and output is not ordered.\n -- Using default char set."
    if (!isHtmlColour && charsMapping && charsMapping.size() < 16)
        if (i == 0) println "ERROR: non-colour custom char set REJECTED -- size is less than 16 (${charsMapping.size()})\n -- Using default char set."
    if (!isCharSequ && charsMapping?.size() < 16)
        charsMapping = isHtmlColour ? charset2 : charset1
    
    fileName = opt.outFile ?: opt.outDir ? '' : isMultiImg ? '' : input("save ascii art into File (SCREEN = print to screen) [${fileName}]: ") ?: fileName
    ////////////INPUT END////////////

    def yScaleOffset = isHtmlColour ? 0.7 : 0.6 // ascii imgs looked too "tall" -- dev tweakable!
    def cSpace = isHtmlColour ? CS.CS_sRGB : CS.CS_GRAY

    ////////GENERATE////////
    def img = imgSrc
    if (scale != 1.0) {
        def tx = new AffineTransform()
        tx.scale(scale, scale * yScaleOffset)
        def op = new AffineTransformOp(tx, AffineTransformOp.TYPE_BILINEAR)
        def scaled = new BufferedImage((int) (imgSrc.width * scale), (int) (imgSrc.height * scale * yScaleOffset), imgSrc.type)
        img = op.filter(imgSrc, scaled)
    }

    img = new ColorConvertOp(CS.getInstance(cSpace), null).filter(img, null)

    BigInteger pixelCntr = 0G
    def ascii = { rgb ->
        int r = (rgb & 0x00FF0000) >> 16
        int g = (rgb & 0x0000FF00) >> 8
        int b = (rgb & 0x000000FF)

        int gs
        if (isCharSequ)  gs = (pixelCntr++) % charsMapping.size()
        else  gs = ((int) ( r + g + b ) / 3) >> 4 // multiple of 16

        return [ charsMapping.charAt(gs), [r,g,b] ]
    }

    String preStyle = " style='opacity:1.0;font-size:0.8em;line-height:85%;${ isBgColour ? 'color:#FFF;' : '' }'"
    String spanStyle = isBgColour ? "background-color" : "color"

    StringBuilder sb = new StringBuilder()
    if(isHtmlColour) sb.append("<style>pre img{opacity:0.0;border:4px dotted #444} pre img:hover{opacity:0.95;}</style>"+nl+
        "<pre${preStyle}>"+nl+
        "<div style='position:absolute'><img src='${!isRemote ? 'file://' : ''}${src}' style='position:absolute;top:5px;left:5px;'/></div>"+nl)
    img.height.times { y ->
        img.width.times { x ->
            (chr, rgb) = ascii(img.getRGB(x, y))
            if (isBgColour || (isHtmlColour && chr != ' '))
                sb.append("<span style='${spanStyle}:rgb(${rgb.join(',')});'>${chr}</span>")
            else
                sb.append(chr)
        }
        sb.append(nl)
    }
    if(isHtmlColour) sb.append("</pre>"+(nl * 2))
    ////////GENERATE////////

    if (fileName == 'SCREEN') {
        println sb.toString()
    }
    else {
        if (!fileName) {
            File f = new File(src) // to get file name and parent fields
            String fExt = opt.outFile ? '' : '.ascii'
            fExt += opt.outFile ? '' : ('.' + (opt.ext ?: isHtmlColour ? 'html' : 'txt'))
            fileName =  (opt.outDir ?: f.parent) + slash + f.name + fExt
        }

        boolean ok = !opt.vf ?: input("WARNING: writing to file ${fileName} ok? [Y/n]").toLowerCase().contains('n') ? false : true
        File f = new File(fileName)
        if (ok) {
            f << sb.toString()
            println "\t>> ${f.name}"
        }
    }

    convert = isMultiImg ? false : (input('>> export this image to ascii format again? [y/N]: ').toLowerCase().contains('y') ? true : false)
    if (convert) println '=' * 40
}

} catch (Exception e) { println "\tERROR: ${e.toString()}"}
}


gist link

Thursday, December 15, 2011

rabbitMQ - Publish/Subscribe

@Grab('com.rabbitmq:amqp-client:2.7.0')
import com.rabbitmq.client.*

public class SendReceive {
  private String QUEUE
  private Channel channel
  
  public SendReceive( String hostName = "localhost", String queue = "hello" ) {
        QUEUE = queue
        ConnectionFactory factory = new ConnectionFactory()
//      factory.setUsername(userName)
//      factory.setPassword(password)
//      factory.setVirtualHost(virtualHost)
        factory.setHost(hostName)
//      factory.setPort(portNumber)
        Connection connection = factory.newConnection()
        channel = connection.createChannel()
        channel.exchangeDeclare(QUEUE, "fanout")
  }

  public void send( String message )
      throws java.io.IOException {
        channel.basicPublish(QUEUE, "", null, message.getBytes())
        println(" [x] Sent: $message")
        
        //channel.close()
        //connection.close()
  }

  public void receive()
      throws java.io.IOException, java.lang.InterruptedException {
        String queueName = channel.queueDeclare().getQueue();
        channel.queueBind(queueName, QUEUE, "");
        
        QueueingConsumer consumer = new QueueingConsumer(channel)
        channel.basicConsume(queueName, true, consumer)
        println(" [*] Waiting for messages. To exit press CTRL+C")

        while (true) { //loop forever!
            QueueingConsumer.Delivery delivery = consumer.nextDelivery() // blocks for next message!
            String message = new String(delivery.getBody())
            println(" [x] Received: $message")
        }
    }
}

def input = System.console().&readLine // convenience method

def client = new SendReceive(
    input('\nEnter rabbitMQ host location: '),
    input('\nEnter rabbitMQ queue name: ')
)

String userType = input('\n[s]end or [r]eceive?: ')

if (userType && userType == 'r') {
    client.receive()
}
else {
    while(true) {
        String msg = input('\nType a message to send -- To exit press CTRL+C: ')
        client.send(msg)
    }
}

rabbitMQ - Queue

@Grab('com.rabbitmq:amqp-client:2.7.0')
import com.rabbitmq.client.*

public class SendReceive {
  private String QUEUE
  private Channel channel
  
  public SendReceive( String hostName = "localhost", String queue = "hello" ) {
        QUEUE = queue
        ConnectionFactory factory = new ConnectionFactory()
//      factory.setUsername(userName)
//      factory.setPassword(password)
//      factory.setVirtualHost(virtualHost)
        factory.setHost(hostName)
//      factory.setPort(portNumber)
        Connection connection = factory.newConnection()
        channel = connection.createChannel()
        channel.queueDeclare(QUEUE, false, false, false, null)
  }

  public void send( String message )
      throws java.io.IOException {
        channel.basicPublish("", QUEUE, null, message.getBytes())
        println(" [x] Sent: $message")
        
        //channel.close()
        //connection.close()
  }

  public void receive()
      throws java.io.IOException, java.lang.InterruptedException {

        QueueingConsumer consumer = new QueueingConsumer(channel)
        channel.basicConsume(QUEUE, true, consumer)
        println(" [*] Waiting for messages. To exit press CTRL+C")

        while (true) { //loop forever!
            QueueingConsumer.Delivery delivery = consumer.nextDelivery() // blocks for next message!
            String message = new String(delivery.getBody())
            println(" [x] Received: $message")
        }
    }
}

def input = System.console().&readLine // convenience method

def client = new SendReceive(
    input('\nEnter rabbitMQ host location: '),
    input('\nEnter rabbitMQ queue name: ')
)

String userType = input('\n[s]end or [r]eceive?: ')

if (userType && userType == 'r') {
    client.receive()
}
else {
    while(true) {
        String msg = input('\nType a message to send -- To exit press CTRL+C: ')
        client.send(msg)
    }
}