[svn-commits] tilghman: trunk r107721 - in /trunk: configs/ contrib/scripts/

SVN commits to the Digium repositories svn-commits at lists.digium.com
Tue Mar 11 15:58:43 CDT 2008


Author: tilghman
Date: Tue Mar 11 15:58:42 2008
New Revision: 107721

URL: http://svn.digium.com/view/asterisk?view=rev&rev=107721
Log:
Add contributed script for separation of database access from Asterisk

Added:
    trunk/configs/dbsep.conf.sample   (with props)
    trunk/contrib/scripts/dbsep.cgi   (with props)

Added: trunk/configs/dbsep.conf.sample
URL: http://svn.digium.com/view/asterisk/trunk/configs/dbsep.conf.sample?view=auto&rev=107721
==============================================================================
--- trunk/configs/dbsep.conf.sample (added)
+++ trunk/configs/dbsep.conf.sample Tue Mar 11 15:58:42 2008
@@ -1,0 +1,35 @@
+#
+# Configuration file for dbsep.cgi
+#
+# The purpose of this file is to provide realtime access to a database,
+# possibly through ODBC, without needing to load the ODBC drivers into
+# Asterisk, since there are several backend drivers which are rather
+# buggy.
+#
+# We accomplish this separation by using the res_config_curl realtime
+# driver to connect to a server running dbsep.cgi (or another, which
+# implements the same protocol).
+#
+# This file contains the information necessary to configure dbsep.cgi.
+#
+#
+# Once installed to a web server, you'll need to preload func_curl.so
+# and res_config_curl.so in modules.conf and configure extconfig.conf:
+#
+# voicemail => curl,http://server/path/to/dbsep.cgi/voicemail
+# sippeers => curl,http://server/path/to/dbsep.cgi/sipfriends
+# sipusers => curl,http://server/path/to/dbsep.cgi/sipfriends
+#
+
+# The Data Source Name, as specified by the Perl DBI module.
+dsn=somedsn
+
+# Connected database user
+dbuser=someuser
+
+# And its password
+dbpass=password
+
+# For most databases, this is fine.  Set to 'no' for Sybase or MS SQL Server.
+backslash_is_escape=yes
+

Propchange: trunk/configs/dbsep.conf.sample
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: trunk/configs/dbsep.conf.sample
------------------------------------------------------------------------------
    svn:keywords = Id Date Revision Author

Propchange: trunk/configs/dbsep.conf.sample
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: trunk/contrib/scripts/dbsep.cgi
URL: http://svn.digium.com/view/asterisk/trunk/contrib/scripts/dbsep.cgi?view=auto&rev=107721
==============================================================================
--- trunk/contrib/scripts/dbsep.cgi (added)
+++ trunk/contrib/scripts/dbsep.cgi Tue Mar 11 15:58:42 2008
@@ -1,0 +1,209 @@
+#!/usr/bin/perl
+#
+# Copyright (c) 2008 Digium, Inc.
+#
+# Tilghman Lesher <dbsep.cgi at the-tilghman.com>
+#
+# See http://www.asterisk.org for more information about
+# the Asterisk project. Please do not directly contact
+# any of the maintainers of this project for assistance;
+# the project provides a web site, mailing lists and IRC
+# channels for your use.
+#
+# This program is free software, distributed under the terms of
+# the GNU General Public License Version 2. See the LICENSE file
+# at the top of the source tree.
+#
+# $Id$
+#
+
+use CGI;
+use DBI;
+use strict;
+
+my ($cgi, $dbh, %cfg, $table, $mode);
+
+# The following settings are expected:
+#
+# dsn=<some valid dsn>
+# dbuser=<user>
+# dbpass=<passwd>
+# backslash_is_escape={yes|no}
+#
+open CFG, "</etc/asterisk/dbsep.conf";
+while (<CFG>) {
+	chomp;
+	next if (m/^[#;]/);
+	next if (m/^\s*$/);
+	my ($name,$value) = split '=';
+	$cfg{lc($name)} = $value;
+}
+close CFG;
+
+$cgi = new CGI;
+
+$ENV{PATH_INFO} =~ m/\/([^\/]*)\/([^\/]*)$/;
+($table, $mode) = ($1, lc($2));
+
+print STDERR "PATH_INFO=$ENV{PATH_INFO}, table=$table, mode=$mode\n";
+
+if ($mode eq 'single') {
+	# All parameters as POST
+	my ($sql, $sth, $row, @answer);
+	$sql = "SELECT * FROM $table WHERE " . join(" AND ", cgi_to_where_clause($cgi, \%cfg));
+	$dbh = DBI->connect($cfg{dsn}, $cfg{dbuser}, $cfg{dbpass});
+	$sth = $dbh->prepare($sql) || throw_error("Invalid query: $sql");
+	$sth->execute() || throw_error("Invalid query: $sql");
+	$row = $sth->fetchrow_hashref();
+	foreach (keys %$row) {
+		push @answer, encode($_) . "=" . encode($row->{$_});
+	}
+	$sth->finish();
+	$dbh->disconnect();
+	print "Content-type: text/plain\n\n";
+	print join("&", @answer) . "\n";
+} elsif ($ENV{PATH_INFO} =~ m/multi$/) {
+	# All parameters as POST
+	my ($sql, $sth, @answer);
+	$sql = "SELECT * FROM $table WHERE " . join(" AND ", cgi_to_where_clause($cgi, \%cfg));
+	$dbh = DBI->connect($cfg{dsn}, $cfg{dbuser}, $cfg{dbpass});
+	$sth = $dbh->prepare($sql) || throw_error("Invalid query: $sql");
+	$sth->execute() || throw_error("Invalid query: $sql");
+	print "Content-type: text/plain\n\n";
+	while (my $row = $sth->fetchrow_hashref()) {
+		@answer = ();
+		foreach (keys %$row) {
+			push @answer, encode($_) . "=" . encode($row->{$_});
+		}
+		print join("&", @answer) . "\n";
+	}
+	$sth->finish();
+	$dbh->disconnect();
+} elsif ($ENV{PATH_INFO} =~ m/update$/) {
+	# where clause in GET, update parameters in POST
+	my (%get, @get, $sql, $name, $value, $affected);
+	foreach (split '&', $ENV{QUERY_STRING}) {
+		($name, $value) = split '=';
+		$name = decode($name);
+		next if (!isname($name));
+		$value = escape_value(decode($value));
+		if ($name =~ m/ /) {
+			push @get, "$name '$value'";
+		} else {
+			push @get, "$name='$value'";
+		}
+		$get{$name}++;
+	}
+	$sql = "SELECT " . join(",", cgi_to_where_clause($cgi, \%cfg, \%get)) . " FROM $table WHERE " . join(" AND ", @get);
+	$dbh = DBI->connect($cfg{dsn}, $cfg{dbuser}, $cfg{dbpass});
+	$affected = $dbh->do($sql);
+	$dbh->disconnect();
+	print "Content-type: text/html\n\n$affected\n";
+} elsif ($ENV{PATH_INFO} =~ m/store$/) {
+	# All parameters as POST
+	my (@param, $sql, @fields, @values, $affected);
+	foreach my $param (cgi_to_where_clause($cgi, \%cfg)) {
+		my ($name, $value) = split /=/, $param;
+		push @fields, $name;
+		push @values, $value;
+	}
+	$sql = "INSERT INTO $table (" . join(",", @fields) . ") VALUES (" . join(",", @values) . ")";
+	$dbh = DBI->connect($cfg{dsn}, $cfg{dbuser}, $cfg{dbpass});
+	$affected = $dbh->do($sql);
+	$dbh->disconnect();
+	print "Content-type: text/html\n\n$affected\n";
+} elsif ($ENV{PATH_INFO} =~ m/destroy$/) {
+	# All parameters as POST
+	my ($sql, $affected);
+	$sql = "DELETE FROM $table WHERE " . join(" AND ", cgi_to_where_clause($cgi, \%cfg));
+	$dbh = DBI->connect($cfg{dsn}, $cfg{dbuser}, $cfg{dbpass});
+	$affected = $dbh->do($sql);
+	$dbh->disconnect();
+	print "Content-type: text/html\n\n$affected\n";
+} elsif ($ENV{PATH_INFO} =~ m/static$/) {
+	# file parameter in GET, no POST
+	my (@get, $filename, $sql, $sth);
+	@get = split '&', $ENV{QUERY_STRING};
+	foreach (@get) {
+		my ($name, $value) = split '=';
+		if (decode($name) eq 'file') {
+			$filename = decode($value);
+			last;
+		}
+	}
+	$sql = "SELECT cat_metric, category, var_name, var_val FROM $table WHERE filename=" . escape_value($filename) . " AND commented=0 ORDER BY cat_metric DESC, var_metric ASC, category, var_name";
+	$dbh = DBI->connect($cfg{dsn}, $cfg{dbuser}, $cfg{dbpass});
+	$sth = $dbh->prepare($sql) || throw_error("Invalid query: $sql");
+	$sth->execute() || throw_error("Invalid query: $sql");
+	print "Content-type: text/plain\n\n";
+	while (my $row = $sth->fetchrow_hashref()) {
+		my @answer = ();
+		foreach (keys %$row) {
+			push @answer, encode($_) . "=" . encode($row->{$_});
+		}
+		print join("&", @answer) . "\n";
+	}
+	$sth->finish();
+	$dbh->disconnect();
+} else {
+	print "Content-type: text/plain\n\nUnknown query\n";
+}
+
+sub encode {
+	my ($stuff) = @_;
+	$stuff =~ s/([^a-zA-Z0-9_\.])/uc sprintf("%%%02x",ord($1))/eg;
+	return $stuff;
+}
+
+sub decode {
+	my ($stuff) = @_;
+	$stuff =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
+	return $stuff;
+}
+
+sub isname {
+	my ($name) = @_;
+	if ($name =~ m#[^A-Za-z0-9_ ]#) {
+		return 0;
+	} else {
+		return 1;
+	}
+}
+
+sub escape_value {
+	my ($value, $cfg) = @_;
+	if ($cfg->{backslash_is_escape} =~ m/^(no|0|false)$/i) {
+		$value =~ s#'#''#g;
+	} else {
+		$value =~ s#(['\\])#$1$1#g;
+	}
+	return $value;
+}
+
+sub cgi_to_where_clause {
+	my ($cgi, $cfg, $get) = @_;
+	my @param = ();
+
+	foreach my $name ($cgi->param()) {
+		my $value = escape_value($cgi->param($name), $cfg);
+
+		# Ensure name isn't funny-like
+		next if (!isname($name));
+		next if ($get->{$name});
+
+		if ($name =~ m# #) {
+			push @param, "$name '$value'";
+		} else {
+			push @param, "$name='$value'";
+		}
+	}
+	return join(" AND ", @param);
+}
+
+sub throw_error {
+	my ($msg) = @_;
+	print "Content-type: text/plain\n\n$msg\n";
+	print STDERR $msg . "\n";
+	exit;
+}
+

Propchange: trunk/contrib/scripts/dbsep.cgi
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: trunk/contrib/scripts/dbsep.cgi
------------------------------------------------------------------------------
    svn:executable = *

Propchange: trunk/contrib/scripts/dbsep.cgi
------------------------------------------------------------------------------
    svn:keywords = Id Revision Date Author

Propchange: trunk/contrib/scripts/dbsep.cgi
------------------------------------------------------------------------------
    svn:mime-type = text/plain




More information about the svn-commits mailing list