pop3d_udb.tcl
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 namespace ::pop3d::udb {
00014
00015
00016
00017
00018
00019
00020 variable counter 0
00021
00022
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
00040
00041
00042
00043
00044
00045
00046
00047
00048
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
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
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
00110
00111
00112
00113
00114
00115
00116
00117
00118
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
00303
00304 package provide pop3d::udb $::pop3d::udb::version
00305