# $Id: Text.pm,v 1.2 2003/01/16 19:41:31 lstein Exp $ package HTTPD::UserAdmin::Text; use HTTPD::UserAdmin (); use Carp (); use strict; use vars qw(@ISA $DLM $VERSION); @ISA = qw(HTTPD::UserAdmin::DBM HTTPD::UserAdmin); $VERSION = (qw$Revision: 1.2 $)[1]; $DLM = ":"; my %Default = (PATH => ".", DB => ".htpasswd", FLAGS => "rwc", ); sub new { my($class) = shift; my $self = bless { %Default, @_ }, $class; #load the DBM methods $self->load("HTTPD::UserAdmin::DBM"); $self->db($self->{DB}); return $self; } #do this so we can borrow from the DBM class sub _tie { my($self) = @_; my($fh,$db) = ($self->gensym(), $self->{DB}); printf STDERR "%s->_tie($db)\n", $self->class if $self->debug; $db =~ /^([^<>;|]+)$/ or Carp::croak("Bad file name '$db'"); $db = $1; #untaint open($fh, $db) or return; my($key,$val); while(<$fh>) { #slurp! need a better method here. ($key,$val) = $self->_parseline($fh, $_); $self->{'_HASH'}{$key} = $val; } CORE::close $fh; } sub _untie { my($self) = @_; return unless exists $self->{'_HASH'}; $self->commit; delete $self->{'_HASH'}; } sub commit { my($self) = @_; return if $self->readonly; my($fh,$db) = ($self->gensym(), $self->{DB}); my($key,$val); $db =~ /^([^<>;|]+)$/ or return (0, "Bad file name '$db'"); $db = $1; #untaint my $tmp_db = "$db.$$"; # Use temp file until write is complete. open($fh, ">$tmp_db") or return (0, "open: '$tmp_db' $!"); while(($key,$val) = each %{$self->{'_HASH'}}) { print $fh $self->_formatline($key,$val) or return (0, "print: '$tmp_db' failed: $!"); } CORE::close $fh or return (0, "close: '$tmp_db' failed: $!"); my $mode = (stat $db)[2]; chmod $mode, $tmp_db if $mode; rename( $tmp_db,$db ) or return (0, "rename '$tmp_db' to '$db' failed: $!"); 1; } sub _parseline { my($self,$fh,$line) = @_; chomp $line; my($key, $val) = split($DLM, $line, 2); return ($key,$val); } sub _formatline { my($self,$key,$val) = @_; join($DLM, $key,$val) . "\n"; } package HTTPD::UserAdmin::Text::_generic; use vars qw(@ISA); @ISA = qw(HTTPD::UserAdmin::Text HTTPD::UserAdmin::DBM); 1; __END__