Quick and Easy FTP Proxy using SSH

I’ve been having trouble connection to a few of my clients FTP servers while I’ve been freelancing in China. So I looked around for a simple way to proxy my FTP connections. If you have a linux/mac server you can proxy through it. I used my Free Amazon EC2 Server.

All you need to do is run this on your local box.

 ssh -D 9999 ##HOSTNAME##

Then in ftp client instruct it to use a SOCK5 server

It’s that easy!

Btw, you can do this on windows almost as easy, you just need to use Putty for the ssh command part. Checkout this nice blog post from Chris Swan for information about using Putty.



Simple FXG Path Viewer

<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
			import mx.graphics.SolidColor;

			import spark.primitives.Path;

			public var color:uint = 0xFF0000;
			public var path:Path;

			protected function updatePath(changeColor:Boolean=false):void

				path = new Path();
				path.percentWidth = path.percentHeight = sizeCheck.selected ? Number.NaN : 100;
				path.data = dataTextArea.text;
				path.fill=new SolidColor(color);


	<s:VGroup horizontalAlign="right" bottom="10" left="10" top="10" right="10">
		<s:Group id="pathGroup" width="100%" height="100%" click="updatePath(true)" />
		<s:CheckBox label="Actual Size" selected="true" click="updatePath()" id="sizeCheck" />
		<s:TextArea height="100" id="dataTextArea" change="updatePath()" width="100%"/>

Offset Bézier Curves

Perfect Solution

Short answer it’s impossible to create a perfect offset curve.

The curve at a fixed offset from a given Bézier curve, often called an offset curve (lying “parallel” to the original curve, like the offset between rails in a railroad track), cannot be exactly formed by a Bézier curve (except in some trivial cases). However, there are heuristic methods that usually give an adequate approximation for practical purposes.


Imperfect Solution

So here is a heuristic method. Convert the Curve to a poly line spline. Then merge/clip the expanded lines.

  1. Subdivide the Curve into Line Segments
  2. Offset Line Segments
  3. Merge/Clip Intersections

Step #1: Subdivide the Curve into Line Segments

To convert the curve to line segments we use De Casteljau’s algorithm.

public function subDivide( time:Number ):Vector.<CubicBezierCurve>
	//Outside Guide Lines
	var outerA:StraightLine = new StraightLine( pointA, controlPointA );
	var outerBridge:StraightLine = new StraightLine( controlPointA, controlPointB );
	var outerB:StraightLine = new StraightLine( controlPointB, pointB );

	//Inner Guide Lines
	var innerA:StraightLine = new StraightLine( outerA.lerp( time ), outerBridge.lerp( time ));
	var innerB:StraightLine = new StraightLine( outerBridge.lerp( time ), outerB.lerp( time ));

	//Point at time
	var newPoint:Point = new StraightLine( innerA.lerp( time ), innerB.lerp( time )).lerp( time );

	//Return Vector
	var newCurves:Vector.<CubicBezierCurve> = new Vector.<CubicBezierCurve>();

	//Left Curve
	var leftCurve:CubicBezierCurve = new CubicBezierCurve();
	leftCurve.pointA = pointA;
	leftCurve.controlPointA = outerA.lerp( time );
	leftCurve.controlPointB = innerA.lerp( time );
	leftCurve.pointB = newPoint;
	newCurves.push( leftCurve );

	//Right Curve
	var rightCurve:CubicBezierCurve = new CubicBezierCurve();
	rightCurve.pointA = newPoint;
	rightCurve.controlPointA = innerB.lerp( time );
	rightCurve.controlPointB = outerB.lerp( time );
	rightCurve.pointB = pointB;
	newCurves.push( rightCurve );

	//Return Vector containing new curves.
	return newCurves;

When your flattening a curve some curves need more subdivision than others. You can check the flatness level to determine if the curve needs to be sub divided again and again. This will help optimize your algorithm for offsetting, by breaking the curve into as few of lines as visually required.

Here is a cool method to find flatness of a line.

public function get flatness():Number
	var ux:Number = Math.pow( 3 * controlPointA.x - 2 * pointA.x - pointB.x, 2 );
	var uy:Number = Math.pow( 3 * controlPointA.y - 2 * pointA.y - pointB.y, 2 );
	var vx:Number = Math.pow( 3 * controlPointB.x - 2 * pointB.x - pointA.x, 2 );
	var vy:Number = Math.pow( 3 * controlPointB.y - 2 * pointB.y - pointA.y, 2 );

	if( ux < vx )
		ux = vx;

	if( uy < vy )
		uy = vy;

	return ux + uy;

This is converted from the great article about curve flattening.

So now we use these function to subdivide the curve. Here are sample results. This is when using a tolerance of <= 0.15

Original Curve

Subdivided Line Segments (16 lines)

Original Curve

Subdivided Line Segments (26 lines)

Step #2 Offset Line Segments

Next we create parallel lines for each of the lines in our line segment spline.

Offsetting lines is easy and mathematically supported 😉 Here is a sample function.

public function createParrallelLine( difference:Number ):StraightLine {
	var perp_x:Number = -rise
	var perp_y:Number = run;
	var len:Number = Math.sqrt(( perp_x * perp_x ) + ( perp_y * perp_y ));

	perp_x = ( perp_x / len ) * difference;
	perp_y = ( perp_y / len ) * difference;

	var parrallelLine:StraightLine = new StraightLine( new Point( pointA.x - perp_x, pointA.y - perp_y ), new Point( pointB.x - perp_x, pointB.y - perp_y ));

	return parrallelLine;

Basically it creates use perpendicular slopes and linear interpolation to create perfectly positioned parallel line. It will also always stay on the correct edge of the curve, as long as the direction of all the lines are the same. Clockwise or Counter-Clockwise.

Offset of 1px

Step #3: Merge/Clip

The next step we connect the expanded curve lines, and we determine if the best course of action is to create a new line between them, or if we should remove/cut a existing line.

Check for intersections if your lines intersect, then clip. else create new line between, or if your fancy, you can use another curve, and use the intersection point as the control point.


I highlighted the intersections with blue. You can see how they mesh nicely.

Final Results

Here is some final results with a 2px offset curve. Original is red, offset is blue.

Related Documents

Flash Builder 4 issues with using "Premium" projects in "Standard" version.

If you try and compile a “Premium” project and it’s complaining about “function Assert not found”.

Just add

      <libraryPathEntry kind="1" linkType="1" path="${FLEXUNIT_LIB_LOCATION}/version4libs/Common/"/>
      <libraryPathEntry kind="1" linkType="1" path="${FLEXUNIT_LIB_LOCATION}/version4libs/FlexProject/"/>
      <libraryPathEntry kind="1" linkType="1" path="${FLEXUNIT_LOCALE_LOCATION}/version4locale/"/>

into your projects .actionScriptProperties file. And it will build!

How to make a small Gentoo distro

First off, Gentoo is awesome for making small or custom linux distributions. It allows you (with emerge) to build little package tarballs and make your own image.

Now. to get started add this to your gentoo make.conf


That will tell portage to create the tarball packages every time you emerge anything.

This next part is up for debate. The bare minimal packages in my opinion are bash, baselayout, busybox, openrc. So lets emerge them

emerge bash baselayout busybox openrc

After this is done. And it can take a while. You should have a nice directory struct in /usr/portage/packages. Look for the 4 that you just built. After you got them. create a directory to load build your minimal gentoo distro in.

mkdir -p /build/minimal

The -p just tells it to make all the parent directories too. so it will make /build and then make /build/minimal

now copy those tarballs into this path like so

cp sys-apps/baselayout-1.12.13.tbz2 /build/minimal/
cp sys-apps/busybox-1.16.0.tbz2 /build/minimal/
cp sys-apps/openrc-0.6.1-r1.tbz2 /build/minimal/
cp app-shells/bash-4.0_p37.tbz2 /build/minimal/

Untar them.

cd /build/minimal
tar -xjvf *

The next step you need to figure out what libraries bash needs to run. do this.

ldd bin/bash

Should give you something like this.

        linux-gate.so.1 =>  (0xb78b8000)
        libncurses.so.5 => /lib/libncurses.so.5 (0xb786a000)
        libdl.so.2 => /lib/libdl.so.2 (0xb7866000)
        libc.so.6 => /lib/libc.so.6 (0xb771e000)
        /lib/ld-linux.so.2 (0xb78b9000)

Those are the libs you will need. Go ahead and copy them over.

cp /lib/libncurses.so.5 /build/minimal/lib/
cp /lib/libdl.so.2 /build/minimal/lib/
cp /lib/libc.so.6 /build/minimal/lib/
cp /lib/ld-linux.so.2 /build/minimal/lib/

And now you can chroot inside your minimal enviroment.

chroot /build/minimal/ /bin/bash --login