pop3d_udb.tcl

Go to the documentation of this file.
00001 /*  -*- tcl -*-*/
00002 /*  pop3d_udb.tcl --*/
00003 /* */
00004 /*  Implementation of a simple user database for the pop3 server*/
00005 /* */
00006 /*  Copyright (c) 2002 by Andreas Kupries*/
00007 /* */
00008 /*  See the file "license.terms" for information on usage and redistribution*/
00009 /*  of this file, and for a DISCLAIMER OF ALL WARRANTIES.*/
00010 /*  */
00011 /*  RCS: @(#) $Id: pop3d_udb.tcl,v 1.6 2004/01/15 06:36:13 andreas_kupries Exp $*/
00012 
00013 namespace ::pop3d::udb {
00014     /*  Data storage in the pop3d::udb module*/
00015     /*  -------------------------------------*/
00016     /*  One array per object containing the db contents. Keyed by user name.*/
00017     /*  And the information about the last file data was read from.*/
00018 
00019     /*  counter is used to give a unique name for unnamed databases*/
00020     variable counter 0
00021 
00022     /*  commands is the list of subcommands recognized by the server*/
00023     variable commands [list \
00024         "add"       \
00025         "destroy"           \
00026         "exists"        \
00027         "lookup"        \
00028         "read"      \
00029         "remove"        \
00030         "rename"        \
00031         "save"      \
00032         "who"       \
00033         ]
00034 
00035     variable version ;  version =  1.1
00036 }
00037 
00038 
00039 /*  ::pop3d::udb::new --*/
00040 /* */
00041 /*  Create a new user database with a given name; if no name is given, use*/
00042 /*  p3udbX, where X is a number.*/
00043 /* */
00044 /*  Arguments:*/
00045 /*  name    name of the user database; if null, generate one.*/
00046 /* */
00047 /*  Results:*/
00048 /*  name    name of the user database created*/
00049 
00050 ret  ::pop3d::udb::new (optional name ="") {
00051     variable counter
00052     
00053     if { [llength [info level 0]] == 1 } {
00054     incr counter
00055     set name "p3udb${counter}"
00056     }
00057 
00058     if { ![string equal [info commands ::$name] ""] } {
00059     return -code error \
00060         "command \"$name\" already exists,\
00061         unable to create user database"
00062     }
00063 
00064     # Set up the namespace
00065     namespace eval ::pop3d::udb::udb::$name {
00066     variable user     ;  array set user {}
00067     variable lastfile ""
00068     }
00069 
00070     # Create the command to manipulate the user database
00071     interp alias {} ::$name {} ::pop3d::udb::UdbProc $name
00072 
00073     return $name
00074 }
00075 
00076 /* */
00077 /*  Private functions follow*/
00078 
00079 /*  ::pop3d::udb::UdbProc --*/
00080 /* */
00081 /*  Command that processes all user database object commands.*/
00082 /* */
00083 /*  Arguments:*/
00084 /*  name    name of the user database object to manipulate.*/
00085 /*  args    command name and args for the command*/
00086 /* */
00087 /*  Results:*/
00088 /*  Varies based on command to perform*/
00089 
00090 ret  ::pop3d::udb::UdbProc (type name , optional cmd ="" , type args) {
00091 
00092     # Do minimal args checks here
00093     if { [llength [info level 0]] == 2 } {
00094     return -code error \
00095         "wrong # args: should be \"$name option ?arg arg ...?\""
00096     }
00097     
00098     # Split the args into command and args components
00099     if { [llength [info commands ::pop3d::udb::_$cmd]] == 0 } {
00100     variable commands
00101     set optlist [join $commands ", "]
00102     set optlist [linsert $optlist "end-1" "or"]
00103     return -code error "bad option \"$cmd\": must be $optlist"
00104     }
00105     eval [list ::pop3d::udb::_$cmd $name] $args
00106 }
00107 
00108 
00109 /*  ::pop3d::udb::_destroy --*/
00110 /* */
00111 /*  Destroy a user database, including its associated command and*/
00112 /*  data storage.*/
00113 /* */
00114 /*  Arguments:*/
00115 /*  name    Name of the database to destroy.*/
00116 /* */
00117 /*  Results:*/
00118 /*  None.*/
00119 
00120 ret  ::pop3d::udb::_destroy (type name) {
00121     namespace delete ::pop3d::udb::udb::$name
00122     interp alias {} ::$name {}
00123     return
00124 }
00125 
00126 
00127 ret  ::pop3d::udb::_add (type name , type usrName , type password , type storage) {
00128     # @c Add the user <a usrName> to the database, together with its
00129     # @c password and a storage reference. The latter is stored and passed
00130     # @c through this system without interpretation of the given value.
00131 
00132     # @a usrName:  The name of the user defined here.
00133     # @a password: Password given to the user.
00134     # @a storage:  symbolic reference to the maildrop of user <a usrName>.
00135     # @a storage:  Usable for a storage system only.
00136 
00137     if {$usrName  == {}} {return -code error "user specification missing"}
00138     if {$password == {}} {return -code error "password not specified"}
00139     if {$storage  == {}} {return -code error "storage location not defined"}
00140 
00141     upvar ::pop3d::udb::udb::${name}::user user
00142 
00143     set      user($usrName) [list $password $storage]
00144     return
00145 }
00146 
00147 
00148 ret  ::pop3d::udb::_remove (type name , type usrName) {
00149     # @c Remove the user <a usrName> from the database.
00150     #
00151     # @a usrName: The name of the user to remove.
00152 
00153     if {$usrName == {}} {return -code error "user specification missing"}
00154 
00155     upvar ::pop3d::udb::udb::${name}::user user
00156 
00157     if {![::info exists user($usrName)]} {
00158     return -code error "user \"$usrName\" not known"
00159     }
00160 
00161     unset user($usrName)
00162     return
00163 }
00164 
00165 
00166 ret  ::pop3d::udb::_rename (type name , type usrName , type newName) {
00167     # @c Renames user <a usrName> to <a newName>.
00168     # @a usrName: The name of the user to rename.
00169     # @a newName: The new name to give to the user
00170 
00171     if {$usrName == {}} {return -code error "user specification missing"}
00172     if {$newName == {}} {return -code error "user specification missing"}
00173 
00174     upvar ::pop3d::udb::udb::${name}::user user
00175 
00176     if {![::info exists user($usrName)]} {
00177     return -code error "user \"$usrName\" not known"
00178     }
00179     if {[::info exists user($newName)]} {
00180     return -code error "user \"$newName\" is known"
00181     }
00182 
00183     set data $user($usrName)
00184     unset     user($usrName)
00185 
00186     set user($newName) $data
00187     return
00188 }
00189 
00190 
00191 ret  ::pop3d::udb::_lookup (type name , type usrName) {
00192     # @c Query database for information about user <a usrName>.
00193     # @c Overrides <m userdbBase:lookup>.
00194     # @a usrName: Name of the user to query for.
00195     # @r a 2-element list containing password and storage 
00196     # @r reference for user <a usrName>, in this order.
00197 
00198     upvar ::pop3d::udb::udb::${name}::user user
00199 
00200     if {![::info exists user($usrName)]} {
00201     return -code error "user \"$usrName\" not known"
00202     }
00203     return $user($usrName)
00204 }
00205 
00206 
00207 ret  ::pop3d::udb::_exists (type name , type usrName) {
00208     # @c Determines wether user <a usrName> is registered or not.
00209     # @a usrName:     The name of the user to check for.
00210 
00211     upvar ::pop3d::udb::udb::${name}::user user
00212 
00213     return [::info exists user($usrName)]
00214 }
00215 
00216 
00217 ret  ::pop3d::udb::_who (type name) {
00218     # @c Determines the names of all registered users.
00219     # @r A list containing the names of all registered users.
00220 
00221     upvar ::pop3d::udb::udb::${name}::user user
00222 
00223     return [array names user]
00224 }
00225 
00226 
00227 ret  ::pop3d::udb::_save (type name , optional file ={)} {
00228     # @c Stores the current contents of the in-memory user database
00229     # @c into the specified file.
00230 
00231     # @a file: The name of the file to write to. If it is not specified, or
00232     # @a file: as empty, the value of the member variable <v externalFile>
00233     # @a file: is used instead.
00234 
00235     # save operation: do a backup of the file, write new contents,
00236     # restore backup in case of problems.
00237 
00238     upvar ::pop3d::udb::udb::${name}::user user
00239     upvar ::pop3d::udb::udb::${name}::lastfile lastfile
00240 
00241     if {$file == {}} {
00242      file =  $lastfile
00243     }
00244     if {$file == {}} {
00245     return -code error "No file known to save data into"
00246     }
00247 
00248      tmp =  [file join [file dirname $file] [pid]]
00249 
00250        f =  [open $tmp w]
00251     puts $f "/*  -*- tcl -*-"*/
00252     puts $f "/*  ----------- user authentication database -"*/
00253     puts $f ""
00254 
00255     foreach name [array names user] {
00256      password =  [lindex $user($name) 0]
00257      storage =   [lindex $user($name) 1]
00258 
00259     puts $f "\tadd [list $name] [list $password] [list $storage]"
00260     }
00261 
00262     puts  $f ""
00263     close $f
00264     
00265     if {[file exists $file]} {
00266     file rename -force $file $file.old
00267     }
00268     file rename -force $tmp $file
00269     return
00270 }
00271 
00272 
00273 ret  ::pop3d::udb::_read (type name , type path) {
00274     # @c Reads the contents of the specified <a path> into the in-memory
00275     # @c database of users, passwords and storage references.
00276 
00277     # @a path: The name of the file to read.
00278 
00279     # @n The name of the file is remembered internally, and used by
00280     # @n <m save> (if called without or empty argument).
00281 
00282     upvar ::pop3d::udb::udb::${name}::user user
00283     upvar ::pop3d::udb::udb::${name}::lastfile lastfile
00284 
00285     if {$path == {}} {
00286     return -code error "No file known to read from"
00287     }
00288 
00289     set lastfile $path
00290 
00291     foreach key [array names user] {unset user($key)}
00292 
00293     set ip [interp create -safe]
00294     interp alias $ip add {} ::pop3d::udb::_add $name
00295     $ip invokehidden -global source $path
00296     interp delete $ip
00297 
00298     return
00299 }
00300 
00301 /* */
00302 /*  Module initialization*/
00303 
00304 package provide pop3d::udb $::pop3d::udb::version
00305 

Generated on 21 Sep 2010 for Gui by  doxygen 1.6.1