My attempts at forcing OpenWRT onto DIR-645 or DIR-655

May 5th, 2012
by alexw

What a pain in the ass. I appreciate DLink releasing source for the DIR-645 and DIR-655, but, really guys, do it right or don’t do it at all.
First I have to thank tumbe toene for his(her?) post, without which I would never have found DLinks GPL download links (here, and here).
Second, I’m no noob, but i have to admit (with much chagrin) that I had never compiled a linux kernel before this. Maybe I still haven’t, does it count if it compiles, but won’t flash?
I’ve now tried this (dozens?) of times for both the 645 and the 655 with (almost) zero success. The readmes in the downloaded rars are laughable, including instructions like “Step 1. Install fedora linux 10″ (ah, yes, the “install an unfamiliar, out-of-date, operating system” instruction). In fact I DID install fedora in a virtual box just to see if that was the problem, only to find out fedora doesn’t really do rar files…brilliant.
Then there’s “Copy the blah.tar.gz into /home/trunk directory.” Yep, that’s me, “trunk,” pleased to meet you.
You’ll also be instructed to copy (as root) an unknown gcc into your /opt directory and install their version of fakeroot. NOT best practice at the very least, serious security NO-NOs at worst.
But then you get to the real meat of the incompetence, or laziness, when you start trying to actually make the damn things. The 645 says, ”
Step 3. Building the image

1) $make

2) $make

3) $make”
uh, are you just assuming the first two will fail? But, no, the actual makefile targets change as you go. Next,
“Do you want to rebuild the linux kernel ? (yes/no) : yes”
returns:
[: 19: yes: unexpected operator
which DOES NOT stop the make process, or alert you, it just fails to compile the kernel. (I’m assuming fedora’s read command works differently than mint’s, I just edited the makefile and got rid of the prompt).
A while later, after MANY warnings, you’ll be notified:

-e Building pppd …
auth.o: In function `plogin’:
/home/username/trunk/DIR645A1_GPL101/progs.gpl/pppd.alpha/auth.c:1477: undefined reference to `crypt’
auth.o: In function `check_passwd’:
/home/username/trunk/DIR645A1_GPL101/progs.gpl/pppd.alpha/auth.c:1291: undefined reference to `crypt’
pppcrypt.o: In function `DesDecrypt’:
/home/username/trunk/DIR645A1_GPL101/progs.gpl/pppd.alpha/pppcrypt.c:153: undefined reference to `encrypt’
pppcrypt.o: In function `DesEncrypt’:
/home/username/trunk/DIR645A1_GPL101/progs.gpl/pppd.alpha/pppcrypt.c:137: undefined reference to `encrypt’
pppcrypt.o: In function `DesSetkey’:
/home/username/trunk/DIR645A1_GPL101/progs.gpl/pppd.alpha/pppcrypt.c:122: undefined reference to `setkey’

If you haven’t given up yet and hunt this error down, you’ll find that the LIBS argument passed to the compiler (in …/progs.gpl/pppd.alpha/Makefile at line 252) is empty…I couldn’t be bothered to figure out why (maybe cause it’s ALPHA?!?!), and forced it to include crypt.h by adding “-lcrypt” to the end of the line.

A long while later, it finished compiling…I uploaded it over the web interface…and I finally had…exactly the same firmware. No new options, no new software, no new open ports, not a damn thing, oh, except my hardware version now read “N/A” instead of “A1″…SUCCESS, sort of.

There was no menuconfig (or any config) target in the makefile, so I went back and looked over the .config file to see if there were any interesting options in there. Bupkis. Just for the fun of it I updated the ELBOX_FIRMWARE_VERSION, ELBOX_FIRMWARE_REVISION, and ELBOX_FIRMWARE_SIGNATURE variables to reflect my frustration, recompiled, and…it failed to flash.

WTF?!? DLink, why did you provide me with a buggy, insecure, poorly documented build environment that doesn’t even give me any more options than the stock firmware?

But, comparatively, the 645 was the easy one. Further travails on the 655 to come…

Posted in Projects | Comments (0)

Robot!!!

June 16th, 2011
by alexw

This is the robot i’m presently building. Just some pictures for now.

Posted in Uncategorized | Comments (0)

WolfTrack

March 9th, 2011
by alexw

This was a “dashboard” I and a designer developed for my last job. It is, without a doubt, the single largest coding project I have ever attempted, much less accomplished. It’s something like 10,000 lines of java, php, SQL, HTML, javascript, flash, iMacros scripts, and configuration.
Basically WolfTrack / R2B2 is like having an accountant in house without having to pay for it (albeit a not very bright one).
The R2B2 part uses iMacros (Scripting Edition) in combination with java “scrapers” to go to websites periodically and pull any relevant data (customized by the iMacros script). As new cost/revenue sources are added, removed, it uses a template system to adapt. I currently have 16 scrapers for all the major advertisers (Google, Yahoo, etc) and many others.
Next the system takes all that data and enters it into a MySQL database which keeps track of cost/revenue from the time the system got set up. This means that you can go back and compare previous days, weeks, months, even years. All of the data is held in a very granular DB architecture, so it can be interpreted however you see fit.
Finally the front end (WolfTrack) is a group of PHP pages which takes all the data from the DB and presents it in a simple graphical format. Take a look at the screen shots below and you can see it shows you revenue throughout the day in 15 minute increments. It shows you how your revenue is compared to yesterday throughout the day. It shows you today’s costs and yesterdays costs and GP estimates. At the bottom is a long term graph showing the performance of each cost/revenue stream over the entire life of the system.
John Levan did the design and I think it turned out very well, it’s intuitive and simple. These were designed to show on four 42″ screens around the office, sort of a moral booster (except when revenue was low, then it just taunted us).

Unfortunately, my last employer owns the rights to this code, so I can’t publish it :(
NOTE: the horizontal positioning is off in the captures because the site was designed for 1080p and I don’t have a monitor that’ll do that.

Posted in Software | Comments (0)

JAVA Indentation Class

March 8th, 2011
by alexw

This is a java version of the PHP indentation class.

public class indentation
{
 int minDepth, maxDepth, startDepth, currDepth;
 String indentString;

 public indentation()
 {
  this(0,0,0,"\t");
 }

 public indentation(String newIndentString)
 {
  this(0,0,0,newIndentString);
 }

 public indentation(int minDepth, int maxDepth, int startDepth, String indentString)
 {
  this.minDepth = minDepth;
  this.maxDepth = maxDepth;
  this.startDepth = startDepth;
  this.indentString = indentString;
  this.currDepth = 0;
 }

 public void reset()
 {
  currDepth = 0;
 }

 public void setIndentString(String newIndentString)
 {
  indentString = newIndentString;
 }

 public int getCurrDepth()
 {
  return currDepth;
 }

 public int in(int inDepth)
 {
  currDepth += inDepth;
  return currDepth;
 }

 public int out(int outDepth)
 {
  currDepth -= outDepth;
  return currDepth;
 }

 public String toString()
 {
  StringBuffer sb = new StringBuffer();
  for(int i = 0; i < currDepth; i++)
   sb.append(indentString);
  return sb.toString();
 }
}

Posted in Repository, Software | Comments (0)

JAVA Static Methods

March 8th, 2011
by alexw

I find myself writing all sorts of little simple functions (usually I feel like these should be native to the language, but whatever).
This is a place for those, because it can be nice to have little building blocks available instead of rewriting them every time.

public class statics
{
 /***********************************************************/
 public static int stringLocInSet(String string, String[] set)
 {
  if(set.length == 0)
   return -1;
  int i = 0;

  while((i < set.length) && !(set[i].equals(string)))
  {
   i++;
  }

  if(i < set.length)
   return i;
  else
   return -1;
 }
 /***********************************************************/
 public static boolean stringInSet(String string, String[] set)
 {
  return ((stringLocInSet(string, set) >= 0) ? true : false);
 }
 /***********************************************************/
 public static StringBuffer replaceAll(StringBuffer searchIn, String searchFor, String replaceWith)
 {
  int startPos = searchIn.indexOf(searchFor);
  if(startPos >= 0)
  {
   searchIn.replace(startPos, startPos + searchFor.length(), replaceWith);
  }
  return searchIn;
 }
 /***********************************************************/
 public static String prompt(String promptString)
  throws java.io.IOException
 {
  return stringPrompt(promptString);
 }
 /***********************************************************/
 public static String stringPrompt(String promptString)
  throws java.io.IOException
 {
  System.out.print(promptString);
  return(inLine());
 }
 /***********************************************************/
 public static String inLine()
  throws java.io.IOException
 {
  java.io.BufferedReader bf = new java.io.BufferedReader(new java.io.InputStreamReader(System.in));
  return bf.readLine();
 }
 /***********************************************************/
 public static int countInstances(String someString, char someChar)
 {
  int instanceCount = 0;
  int ndx = -1;
  while((ndx = someString.indexOf(someChar, ndx + 1)) > 0)
  {
   instanceCount++;
  }
  return instanceCount;
 }
 /***********************************************************/
 public static String getNextFileName(String filePath)
 {
  return getNextFile(filePath).getPath();
 }
 /***********************************************************/
 public static java.io.File getNextFile(String filePath)
 {
  return getNextFile(new java.io.File(filePath));
 }
/***********************************************************/
 public static java.io.File getNextFile(java.io.File myFile)
 {
  java.io.File tempFile = myFile;
  for(int fileOrder = 1; tempFile.exists(); fileOrder++)
  {
   tempFile = new java.io.File(myFile.getPath() + "." + fileOrder);
  }
  return tempFile;
 }
/***********************************************************/
 public static String now()
 {
  return now("Ymd", false);
 }

 //These are the php identifiers, not the java ones
 //w = Day of the week, 1 digit (0-6)
 //d = Day of the month, 2 digits with leading zeros (01-31)
 //j = Day of the month, without leading zeros (1-31)
 //D = Day Name, abreviated, 3 letters (Mon-Sun)
 //l = Day Name, spelled out (Sunday-Saturday)
 //z = Day of the year (0-365)
 //F = Month Name, spelled out (January-December)
 //M = Month Name, abreviated (Jan-Dec)
 //m = Month of the year, 2 digits with leading zeros (01-12)
 //n = Month of the year, without leading zeros (1-12)
 //Y = Year, 4 digits
 //y = Year, 2 digits
/***********************************************************/
 public static String now(String format, boolean zeroIndexMonths)
 {
  java.util.Calendar now = java.util.Calendar.getInstance();
  StringBuffer sb = new StringBuffer();
  for(int i = 0; i < format.length(); i++)
  {
   switch(format.charAt(i))
   {
    case 'y':
     sb.append(now.get(java.util.Calendar.YEAR));
    break;
    case 'Y':
     String year = now.get(java.util.Calendar.YEAR) + "";
     while(year.length() < 4)
      year = "0" + year;
      sb.append(year);
    break;
    case 'n':
     sb.append(!zeroIndexMonths ? now.get(java.util.Calendar.MONTH) : (now.get(java.util.Calendar.MONTH) + 1));
    break;
    case 'm':
     int month = now.get(java.util.Calendar.MONTH);
     if(!zeroIndexMonths)
      month++;
     sb.append(((month + "").length() == 2) ? month : "0" + month);
    break;
    case 'w':
     sb.append(now.get(java.util.Calendar.DAY_OF_WEEK));
    break;
    case 'd':
     sb.append(((now.get(java.util.Calendar.DAY_OF_MONTH) + "").length() == 2) ? (now.get(java.util.Calendar.DAY_OF_MONTH)) : "0" + (now.get(java.util.Calendar.DAY_OF_MONTH)));
    break;
    case 'j':
     sb.append(now.get(java.util.Calendar.DAY_OF_MONTH));
    break;
    case 'z':
     sb.append(now.get(java.util.Calendar.DAY_OF_YEAR));
    break;
    case 'l':
     switch(now.get(java.util.Calendar.DAY_OF_WEEK))
     {
      case 0:
       sb.append("Sunday");
      break;
      case 1:
       sb.append("Monday");
      break;
      case 2:
       sb.append("Tuesday");
      break;
      case 3:
       sb.append("Wednesday");
      break;
      case 4:
       sb.append("Thursday");
      break;
      case 5:
       sb.append("Friday");
      break;
      case 6:
       sb.append("Saturday");
      break;
         }
    break;
    case 'D':
     switch(now.get(java.util.Calendar.DAY_OF_WEEK))
     {
      case 0:
       sb.append("Sun");
      break;
      case 1:
       sb.append("Mon");
      break;
      case 2:
       sb.append("Tue");
      break;
      case 3:
       sb.append("Wed");
      break;
      case 4:
       sb.append("Thu");
      break;
      case 5:
       sb.append("Fri");
      break;
      case 6:
       sb.append("Sat");
      break;
         }
    break;
    case 'F':
     switch(now.get(java.util.Calendar.MONTH))
     {
      case 0:
       sb.append("January");
      break;
      case 1:
       sb.append("February");
      break;
      case 2:
       sb.append("March");
      break;
      case 3:
       sb.append("April");
      break;
      case 4:
       sb.append("May");
      break;
      case 5:
       sb.append("June");
      break;
      case 6:
       sb.append("July");
      break;
      case 7:
       sb.append("August");
      break;
      case 8:
       sb.append("September");
      break;
      case 9:
       sb.append("October");
      break;
      case 10:
       sb.append("November");
      break;
      case 11:
       sb.append("December");
      break;
         }
    break;
    case 'M':
     switch(now.get(java.util.Calendar.MONTH))
     {
      case 0:
       sb.append("Jan");
      break;
      case 1:
       sb.append("Feb");
      break;
      case 2:
       sb.append("Mar");
      break;
      case 3:
       sb.append("Apr");
      break;
      case 4:
       sb.append("May");
      break;
      case 5:
       sb.append("Jun");
      break;
      case 6:
       sb.append("Jul");
      break;
      case 7:
       sb.append("Aug");
      break;
      case 8:
       sb.append("Sep");
      break;
      case 9:
       sb.append("Oct");
      break;
      case 10:
       sb.append("Nov");
      break;
      case 11:
       sb.append("Dec");
      break;
    }
    break;
    default:
     sb.append(format.charAt(i));
   }
  }
  return sb.toString();
 }
/***********************************************************/
 public static void copyFile(java.io.File src, java.io.File dest)
        throws java.io.IOException
 {
  java.io.File finalDest;
  if(dest.exists() && dest.isDirectory())
   finalDest = new java.io.File(dest.getPath() + java.io.File.pathSeparatorChar + src.getName());
  else
   finalDest = dest;

  java.io.InputStream in = new java.io.FileInputStream(src);
  java.io.OutputStream out = new java.io.FileOutputStream(finalDest);
  byte[] buf = new byte[1024];
  int len;
  while((len = in.read(buf)) > 0)
  {
   out.write(buf, 0, len);
  }
  in.close();
  out.close();
 }
/***********************************************************/
 public static final String[] BASE10TOKENS = {"0","1","2","3","4","5","6","7","8","9"};
/***********************************************************/
 public static String intToString(int parseMe)
 {
  return intToString(parseMe, BASE10TOKENS);
 }
/***********************************************************/
 public static String intToString(int parseMe, String[] tokens)
 {
  StringBuffer soFar = new StringBuffer();
  int temp = parseMe;
  do
  {
   soFar.insert(0, tokens[(temp /= tokens.length) % tokens.length]);
  }
  while(temp >= tokens.length);
  return soFar.toString();
 }
/***********************************************************/
 public static String arrayToString(int[] array)
 {
  Integer[] wrappers = new Integer[array.length];
  for(int i = 0; i < wrappers.length; i++)
  {
   wrappers[i] = new Integer(array[i]);
  }
  return arrayToString(wrappers);
 }

/**************************************************************/
 //this only works if all the rows have the same
 //number of objects
 public static String arrayToString(Object[] array)
 {
  return arrayToString(array, null);
 }
/**************************************************************/
 public static String arrayToString(Object[] array, Object[] headers)
 {
  Object[][] obj = new Object[1][];
  obj[0] = array;
  return arrayToString(obj, headers);
 }
/**************************************************************/
 public static String arrayToString(Object[][] array, Object[] headers)
 {
  return arrayToString(array, headers, false, false);
 }
/**************************************************************/
 public static String arrayToString(Object[][] array)
 {
  return arrayToString(array, null);
 }
/**************************************************************/
 public static String arrayToString(Object[][] array, Object[] headers, boolean showIndicies, boolean hiliteHeaders)
 {
  if(array == null || array.length == 0)
  {
   return "";
  }

  int maxRowLength = 0;
  StringBuffer sb = new StringBuffer();
  char rowSepChar = '-';

  //gotta get the length of the longest cell in each column
  int[] colMaxLengths = new int[array[0].length]; //this assumes the rows all have the same number of elements
  //check to make sure headers is the same length as array[]
  if(headers != null)
  {
   if(headers.length != array[0].length)
   {
    System.out.println("alexUtils.arrayToString(...) Error:\n headers.length != array[0].length");
    return "";
   }
   else
   {
    for(int i = 0; i < headers.length; i ++)
    {
     colMaxLengths[i] = headers[i].toString().length();
    }
   }
  }

  for(int colNDX = 0; colNDX < array[0].length; colNDX++)
  {
   for(int rowNDX = 0; rowNDX < array.length; rowNDX++)
   {

//    if(array[rowNDX][colNDX] == null)
//     array[rowNDX][colNDX] = (Object)((new String("<NULL>")));

    int tempFieldLength;
    if(array[rowNDX][colNDX] == null)
     tempFieldLength = 6; //"<NULL>".length() == 6
    else
         tempFieldLength = array[rowNDX][colNDX].toString().length();
    if(showIndicies)
    {
     tempFieldLength += (" [" + rowNDX + "," + colNDX + "]").length();
    }
    if(tempFieldLength > colMaxLengths[colNDX])
    {
     colMaxLengths[colNDX] = tempFieldLength;
    }
   }
  }

  StringBuffer sb2 = new StringBuffer();
  sb2.append("+");
  for(int colNDX = 0; colNDX < colMaxLengths.length; colNDX++)
  {
   for(int rowSepCharNDX = 0; rowSepCharNDX < colMaxLengths[colNDX]; rowSepCharNDX++)
   {
    sb2.append(rowSepChar);
   }
   sb2.append("+");
  }
  String rowSep = sb2.toString();

  if(headers != null)
  {
   sb.append(rowSep.replace('-', '=').replace('+', '='));
   sb.append("\n|");
   for(int headerNDX = 0; headerNDX < headers.length; headerNDX++)
   {
    sb.append(centerL(headers[headerNDX].toString(), colMaxLengths[headerNDX]) + "|");
   }
   sb.append("\n");
  }

  if(headers != null)
   sb.append(rowSep.replace('-', '=').replace('+', '='));
  else
  sb.append(rowSep.replace('+', '-'));
  for(int rowNDX = 0; rowNDX < array.length; rowNDX++)
  {
   if(rowNDX != 0)
    sb.append(rowSep);
   sb.append("\n|");
   for(int colNDX = 0; colNDX < array[rowNDX].length; colNDX++)
   {
        StringBuffer tempFieldSB;
    if(array[rowNDX][colNDX] == null)
     tempFieldSB = new StringBuffer("<NULL>");
    else
     tempFieldSB = new StringBuffer(array[rowNDX][colNDX].toString());
        String indexString = "";
        if(showIndicies)
        {
     indexString = new String(" [" + rowNDX + "," + colNDX + "]");
    }
    int totalFieldLength = tempFieldSB.length() + indexString.length();
    for(int exSpaceNDX = colMaxLengths[colNDX] - totalFieldLength; exSpaceNDX > 0; exSpaceNDX--)
    {
     tempFieldSB.append(" ");
        }
    sb.append(tempFieldSB + indexString);
        sb.append("|");
   }
   sb.append("\n");
  }
  sb.append(rowSep.replace('+', '-'));
  return sb.toString();
 }
/**************************************************************/
public static String centerL(String datum, int retStrLength)
 {
  if(datum.length() > retStrLength)
  {
//System.out.println("alexUtils.centerL(...) Error:\ndatum.Length() > retStrLength)");
   return "";
  }
  StringBuffer sb = new StringBuffer();
  datum = datum.trim();
  int exSpaceLength = retStrLength - datum.length();
  int leadingSpaceLength = (exSpaceLength % 2 == 0 ? exSpaceLength/2 : (int)java.lang.Math.floor(exSpaceLength/2));
  int trailingSpaceLength = (exSpaceLength % 2 == 0 ? exSpaceLength/2 : (int)java.lang.Math.floor(exSpaceLength/2) + 1);
  while(leadingSpaceLength > 0)
  {
   sb.append(" ");
   leadingSpaceLength--;
  }
  sb.append(datum);
  while(trailingSpaceLength > 0)
  {
   sb.append(" ");
   trailingSpaceLength--;
  }
  return sb.toString();
 }
/***********************************************************************/

 public static String hashMapToString(java.util.HashMap hm)
 {
System.out.println("hmtoSTring, hm =? null?" + (hm == null));
System.out.println("hm.size() = " + hm.size());
  StringBuffer sb = new StringBuffer();
  java.util.Set keys = hm.keySet();
System.out.println("keys =? null?" + (keys == null));
System.out.println("keys.size() = " + keys.size());
  java.util.Iterator it = keys.iterator();
System.out.println("it =? null?" + (it == null));
  while(it.hasNext())
  {
   String nextKey = (String)it.next();
   sb.append(nextKey + ": " + hm.get(nextKey) + "\n");
  }

  //do
  //{
   //nextKey = (String)it.next();
//System.out.println("nextKey: " + nextKey);
   //sb.append(nextKey + ": " + hm.get(nextKey) + "\n");
  //}
  //while(it.hasNext());

  return sb.toString();
 }

/***********************************************************************/

public static java.util.ArrayList rsToStrArrayList(java.sql.ResultSet rs)
        throws java.sql.SQLException
 {
  java.sql.ResultSetMetaData rsmd = rs.getMetaData();
  java.util.ArrayList retArray = new java.util.ArrayList();
  while(rs.next())
  {
   String[] currRow = new String[rsmd.getColumnCount()];
   for(int colNDX = 1; colNDX <= rsmd.getColumnCount(); colNDX++)
   {
    currRow[colNDX - 1] = rs.getString(colNDX).trim();
   }
   retArray.add(currRow);
  }
  return retArray;
 }

/***********************************************************************/
 public static String[][] arrayListToStrArray(java.util.ArrayList al)
 {
  String[][] strArray = new String[al.size()][];
  for(int rowNDX = 0; rowNDX < al.size(); rowNDX++)
  {
   strArray[rowNDX] = (String[])(al.get(rowNDX));
  }
  return strArray;
 }
/***********************************************************************/
 public static String rsToString(java.sql.ResultSet rs)
        throws java.sql.SQLException
 {
  return arrayToString(arrayListToStrArray(rsToStrArrayList(rs)));
 }

/**************************************************************/

 public static org.w3c.dom.Node getDocumentNode(String filePath)
        throws javax.xml.parsers.ParserConfigurationException, org.xml.sax.SAXException, java.io.IOException
 {
   javax.xml.parsers.DocumentBuilderFactory factory = javax.xml.parsers.DocumentBuilderFactory.newInstance();
   javax.xml.parsers.DocumentBuilder builder = factory.newDocumentBuilder();
   org.w3c.dom.Document document = builder.parse(new java.io.File(filePath));
   return document;
 }

/**************************************************************/
 public static org.w3c.dom.Node getDocumentNode(java.io.InputStream is)
        throws javax.xml.parsers.ParserConfigurationException, org.xml.sax.SAXException, java.io.IOException
 {
System.out.println("getDocumentNode("+is+")");
   javax.xml.parsers.DocumentBuilderFactory factory = javax.xml.parsers.DocumentBuilderFactory.newInstance();
   javax.xml.parsers.DocumentBuilder builder = factory.newDocumentBuilder();
   org.w3c.dom.Document document = builder.parse(is);
   return document;
 }

/**************************************************************/
public static org.w3c.dom.Node getNode(String nodeName, java.io.InputStream is)
        throws javax.xml.parsers.ParserConfigurationException, org.xml.sax.SAXException, java.io.IOException
 {
  return getNode(nodeName, getDocumentNode(is));
 }
/**************************************************************/
 public static org.w3c.dom.Node getNode(String nodeName, org.w3c.dom.Node containingNode)
  {
   if(containingNode.getNodeName().equals(nodeName))
    return containingNode;
   else
   {
    if(containingNode.hasChildNodes())
    {
     org.w3c.dom.NodeList nl = containingNode.getChildNodes();
     for(int i = 0; i < nl.getLength(); i++)
     {
      if(nl.item(i).getNodeType() != org.w3c.dom.Node.TEXT_NODE)
       return getNode(nodeName, nl.item(i));
         }
    }
    else
    {
     return null;
    }
   }
   return null;
  }
/**************************************************************/
 public static String getStackTraceAsString(Exception e)
 {
  StackTraceElement[] stes = e.getStackTrace();
  StringBuffer sb = new StringBuffer();
  for(int i = 0; i < stes.length; i++)
  {
   sb.append(stes[i].toString() + "\n");
  }
  return sb.toString();
 }
/**************************************************************/
 public static String replaceFileSuffix(String origPath, String newSuffix)
 {
  return(origPath.substring(0, origPath.lastIndexOf('.')) + newSuffix);
 }

}

Posted in Repository, Software | Comments (0)

JAVA dbWrapper/dbHandler

March 8th, 2011
by alexw

This is a set of classes I wrote when I was having to code for both SQL Server and Postgres quite often. It abstracts common db functionality (like connecting, querying, etc) so you don’t have to remember Microsoft’s idiosyncrasies and arbitrary, proprietary standards.
It’s also handy that it’s written in java so it can be used cross-platform (I used it all the time on Win2000 and FC3). The only problem with it…it doesn’t support MySQL which is what I use pretty much exclusively now.
I wrote it in ’04, I have no idea if it even compiles, much less runs. Maybe I’ll come back to it someday.
dbWrapper.tar.gz
dbHandler.tar.gz

Posted in Uncategorized | Comments (0)

Direct Neural Interface Is Coming!

March 6th, 2011
by alexw

Check out this guy who, among other things, hooked up sonar to the nerves in his arm.

My Body, My Laboratory

Posted in Uncategorized | Comments (0)

PHP Sortable Table

March 4th, 2011
by alexw

This is a set of classes I wrote in ’04 to present a table on a page that can be sorted by its columns.  Kinda like your file manager with the “Name,” “Size,” Type” headings.  There’s probably a better way to do this now, but it was a good programming exercise when I was getting into PHP.

sortableTableExample.php

<HTML>
 <HEAD>
 <?
  require_once("sortableTableClass.php");

  $Cu = array("commonName"=>"Copper", "density"=>"8.9", "conductivity"=>"58.5", "resistance"=>"100");
  $Al = array("commonName"=>"Aluminum", "density"=>"2.7", "conductivity"=>"36", "resistance"=>"62");
  $Au = array("commonName"=>"Gold", "density"=>"19.3", "conductivity"=>"45.5", "resistance"=>"78");

  $data = array($Cu, $Al, $Au);
  $header = array("Metal", "Density", "Conductivity", "Resistance");
  $mySortableTable = new sortableTable($data, $header);

 ?>
 </HEAD>
 <BODY>
  <?
      array_invert(array_invert($data));

   $mySortableTable->writeTable("mySortableTable");
  ?>
 </BODY>
</HTML>

globals.php

<?
 require_once("functions.php");
 $defElementDelim = ";";
 $defRowDelim = "|";
?>

functions.php

<?
/*******************************************************/
 function stringToArray($str, $elementDelim = "NULL", $rowDelim = "NULL")
 {
  global $defElementDelim, $defRowDelim;
  if($elementDelim == "NULL")
   $elementDelim = $defElementDelim;

  if($rowDelim == "NULL")
   $rowDelim = $defRowDelim;

  $retArr = array();

  if((strpos($str, $rowDelim) == FALSE)) //there are NOT rowDelim characters in the string
  {
   if(strpos($str, $elementDelim) == FALSE)  //there are NOT rowDelim or elementDelim characters in the string
   {
    return array($str);
   }
   else //there ARE elementDelim characters in the string
   {
    $retArr = explode($elementDelim, $str);
   }
  }
  else //there ARE rowDelim characters in the string
  {
   $rowArr = explode($rowDelim, $str);//get an array of strings, each representing a row
   foreach($rowArr as $row)
   {
    $retArr[] = explode($elementDelim, $row);
   }
  }

  return $retArr;
 }
/*******************************************************/
 function arrayToString($arr, $elementDelim = "NULL", $rowDelim = "NULL")
 {
  global $defElementDelim, $defRowDelim;
  if($elementDelim == "NULL")
   $elementDelim = $defElementDelim;

  if($rowDelim == "NULL")
   $rowDelim = $defRowDelim;

  $retStr = "";
  $tempRowDelim = "";

  foreach($arr as $dim)
  {
   if(is_array($dim))
   {
    //$retStr .= $tempRowDelim . implode($elementDelim, $dim);

   }
   else
   {
    return implode($elementDelim, $arr);
   }
   $tempRowDelim = $rowDelim;
  }
  return $retStr;
 }
/********************************************************/
 function alertPostVars()
 {
  print("<SCRIPT>");
  foreach($_POST as $postVar)
  {
   print("alert('" . key($_POST) . " : " . $postVar . "');");
  }
  print("</SCRIPT>");
 }
/********************************************************/

 function array_invert($arr)
  {
   $tempArray = array();

   $rowKeys = array_keys($arr);
   for($i = 0; $i < count($rowKeys); $i++)
   {
    $rowKey = $rowKeys[$i];
    $row = $arr[$rowKey];
    $colKeys = array_keys($row);
    for($j = 0; $j < count($colKeys); $j++)
    {
     $colKey = $colKeys[$j];
     $tempArray[$colKey][$rowKey] = $arr[$rowKey][$colKey];
    }
   }
   return $tempArray;
  }
/********************************************************/

  function propagatePostVars()
  {
   $retVal = "";
   foreach($_POST as $varName=>$varValue)
    $retVal .= "<INPUT TYPE=\"hidden\" NAME=\"$varName\" VALUE=\"$varValue\"/>";
   return $retVal;
  }
/********************************************************/

  function propagateGetVars()
  {
   $retVal = "?";
   $delim = "";
   foreach($_GET as $varName=>$varValue)
   {
    $retVal .= "$varName=$varValue" . $delim;
    $delim = "&";
   }
   return $retVal;
  }
?>

tableClass.php

<?
 require_once("indentationClass.php");
 class table
 {
  //a 2d array of the data in the table
  var $data;

  //a 1d array of the header values
  var $header;

  //an indentation object to keep
  //everything aligned
  var $indent;

  //a 1d array of the formats in
  //which to present the data
  /* eg:
        if we had a $data variable with 3 columns, firstName,
        lastName, and webPage, we could make what would
        normally just be a string for the web page into
        a link with the following format array:
    $formats = array(0, 0, "<A HREF=<element/>><element/></A>");
    which will replace the <element/> tag with whatever data
    is in that table cell
   */

  var $formats;
  var $prepFuncs;

  function table($data, $header)
  {
   $this->indent = new indentation();
   $this->setData($data);
   $this->setHeader($header);
  }

  function setFormats($formats)
  {
   $this->formats = $formats;
  }

  function setData($data)
  {
   $this->data = $data;
  }
  function setHeader($header)
  {
   $this->header = $header;
  }

  function setPrepFuncs($prepFuncs)
  {
   $this->prepFuncs = $prepFuncs;
  }

  function buildHeader()
  {
   $html .= $this->indent->toString() . "<THEAD>\n";
   $this->indent->in();
   $html .= $this->indent->toString() . "<TR>\n";
   $this->indent->in();
   foreach($this->header as $element)
   {
    $html .= $this->indent->toString() . "<TH>" . $element . "</TH>\n";
   }
   $this->indent->out();
   $html .= $this->indent->toString() . "</TR>\n";
   $this->indent->out();
   $html .= $this->indent->toString() . "</THEAD>\n";
   return $html;
  }

  function toHTML()
  {
   $html = "";

   $html .= $this->indent->toString() . "<TABLE BORDER=1>\n";
   $this->indent->in();

   if($this->header != null)
    $html .= $this->buildHeader($this->indent);

   $html .= $this->indent->toString() . "<TBODY>\n";
   $this->indent->in();

   $rowKeys = array_keys($this->data);
   for($rowNDX = 0; $rowNDX < count($rowKeys); $rowNDX++)
   {
    $html .= $this->indent->toString() . "<TR>\n";
    $this->indent->in();
    $colKeys = array_keys($this->data[$rowKeys[$rowNDX]]);
    for($colNDX = 0; $colNDX < count($colKeys); $colNDX++)
    {
     $element = $this->data[$rowKeys[$rowNDX]][$colKeys[$colNDX]];
     $html .= $this->indent->toString() ."<TD>";

     //check to see if there is a prepFunc (preperatory function)
     //with associative key of $colKeys[$colNDX]
     if(!isset($this->prepFuncs[$colKeys[$colNDX]]))
     {
      //if not just print the element
      $html .= $element;
     }
     else
     {
      // run the function on the string
      //assumes the function has signature:
      //functionName($data, $columnName, $columnNumber, $theWholeRow);
      $tempElement = $this->prepFuncs[$colKeys[$colNDX]]($element,$colKeys[$colNDX],$colNDX,$this->data[$rowKeys[$rowNDX]]);
      $html .= $tempElement;
     }
/*
     //check to see if there is a format string
     //with associative key of $colKeys[$colNDX]
     if(!isset($this->formats[$colKeys[$colNDX]])")
     {
      //if not just print the element
      $html .= $element;
     }
     }
     else
     {
     $format = $this->formats[$colKeys[$colNDX]];
      //but if there is, replace the
      //various tags
      //use arrays for the simple replacements
      $patterns = array("<data/>", "<columnName/>", "<columnNum/>", "<rowNum/>");
      $replacements = array($element, $colKeys[$colNDX], $colNDX, $rowNDX);
      $tempElement = str_replace($patterns, $replacements, $format);

      //get the name of the column from
      //which to get the data
      $colRegex = "<column=\"(.+)\"\/>";
      ereg($colRegex, $tempElement, $colReg);
      //then replace the column tag with whatever
      //data is in the same row in whatever column
      //was referenced
      $tempElement = ereg_replace($colRegex, $this->data[$rowKeys[$rowNDX]][$colReg[1]], $tempElement);
      $html .= $tempElement;
     }
*/

     $html .= "</TD>\n";
    }
    $this->indent->out();
    $html .= $this->indent->toString() . "</TR>\n";
   }

   $this->indent->out();
   $html .= $this->indent->toString() . "</TBODY>\n";
   $this->indent->out();
   $html .= $this->indent->toString() . "</TABLE>\n";
   return $html;
  }
 }
?>

sortableTableClass.php

<?
 require_once("functions.php");
 require_once("tableClass.php");

 class sortableTable
        extends table
 {
  //the name of the column by which to sort
  var $sortColumn;

  //the direction in which to sort ("SORT_ASC" or "SORT_DESC")
  var $sortDirection;

  //the comparison method with which to sort
  var $sortMethod;

  /************************************
   *
   *    The Constructor
   *
   ************************************/
  function sortableTable($data, $header)
  {
   //call the table constructor
   parent::table($data, $header);
   if($_POST['data'] != null)
   {
    $this->setData(unserialize(stripslashes($_POST['data'])));
   }

   if($_POST['header'] != null)
   {
    $this->setHeader(unserialize(stripslashes($_POST['header'])));
   }

   if($_POST['sortOrder'] != null)
   {
    $this->setSortOrder($_POST['sortOrder']);
   }
   else
   {
    $this->setSortOrder("title");
   }
   if($_POST['sortDirection'] != null)
   {
    $this->setSortDirection($_POST['sortDirection']);
   }
   else
   {
    $this->setSortDirection("SORT_ASC");
   }
  }
  function setSortOrder($newSortOrder)
  {
   $this->sortOrder = $newSortOrder;
  }

  function setSortDirection($newSortDirection)
  {
   $this->sortDirection = $newSortDirection;
  }

  function buildHeader($indent)
  {
   $html = $indent->toString() . "<THEAD>\n";
   $indent->in();
   $html .= $indent->toString() . "<TR>\n";
   $indent->in();
   //go through each of the header fields
   foreach($this->header as $element)
   {
    //and write the link to the javascript
    $html .= $indent->toString() . "<TH>";
    $html .= "<A HREF=\"javascript:resort('". $element ."', '". ($this->sortDirection == "SORT_ASC" ? "SORT_DESC" : "SORT_ASC") ."');\">";
    //then write the actual element
    $html .= $element;

    //if this column is the one by which it is sorted...
    if($element == $this->sortOrder)
    {
     //if it's sorted ascending, put a carat (^)
     if($this->sortDirection == "SORT_ASC")
      $html .= "&nbsp;(^)";
     //if it's sorted descending, put a V
     elseif($this->sortDirection == "SORT_DESC")
      $html .= "&nbsp;(V)";
    }
    $html .= "</A></TH>\n";
   }
   $indent->out();
   $html .= $indent->toString() . "</TR>\n";
   $indent->out();
   $html .= $indent->toString() . "</THEAD>\n";
   return $html;
  }
  function toHTML($indent=NULL)
  {
   $this->resort();
   if($indent == NULL)
    $indent = new indentation();
   return parent::toHTML($indent);
  }

  function resort()
  {
   //invert the array because it will be
   //indexed by the rows, not the columns,
   //but it's the columns by which we need
   //to sort
   $invertedData = array_invert($this->data);

   $sortFields = array();

   //get the keys of $invertedData
   //which we'll need later to build the
   //array_multisort statement
   $dataKeys = array_keys($invertedData);

   //go through the headers
   for($i = 0; $i < count($this->header); $i++)
   {
    //if this is the column by which we want to sort...
    if($this->header[$i] == $this->sortOrder)
    {
     //put this column at the begining of $sortFields
     array_splice($sortFields, 0, 0, "\$invertedData['" . $dataKeys[$i] . "']");
     //added this 'cause it put capitol 'Z' before lower case 'a' otherwise
     array_splice($sortFields, 1, 0, SORT_STRING);
     //and add its sort direction
     array_splice($sortFields, 2, 0, $this->sortDirection);
    }
    else
    {
     $sortFields[] = "\$invertedData['" . $dataKeys[$i] . "']";
     //added this 'cause it put capitol 'Z' before lower case 'a' otherwise
     $sortFields[] = SORT_STRING;
     $sortFields[] = SORT_ASC;
    }
   }
   $sortStmt = "array_multisort(";
   $sortStmt .= implode(",", $sortFields);
   $sortStmt .= ");";
//print("sortStmt: ". $sortStmt);
   eval($sortStmt);
   $this->setData(array_invert($invertedData));
  }

  function writeTable($formName=NULL)
  {
   if($formName == NULL)
    $formName = "sortableTableForm";
   $this->writeJS($formName);
   print("<FORM NAME='" . $formName . "' ACTION='" . $_SERVER['PHP_SELF'] . propagateGetVars() . "' METHOD=\"POST\">" . propagatePostVars() . $this->toHTML($this->indent) . "</FORM>");
  }

  function writeJS($formName)
  {
   print("
    <SCRIPT>
        function resort(element, direction)
        {
         var data = document.createElement(\"input\");
         data.type = \"hidden\";
         data.name = \"data\";
         data.value = '" . addslashes(serialize($this->data)) . "';
         document.forms['". $formName ."'].appendChild(data);

         var header = document.createElement(\"input\");
         header.type = \"hidden\";
         header.name = \"header\";
         header.value = '" . addslashes(serialize($this->header)) . "';

         document.forms['" . $formName . "'].appendChild(header);

         var sortOrder = document.createElement(\"input\");
         sortOrder.type = \"hidden\";
         sortOrder.name = \"sortOrder\";
         sortOrder.value = element;
         document.forms['" . $formName . "'].appendChild(sortOrder);

         var sortDirection = document.createElement(\"input\");
         sortDirection.type = \"hidden\";
         sortDirection.name = \"sortDirection\";
         if(sortOrder.value == element)
         {
          if(direction == \"SORT_DESC\")
           sortDirection.value = \"SORT_ASC\";
          else
           sortDirection.value = \"SORT_DESC\";
         }
         sortDirection.value = direction;
         document.forms['" . $formName . "'].appendChild(sortDirection);

         document.forms['" . $formName . "'].submit();
        }
        </SCRIPT>
   ");
  }

 }
?>

It also uses indentationClass.php

Posted in Repository, Software | Comments (0)

PHP Indentation Class

March 1st, 2011
by alexw

This is a php class I wrote to help keep dynamically generated HTML aligned.  Very simple, very easy to use, of limited value.

It has only 4 functions:

indentation($initialDepth = 0, $indentChar = ‘     ‘) : the constructor, I’m assuming the arguments are self-explanatory. Note, however, that you can initialise it with another depth, allowing you to keep it aligned “outside” code. You can also pass an indent object down/up a stack and keep indentation in dynamic html clean across multiple functions/blocks. There are examples of both of these in the PHP Sortable Table.

in($depth = 1): increase the indentation by $depth many $indentChar’s (note that $indentChar can also be a string)

out($depth = 1): opposite of in

toString(): returns a string of $indentChar’s equal to the number of times you’ve called in(…) minus the number of times you’ve called out(…)

If you’re careful with your ins and outs, you can dynamically generate HTML which you can still read in the source view of a browser.

The code is below:

<?
 class indentation
 {
  var $currDepth;
  var $indentChar;

  function indentation($initialDepth = 0, $indentChar = '       ')
  {
   $this->currDepth = $initialDepth;
   $this->indentChar = $indentChar;
  }

  function in($depth = 1)
  {
   $this->currDepth += $depth;
  }

  function out($depth = 1)
  {
   $this->currDepth -= $depth;
  }

  function toString()
  {
   $indent = "";
   for($i = 0; $i < $this->currDepth; $i++)
    $indent .= $this->indentChar;
   return $indent;
  }
 }
?>

Posted in Repository, Software | Comments (0)

Searching for a good CAD program for Ubuntu

March 1st, 2011
by alexw

So I used to use AutoCAD 2006 and I suppose I could just get the new version, but I’d really like to use something open source.

I’ve tried Wings3D , which is great except that you can’t really make holes in things which is kind of important to engineering.

I just downloaded PyCAD, so we’ll see how that works.

Also, neither of the above will read DWG files, and the only thing I’ve found that will is Lx-Viewer.  But it needs the OpenDWG libraries which I can’t find.

Oh, and tell me how it’s ok for the precompiled version to come with those libraries, but not source…?  Did I mention I hate IP law.

Posted in Software | Comments (0)