Fedora ARM Image Installer (FAII)

So my third "git-worthy" project is called the Fedora ARM Image Installer. It will basically allow one to "easily" convert an SD-Card into a bootable ARM media device. It is written in Python (2 & 3 for Linux & Windows) and it is based on the PyQt4 GUI framework giving it a more native feel for each platform. Below are some screenshots and links!

Source Code (Git Hub)
Binary Program (Fedora People)
Fedora Wiki

Fedora ARM Image Installer (FAII)

Fedora Losing My WiFi Inet…

So Fedora has been disconnecting me a lot lately from my home wifi and I think it’s because I have disabled a lot of background services that I don’t need. Anyway, I’m trying something new:

yum remove NetworkManager
mkdir /etc/wifi
wpa_passphrase "your_ssid_here" > /etc/wifi/home.conf

Run this script as root when wanting to connect to wifi (assumes the wlan0 interface):

#!/bin/bash
pkil=`which killall`
intf=`which ifconfig`
scan=`which iwlist`
wpas=`which wpa_supplicant`
dhcp=`which dhclient`
ifce="wlan0"
while true
do
	ping -c 1 google.ca > /dev/null 2>&1
	if [ $? -eq 0 ]
	then
		sleep 10
		continue
	fi
	for file in /etc/wifi/*
	do
		$intf "$ifce" up
		ssid=`cat $file | grep -i 'ssid' | sed -e 's/^[ \t]*ssid="//g' -e 's/"[ \t]*$//g'`
		exis=`$scan "$ifce" scan | grep -i "$ssid"`
		if [ "$exis" != "" ]
		then
			echo "[`date`] connecting to [$ssid]..."
			$pkil -9 wpa_supplicant > /dev/null 2>&1
			$pkil -9 dhclient > /dev/null 2>&1
			$intf "$ifce" up
			$wpas -Dwext -i "$ifce" -c "$file" > /dev/null 2>&1 &
			$dhcp "$ifce" > /dev/null 2>&1 &
			break
		fi
	done
	sleep 10
done
Fedora Losing My WiFi Inet…

Bored And Off Topic!

Just wanted to see how many lines of Python it took me to make a generalized password bruteforce script…

import time

slst = "abcdefghijklmnopqrstuvwxyz"
slen = (len(slst) - 1)
dwrd = [0]
dlen = 1

numb = 0
last = time.time()
wait = 2

while (1):
	# process password
	i = 0
	s = ""
	while (i < dlen):
		s = (s + slst[dwrd[i]])
		i = (i + 1)
	# print stats
	numb = (numb + 1)
	pres = time.time()
	if ((pres - last) >= wait):
		print("pw=[%s] @ [%d p/s]" % (s, numb / wait))
		numb = 0
		last = pres
	# overflow increase
	dwrd[dlen - 1] = (dwrd[dlen - 1] + 1)
	i = (dlen - 1)
	u = 1
	while (i > -1):
		if (dwrd[i] > slen):
			dwrd[i] = 0
			if ((i - 1) > -1):
				dwrd[i - 1] = (dwrd[i - 1] + 1)
		else:
			u = 0
		i = (i - 1)
	# length expansion
	if (u == 1):
		i = 0
		while (i < dlen):
			dwrd[i] = 0
			i = (i + 1)
		dwrd.append(0)
		dlen = (dlen + 1)
Bored And Off Topic!

Formatting Flat Files As Block Devices

Here’s a small shell script based on dd’s output which helps to partition a flat file, split it up into its respective partitions so they can be formatted and put them all back together again.

#!/bin/bash

if [ "${1}" == "c" ]
then
	if [ "${3}" == "" ]
	then
		echo "Usage: $0 $1 <filename> <filesize>"
		exit 1
	fi
	echo "Creating new file [${2}]..."
	dd if=/dev/zero of=${2} bs=${3}G count=1 > /dev/null 2>&1
	echo "Partition the new flat file ( fdisk ${2} )"
	echo
fi

if [ "${1}" == "s" ]
then
	if [ "${2}" == "" ]
	then
		echo "Usage: $0 $1 <filename>"
		exit 1
	fi
	unit=`fdisk -l "${2}" | grep -i '^Units' | sed -e 's/^.* \([0-9][0-9]*\) bytes.*$/\1/g'`
	lase="-1"
	numb=0
	fdisk -l "${2}" | sed -e 's/^[ \t]*//g' -e 's/\*//g' | grep -i "^${2}[0-9][0-9]*" | while read line
	do
		curb=`echo "${line}" | awk '{ print $2 }'`
		cure=`echo "${line}" | awk '{ print $3 }'`
		let size="${cure} - ${curb} + 1"
		let diff="${curb} - ${lase} - 1"
		if [ ${diff} -gt 0 ]
		then
			let endi="${curb} - 1"
			let skip="${lase} + 1"
			echo "[${numb}] Unused space [${skip} - ${endi}] [${diff} blocks]..."
			dd if=${2} bs=${unit} skip=${skip} count=${diff} of=${2}${numb} > /dev/null 2>&1
			let numb="${numb} + 1"
		fi
		echo "[${numb}] Carving partition [${curb} - ${cure}] [${size} blocks]..."
		dd if=${2} bs=${unit} skip=${curb} count=${size} of=${2}${numb} > /dev/null 2>&1
		let numb="${numb} + 1"
		lase="${cure}"
	done
	fdisk -l "${2}" | sed -e 's/^[ \t]*//g' -e 's/\*//g' | grep -i "^${2}[0-9][0-9]*" | tail -n 1 | while read line
	do
		endi=`echo "${line}" | awk '{ print $3 }'`
		let rest="${endi} + 1"
		numb="9"
		echo "[${numb}] Copying ending [${rest} - <end>]..."
		dd if=${2} bs=${unit} skip=${rest} of=${2}${numb} > /dev/null 2>&1
	done
	echo
	echo "Create any filesystem needed ( mkfs.* ${2}[0-9] )"
	echo "Mount any filesystem needed ( mount -o loop ${2}[0-9] /mnt/tmp[0-9] )"
	echo "Copy any files needed ( cp -r source/* /mnt/tmp[0-9]/ )"
	echo "Unmount any filesystem needed ( umount /mnt/tmp[0-9] )"
	echo
fi

if [ "${1}" == "j" ]
then
	if [ "${2}" == "" ]
	then
		echo "Usage: $0 $1 <filename>"
		exit 1
	fi
	echo "Writing to file [${2}.join]..."
	cat ${2}[0-9]* > ${2}.join
	echo
fi

Formatting Flat Files As Block Devices

[offtopic] iTunes Library Scripts

So I was trying to get my pc laptop setup for fudcon which meant a triple boot setup between windows, ubuntu and fedora. I had some troubles importing various important information about my music within iTunes.

Here is a script to remove duplicate songs in an iTunes folder:

import hashlib
import os
import re
import sys

def hash(fnam):
	fobj = open(fnam, "r")
	hobj = hashlib.sha256()
	
	while (1):
		data = fobj.read(2**20)
		
		if (not data):
			break
		
		hobj.update(data)
	
	return hobj.hexdigest()

fdic = {}

while (1):
	file = sys.stdin.readline()
	
	if (not file):
		break
	
	file = file.strip()
	uniq = hash(file)
	
	if (uniq in fdic.keys()):
		print("removing:",file)
		os.unlink(file)
	
	else:
		print("found:",file)
		fdic[uniq] = file

This script attempts to merge an old iTunes library xml file with a newly imported one. The result is a merged iTunes library xml file that can then be re-imported into iTunes thus restoring some various meta-data about your music. Note: Before you re-import the merged xml playlist file, make sure you delete the current one and disable the check-box stating to copy songs into the media folder.

import os
import re
import sys

if (len(sys.argv) < 3):
	print("Usage: %s <source> <merge>" % (sys.argv[0]))
	sys.exit(0)

def outp(ordr, dict, line):
	for item in ordr:
		sys.stdout.write(dict[item][1])
	
	sys.stdout.write(line)
	sys.stdout.flush()

def xmlr(fnam, sdic={}):
	alen = len(sys.argv)
	slen = len(sdic.keys())
	xord = []; xdic = {}
	xobj = open(fnam, "r")
	
	xdat = {}
	
	while (1):
		xlin = xobj.readline()
		
		if (not xlin):
			break
		
		slin = xlin.strip("\0\t\r\n ")
		xreg = re.match("^<key>([^<]+)</key>(<[^>]+>[^<]+<[^>]+>)$", slin)
		
		try:
			xkey = (xdic["Artist"][0] + xdic["Album"][0] + xdic["Name"][0])
		
		except:
			xkey = ""
		
		if (slin == "<dict>"):
			if (slen > 0):
				outp(xord, xdic, xlin)
			
			xord = []; xdic = {}
		
		elif (xreg):
			if (xreg.group(1) not in xord):
				xord.append(xreg.group(1))
			
			xdic[xreg.group(1)] = [xreg.group(2), xlin]
		
		elif (slin == "</dict>"):
			if (slen < 1):
				xdat[xkey] = xdic
			
			else:
				for x in range(3, alen):
					try:
						xdic[sys.argv[x]] = sdic[xkey][sys.argv[x]]
						
						if (sys.argv[x] not in xord):
							xord.append(sys.argv[x])
					
					except:
						#print("error:",sys.exc_info())
						pass
				
				outp(xord, xdic, xlin)
			
			xord = []; xdic = {}
		
		else:
			if (slen > 0):
				outp(xord, xdic, xlin)
			
			xord = []; xdic = {}
	
	return xdat

sdat = xmlr(sys.argv[1])
ddat = xmlr(sys.argv[2], sdic=sdat)

Here’s an example of how to use the command:

python.exe /cygdrive/c/Users/jon/Desktop/itml.py /cygdrive/g/tmp/itunes/iTunes\ Music\ Library0.xml /cygdrive/g/tmp/itunes/iTunes\ Music\ Library.xml 'Date Added' 'Play Count' | unix2dos.exe | tee /cygdrive/g/tmp/itunes/iTunes\ Music\ Library2.xml && cp /cygdrive/g/tmp/itunes/iTunes\ Music\ Library2.xml /cygdrive/g/tmp/itunes/iTunes\ Music\ Library3.xml
[offtopic] iTunes Library Scripts

[updated] F15 Koji Que Script

Here it is, hopefully it works a bit better!

#!/bin/bash
export x=1
export l=`find ./f15srpms -type f | grep -i '\.src\.rpm' | wc -l`
koji list-tagged dist-f15 > /tmp/pkoji.txt
find ./f15srpms -type f | sort -R | grep -i '\.src\.rpm' > /tmp/pkgsl.txt
while true
do
	while true
	do
		ak list-tagged dist-f15 > /tmp/akoji.txt
		ak list-tasks --mine --quiet | grep '^[0-9]' | grep -Ei ' (open|free) .* build' > /tmp/tasks.txt
		#echo "number of our tasks == `cat /tmp/tasks.txt | wc -l`"
		n=`cat /tmp/tasks.txt | wc -l`
		if [ $n -ge 10 ]
		then
			break
		fi
		p=`cat /tmp/pkgsl.txt | head -n "$x" | tail -n 1`
		q=`basename "$p" | sed -e 's/-[^-]*-[^-]*$//'`
		let x="($x % $l) + 1"
		#echo "checking pkg [$p] name [$q] not built on (akoji) and built on (pkoji)"
		c=`cat /tmp/akoji.txt /tmp/tasks.txt | grep -i "$q"`
		if [ "$c" != "" ]
		then
			continue
		fi
		c=`cat /tmp/pkoji.txt | grep -i "$q"`
		if [ "$c" == "" ]
		then
			continue
		fi
		echo "queing [$p] position [$x]"
		ak build dist-f15 "$p" --nowait --background
	done
	sleep 60
done

[updated] F15 Koji Que Script

[off-topic] Fighting Governments — DNS Re-Implemented

The U.S. government is taking down websites using DNS poisoning/hijacking methods on pages that are claimed to be infringing on copyright law. I have re-written a *really* basic DNS server which re-implements DNS forwarding/proxying, DNS caching and DNS un-blacklisting of A/IN/IPv4 records. Basically, if one were to run their own DNS server (like the one below) and maintain a simple list of government-poisoned IP addresses for it, the DNS server would be able to provide (previously expired but still good) IPv4 addresses for the blocked site. This could essentially allow one to re-access a now blacklisted website.

Here is a screen shot of my computer using this basic DNS server to visit slashdot:

$ host slashdot.org
slashdot.org has address 216.34.181.45
slashdot.org mail is handled by 10 mx.sourceforge.net.

And here is what it would look like if it were taken down via DNS poisoning:

$ host slashdot.org
slashdot.org has address 74.81.170.110
slashdot.org has address 216.34.181.45
slashdot.org mail is handled by 10 mx.sourceforge.net.

Once this happens, all one has to do now is append the newly offending IP address to the DNS server’s black list text file like so:

# cat dnsb.txt 
74.81.170.110

And if you perform another DNS request to the same (custom) DNS server, you get the last cached answers bringing you back to slashdot:

$ host slashdot.org
slashdot.org has address 216.34.181.45
slashdot.org mail is handled by 10 mx.sourceforge.net.

The code below is simply proof-of-concept software and should *NOT* be used for production as I have implemented everything from scratch here and know very little about how DNS really works (i.e. message compression).

import os
import re
import socket
import sqlite3
import sys
import time

sqlo = sqlite3.connect("dnsd.db")
sqlc = sqlo.cursor()

def fixs(inpt):
	outp = ""
	
	for letr in inpt:
		if (ord(letr) < 32):
			outp += "."
		
		else:
			outp += letr
	
	return outp

def rslv():
	nlst = []
	fobj = open("/etc/resolv.conf", "r")
	
	dnsl = fobj.readlines()
	
	for dnse in dnsl:
		item = dnse.strip("\0\t\r\n ")
		regx = re.match("^nameserver[ \t]*(.*)$", item)
		
		if (regx):
			addr = regx.group(1)
			nlst.append(addr)
	
	return nlst

def forw(addr, data):
	resp = ""
	serv = (addr, 53)
	nobj = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
	
	try:
		nobj.settimeout(5)
		nobj.sendto(data, serv)
		resp = nobj.recv(2**20)
	
	except:
		pass
	
	try:
		nobj.close()
	
	except:
		pass
	
	return resp

def answ(data, deet=False):
	# http://www.ietf.org/rfc/rfc1035.txt
	
	requ = 13
	null = (requ + data[requ:].find("\0"))
	dtyp = (null + 5)
	dlen = (dtyp + 10)
	
	size = len(data)
	name = fixs(data[requ:null])
	begi = -1
	endi = -1
	ansl = []
	
	while ((dlen + 1) < size):
		dsiz = ((ord(data[dlen]) << 8) + ord(data[dlen + 1]))
		dsig = (dtyp + 4)
		
		if (((dlen + 5) < size) and (data[dtyp:dsig] == "\xc0\x0c\x00\x01")):
			if (deet == True):
				if (begi == -1):
					begi = dtyp
				
				else:
					endi = (dlen + 1 + dsiz + 1)
			
			addr = ""
			
			for x in range(2, 2 + 4):
				addr += ("." + str(ord(data[dlen + x])))
			
			ansl.append([name, addr[1:]])
		
		dtyp = (dlen + 1 + dsiz + 1)
		dlen = (dtyp + 10)
	
	if (begi == -1):
		begi = (null + 5)
		endi = begi
	
	if (deet == False):
		return ansl
	
	else:
		return [begi, endi]

def sqle(comd, outp=False):
	global sqlo
	global sqlc
	
	try:
		sqlc.execute(comd)
	
	except:
		pass
	
	if (outp == False):
		sqlo.commit()
	
	else:
		return sqlc.fetchall()

def filt():
	try:
		fobj = open("dnsb.txt", "r")
		
		for line in fobj.readlines():
			addr = line.strip("\0\t\r\n ")
			sqle("DELETE FROM data WHERE addr = '%s';" % (addr))
		
		fobj.close()
	
	except:
		return 0
	
	return 1

def cche(name):
	dbdl = sqle("SELECT * FROM data WHERE name = '%s';" % (name), outp=True)
	outp = []
	
	for dbdi in dbdl:
		adrl = dbdi[1].split(".")
		adrs = ""
		
		for adri in adrl:
			adrs += chr(int(adri))
		
		outp.append([int(dbdi[2]), adrs])
	
	outp.sort()
	outp.reverse()
	
	return outp

def shim(data, adrl):
	hedn = [6, 8]
	payn = answ(data, deet=True)
	
	lead = (payn[0] + 12)
	size = len(adrl)
	
	dlen = (chr((size >> 8) & 0xff) + chr((size >> 0) & 0xff))
	head = (data[:hedn[0]] + dlen + data[hedn[1]:payn[0]])
	
	payl = ""
	
	for adri in adrl:
		payl += (data[payn[0]:lead] + adri[1])
	
	payl += data[payn[1]:]
	
	outp = (head + payl)
	
	# beg: compression offset bypass
	
	outp = (outp[:8] + chr(0) + chr(0) + outp[10:])
	outp = (outp[:10] + chr(0) + chr(0) + outp[12:])
	
	# end: compression offset bypass
	
	# beg: compression offset fix
	'''
	x = 0
	l = len(outp)
	s = ((ord(data[6]) << 8) + ord(data[7]))
	d = ((size - s) * 16)
	
	if (d > 0):
		while ((x + 1) < l):
			o = ((ord(outp[x]) << 8) + ord(outp[x + 1]))
			
			if ((o & 0xff00) == 0xc000):
				o = (o & 0x00ff)
				
				if (o > 0x0c):
					o = (o + d)
					outp = (outp[:x] + chr((o >> 8) & 0xff) + chr((o >> 0) & 0xff) + outp[x + 2:])
			
			x = (x + 2)
	'''
	# end: compression offset fix
	
	return outp

def debg(addr, requ, answ):
	adrl = addr.split(".")
	adrl[3] = "x"
	prio = ""
	
	for letr in answ:
		prio += ("." + str(ord(letr)))
	
	print("[%s] requ [%s] answ [%s, ...]" % (".".join(adrl), requ, prio[1:]))

def serv():
	snam = ("", 53)
	sobj = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
	
	sobj.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
	sobj.bind(snam)
	
	while (1):
		(data, addr) = sobj.recvfrom(2**20)
		rlvl = rslv()
		
		for rlvi in rlvl:
			dnsr = forw(rlvi, data)
			
			if (dnsr):
				resl = answ(dnsr)
				
				if (len(resl) > 0):
					for resi in resl:
						dnsq = re.sub("[^0-9A-Za-z\.\-]", "", resi[0])
						dnsa = re.sub("[^0-9\.]", "", resi[1])
						epch = str(int(time.time()))
						
						dbdl = sqle("SELECT * FROM data WHERE name = '%s' AND addr = '%s';" % (dnsq, dnsa), outp=True)
						
						if (len(dbdl) < 1):
							sqle("INSERT INTO data VALUES ('%s', '%s', '0');" % (dnsq, dnsa))
						
						sqle("UPDATE data SET time = '%s' WHERE name = '%s' AND addr = '%s';" % (epch, dnsq, dnsa))
					
					filt()
					dbdl = cche(dnsq)
					
					if (len(dbdl) > 0):
						debg(addr[0], resl[0][0], dbdl[0][1])
						#a=open("a","w");a.write(dnsr);a.close();
						dnsr = shim(dnsr, dbdl)
						#b=open("b","w");b.write(dnsr);b.close();
				
				sobj.sendto(dnsr, addr)
				break

def priv():
	# get username & os.setgid() & os.setuid()
	pass

if (__name__ == "__main__"):
	sqle("CREATE TABLE data (name VARCHAR(256), addr VARCHAR(256), time VARCHAR(256));")
	priv()
	serv()

[off-topic] Fighting Governments — DNS Re-Implemented

Attempting To Finally Contribute

So I haven’t had much to talk about lately due the amount of work given for the last few weeks remaining in school and the building of Fedora 15 for ARMv5 and ARMv7. However, in my spare time, I’ve been trying to contribute positively to the Koji Build System project by submitting mailing list items containing source code unified diff patches. Most of my posts/changes contain feature enhancements requested by other people that I found to be somewhat interesting to code. If you’re interested in viewing the mailing list items, the links can be found below:

Hosts-Page Colour Highlight: [ Ticket ] [ Patch ]
Hosts-Page “Life-Line” Links: [ Ticket ] [ Patch ]
Host-Info Latest-Builds Links: [ Ticket ] [ Patch ]
Koji-Client watch-logs “tail”: [ Ticket ] [ Patch ]
Koji-Hub RPMTAG_SIGSHA2 Hashing: [ Ticket ] [ Patch ]

Attempting To Finally Contribute

PHP Koji Stats Page

Note: put this in a cron job as it may take a while to run. Use the output to generate a basic html page instead.

stats.php

<?php
	date_default_timezone_set("EST");
	$dta = date(DATE_RFC822);
	$dis = "dist-f15";
	$hua = "http://arm.koji.fedoraproject.org/kojihub";
	$hub = "http://koji.fedoraproject.org/kojihub";
	
	function p($n)
	{
		preg_match("/^(.*)-([^-]+)-([^-]+)$/", $n, $m);
		return $m;
	}
	
	$a = array();
	exec("/usr/bin/koji -s '".$hua."' list-tagged '".$dis."' --latest --quiet | /bin/awk '{ print $1 }'", $a);
	$b = array();
	exec("/usr/bin/koji -s '".$hub."' list-tagged '".$dis."' --latest --quiet | /bin/awk '{ print $1 }'", $b);
	
	$err = array(); $unb = array(); $dif = array(); $wor = array(); $fin = array();
	
	$t = array();
	foreach ($a as $i)
	{
		$n = p($i);
		array_push($t, $n[1]);
	}
	
	$u = array();
	foreach ($b as $i)
	{
		$n = p($i);
		$c = array_search($n[1], $t);
		if ($c === FALSE)
		{
			array_push($u, $i);
		}
		else if ($a[$c] != $i)
		{
			array_push($dif, array($a[$c], $i));
		}
		else if ($a[$c] == $i)
		{
			array_push($fin, $i);
		}
	}
	
	$c = 0; $s = ""; $l = count($u); $v = array();
	for ($x = 0; $x < $l; $x += 1)
	{
		$s = ($s."'".$u[$x]."' ");
		$c = ($c + 1);
		if (($c >= 256) or ($x == ($l - 1)))
		{
			exec("/usr/bin/koji -s '".$hua."' buildinfo ".$s." | /bin/grep -Ei '^(genericerror|no such build|build|state): .*$'", $v);
			$c = 0; $s = "";
		}
	}
	array_push($v, "");
	
	$b = ""; $s = "";
	foreach ($v as $i)
	{
		$m = array(); $n = array();
		if (preg_match("/^state: (.*)$/i", $i, $m))
		{
			$s = trim($m[1]);
		}
		else if (preg_match("/^.*: ([^ ]*).*$/i", $i, $n) or ($b != ""))
		{
			if ($b != "")
			{
				if ($s == "COMPLETE")
				{
					array_push($fin, $b);
				}
				else if ($s == "BUILDING")
				{
					array_push($wor, $b);
				}
				else if ($s == "")
				{
					array_push($unb, $b);
				}
				else
				{
					array_push($err, $b);
				}
			}
			$b = trim($n[1]); $s = "";
		}
	}
	
	$dtb = date(DATE_RFC822);
?>

<html>
	<head>
		<title>Koji Stats Page</title>
		<style>
			a
			{
				color: black;
				text-decoration: none;
			}
			table
			{
				width: 95%;
			}
			.errb
			{
				background-color: #FF6A6A;
			}
			.unbb
			{
				background-color: #FFA812;
			}
			.difb
			{
				background-color: #FFD700;
			}
			.work
			{
				background-color: #33FF33;
			}
			.buib
			{
				background-color: #499DF5;
			}
			.head
			{
				text-align: left;
				width: 95%;
				display: none;
			}
			.butt
			{
				border: 1px solid black;
				padding-left: 10px;
				padding-right: 10px;
			}
			.list
			{
				border: 1px dotted black;
				text-align: left;
				padding-top: 10px;
				padding-left: 10px;
				width: 95%;
				height: 512px;
				overflow: auto;
			}
		</style>
		<script>
			function show(name)
			{
				var x, objc;
				var elem = ["erro", "unbu", "diff", "work", "buil"];
				for (x = 0; x < elem.length; ++x)
				{
					objc = document.getElementById(elem[x]);
					objc.style.display = "none";
				}
				for (x = 0; x < elem.length; ++x)
				{
					if (name == elem[x])
					{
						objc = document.getElementById(elem[x]);
						objc.style.display = "block";
					}
				}
			}
			function init()
			{
				var objc = document.getElementById("head");
				objc.style.display = "block";
			}
		</script>
	</head>
	<body onload="init();">
		<b><?php print($dis." / ".$dta." / ".$dtb); ?></b>
		<br /><br />
		<center>
			<div id="head" class="head">
				<span class="butt errb"><a href="javascript:show('erro');">Errors [<?php echo count($err); ?>]</a></span>
				<span class="butt unbb"><a href="javascript:show('unbu');">Unbuilt [<?php echo count($unb); ?>]</a></span>
				<span class="butt difb"><a href="javascript:show('diff');">Different [<?php echo count($dif); ?>]</a></span>
				<span class="butt work"><a href="javascript:show('work');">Working [<?php echo count($wor); ?>]</a></span>
				<span class="butt buib"><a href="javascript:show('buil');">Built [<?php echo count($fin); ?>]</a></span>
			</div>
			<br />
			<div id="erro" class="list"><center><table>
				<?php foreach ($err as $i) { print("<tr><td class='butt errb'><a href=\"javascript:logs('".$i."');\">".$i."</a></td></tr>\n"); } ?>
			</table></center></div>
			<div id="unbu" class="list" style="display: none"><center><table>
				<?php foreach ($unb as $i) { print("<tr><td class='butt unbb'><a href=\"javascript:logs('".$i."');\">".$i."</a></td></tr>\n"); } ?>
			</table></center></div>
			<div id="diff" class="list" style="display: none"><center><table>
				<?php foreach ($dif as $i) { print("<tr><td class='butt difb'><a href=\"javascript:logs('".$i[0]."');\">".$i[0]." [".$i[1]."]</a></span></td></tr>\n"); } ?>
			</table></center></div>
			<div id="work" class="list" style="display: none"><center><table>
				<?php foreach ($wor as $i) { print("<tr><td class='butt work'><a href=\"javascript:logs('".$i."');\">".$i."</a></td></tr>\n"); } ?>
			</table></center></div>
			<div id="buil" class="list" style="display: none"><center><table>
				<?php foreach ($fin as $i) { print("<tr><td class='butt buib'><a href=\"javascript:logs('".$i."');\">".$i."</a></td></tr>\n"); } ?>
			</table></center></div>
		</center>
	</body>
</html>

PHP Koji Stats Page

2x Random Scripts

Koji Build Que’r

qu.sh
#!/bin/bash
export l=`find ~/Desktop/f15v5.0 -type f | grep -i '\.src\.rpm' | wc -l`
export x=1
while true
do
	ak list-tagged dist-f15 > /tmp/t
	while true
	do
		ak list-tasks --mine --quiet | grep '^[0-9]' | grep -Ei ' (open|free) .* build' > /tmp/n
		#echo "got tasks..." ; cat /tmp/n | wc -l ; echo
		if [ `cat /tmp/n | wc -l` -ge 10 ]
		then
			break
		fi
		p=`find ~/Desktop/f15v5.0 -type f | grep -i '\.src\.rpm' | head -n "$x" | tail -n 1`
		q=`basename "$p" | sed -e 's/[^0-9A-Za-z]/./g' -e 's/\.src\.rpm//g'`
		#echo "checking pkg [$p] [$q]..." ; echo
		c=`cat /tmp/n /tmp/t | grep -i "$q"`
		let x="($x % $l) + 1"
		if [ "$c" != "" ]
		then
			continue
		fi
		echo "queing [$p] skipped [$x]"
		ak build dist-f15 "$p" --nowait
		let n="$n + 1"
	done
	sleep 60
done

and a javascript host highlighter

hosts.js
// ==UserScript==
// @name           hosts
// @namespace      builds
// @include        http://arm.koji.fedoraproject.org/koji/hosts?order=last_update&state=enabled
// ==/UserScript==

var dateob = new Date();
var yerstr = (dateob.getFullYear() + "");
var monstr = ((dateob.getMonth() + 1) + "");
var daystr = (dateob.getDate() + "");
var srcobj = document.getElementById("loginInfo");
var scdate = (parseInt(yerstr + monstr + daystr + srcobj.innerHTML.replace(/[^0-9]/g, "").substring(6)) / 100);
var dsttab = document.getElementsByClassName("data-list");
var dstrow = dsttab[0].getElementsByTagName("tr");

for (var x = 0; x < dstrow.length; ++x)
{
	var dstcol = dstrow[x].getElementsByTagName("td");
	
	if (dstcol.length > 5)
	{
		var chdate = (parseInt(dstcol[5].innerHTML.replace(/[^0-9]/g, "")) / 100);
		
		if ((scdate - 5) >= chdate)
		{
			var lnklst = dstcol[1].getElementsByTagName("a");
			
			for (var y = 0; y < lnklst.length; ++y)
			{
				lnklst[y].innerHTML = ("<font color='red'>" + lnklst[y].innerHTML + "</font>");
			}
		}
	}
}

2x Random Scripts