My technology musings

On demand objects

While writing a REST API it dawned on me I was going to need multiple database connections to multiple servers (a cluster isn’t really viable at this time…); the generic way for database objects is to use included files with the database object instantiated… well this from my view is additional overhead / processing time when you may not even use that database connection.

What i’ve devised is a basic singleton class which builds a object list of the objects to be instantiated BUT only a blueprint of the object so it doesn’t instantiate on load and ONLY instantiates when required.

It’s made up of two objects, one is a simple wrapper for the object to be created, the other, the main driver for doing so.

The wrapper is extremely basic, one constructor, one getter:

class demandObject
{
   private $obj;
   private $params;
   private $funcName;
 
   function __construct($obj, $params, $funcName = false)
   {
      $this->name = (string) $obj;
 
      if($params === false)
         $params = array();
 
      $this->params = $params;
 
      if($funcName === true)
         $funcName = 'getInstance';
 
      $this->funcName = $funcName;
   }
 
   public function __get($var)
   {
      if(isset($this->$var))
         return $this->$var;
   }
}

Pretty self explanatory… the driver is a little more indepth:

class ondemand
{  
  public static $instance;
 
  private $pre = array();
  private $post = array();
 
  // Could have caching initiated here?
  function __construct()
  {
    self::$instance = $this;
  } 
 
  public static function getInstance()
  {
    if(!isset(self::$instance))
      new self;
 
    return self::$instance;
  }
 
  public function __get($ident)
  {
    return $this->__initObject($this->pre[$ident]);
  }
 
  public function __set($ident, demandObject $obj)
  {
    $this->pre[$ident] = $obj;
  }
 
  private function __initObject(demandObject $obj)
  {
    if(isset($this->post[$obj->name]))
      return $this->post[$obj->name];
 
    if($obj->funcName === false)
    {
       $ro = new ReflectionClass($obj->name);
       $o = $ro->newInstanceArgs($obj->params);
    }
    else
    {
       $o = call_user_func_array(array($obj->name, $obj->funcName), $obj->params);
    }
 
    $this->post[$obj->name] = $o;
 
    return $o;   
  }
}

What we have here is a singleton pattern being used to maintain a single array of objects to be instantiated, depending if this object has a primary function to call first, or whether it just calls the object’s constructor, we instantiate the object in a getter using this logic.

I’m not going to really go into much detail, here’s an example of how it would be used:

// example object
class x
{
   private $myX;
 
   function __construct($x)
   {
      $this->myX = $x;
   }
 
   public function getX()
   {
      return $this->myX;
   }
}
 
$demand = ondemand::getInstance();
$demand->myX = new demandObject('x', array('Hello World'));
 
/* Script that doesn't require the object x... */
 
// aha, now we need to use it!
echo $demand->myX->getX(), "\n";

So as you can see, x isn’t instantiated unless needed, obviously not really required for an object of such simplicity as x, but it serves as an example.

If the object also used a singleton pattern, and its method was called ‘getInstance’ you can simply tell provide it a boolean of true and it’ll use that rather than the default constructor:

$demand->myY = new demandObject('y', array('Hello World'), true);

It can also be provided as a string to the method name. Simple but elegant.

No comments

mrsync – rsync queuing script

I have an upcoming task to transfer a LOT of files from one server to another, I wrote this to try and speed up the transfer process at the sake of IO load.

While writing this script a single rsync process has been running, it would take on estimate 10 days to complete, this is even with the latest rsync which has had huge improvements!

It’s still a little rough around the edges, but for my use it should cope, later today I’ll add in support for it to only start a process if the the same rsync isn’t running, if it is, log it as a running job and have it handle the same way as any other running job.

For help on using it, run it without any arguments or with ‘–help’ flag.

#!/bin/bash
#!/bin/bash
#
# @author Ed Cradock
# @date 10 February 2010
#
# Mrsync - Execute multiple rsync's with queue system
#
 
# Flags
NEXTARG=0
ERROR=0
GOTO_DAEMON_MODE=0
 
# User set options
FILE_LIST=0
LOG_DIR="./mrsync-logs"
OP_DIR="$HOME/.mrsync"
JOBS=4
IS_SSH=""
 
# Counters
RUNNING_RSYNC=0
TOTAL_JOB_COUNT=0
CURRENT_JOB=0
 
# Temporary file names
TMP_RUNNING_JOBS=".mrsync-running-jobs"
TMP_COMPLETED=".mrsync-completed"
 
function PROCESS_BY_ID_EXISTS
{
   if [[ $1 != [0-9]* ]]; then
      return 0
   fi
 
   if [ $(ps --pid $1 --no-header | wc -l) -gt 0 ]; then
      return 1
   else
      return 0
   fi
}
 
# Some what flimsy... 
# but let's ensure there's no rsync running doing the same task
function PROCESS_BY_ARG_EXISTS
{
   return $(ps aux --no-header | awk '{ print $11 }' | grep -E  "^rsync" | grep $1 | wc -l)
}
 
function PROCESS_COMPLETED
{
   while read complete; do
      COMPLETE_PID=${complete%% *}
      COMPLETE_PS=${complete#* }
 
      if [ "$1" == "$COMPLETE_PID" -a "$2" == "$COMPLETE_PS" ]; then
         return 1
      fi
   done < $TMP_COMPLETED
 
   return 0
}
 
function FLUSH_TEMPORARY_FILES
{
   :> $TMP_RUNNING_JOBS
   :> $TMP_COMPLETED
}
 
function DO_JOB
{
   CURRENT_JOB=$(expr $CURRENT_JOB + 1)
   RSYNC="rsync -avz $IS_SSH $1 $2"
   RUNNING_RSYNC=$(expr $RUNNING_RSYNC + 1)
   CLEAN_NAME=$(echo $RSYNC | sed -r 's/[^a-zA-Z0-9]+/-/g')
 
   ($RSYNC &> $LOG_DIR/$CLEAN_NAME) &
 
   JOB_PID=$!
   echo "$JOB_PID $RSYNC" >> $TMP_RUNNING_JOBS
   echo "[Executing] $RSYNC"
}
 
function DAEMON_MODE
{
   JOBS_COMPLETE=0
 
   while [ 1 ]; do
      while read entry; do
         CIT=$(expr $CIT + 1)
         ENTRY_PID=${entry%% *}
         ENTRY_PS=${entry#* }
 
         PROCESS_BY_ID_EXISTS $ENTRY_PID
 
         if [ $? == 0 ]; then
            PROCESS_COMPLETED $ENTRY_PID "$ENTRY_PS"
 
            if [ $? == 0 ]; then
               echo "[Completed] $ENTRY_PS"
               echo "$ENTRY_PID $ENTRY_PS" >> $TMP_COMPLETED
 
               if [ $TOTAL_JOB_COUNT -eq $CURRENT_JOB -a $CIT -eq $TOTAL_JOB_COUNT ]; then
                  JOBS_COMPLETE=1
                  break
               fi
 
               RUNNING_RSYNC=$(expr $RUNNING_RSYNC - 1)
               JOBS_REMAINING=$(expr $TOTAL_JOB_COUNT - $CURRENT_JOB)
 
               if [ $JOBS_REMAINING -gt 0 ]; then
                  i=0
                  while read line; do
                     i=$(expr $i + 1)
                     SRC=${line%% *}
                     DEST=${line#* }
 
                     if [ $i -gt $CURRENT_JOB -a $RUNNING_RSYNC -lt $JOBS ]; then
                        DO_JOB "$SRC" "$DEST"
                     fi
                  done < $FILE_LIST
               fi
            fi
         fi
 
         if [ $CIT -eq $TOTAL_JOB_COUNT ]; then
            CIT=0
         fi
      done < $TMP_RUNNING_JOBS
 
      if [ $JOBS_COMPLETE -eq 1 ]; then
         echo "All done! :)"
         exit
      fi
   done
}
 
function HELP
{
   echo -e " \033[1mmrsync - Queued rsync'ing\033[0m"
   echo " --file-list <filename> - mandatory, a file to read in the required rsyncs."
   echo " --log-dir <filename> - specify log directory [ mrsync-logs ]"
   echo " --jobs <max concurrent> - maximum jobs to execute at one time [4]"
   echo " --op-dir <filename> - specify an alternate mrsync operations directory [~/.mrsync]"
   echo " --ssh - to use ssh as transport medium"
   echo " --help - display this message"
   exit
}
 
 
# Handle user set options
for arg in $*; do
   # Handle argument values
   if [ "$NEXTARG" != 0 ]; then
 
      case $NEXTARG in
         FILE_LIST)
            if [ ! -e $arg ]; then
               echo "Error: Filename list file does not exist."
               ERROR=1
            fi
         ;;
         JOBS)
            if [[ $arg != [0-9]* ]]; then
               echo "Error: Jobs must be an integer, defaulting to $JOBS."
               ERROR=1
            fi
         ;;
         LOG_DIR)
            if [ ! -d $arg ]; then
               mkdir $arg &> /dev/null
 
               if [ ! -d $arg ]; then
                  echo "Log directory does not exist and an attempt to create it failed."
                  ERROR=1
               fi
            fi
         ;;
         OP_DIR)
            if [ ! -d $arg ]; then
               mkdir $arg &> /dev/null
 
               if [ ! -d $arg ]; then
                  echo "Log directory does not exist and an attempt to create it failed."
                  ERROR=1
               fi
            fi
         ;;
         *)
            ERROR=1
         ;;
      esac
 
      if [ $ERROR == 1 ]; then
         NEXTARG=0
         continue
      fi
 
      read $NEXTARG <<< $arg
      NEXTARG=0
   fi   
 
   if [ ${arg:0:2} == "--" ]; then
      case ${arg:2} in
         file-list)
            NEXTARG="FILE_LIST";;
 
         jobs)
            NEXTARG="JOBS";;
 
         log-dir)
            NEXTARG="LOG_DIR";;
 
         op-dir)
            NEXTARG="OP_DIR";;
 
         ssh)
            IS_SSH="-a ssh";;
 
         help)
            HELP;;
 
         *)
            echo "unknown argument $arg"
            help
         ;;
      esac       
   fi
done
 
 
if [ ! -e $FILE_LIST ]; then 
   HELP
fi
 
if [ ! -e $LOG_DIR ]; then
   mkdir $LOG_DIR &> /dev/null
 
   if [ ! -e $LOG_DIR ]; then
      echo "Failed to create log dir, please specify one with --log-dir or give permissions for mrsync to create one within this directory."
      exit
   fi
fi
 
if [ ${LOG_DIR#${LOG_DIR%?}} == "/" ]; then
   LOG_DIR=$(echo $LOG_DIR | sed 's/.$//')
fi
 
if [ ! -d $OP_DIR ]; then
   mkdir $OP_DIR &> /dev/null
 
   if [ ! -d $OP_DIR ]; then
      echo "Failed to create temporary directory, please specify one with --op-dir or give permissions for mrsync to create one at $OP_DIR."
      exit
   fi
fi
 
if [ ${OP_DIR#${OP_DIR%?}} == "/" ]; then
   OP_DIR=$(echo $OP_DIR | sed 's/.$//')
fi
 
TMP_RUNNING_JOBS="$OP_DIR/$TMP_RUNNING_JOBS"
TMP_COMPLETED="$OP_DIR/$TMP_COMPLETED"
 
FLUSH_TEMPORARY_FILES
 
while read line; do
   SRC=${line%% *}
   DEST=${line#* }
   TOTAL_JOB_COUNT=$(expr $TOTAL_JOB_COUNT + 1)
 
   PROCESS_BY_ARG_EXISTS $SRC $DEST $args
 
   if [ $? == 0 ]; then
      if [ $RUNNING_RSYNC -lt $JOBS ]; then
         DO_JOB "$SRC" "$DEST"
      else
         echo "Dropping into daemon mode"
         break
      fi
   fi
done < $FILE_LIST
 
DAEMON_MODE
No comments

Lazy way for adding new IP addresses on Debian

Today I was given the fun task of adding around 30 IP addresses to a server, well being the lazy person I am, I decided to script it… here’s what I came up with:

#!/bin/bash
##
# Add separate virtual interfaces for a list of of IP addresses
# to the debian specific /etc/network/interfaces
# @author Ed Cradock
#
##
 
NETWORK_IFS="/etc/network/interfaces";
CURRENT_IFNO=`grep "iface eth0" $NETWORK_IFS | tail -n 1 | cut -d":" -f2 | cut -d" " -f1`;
CURRENT_NETM=`grep "netmask" $NETWORK_IFS | head -n 1 | cut -d" " -f2`;
 
function addInterface
{
        CURRENT_IFNO=$(($2 + 1));
 
        echo -e "\nauto eth0:$CURRENT_IFNO" >> $1;
        echo -e "\niface eth0:$CURRENT_IFNO inet static" >> $1;
        echo -e "\taddress $3" >> $1;
        echo -e "\tnetmask $4" >> $1;
 
        # Finally bring up the interface
        ifup "eth0:$CURRENT_IFNO";
}
 
if [ $# -ne 0 ]; then
        if [ -f $1 ]; then
                for IPADDR in `cat $1`; do
                        addInterface $NETWORK_IFS $CURRENT_IFNO $IPADDR $CURRENT_NETM;
                done
        else
                for IPADDR in $*; do
                        addInterface $NETWORK_IFS $CURRENT_IFNO $IPADDR $CURRENT_NETM;
                done
        fi
else
        echo "Usage: $0 [<file with ipaddresses>|<ipaddress>, ...]";
fi

Sumarised, it takes either a file full of IP addresses (this is the technique I used) and adds the interfaces to /etc/network/interfaces, then brings the interface up; Alternatively it can accept multiple ip addresses given as arguments.

Definitely a script I’ll use in the future.

No comments

rsync woes

I have been using rsync recently to transfer a farm of files from one server  to another, I managed to make a glaring omission when reading the documentation which really left me in a rut…

Summed up, rsync … /src /destination is NOT rsync /src/ destination, by missing the trailing ‘/’ at the end of the source, rsync will copy a directory named ’src’ into  destination directory; however WITH it, it copies the files in src to destination (the desired behaviour).

This has caused me a lot of issues, so watch out!

No comments

Using mysqldump for a set amount of results

My friend Greg has kindly been developing a script based on a MySQL database table I have created, the table at current is just shy of 50,000 rows and he needed a sampler of the rows to work on…

Unfortunately mysqldump doesn’t have a switch to specify a set number of rows, but it is possible to do via the ‘–where’ switch, like so:

mysqldump -u mydbuser -p --where="1=1 LIMIT 10" mydb mytable

Unfortunately you can’t just set the where clause to ‘LIMIT 10′ as that creates an error, but have it force an always true condition and you’re away.

A useful little trick.

No comments

MSN on the move

Okay been a while since I posted anything, just been rather busy.

So my phone runs Windows Mobile 6 and because it’s a HTC handset released by Orange the Microsoft MSN Messenger which usually accompanies Windows Mobile 6 is not present.

I’ve been on the lookout for a free alternative and I stumbled across a nice client today named ‘Palringo’, what makes Palringo different is that it does not operate from your phone directly, you have to create a Palringo account; then add the accompanying services, such as MSN etc.

These added services are then stored on your account, the security of this concerns me as my password is stored somewhere on their server. I hope they use some form of key based hashing, the key being the password you enter to get into the account, then if their system is ever compromised all they then have is a bunch of hashed passwords.

I signed up for a new account and linked it to an MSN Live account, what’s pretty nifty about this software though is the ability to send voice messages and photo’s directly from the handset, you click ’send photo’ and it loads your phone’s camera, you take the shot, and when you get back to Palringo, the image has sent, very useful.

Very nice looking app too, here’s a screenshot I pinched from the website:
Palringo Instant Messenger

Supports lots of platforms too, I’m just not quite sure what the catch is…

1 comment

Smallest PHP IRC bot

A friendly one day competition was held on Zymic’s IRC a few weeks ago where the challenge was to write the smallest (in characters and lines) IRC bot, here was my entry:

for(fputs($s=fsockopen('irc.zymic.com',6667),"USER b b b b\nNICK b\nJOIN #bots\n");1;eregi(":(.*)!.*(PRIVMSG) (.*) :((hello)|(quit))|PING (.*)",fgets($s),$m),$m[5]||$m[7]?fputs($s,!$m[7]? "$m[2] $m[3] :Hi, $m[1]\n":"PING $m[7]\n"):($m[6]?die:0),$m='');

1 line; 253 characters

Highly unoptimised, but that was to keep the character count down.

Really fun challenge, I did end up winning, but it was definitely the fun of writing it more than the winning.

Some of the other entries can be found here : http://competition.pastebin.com

No comments

Restricting outgoing urls with iptables

I was having a nose through the iptables manual and came across the extension ‘owner’, basically, here’s the manual page excerpt:

owner
This module attempts to match various characteristics of the packet creator, for locally-generated packets.  It is only valid in the OUTPUT chain, and even  this  some
packets (such as ICMP ping responses) may have no owner, and hence never match.
 
--uid-owner userid
Matches if the packet was created by a process with the given effective user id.
 
--gid-owner groupid
Matches if the packet was created by a process with the given effective group id.
 
--pid-owner processid
Matches  if  the  packet  was  created by a process with the given process id.  (Please note: This option requires kernel support that might not be available in
official Linux kernel sources or Debian’s packaged Linux kernel sources.  And if support for this option is available for the specific Linux kernel source  ver‐
sion, that support might not be enabled in the current Linux kernel binary.)
 
--sid-owner sessionid
Matches  if  the  packet  was created by a process in the given session group.  (Please note: This option requires kernel support that might not be available in
official Linux kernel sources or Debian’s packaged Linux kernel sources.  And if support for this option is available for the specific Linux kernel source  ver‐
sion, that support might not be enabled in the current Linux kernel binary.)
 
--cmd-owner name
Matches  if  the  packet was created by a process with the given command name.  (Please note: This option requires kernel support that might not be available in
official Linux kernel sources or Debian’s packaged Linux kernel sources.  And if support for this option is available for the specific Linux kernel source  ver‐
sion, that support might not be enabled in the current Linux kernel binary.)
 
NOTE: pid, sid and command matching are broken on SMP

It then dawned on me what I could use this for.

I wanted a way to restrict outgoing urls used within php, so for example, script-x could communicate with api.recaptcha.net, but script-x could not communicate say with mrmiagisguidetokarate.com.

First I created a new chain within the filter table:

~$ iptables -N outgoingurls

Then I set the default policy for this chain to ‘ACCEPT’

iptables -A outgoingurls -j ACCEPT

We now add the iptables rule which will drop all outgoing connections from apache:

iptables -A OUTPUT -m owner --uid-owner www-data -j REJECT

Notice the REJECT as opposed to DROP, REJECT sends an ICMP response back to inform that the connection is refused and does not hang as much.

Now to allow just recaptcha.net (64.34.251.150):

iptables -A OUTPUT -p tcp -m owner --uid-owner www-data -d 64.34.251.150 -j outgoingurls

If we were ever wanting to disable all urls we can set the default policy of the outgoingurls chain to REJECT, or else we can just flush the chain.

The caveat to this technique that it can only really be done on an IP address level, that IP address may host multiple sites which could lead to nasties not being filtered, so user beware.

An optional technique but using the owner extension again is to redirect outgoing urls to an intermediary proxy which could sift through the payload and filter it based on that; the downside to this technique is that although it does the job it’s a very long winded and expensive (resources wise) process, but if you were to want to something similar, you could filter to your proxy like so:

iptables -t nat -A PREROUTING -t tcp -m owner --owner-uid www-data -j DNAT --to 192.168.1.100:8080
iptables -t nat -A OUTPUT -t tcp -m owner --owner-uid www-data -j DNAT --to 192.168.1.100:8080
iptables -t nat -A PREROUTING -t tcp -m owner --owner-uid www-data -s 192.168.1.100 -j ACCEPT
iptables -t nat -A OUTPUT -t tcp -m owner --owner-uid www-data -s  -s 192.168.1.100 -j ACCEPT

You would need to bind your proxy to 192.168.1.100, so you could create an additional address to bind onto like so:

ifconfig eth0:0 192.168.1.100 netmask 255.255.255.0

That done anything outgoing (that is not from your proxy address) will be passed off the proxy, anything that is from your proxy is allowed.

I wrote this in a bit of a rush, so apologies for any inaccuracies, I’ll review it next time I’m online.

1 comment

Obfuscation… it’s like cling film over the toilet seat.

A friend of mine started telling me about a php script obfuscation / encoding application, I was none too convinced that it could have any viable use to thwart the theft of code, and my preconceptions were bang on the nail.

I shall from this point on be calling the application ‘obfuscator-x’(so not to jeopardise anyone’s codebase who actually attempt to protect their source with the product).

Obfuscation-x basically is a windows application which takes your source files then garbles them to the extent they are not easily readable, yet can be used as you normally would. Obfuscation-x does this through the means of shifting bytes backwards and forwards in a predetermined algorithm.

Let me show you the source of the original script which is being encoded / obfuscated:

<?php echo 'Hello World'; ?>

Now we look at the obfuscated / encoded source:

if (!function_exists("a"))  {   function a($b)   {    $b = base64_decode($b);    $a = 0;    $c = 0;    $d = 0;    $e = (ord($b[1]) << 8) + ord($b[2]);    $f = 3;    $g = 0;    $h = 16;    $i = "";    $j = strlen($b);    $k = __FILE__;    $k = file_get_contents($k);    $l = 0;    preg_match(base64_decode("LyhwcmludHxzcHJpbnR8ZWNobykv"), $k, $l);    for (;$f<$j;)    {     if (count($l)) exit;     if ($h == 0)     {      $e = (ord($b[$f++]) << 8);      $e += ord($b[$f++]);      $h = 16;     }     if ($e & 0x8000)     {      $a = (ord($b[$f++]) << 4);      $a += (ord($b[$f]) >> 4);      if ($a)      {       $c = (ord($b[$f++]) & 0x0F) + 3;       for ($d = 0; $d < $c; $d++)        $i[$g+$d] = $i[$g-$a+$d];       $g += $c;      }      else      {       $c = (ord($b[$f++]) << 8);       $c += ord($b[$f++]) + 16;       for ($d = 0; $d < $c; $i[$g+$d++] = $b[$f]);       $f++; $g += $c;      }     }     else $i[$g++] = $b[$f++];     $e <<= 1;     $h--;     if ($f == $j)     {      $k = implode("", $i);      $k = "?".">".$k."<"."?";      return $k;     }    }   }  }  
eval(a("QAAAPD9waHAgZWNobyAnSGVsbAAEbyBXb3JsZCc7ID8+IAAU"));

Variables and function names have been changed

The first thing that initially hit me is the amount of extra bytes your file needs just to be interpreted…
If you’re not experienced in php you might think that it looks pretty secure, but how wrong you’d be, first let’s look at that last line:

eval(a("QAAAPD9waHAgZWNobyAnSGVsbAAEbyBXb3JsZCc7ID8+IAAU"));

This is the encoded source in a base64 format but being passed through the ‘a’ function to decode it… so all we have to do is output the bit going into eval, now the developers of the software have attempted to prevent this, but in such a way it’s almost laughable, where, here’s where:

preg_match(base64_decode("LyhwcmludHxzcHJpbnR8ZWNobykv"), $k, $l);    for (;$f<$j;)    {     if (count($l)) exit;

Basically this decoded says this:

/(print|sprint|echo)/

Now that is damn right ridiculous, that doesn’t even take into account ‘var_dump’, ‘var_export’, now of course it’s impossible to have a 100% fool proof obfuscator but steps like this if they are attempting to thwart attempts should most definitely be taken into consideration. If you’ve followed thus far then it’s pretty obvious how to get the source:

var_dump(a("QAAAPD9waHAgZWNobyAnSGVsbAAEbyBXb3JsZCc7ID8+IAAU"));

It’s hardly going to take a genius to work that out!

So it got me thinking… could you obfuscate the function’s being called, well the answer to an extent (and at the price of inefficiency!) is yes. This is really just a test case and I personally wouldn’t recommend even thinking about using a technique like this…

So here is my attempt at function name obfuscation:

$a=array(0x69,0x6d,0x70,0x6c,0x6f,0x64,0x65);
array_unshift($a, str_repeat('%c',count($a)));
$f=call_user_func_array('sprintf', $a);
print_r($f('|', array('a','b','c')));

Broken down the first line is an array of hexadecimal representations of the character codes, second line places the proper character formatting string within the first entry in the array (so it’s the first argument passed to sprintf), the 3rd line is pretty obvious and assigns the function name to $f, then calling $f( … ) gives you the function. Ridiculously impractical, but then again, so are most obfuscators.

To build any function in this way I wrote a quick function:

function fObs($f)
{
   if(function_exists($f))
   {
      $x = array();$s ='$a=array('; $i = 0;
      for($i = 0, $len = strlen($f); $i < $len; $i++)
         $s.= sprintf('0x%02s,', dechex(ord($f[$i])));
      return substr($s, 0, -1).');';
   }
   return $f;
}
 
echo fObs('implode');

The array string could then be used within the script, you’ll have to excuse the short, non-concise variables names, it is after all a very dirty function.

Overall, don’t buy obfuscators… if you really want a better chance of protecting your source you can use something like Zend Encoder or IonCube, these have the distinct advantage that they compile your script into byte code, still not impossible to reverse engineer, but you’re more likely to keep the majority of snoopers out (until some bright spark releases an application to the masses for decoding it).

I believe that about concludes this blog post.

No comments

First of many…

I’m not too seasoned at writing blogs, so bear with me…

This blog is really just a place for me to document my little findings, the topics will tend to be related to Linux, server administration and web development but I’m sure I’ll digress at points and blab on about some other tuneful topic.

I will start off by saying, I will not be one of those bloggers who feels like documenting his entire life… if you want to know what I had for dinner, what I got up to, or perhaps what I’m wearing, or even the current track I’m listening to then: pass me your name, address and I’ll endeavour to take out a restraining order on you. :)

I’ll also admit this is more-so a persistent repertoire for my findings / musings than contributions to help the masses… but if it helps, all the better.

I also feel obliged to almost apologise for using 3rd party software, I do consider myself a bit of a purist, but I needed a blog quick to jot down my findings and with more pressing things to work on I really didn’t have the time to write my own blog… maybe in the future.

Now that’s out the way, I’m off to find a plugin for syntax highIighting within my posts and after that I suppose I better get writing some meaningful content!

No comments