Posts Tagged Code
Natural order sorting strings with numbers
The following python code makes natural sorting sequences of lexical and numerical values a little easier. It supports any iterable containing strings which have embedded numbers. In short it would give you this:
foo1 < foo2 < foo10
instead of this:
foo1 < foo10 < foo2
As an example, if you have this sequence:
>>> seq = ['foo', 'foo1', 'foo2', 'foo10', 'foobar10', '20', '100', '1', '3', 'bar1']
a regular sort would produce this:
>>> sorted(seq) ['1', '100', '20', '3', 'bar1', 'foo', 'foo1', 'foo10', 'foo2', 'foobar10']
whereas a natural sort would produce this:
>>> natural_sort(seq) ['1', '3', '20', '100', 'bar1', 'foo', 'foo1', 'foo2', 'foo10', 'foobar10']
Here is the code:
import re
def natsort_key(item):
chunks = re.split('(\d+(?:\.\d+)?)', item)
for ii in range(len(chunks)):
if chunks[ii] and chunks[ii][0] in '0123456789':
if '.' in chunks[ii]: numtype = float
else: numtype = int
chunks[ii] = (0, numtype(chunks[ii]))
else:
chunks[ii] = (1, chunks[ii])
return (chunks, item)
def natural_sort(seq):
sortlist = [item for item in seq]
sortlist.sort(key=natsort_key)
return sortlist
Simple HTTP POST in Java
Today I was helping a friend debug a web service they had implemented. Their side was working correctly but the developer who was trying to interface with it seemed to be running into many problems. Since they were integrating an application written in Java, I whipped up a simple test for them. All we really needed to do was to send a few variables using HTTP POST to this resource and make sure it returned exactly what we were expecting.
This uses standard libraries only, and doesn’t require anything third party. It does nothing fancy at all, just simply posts data to a URL. Hopefully you find this useful at some point.
src/postit/Main.java
/*
* Java POST Example
*/
package postit;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;
import java.net.URLEncoder;
import java.io.DataOutputStream;
import java.io.DataInputStream;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @author Greg
*/
public class Main {
/**
* Pretend you're a script...
*/
public static void main(String[] args) {
final String server = "somewhere.ontheinter.net";
URL url = null;
try {
url = new URL("http://" + server + "/we-expect-post/data");
} catch (MalformedURLException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
HttpURLConnection urlConn = null;
try {
// URL connection channel.
urlConn = (HttpURLConnection) url.openConnection();
} catch (IOException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
// Let the run-time system (RTS) know that we want input.
urlConn.setDoInput (true);
// Let the RTS know that we want to do output.
urlConn.setDoOutput (true);
// No caching, we want the real thing.
urlConn.setUseCaches (false);
try {
urlConn.setRequestMethod("POST");
} catch (ProtocolException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
try {
urlConn.connect();
} catch (IOException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
DataOutputStream output = null;
DataInputStream input = null;
try {
output = new DataOutputStream(urlConn.getOutputStream());
} catch (IOException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
// Specify the content type if needed.
//urlConn.setRequestProperty("Content-Type",
// "application/x-www-form-urlencoded");
// Construct the POST data.
String content =
"name=" + URLEncoder.encode("Greg") +
"&email=" + URLEncoder.encode("greg at code dot geek dot sh");
// Send the request data.
try {
output.writeBytes(content);
output.flush();
output.close();
} catch (IOException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
// Get response data.
String str = null;
try {
input = new DataInputStream (urlConn.getInputStream());
while (null != ((str = input.readLine()))) {
System.out.println(str);
}
input.close ();
} catch (IOException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
Simple OpenVPN Server Statistics
Ever wondered what the status of your OpenVPN server is, or wanted some simple stats ?
Here is a really simple script to give you some info. The output looks like this:
greg@leonis:~$ vpnstatus Common Name Virtual Address Real Address Sent Received Connected Since greg.vpn 10.8.142.6 196.9.23.59 1.11 MB 282.50 KB Thu Jul 16 09:07:15 2009
Firstly, ensure your server is actually saving the stats somewhere (/etc/openvpn/openvpn.status in my example):
greg@leonis:~$ grep status /etc/openvpn/server.conf status openvpn.status
Once that is happening, drop this code into a file and make it executable.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
STATUS = "/etc/openvpn/openvpn.status"
status_file = open(STATUS, 'r')
stats = status_file.readlines()
status_file.close()
hosts = []
headers = {
'cn': 'Common Name',
'virt': 'Virtual Address',
'real': 'Real Address',
'sent': 'Sent',
'recv': 'Received',
'since': 'Connected Since'
}
sizes = [
(1<<50L, 'PB'),
(1<<40L, 'TB'),
(1<<30L, 'GB'),
(1<<20L, 'MB'),
(1<<10L, 'KB'),
(1, 'B')
]
def byte2str(size):
for f, suf in sizes:
if size >= f:
break
return "%.2f %s" % (size / float(f), suf)
for line in stats:
cols = line.split(',')
if len(cols) == 5 and not line.startswith('Common Name'):
host = {}
host['cn'] = cols[0]
host['real'] = cols[1].split(':')[0]
host['recv'] = byte2str(int(cols[2]))
host['sent'] = byte2str(int(cols[3]))
host['since'] = cols[4].strip()
hosts.append(host)
if len(cols) == 4 and not line.startswith('Virtual Address'):
for h in hosts:
if h['cn'] == cols[1]:
h['virt'] = cols[0]
fmt = "%(cn)-25s %(virt)-18s %(real)-15s %(sent)13s %(recv)13s %(since)25s"
print fmt % headers
print "\n".join([fmt % h for h in hosts])
Run something as another user
Here is a simple way to run something on UNIX / Linux as another user, without having to resort to weird sudo incantations. The Makefile is left as an exercise for the reader.
This has only been tested on FreeBSD, Debian Linux and OpenSolaris so far.
Compile with: cc -o setuid setuid.c
#include <stdio.h>
#include <sys/types.h>
#include <pwd.h>
#include <grp.h>
int main(int argc, const char **argv) {
/* Check command line */
if (argc < 3) {
fprintf(stderr, "Usage: %s user cmd\n", argv[0]);
return 1;
}
struct passwd *pw;
pw = getpwnam(argv[1]);
if (pw==NULL) {
fprintf(stderr, "User not found\n");
return 1;
}
if (initgroups(argv[1], pw->pw_gid)==-1) {
perror("initgroups");
return 1;
}
if (setregid(pw->pw_gid, pw->pw_gid)==0 &&
setreuid(pw->pw_uid, pw->pw_uid)==0) {
argv += 2;
execvp(argv[0], argv);
perror("exec");
return 1;
}
perror("setre[gu]id");
return 1;
}