Base64 decoding in Javascript

I never wrote a decoder in my previous post, so here’s my first iteration while half asleep.

function b64d(str) {

        var charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";


        var str_pos = 0;
        var str_len = str.length;

        var numbits=0;
        var curval=0;

        var data = "";
        var done = false;

        while (done == false){
                // Not enough bits, get more
                if (numbits < 8) {
                        var nextchar = str.charAt(str_pos++);
                        if (nextchar == "=") { break; }
                        var sixbits = charset.indexOf(nextchar);
                        curval = (curval << 6) | sixbits;
                        numbits += 6;
                } else {

                        nextbyte = curval >> (numbits - 8);
                        curval = curval - (nextbyte << numbits - 8);
                        numbits -= 8;

                        data += String.fromCharCode(nextbyte);

                        if (str_pos >= str_len && numbits < 8){
                                done = true;
                        }
                }
        }

        return data;

}

Extending NetSNMP

Simple python script that provides an easy interface for extending snmpd.

(I threw this on github as well https://github.com/jceresini/snmp_pass_thru)

snmp_pass_thru.py

#!/usr/bin/python
import sys,os

# Function to calculate the value to return for a given oid
def calc_oid_value(oid_info):
	cmd_output = os.popen(oid_info['exec']).read().replace('\n',' ').strip()
	if 'func' in oid_info:
		value = oid_info['func'](cmd_output)
	else:
		value = cmd_output
	return value


# Function to support sorting oids
def cmp_oids(oid1,oid2):
	arr1 = oid1.split('.')
	arr2 = oid2.split('.')
	num_items = min(len(arr1),len(arr2))
	for i in range(0,num_items):
		num1=arr1[i]
		num2=arr2[i]
		if num1 > num2:
			return 1
		elif num1 < num2:
			return -1
	# If we make it this far, theyre either the same, or one has more pieces
	if len(arr1) > len(arr2):
		return 1
	elif len(arr2) > len(arr1):
		return -1
	else:
		return 0
# Function to handle snmpget/walk requests
def execute(oid_details):

	# Sort all oids this script knows how to handle
	oid_list = oid_details.keys()
	oid_list.sort(cmp_oids)

	requested_oid=sys.argv[2]

	# if its an snmpget, see if we know that oid
	if sys.argv[1] == '-g':
		if requested_oid in oid_details:
			oid_to_return=requested_oid
		else:
			oid_to_return=None

	if sys.argv[1] == '-n':
		if requested_oid not in oid_list:
			oid_list.append(requested_oid)
			oid_list.sort(cmp_oids)
	
		next_index = oid_list.index(requested_oid) + 1
		if next_index < len(oid_list):
			next_oid=oid_list[next_index]
			oid_to_return=next_oid
		else:
			oid_to_return=None

	if oid_to_return:
		print oid_to_return
		print oid_details[oid_to_return]['type']
		print calc_oid_value(oid_details[oid_to_return])

example.py

#!/usr/bin/env python
import snmpd_pass_thru

oid_details={
	'.1.3.6.1.4.1.12345.1.2.1': {
		'exec': 'cat /etc/redhat-release',
		'type': 'String'
	},
	'.1.3.6.1.4.1.12345.1.2.2': {
		'exec': 'cat /etc/redhat-release',
		'type': 'Integer',
		'func': lambda x: int(x=='Fedora release 22 (Twenty Two)')
	},
}

snmpd_pass_thru.execute(oid_details)

snmpd.conf

[...]
pass .1.3.6.1.4.1.12345 /path/to/example.py
[...]

Base64 in Javascript

Decided to play around with writing my own base64 in javascript, as a piece to a larger project I’m considering playing around with.

function b64e(str) {

        var charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

        var str_pos = 0;
        var str_len = str.length;

        var numbits=0;
        var curval=0;

        var b64str = "";
        var done = false;

        while (done == false){
                // Not enough bits, get more
                if (numbits < 6) {
                        var nextbyte = str.charCodeAt(str_pos++);
                        curval = (curval << 8) | nextbyte;
                        numbits += 8;
                }

                sixbits = curval >> (numbits - 6);
                curval = curval - (sixbits << numbits - 6);
                numbits -= 6;

                b64str += charset[sixbits];

                if (str_pos >= str_len && numbits < 6){
                        done = true; 
                }
        }

        //handle extra bits now
        if (numbits > 0){
                sixbits = curval << (6-numbits)
                numbits -= 6;
                b64str += charset[sixbits];
        }

        b64str += Array((numbits/-2) + 1).join('=');

        return b64str;

}

Setting up a local CentOS mirror

I decided to set up a local CentOS mirror. Having never done so before, I searched for some examples, and then tweaked things to fit my needs. The basis of the script below was borrowed from here

#!/bin/bash

VERSIONS="6 7"
LOCKFILE=/var/lock/subsys/centos_mirror
MIRROR=[public mirror]
DESTINATION=[destination]

# Make sure rsync isn't already running
# not the best method, but should prevent cron from starting multiple copies
if [ -f $LOCKFILE ] && kill -0 `cat $LOCKFILE`; then
    echo "CentOS mirror sync is currently running"
    exit 1
fi

# Write current pid to lock file
echo $$ > $LOCKFILE

# Build rsync filter for desired versions
filter="--exclude \"isos\" --exclude \"local*\" "
for version in $VERSIONS; do
    filter="$filter --include \"$version*/***\""
    filter="$filter --include \"$version\"" 
done
filter="$filter --exclude \"*\""

# Start rsync
# eval is needed because there are quotes in the 'filter' variable
eval /bin/rsync -aqSH --partial --timeout=300 --delete $filter $MIRROR::centos $DESTINATION

# Remove lock
/bin/rm -f $LOCKFILE

This should also capture the major version symlinks, so you can setup your local CentOS machines with the proper repo url, as opposed to a specific minor version. Make sure your web server is configured to properly serve symlinked files/directories.