moving the shell functions into a jruby script
This commit is contained in:
parent
de9f279ed4
commit
9f5054d2a3
3 changed files with 100 additions and 320 deletions
23
README.md
23
README.md
|
@ -23,3 +23,26 @@ You can use either ant, or maven. I included the only two jar deps, for local
|
||||||
tools and ant builds.
|
tools and ant builds.
|
||||||
But the unit tests are currently run with maven.
|
But the unit tests are currently run with maven.
|
||||||
|
|
||||||
|
|
||||||
|
Tools
|
||||||
|
=====
|
||||||
|
|
||||||
|
The CLI class was done away with, so as not to ship in the jar, anything uneeded for
|
||||||
|
the library. It's been rewritten in jRuby (see http://jruby.org/ ).
|
||||||
|
The script ./tools/handy.rb, has plenty of functionality, and feel free to add more.
|
||||||
|
|
||||||
|
** Usage
|
||||||
|
$> jruby tools/handy.rb --help
|
||||||
|
Usage: handy [options]
|
||||||
|
--dot output the dot digraph of content listing (defaults to ./src/test/resources/contents.list
|
||||||
|
--contents FILE use FILE instead of ./src/test/resources/contents.list
|
||||||
|
--cert FILE read contents from certificate FILE
|
||||||
|
--test PATH validate PATH, instead of [/content/beta/rhel/server/5/5server/x86_64/sap/os/repomd.xml]
|
||||||
|
--print print the tree of contents
|
||||||
|
|
||||||
|
$> jruby ./tools/handy.rb --dot > contents.dot && dot -Tpng contents.dot -o contents.png && display contents.png
|
||||||
|
|
||||||
|
$> jruby ./tools/handy.rb --cert ./src/test/resources/test-certv3.pem
|
||||||
|
[/content/beta/rhel/server/5/5server/x86_64/sap/os/repomd.xml] true
|
||||||
|
[/foo/path, /foo/path/always/$releasever, /foo/path/never]
|
||||||
|
|
||||||
|
|
|
@ -1,315 +0,0 @@
|
||||||
package com.hashbangbash.trie;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.DataInputStream;
|
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.BufferedInputStream;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
|
|
||||||
import java.io.FileNotFoundException;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import com.redhat.trie.HuffNode;
|
|
||||||
import com.redhat.trie.NodePair;
|
|
||||||
import com.redhat.trie.PathNode;
|
|
||||||
import com.redhat.trie.PathTree;
|
|
||||||
import com.redhat.trie.PayloadException;
|
|
||||||
|
|
||||||
import java.security.cert.CertificateException;
|
|
||||||
import java.security.cert.X509Certificate;
|
|
||||||
import java.security.cert.CertificateFactory;
|
|
||||||
|
|
||||||
import org.bouncycastle.asn1.DEROctetString;
|
|
||||||
import org.bouncycastle.asn1.ASN1Encodable;
|
|
||||||
import org.bouncycastle.x509.extension.X509ExtensionUtil;
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* App
|
|
||||||
*
|
|
||||||
* This is just a simple class to handle command line interactions
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class App {
|
|
||||||
|
|
||||||
/*
|
|
||||||
* PrettyPrint a PathNode tree
|
|
||||||
*/
|
|
||||||
public static void printTree(PathNode pn, int tab) {
|
|
||||||
StringBuffer nodeRep = new StringBuffer();
|
|
||||||
for (int i = 0; i <= tab; i++) {
|
|
||||||
nodeRep.append(" ");
|
|
||||||
}
|
|
||||||
nodeRep.append("Node [");
|
|
||||||
nodeRep.append(pn.getId());
|
|
||||||
nodeRep.append("]");
|
|
||||||
|
|
||||||
for (PathNode parent : pn.getParents()) {
|
|
||||||
nodeRep.append(" ^ [");
|
|
||||||
nodeRep.append(parent.getId());
|
|
||||||
nodeRep.append("]");
|
|
||||||
}
|
|
||||||
for (NodePair cp : pn.getChildren()) {
|
|
||||||
nodeRep.append(" v [");
|
|
||||||
nodeRep.append(cp.getName());
|
|
||||||
nodeRep.append(" {");
|
|
||||||
nodeRep.append(cp.getConnection().getId());
|
|
||||||
nodeRep.append("} ]");
|
|
||||||
}
|
|
||||||
System.out.println(nodeRep);
|
|
||||||
for (NodePair cp : pn.getChildren()) {
|
|
||||||
printTree(cp.getConnection(), tab + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* PrettyPrint a HuffNode tree
|
|
||||||
*/
|
|
||||||
public static void printTrie(HuffNode hn, int tab) {
|
|
||||||
StringBuffer nodeRep = new StringBuffer();
|
|
||||||
for (int i = 0; i <= tab; i++) {
|
|
||||||
nodeRep.append(" ");
|
|
||||||
}
|
|
||||||
nodeRep.append("Node [");
|
|
||||||
nodeRep.append(hn.getId());
|
|
||||||
nodeRep.append("]");
|
|
||||||
|
|
||||||
nodeRep.append(", Weight [");
|
|
||||||
nodeRep.append(hn.getWeight());
|
|
||||||
nodeRep.append("]");
|
|
||||||
|
|
||||||
nodeRep.append(", Value = [");
|
|
||||||
nodeRep.append(hn.getValue());
|
|
||||||
nodeRep.append("]");
|
|
||||||
|
|
||||||
System.out.println(nodeRep);
|
|
||||||
if (hn.getLeft() != null) {
|
|
||||||
printTrie(hn.getLeft(), tab + 1);
|
|
||||||
}
|
|
||||||
if (hn.getRight() != null) {
|
|
||||||
printTrie(hn.getRight(), tab + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* From the deflated payload, produce the content set lists
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* FIXME - break this apart, so that the hydrated payload
|
|
||||||
* can be structure to more quickly search, and use less memory
|
|
||||||
*
|
|
||||||
* Rename it for tracking, and to be clear about what is happening
|
|
||||||
*/
|
|
||||||
public static List<String> hydrateContentPackage(byte[] compressedBlob) {
|
|
||||||
PathTree pt = new PathTree(compressedBlob);
|
|
||||||
return pt.toList();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static ASN1Encodable objectFromOid(X509Certificate cert, String oid) {
|
|
||||||
if (cert == null) { return null; }
|
|
||||||
|
|
||||||
try {
|
|
||||||
for (String thisOid : cert.getNonCriticalExtensionOIDs()) {
|
|
||||||
if (thisOid.equals(oid)) {
|
|
||||||
return X509ExtensionUtil.fromExtensionValue(cert.getExtensionValue(oid));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (IOException ex) { }
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static byte[] getBytesFromFile(File file) throws IOException {
|
|
||||||
InputStream is = new FileInputStream(file);
|
|
||||||
|
|
||||||
// Get the size of the file
|
|
||||||
long length = file.length();
|
|
||||||
|
|
||||||
// You cannot create an array using a long type.
|
|
||||||
// It needs to be an int type.
|
|
||||||
// Before converting to an int type, check
|
|
||||||
// to ensure that file is not larger than Integer.MAX_VALUE.
|
|
||||||
if (length > Integer.MAX_VALUE) {
|
|
||||||
// File is too large
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create the byte array to hold the data
|
|
||||||
byte[] bytes = new byte[(int)length];
|
|
||||||
|
|
||||||
// Read in the bytes
|
|
||||||
int offset = 0;
|
|
||||||
int numRead = 0;
|
|
||||||
while (offset < bytes.length
|
|
||||||
&& (numRead=is.read(bytes, offset, bytes.length-offset)) >= 0) {
|
|
||||||
offset += numRead;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure all the bytes have been read in
|
|
||||||
if (offset < bytes.length) {
|
|
||||||
throw new IOException("Could not completely read file "+file.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close the input stream and return bytes
|
|
||||||
is.close();
|
|
||||||
return bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static List<String> hydrateFromBytes(byte[] compressedBlob) {
|
|
||||||
return hydrateContentPackage(compressedBlob);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<String> hydrateFromFile(String filename) {
|
|
||||||
try {
|
|
||||||
return hydrateFromBytes(getBytesFromFile(new File(filename)));
|
|
||||||
} catch (IOException ex) {
|
|
||||||
System.out.println(ex);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void byteArrayToFile(byte[] output, String filename) {
|
|
||||||
try {
|
|
||||||
FileOutputStream fos = new FileOutputStream(filename);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* To write byte array to a file, use
|
|
||||||
* void write(byte[] bArray) method of Java FileOutputStream class.
|
|
||||||
*
|
|
||||||
* This method writes given byte array to a file.
|
|
||||||
*/
|
|
||||||
fos.write(output);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Close FileOutputStream using,
|
|
||||||
* void close() method of Java FileOutputStream class.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
fos.flush();
|
|
||||||
fos.close();
|
|
||||||
|
|
||||||
} catch(FileNotFoundException ex) {
|
|
||||||
System.out.println("FileNotFoundException : " + ex);
|
|
||||||
} catch(IOException ioe) {
|
|
||||||
System.out.println("IOException : " + ioe);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<String> listFromFile(String filename) throws IOException, FileNotFoundException {
|
|
||||||
FileInputStream fis;
|
|
||||||
DataInputStream in;
|
|
||||||
BufferedReader br;
|
|
||||||
|
|
||||||
String content;
|
|
||||||
List<String> contentList;
|
|
||||||
|
|
||||||
try {
|
|
||||||
fis = new FileInputStream(filename);
|
|
||||||
} catch (FileNotFoundException ex) {
|
|
||||||
throw ex;
|
|
||||||
} catch (Throwable t) {
|
|
||||||
System.out.printf("ERROR: [%s] %s\n", filename, t);
|
|
||||||
return new ArrayList<String>();
|
|
||||||
}
|
|
||||||
|
|
||||||
in = new DataInputStream(fis);
|
|
||||||
br = new BufferedReader(new InputStreamReader(in));
|
|
||||||
contentList = new ArrayList<String>();
|
|
||||||
|
|
||||||
try {
|
|
||||||
while ((content = br.readLine()) != null) {
|
|
||||||
contentList.add(content);
|
|
||||||
}
|
|
||||||
} catch (IOException ex) {
|
|
||||||
throw ex;
|
|
||||||
}
|
|
||||||
return contentList;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void showTree(String filename) {
|
|
||||||
List<String> contentList;
|
|
||||||
try {
|
|
||||||
contentList = listFromFile(filename);
|
|
||||||
} catch (IOException ex) {
|
|
||||||
System.out.printf("ERROR: [%s] - %s\n", filename, ex);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
showTree(contentList);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void showTree(List<String> contentList) {
|
|
||||||
PathTree pt;
|
|
||||||
try {
|
|
||||||
pt = new PathTree(contentList);
|
|
||||||
printTree(pt.getRootPathNode(), 0);
|
|
||||||
} catch (PayloadException ex) {
|
|
||||||
System.out.println(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ASN1Encodable objectFromCertOid(String certFilename, String oid) {
|
|
||||||
X509Certificate cert;
|
|
||||||
cert = certFromFile(certFilename);
|
|
||||||
return objectFromOid(cert,oid);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static X509Certificate certFromFile(String certFilename) {
|
|
||||||
FileInputStream fis;
|
|
||||||
BufferedInputStream bis;
|
|
||||||
CertificateFactory cf;
|
|
||||||
X509Certificate cert;
|
|
||||||
|
|
||||||
try {
|
|
||||||
fis = new FileInputStream(certFilename);
|
|
||||||
} catch (FileNotFoundException ex) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
bis = new BufferedInputStream(fis);
|
|
||||||
|
|
||||||
|
|
||||||
try {
|
|
||||||
cf = CertificateFactory.getInstance("X.509");
|
|
||||||
} catch (CertificateException ex) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
while (bis.available() > 0) {
|
|
||||||
cert = (X509Certificate) cf.generateCertificate(bis);
|
|
||||||
return cert;
|
|
||||||
}
|
|
||||||
} catch (IOException ex) {
|
|
||||||
} catch (CertificateException cex) {
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
|
||||||
for (String arg : args) {
|
|
||||||
//showTreeFromCSFIle(arg);
|
|
||||||
//showTreeFromCSFIle(arg);
|
|
||||||
|
|
||||||
DEROctetString dos;
|
|
||||||
List<String> contents;
|
|
||||||
|
|
||||||
dos = (DEROctetString)objectFromCertOid(arg, "1.3.6.1.4.1.2312.9.7");
|
|
||||||
//byteArrayToFile(dos.getOctets(), "herp.bin");
|
|
||||||
if ((contents = hydrateFromBytes(dos.getOctets())) == null) {
|
|
||||||
System.out.println("FAIL");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (String content : contents) {
|
|
||||||
System.out.println(content);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -5,9 +5,19 @@ require 'java'
|
||||||
Dir[File.join(BASE_DIR,'lib/*jar')].each {|j| require j }
|
Dir[File.join(BASE_DIR,'lib/*jar')].each {|j| require j }
|
||||||
Dir[File.join(BASE_DIR,'target/*jar')].each {|j| require j }
|
Dir[File.join(BASE_DIR,'target/*jar')].each {|j| require j }
|
||||||
|
|
||||||
|
require 'openssl'
|
||||||
require 'stringio'
|
require 'stringio'
|
||||||
require 'optparse'
|
require 'optparse'
|
||||||
|
|
||||||
|
import java.io.BufferedInputStream
|
||||||
|
import java.io.FileInputStream
|
||||||
|
import java.security.cert.X509Certificate
|
||||||
|
import java.security.cert.CertificateFactory
|
||||||
|
|
||||||
|
import org.bouncycastle.asn1.DEROctetString
|
||||||
|
import org.bouncycastle.asn1.ASN1Encodable
|
||||||
|
import org.bouncycastle.x509.extension.X509ExtensionUtil
|
||||||
|
|
||||||
module Trie
|
module Trie
|
||||||
include_package 'com.redhat.trie'
|
include_package 'com.redhat.trie'
|
||||||
end
|
end
|
||||||
|
@ -44,12 +54,31 @@ def write_children(io, node)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_end(node)
|
# PrettyPrint a PathNode or HuffNode tree
|
||||||
return node if node.getChildren().length == 0
|
def printTree(node, tab)
|
||||||
|
nodeRep = " " * tab
|
||||||
|
|
||||||
|
nodeRep += "Node [#{node.getId}]"
|
||||||
|
nodeRep += ", Weight [#{node.getWeight}]" if node.respond_to? :getWeight
|
||||||
|
nodeRep += ", Value = [#{node.getValue}]" if node.respond_to? :getValue
|
||||||
|
node.getParents.each do |parent|
|
||||||
|
nodeRep += " ^ [#{parent.getId}]"
|
||||||
|
end if node.respond_to? :getParents
|
||||||
node.getChildren.each do |child|
|
node.getChildren.each do |child|
|
||||||
return get_end(child.getConnection())
|
nodeRep += " v [#{child.getName} {#{child.getId}}]"
|
||||||
|
end if node.respond_to? :getChildren
|
||||||
|
|
||||||
|
puts nodeRep
|
||||||
|
|
||||||
|
node.getChildren.each do |child|
|
||||||
|
printTree(child.getConnection, tab+1)
|
||||||
|
end if node.respond_to? :getChildren
|
||||||
|
if node.respond_to?(:getLeft) and node.respond_to?(:getRight)
|
||||||
|
printTree(node.getLeft, tab+1) if node.getLeft != nil
|
||||||
|
printTree(node.getRight, tab+1) if node.getRight != nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def parse_args(args)
|
def parse_args(args)
|
||||||
options = {
|
options = {
|
||||||
:content_list => './src/test/resources/contents.list',
|
:content_list => './src/test/resources/contents.list',
|
||||||
|
@ -63,9 +92,15 @@ def parse_args(args)
|
||||||
opts.on('--contents FILE', "use FILE instead of #{options[:content_list]}") do |o|
|
opts.on('--contents FILE', "use FILE instead of #{options[:content_list]}") do |o|
|
||||||
options[:content_list] = o
|
options[:content_list] = o
|
||||||
end
|
end
|
||||||
|
opts.on('--cert FILE', "read contents from certificate FILE") do |o|
|
||||||
|
options[:certificate] = o
|
||||||
|
end
|
||||||
opts.on('--test PATH', "validate PATH, instead of [#{options[:test_url]}]") do |o|
|
opts.on('--test PATH', "validate PATH, instead of [#{options[:test_url]}]") do |o|
|
||||||
options[:test_url] = o
|
options[:test_url] = o
|
||||||
end
|
end
|
||||||
|
opts.on('--print', "print the tree of contents") do |o|
|
||||||
|
options[:printTree] = o
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
opts.parse!(args)
|
opts.parse!(args)
|
||||||
|
@ -73,6 +108,36 @@ def parse_args(args)
|
||||||
return options
|
return options
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# ick, using java to do SSL
|
||||||
|
def object_from_oid(cert, oid)
|
||||||
|
return unless cert
|
||||||
|
cert.getNonCriticalExtensionOIDs.each do |o|
|
||||||
|
if o == oid
|
||||||
|
return X509ExtensionUtil.fromExtensionValue(cert.getExtensionValue(o))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
# ick, using java to do SSL
|
||||||
|
def value_from_oid(filename, oid)
|
||||||
|
bis = BufferedInputStream.new(FileInputStream.new(filename))
|
||||||
|
cf = CertificateFactory.getInstance("X.509")
|
||||||
|
cert = cf.generateCertificate(bis) # this is an X509Certificate
|
||||||
|
|
||||||
|
object_from_oid(cert, oid)
|
||||||
|
end
|
||||||
|
|
||||||
|
# not working on jRuby. :-(
|
||||||
|
# https://github.com/jruby/jruby/issues/389
|
||||||
|
def value_from_oid_bunk(filename, oid)
|
||||||
|
cert = OpenSSL::X509::Certificate.new(File.read(filename))
|
||||||
|
ext = cert.extensions.detect {|ext| ext.oid == oid }
|
||||||
|
return if ext.nil?
|
||||||
|
|
||||||
|
return OpenSSL::ASN1.decode(OpenSSL::ASN1.decode(ext.to_der).value[1].value).value
|
||||||
|
end
|
||||||
|
|
||||||
def main(args)
|
def main(args)
|
||||||
options = parse_args(args)
|
options = parse_args(args)
|
||||||
|
|
||||||
|
@ -80,8 +145,15 @@ def main(args)
|
||||||
|
|
||||||
puts print_dot(pt(options[:content_list]).getRootPathNode()).read() if options[:dot]
|
puts print_dot(pt(options[:content_list]).getRootPathNode()).read() if options[:dot]
|
||||||
|
|
||||||
#pn = pt.getRootPathNode
|
if options[:printTree]
|
||||||
#Trie::Util.printTree(pn, 0)
|
pn = pt.getRootPathNode
|
||||||
|
printTree(pn, 0)
|
||||||
|
end
|
||||||
|
if options[:certificate]
|
||||||
|
data = value_from_oid(options[:certificate], '1.3.6.1.4.1.2312.9.7')
|
||||||
|
pt = Trie::PathTree.new(data.getOctets)
|
||||||
|
puts pt.toList()
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
main(ARGV) if $0 == __FILE__
|
main(ARGV) if $0 == __FILE__
|
||||||
|
|
Loading…
Reference in a new issue