initialized a basic htpasswd web interface
* imported http://trac.edgewall.org/export/9825/trunk/contrib/htpasswd.py * improved file handling and items management
This commit is contained in:
commit
ea8a8d8d80
1 changed files with 100 additions and 0 deletions
100
htpasswd.py
Normal file
100
htpasswd.py
Normal file
|
@ -0,0 +1,100 @@
|
|||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
$Id$
|
||||
|
||||
A python module for managing htpasswd files.
|
||||
|
||||
The code is based on http://trac.edgewall.org/export/9825/trunk/contrib/htpasswd.py
|
||||
Original author: Eli Carter
|
||||
|
||||
Copyright 2010 Lars Kruse <devel@sumpfralle.de>
|
||||
Copyright before 2010 Eli Carter
|
||||
|
||||
This module is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This module is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with This module. If not, see <http://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
import crypt
|
||||
import shutil
|
||||
import tempfile
|
||||
import random
|
||||
import os
|
||||
|
||||
|
||||
def _get_random_salt():
|
||||
"""Returns a string of 2 random letters"""
|
||||
letters = 'abcdefghijklmnopqrstuvwxyz' \
|
||||
'ABCDEFGHIJKLMNOPQRSTUVWXYZ' \
|
||||
'0123456789/.'
|
||||
return random.choice(letters) + random.choice(letters)
|
||||
|
||||
|
||||
class HtpasswdFile:
|
||||
"""A class for manipulating htpasswd files."""
|
||||
|
||||
def __init__(self, filename, create=False):
|
||||
self.entries = {}
|
||||
self.filename = filename
|
||||
if not create:
|
||||
self.load()
|
||||
|
||||
def load(self):
|
||||
"""Read the htpasswd file into memory.
|
||||
This function may raise an IOError exception.
|
||||
"""
|
||||
self.entries = {}
|
||||
for line in open(self.filename, 'r').readlines():
|
||||
username, pwhash = line.split(':', 1)
|
||||
self.entries[username] = pwhash
|
||||
|
||||
def save(self):
|
||||
"""Write the htpasswd file to disk
|
||||
The file is written in a safe manner: first a temporary file with the
|
||||
resulting content is created in the directory of the original file.
|
||||
Afterwards it is moved to the original filename.
|
||||
This function may raise an IOError exception.
|
||||
"""
|
||||
# create a temporary file besides the original file
|
||||
temp_file, temp_filename = tempfile.mkstemp(
|
||||
dir=os.path.dirname(self.filename), text=True)
|
||||
try:
|
||||
if os.path.isfile(self.filename):
|
||||
# copy the original file mode (mod, timestamps)
|
||||
shutil.copystat(self.filename, temp_filename)
|
||||
for name, pwhash in self.entries.items():
|
||||
os.write(temp_file, "%s:%s%s" % (name, pwhash, os.linesep))
|
||||
os.close(temp_file)
|
||||
except IOError:
|
||||
try:
|
||||
os.remove(temp_filename)
|
||||
except IOError:
|
||||
# ignore errors during failure handling
|
||||
pass
|
||||
else:
|
||||
# move the temporary file to the original filename
|
||||
os.rename(temp_filename, self.filename)
|
||||
|
||||
def update(self, username, password):
|
||||
"""Replace the entry for the given user, or add it if new."""
|
||||
pwhash = crypt.crypt(password, _get_random_salt())
|
||||
self.entries[username] = pwhash
|
||||
|
||||
def delete(self, username):
|
||||
"""Remove the entry for the given user."""
|
||||
if username in self.entries:
|
||||
self.entries.pop(username)
|
||||
|
||||
def get_usernames(self):
|
||||
return self.entries.keys()
|
||||
|
Loading…
Reference in a new issue