summaryrefslogtreecommitdiff
path: root/FS/FS/Conf.pm
diff options
context:
space:
mode:
Diffstat (limited to 'FS/FS/Conf.pm')
-rw-r--r--FS/FS/Conf.pm263
1 files changed, 126 insertions, 137 deletions
diff --git a/FS/FS/Conf.pm b/FS/FS/Conf.pm
index 5f7cb8fec..1c552a4bd 100644
--- a/FS/FS/Conf.pm
+++ b/FS/FS/Conf.pm
@@ -1,14 +1,13 @@
package FS::Conf;
-use vars qw($base_dir @config_items @card_types $DEBUG );
-use MIME::Base64;
+use vars qw($default_dir $base_dir @config_items @card_types $DEBUG );
+use IO::File;
+use File::Basename;
use FS::ConfItem;
use FS::ConfDefaults;
-use FS::conf;
-use FS::Record qw(qsearch qsearchs);
-use FS::UID qw(dbh);
$base_dir = '%%%FREESIDE_CONF%%%';
+$default_dir = '%%%FREESIDE_CONF%%%';
$DEBUG = 0;
@@ -21,8 +20,13 @@ FS::Conf - Freeside configuration values
use FS::Conf;
+ $conf = new FS::Conf "/config/directory";
+
+ $FS::Conf::default_dir = "/config/directory";
$conf = new FS::Conf;
+ $dir = $conf->dir;
+
$value = $conf->config('key');
@list = $conf->config('key');
$bool = $conf->exists('key');
@@ -42,19 +46,39 @@ but this may change in the future.
=over 4
-=item new
+=item new [ DIRECTORY ]
-Create a new configuration object.
+Create a new configuration object. A directory arguement is required if
+$FS::Conf::default_dir has not been set.
=cut
sub new {
- my($proto) = @_;
+ my($proto,$dir) = @_;
my($class) = ref($proto) || $proto;
- my($self) = { 'base_dir' => $base_dir };
+ my($self) = { 'dir' => $dir || $default_dir,
+ 'base_dir' => $base_dir,
+ };
bless ($self, $class);
}
+=item dir
+
+Returns the conf directory.
+
+=cut
+
+sub dir {
+ my($self) = @_;
+ my $dir = $self->{dir};
+ -e $dir or die "FATAL: $dir doesn't exist!";
+ -d $dir or die "FATAL: $dir isn't a directory!";
+ -r $dir or die "FATAL: Can't read $dir!";
+ -x $dir or die "FATAL: $dir not searchable (executable)!";
+ $dir =~ /^(.*)$/;
+ $1;
+}
+
=item base_dir
Returns the base directory. By default this is /usr/local/etc/freeside.
@@ -78,29 +102,20 @@ Returns the configuration value or values (depending on context) for key.
=cut
-sub _config {
- my($self,$name,$agent)=@_;
- my $hashref = { 'name' => $name };
- if (defined($agent) && $agent) {
- $hashref->{agent} = $agent;
- }
- local $FS::Record::conf = undef; # XXX evil hack prevents recursion
- my $cv = FS::Record::qsearchs('conf', $hashref);
- if (!$cv && exists($hashref->{agent})) {
- delete($hashref->{agent});
- $cv = FS::Record::qsearchs('conf', $hashref);
- }
- return $cv;
-}
-
sub config {
- my($self,$name,$agent)=@_;
- my $cv = $self->_config($name, $agent) or return;
-
+ my($self,$file)=@_;
+ my($dir)=$self->dir;
+ my $fh = new IO::File "<$dir/$file" or return;
if ( wantarray ) {
- split "\n", $cv->value;
+ map {
+ /^(.*)$/
+ or die "Illegal line (array context) in $dir/$file:\n$_\n";
+ $1;
+ } <$fh>;
} else {
- (split("\n", $cv->value))[0];
+ <$fh> =~ /^(.*)$/
+ or die "Illegal line (scalar context) in $dir/$file:\n$_\n";
+ $1;
}
}
@@ -111,9 +126,12 @@ Returns the exact scalar value for key.
=cut
sub config_binary {
- my($self,$name,$agent)=@_;
- my $cv = $self->_config($name, $agent) or return;
- decode_base64($cv->value);
+ my($self,$file)=@_;
+ my($dir)=$self->dir;
+ my $fh = new IO::File "<$dir/$file" or return;
+ local $/;
+ my $content = <$fh>;
+ $content;
}
=item exists KEY
@@ -124,8 +142,9 @@ is undefined.
=cut
sub exists {
- my($self,$name,$agent)=@_;
- defined($self->_config($name, $agent));
+ my($self,$file)=@_;
+ my($dir) = $self->dir;
+ -e "$dir/$file";
}
=item config_orbase KEY SUFFIX
@@ -136,11 +155,11 @@ KEY_SUFFIX, if it exists, otherwise for KEY
=cut
sub config_orbase {
- my( $self, $name, $suffix ) = @_;
- if ( $self->exists("${name}_$suffix") ) {
- $self->config("${name}_$suffix");
+ my( $self, $file, $suffix ) = @_;
+ if ( $self->exists("${file}_$suffix") ) {
+ $self->config("${file}_$suffix");
} else {
- $self->config($name);
+ $self->config($file);
}
}
@@ -151,8 +170,12 @@ Creates the specified configuration key if it does not exist.
=cut
sub touch {
- my($self, $name, $agent) = @_;
- $self->set($name, '', $agent);
+ my($self, $file) = @_;
+ my $dir = $self->dir;
+ unless ( $self->exists($file) ) {
+ warn "[FS::Conf] TOUCH $file\n" if $DEBUG;
+ system('touch', "$dir/$file");
+ }
}
=item set KEY VALUE
@@ -162,41 +185,23 @@ Sets the specified configuration key to the given value.
=cut
sub set {
- my($self, $name, $value, $agent) = @_;
+ my($self, $file, $value) = @_;
+ my $dir = $self->dir;
$value =~ /^(.*)$/s;
$value = $1;
-
- warn "[FS::Conf] SET $file\n" if $DEBUG;
-
- my $old = FS::Record::qsearchs('conf', {name => $name, agent => $agent});
- my $new = new FS::conf { $old ? $old->hash
- : ('name' => $name, 'agent' => $agent)
- };
- $new->value($value);
-
- my $error;
- if ($old) {
- $error = $new->replace($old);
- } else {
- $error = $new->insert;
+ unless ( join("\n", @{[ $self->config($file) ]}) eq $value ) {
+ warn "[FS::Conf] SET $file\n" if $DEBUG;
+# warn "$dir" if is_tainted($dir);
+# warn "$dir" if is_tainted($file);
+ chmod 0644, "$dir/$file";
+ my $fh = new IO::File ">$dir/$file" or return;
+ chmod 0644, "$dir/$file";
+ print $fh "$value\n";
}
-
- die "error setting configuration value: $error \n"
- if $error;
-
-}
-
-=item set_binary KEY VALUE
-
-Sets the specified configuration key to an exact scalar value which
-can be retrieved with config_binary.
-
-=cut
-
-sub set_binary {
- my($self,$name, $value, $agent)=@_;
- $self->set($name, encode_base64($value), $agent);
}
+#sub is_tainted {
+# return ! eval { join('',@_), kill 0; 1; };
+# }
=item delete KEY
@@ -205,23 +210,11 @@ Deletes the specified configuration key.
=cut
sub delete {
- my($self, $name, $agent) = @_;
- if ( my $cv = FS::Record::qsearchs('conf', {name => $name, agent => $agent}) ) {
+ my($self, $file) = @_;
+ my $dir = $self->dir;
+ if ( $self->exists($file) ) {
warn "[FS::Conf] DELETE $file\n";
-
- my $oldAutoCommit = $FS::UID::AutoCommit;
- local $FS::UID::AutoCommit = 0;
- my $dbh = dbh;
-
- my $error = $cv->delete;
-
- if ( $error ) {
- $dbh->rollback if $oldAutoCommit;
- die "error setting configuration value: $error \n"
- }
-
- $dbh->commit or die $dbh->errstr if $oldAutoCommit;
-
+ unlink "$dir/$file";
}
}
@@ -237,68 +230,65 @@ sub config_items {
#quelle kludge
@config_items,
( map {
+ my $basename = basename($_);
+ $basename =~ /^(.*)$/;
+ $basename = $1;
new FS::ConfItem {
- 'key' => $_->name,
+ 'key' => $basename,
'section' => 'billing',
'description' => 'Alternate template file for invoices. See the <a href="../docs/billing.html">billing documentation</a> for details.',
'type' => 'textarea',
}
- } FS::Record::qsearch('conf', {}, '', "WHERE name LIKE 'invoice!_template!_%' ESCAPE '!'")
+ } glob($self->dir. '/invoice_template_*')
),
( map {
+ my $basename = basename($_);
+ $basename =~ /^(.*)$/;
+ $basename = $1;
new FS::ConfItem {
- 'key' => '$_->name',
- 'section' => 'billing', #?
- 'description' => 'An image to include in some types of invoices',
- 'type' => 'binary',
- }
- } FS::Record::qsearch('conf', {}, '', "WHERE name LIKE 'logo!_%.png' ESCAPE '!'")
- ),
- ( map {
- new FS::ConfItem {
- 'key' => $_->name,
+ 'key' => $basename,
'section' => 'billing',
'description' => 'Alternate HTML template for invoices. See the <a href="../docs/billing.html">billing documentation</a> for details.',
'type' => 'textarea',
}
- } FS::Record::qsearch('conf', {}, '', "WHERE name LIKE 'invoice!_html!_%' ESCAPE '!'")
+ } glob($self->dir. '/invoice_html_*')
),
( map {
- ($latexname = $_->name ) =~ s/latex/html/;
+ my $basename = basename($_);
+ $basename =~ /^(.*)$/;
+ $basename = $1;
+ ($latexname = $basename ) =~ s/latex/html/;
new FS::ConfItem {
- 'key' => $_->name,
+ 'key' => $basename,
'section' => 'billing',
'description' => "Alternate Notes section for HTML invoices. Defaults to the same data in $latexname if not specified.",
'type' => 'textarea',
}
- } FS::Record::qsearch('conf', {}, '', "WHERE name LIKE 'invoice!_htmlnotes!_%' ESCAPE '!'")
+ } glob($self->dir. '/invoice_htmlnotes_*')
),
( map {
+ my $basename = basename($_);
+ $basename =~ /^(.*)$/;
+ $basename = $1;
new FS::ConfItem {
- 'key' => $_->name,
+ 'key' => $basename,
'section' => 'billing',
'description' => 'Alternate LaTeX template for invoices. See the <a href="../docs/billing.html">billing documentation</a> for details.',
'type' => 'textarea',
}
- } FS::Record::qsearch('conf', {}, '', "WHERE name LIKE 'invoice!_latex!_%' ESCAPE '!'")
- ),
- ( map {
- new FS::ConfItem {
- 'key' => '$_->name',
- 'section' => 'billing', #?
- 'description' => 'An image to include in some types of invoices',
- 'type' => 'binary',
- }
- } FS::Record::qsearch('conf', {}, '', "WHERE name LIKE 'logo!_%.eps' ESCAPE '!'")
+ } glob($self->dir. '/invoice_latex_*')
),
( map {
+ my $basename = basename($_);
+ $basename =~ /^(.*)$/;
+ $basename = $1;
new FS::ConfItem {
- 'key' => $_->name,
+ 'key' => $basename,
'section' => 'billing',
'description' => 'Alternate Notes section for LaTeX typeset PostScript invoices. See the <a href="../docs/billing.html">billing documentation</a> for details.',
'type' => 'textarea',
}
- } FS::Record::qsearch('conf', {}, '', "WHERE name LIKE 'invoice!_latexnotes!_%' ESCAPE '!'")
+ } glob($self->dir. '/invoice_latexnotes_*')
);
}
@@ -1852,6 +1842,26 @@ httemplate/docs/config.html
'type' => 'checkbox',
},
+ #these should become per-user...
+ {
+ 'key' => 'vonage-username',
+ 'section' => '',
+ 'description' => 'Vonage Click2Call username (see <a href="https://secure.click2callu.com/">https://secure.click2callu.com/</a>)',
+ 'type' => 'text',
+ },
+ {
+ 'key' => 'vonage-password',
+ 'section' => '',
+ 'description' => 'Vonage Click2Call username (see <a href="https://secure.click2callu.com/">https://secure.click2callu.com/</a>)',
+ 'type' => 'text',
+ },
+ {
+ 'key' => 'vonage-fromnumber',
+ 'section' => '',
+ 'description' => 'Vonage Click2Call number (see <a href="https://secure.click2callu.com/">https://secure.click2callu.com/</a>)',
+ 'type' => 'text',
+ },
+
{
'key' => 'echeck-nonus',
'section' => 'billing',
@@ -2036,27 +2046,6 @@ httemplate/docs/config.html
},
{
- 'key' => 'logo.png',
- 'section' => 'billing', #?
- 'description' => 'An image to include in some types of invoices',
- 'type' => 'binary',
- },
-
- {
- 'key' => 'logo.eps',
- 'section' => 'billing', #?
- 'description' => 'An image to include in some types of invoices',
- 'type' => 'binary',
- },
-
- {
- 'key' => 'selfservice-ignore_quantity',
- 'section' => '',
- 'description' => 'Ignores service quantity restrictions in self-service context. Strongly not recommended - just set your quantities correctly in the first place.',
- 'type' => 'checkbox',
- },
-
- {
'key' => 'disable_setup_suspended_pkgs',
'section' => 'billing',
'description' => 'Disables charging of setup fees for suspended packages.',