rename package directory
This commit is contained in:
parent
8299b9aca0
commit
dd64ba59b4
47 changed files with 0 additions and 0 deletions
1
debianmemberportfolio/model/.gitignore
vendored
Normal file
1
debianmemberportfolio/model/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
keyringcache
|
26
debianmemberportfolio/model/__init__.py
Normal file
26
debianmemberportfolio/model/__init__.py
Normal file
|
@ -0,0 +1,26 @@
|
|||
# -*- python -*-
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# DDPortfolio service model package
|
||||
# Copyright (c) 2009 Jan Dittberner <jan@dittberner.info>
|
||||
#
|
||||
# This file is part of DDPortfolio service.
|
||||
#
|
||||
# DDPortfolio service is free software: you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Affero General Public License
|
||||
# as published by the Free Software Foundation, either version 3 of
|
||||
# the License, or (at your option) any later version.
|
||||
#
|
||||
# DDPortfolio service 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
|
||||
# Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public
|
||||
# License along with this program. If not, see
|
||||
# <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
"""
|
||||
Model classes and model related utilities for the Debian Member Portfolio
|
||||
service.
|
||||
"""
|
54
debianmemberportfolio/model/dddatabuilder.py
Normal file
54
debianmemberportfolio/model/dddatabuilder.py
Normal file
|
@ -0,0 +1,54 @@
|
|||
# -*- python -*-
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# DDPortfolio service DD data builder
|
||||
# Copyright © 2009, 2010 Jan Dittberner <jan@dittberner.info>
|
||||
#
|
||||
# This file is part of DDPortfolio service.
|
||||
#
|
||||
# DDPortfolio service is free software: you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Affero General Public License
|
||||
# as published by the Free Software Foundation, either version 3 of
|
||||
# the License, or (at your option) any later version.
|
||||
#
|
||||
# DDPortfolio service 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
|
||||
# Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public
|
||||
# License along with this program. If not, see
|
||||
# <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
"""This file contains code to build a representation of a person based
|
||||
on keyring data associated to a given email address."""
|
||||
import logging
|
||||
from ddportfolioservice.model import keyfinder
|
||||
|
||||
TYPE_NO = 0
|
||||
TYPE_DM = 1
|
||||
TYPE_DD = 2
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def build_data(email_address):
|
||||
"""Build a DD data structure from a given email address."""
|
||||
fields = dict([(field, func(str(email_address))) \
|
||||
for (field, func) in \
|
||||
[('gpgfp', keyfinder.getFingerprintByEmail),
|
||||
('name', keyfinder.getRealnameByEmail),
|
||||
('username', keyfinder.getLoginByEmail)]])
|
||||
fields['email'] = email_address
|
||||
if fields['username'] and fields['gpgfp'] and fields['name']:
|
||||
fields['type'] = TYPE_DD
|
||||
elif fields['name'] and fields['gpgfp']:
|
||||
fields['type'] = TYPE_DM
|
||||
else:
|
||||
fields['type'] = TYPE_NO
|
||||
if fields['name']:
|
||||
log.debug('generate wikihomepage from name')
|
||||
fields['wikihomepage'] = "".join(
|
||||
[part.capitalize() for part in fields['name'].split()])
|
||||
|
||||
return fields
|
124
debianmemberportfolio/model/ddportfolio.ini
Normal file
124
debianmemberportfolio/model/ddportfolio.ini
Normal file
|
@ -0,0 +1,124 @@
|
|||
#
|
||||
# Configuration for Debian Member Portfolio Service
|
||||
#
|
||||
# Copyright © 2009-2014 Jan Dittberner <jan@dittberner.info>
|
||||
#
|
||||
# This file is part of the Debian Member Portfolio Service.
|
||||
#
|
||||
# Debian Member Portfolio Service is free software: you can redistribute it
|
||||
# and/or modify it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the License,
|
||||
# or (at your option) any later version.
|
||||
#
|
||||
# Debian Member Portfolio Service 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 Affero
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
[DEFAULT]
|
||||
gnupghome=~/debian/gnupghome
|
||||
keyring.dir=~/debian/keyring.debian.org/keyrings
|
||||
urlbuilder.sections=overview,bugs,build,qa,lists,files,membership,
|
||||
miscellaneous,ssh,ubuntu
|
||||
|
||||
[overview]
|
||||
urls=ddpo,alladdresses
|
||||
ddpo.pattern=http://qa.debian.org/developer.php?login=%(email)s
|
||||
alladdresses.pattern=http://qa.debian.org/developer.php?login=%(name)s
|
||||
|
||||
[bugs]
|
||||
urls=received,reported,usertags,searchall,wnpp,correspondent,graph
|
||||
received.pattern=http://bugs.debian.org/%(email)s
|
||||
reported.pattern=http://bugs.debian.org/from:%(email)s
|
||||
usertags.pattern=http://bugs.debian.org/cgi-bin/pkgreport.cgi?users=%(email)s
|
||||
searchall.pattern=http://bugs-search.debian.org/cgi-bin/search.cgi?phrase=%(name)s;search=search
|
||||
wnpp.pattern=http://qa.debian.org/developer.php?wnpp=%(email)s
|
||||
correspondent.pattern=http://bugs.debian.org/cgi-bin/pkgreport.cgi?correspondent=%(email)s
|
||||
graph.pattern=http://qa.debian.org/data/bts/graphs/by-maint/%(email)s.png
|
||||
|
||||
[build]
|
||||
urls=buildd
|
||||
buildd.pattern=https://buildd.debian.org/status/package.php?p=%(email)s&compact=compact&comaint=yes
|
||||
|
||||
[qa]
|
||||
urls=lintian,lintianfull,piuparts,patchtracker,dmd,duck
|
||||
dmd.pattern=http://udd.debian.org/dmd.cgi?email=%(email)s
|
||||
lintian.pattern=http://lintian.debian.org/maintainer/%(email)s.html
|
||||
lintianfull.pattern=http://lintian.debian.org/full/%(email)s.html
|
||||
piuparts.pattern=http://piuparts.debian.org/sid/maintainer/%(firstchar)s/%(email)s.html
|
||||
patchtracker.pattern=http://patch-tracker.debian.org/email/%(email)s
|
||||
duck.pattern=http://duck.debian.net/?sourcepackage=%(email)s
|
||||
|
||||
[lists]
|
||||
urls=dolists,adolists,gmane
|
||||
dolists.pattern=http://lists.debian.org/cgi-bin/search?author=%(name)s&sort=date
|
||||
adolists.pattern=http://www.google.com/search?q=site%%3Alists.alioth.debian.org+%%22%(name)s%%22
|
||||
gmane.pattern=http://search.gmane.org/?email=%(name)s&group=gmane.linux.debian.*
|
||||
# debconf list search has a tricky URL format
|
||||
# http://lists.debconf.org/lurker/search \
|
||||
# /20100510.202949.00000000@au:%(firstname)s,au:%(lastname)s.en.html
|
||||
# /YYYYMMDD.HHmmss.hashcode@au:%(firstname)s,au:%(lastname)s.en.html
|
||||
# maybe this could be implemented using some custom formatter function
|
||||
|
||||
[files]
|
||||
urls=people,alioth
|
||||
people.pattern=http://people.debian.org/~%(username)s/
|
||||
people.optional=true
|
||||
alioth.pattern=http://alioth.debian.org/~%(aliothusername)s/
|
||||
alioth.optional=true
|
||||
|
||||
[membership]
|
||||
urls=nm,dbfinger,db,webid,alioth,wiki,forum
|
||||
nm.pattern=https://nm.debian.org/public/nmstatus/%(username)s
|
||||
dbfinger.pattern=finger %(username)s@db.debian.org
|
||||
dbfinger.type=finger
|
||||
dbfinger.optional=true
|
||||
db.pattern=http://db.debian.org/search.cgi?uid=%(username)s&dosearch=Search
|
||||
db.optional=true
|
||||
webid.pattern=http://webid.debian.net/maintainers/%(username)s
|
||||
webid.optional=true
|
||||
alioth.pattern=http://alioth.debian.org/users/%(aliothusername)s/
|
||||
alioth.optional=true
|
||||
wiki.pattern=http://wiki.debian.org/%(wikihomepage)s
|
||||
forum.pattern=http://forums.debian.net/memberlist.php?mode=viewprofile&u=%(forumsid)d
|
||||
forum.optional=true
|
||||
|
||||
[miscellaneous]
|
||||
urls=debtags,links,planetname,planetuser,website,search,gpgfinger,gpgweb,contrib
|
||||
debtags.pattern=http://debtags.debian.net/reports/maint/%(email)s
|
||||
planetname.pattern=http://planet-search.debian.org/cgi-bin/search.cgi?terms=%%22%(name)s%%22
|
||||
planetuser.pattern=http://planet-search.debian.org/cgi-bin/search.cgi?terms=%%22%(username)s%%22
|
||||
planetuser.optional=true
|
||||
links.pattern=http://www.google.com/search?hl=en&lr=&q=site%%3Adebian.org+%%22%(name)s%%22+-site%%3Anm.debian.org+-site%%3Alintian.debian.org+-site%%3Abugs.debian.org+-site%%3Alists.debian.org+-site%%3Apackages.debian.org+-site%%3Alists.alioth.debian.org+-site%%3Aftp.debian.org++-site%%3Apackages.qa.debian.org++-site%%3Aftp*.*.debian.org+-inurl%%3Adebian.org%%2Fdevel%%2Fpeople.+-inurl%%3Aindices%%2FMaintainers+-inurl%%3Adebian.org%%2Fdebian%%2Fproject++-inurl%%3A%%2Fdists%%2F&btnG=Search
|
||||
website.pattern=http://www.google.com/search?q=site:www.debian.org+%(name)s
|
||||
search.pattern=http://search.debian.org/cgi-bin/omega?P=%%22%(name)s%%22
|
||||
gpgfinger.pattern=finger %(username)s/key@db.debian.org
|
||||
gpgfinger.type=finger
|
||||
gpgfinger.optional=true
|
||||
gpgweb.pattern=http://db.debian.org/fetchkey.cgi?fingerprint=%(gpgfp)s
|
||||
gpgweb.optional=true
|
||||
nm.pattern=https://nm.debian.org/public/person/%(username)s
|
||||
contrib.pattern=https://contributors.debian.org/contributors/contributor/%(aliothusername)s
|
||||
contrib.optional=true
|
||||
|
||||
[ssh]
|
||||
# SSH functions
|
||||
urls=owndndoms,miainfo,groupinfo
|
||||
# owned *.debian.net domains
|
||||
owndndoms.pattern=ldapsearch -u -x -H ldap://db.debian.org -b dc=debian,dc=org uid=%(username)s dnsZoneEntry
|
||||
owndndoms.type=ldapsearch
|
||||
owndndoms.optional=true
|
||||
# MIA information
|
||||
miainfo.pattern=ssh qa.debian.org /srv/qa.debian.org/mia/mia-query %(emailnoq)s
|
||||
miainfo.type=ssh
|
||||
# Group information
|
||||
groupinfo.pattern=ssh master.debian.org id %(username)s
|
||||
groupinfo.type=ssh
|
||||
groupinfo.optional=true
|
||||
|
||||
[ubuntu]
|
||||
urls=ubuntudiff
|
||||
ubuntudiff.pattern=http://ubuntudiff.debian.net/q/uploaders/%(email)s
|
46
debianmemberportfolio/model/form.py
Normal file
46
debianmemberportfolio/model/form.py
Normal file
|
@ -0,0 +1,46 @@
|
|||
# -*- python -*-
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Debian Member Portfolio Service form handling model
|
||||
# Copyright © 2009-2014 Jan Dittberner <jan@dittberner.info>
|
||||
#
|
||||
# This file is part of Debian Member Portfolio Service.
|
||||
#
|
||||
# Debian Member Portfolio Service is free software: you can redistribute it
|
||||
# and/or modify it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the License,
|
||||
# or (at your option) any later version.
|
||||
#
|
||||
# Debian Member Portfolio Service 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 Affero
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
import formencode
|
||||
|
||||
|
||||
class DeveloperData(formencode.Schema):
|
||||
"""Validation schema for DeveloperData."""
|
||||
allow_extra_fields = True
|
||||
filter_extra_fields = True
|
||||
email = formencode.validators.Email(not_empty=True)
|
||||
name = formencode.validators.String(not_empty=True)
|
||||
gpgfp = formencode.All(formencode.validators.PlainText(),
|
||||
formencode.validators.MinLength(32),
|
||||
formencode.validators.MaxLength(40))
|
||||
username = formencode.validators.PlainText()
|
||||
nonddemail = formencode.validators.Email()
|
||||
aliothusername = formencode.validators.PlainText()
|
||||
mode = formencode.validators.OneOf([u'json', u'html'], if_missing=u'html')
|
||||
forumsid = formencode.validators.Int(if_missing=None)
|
||||
wikihomepage = formencode.validators.String(if_missing=None)
|
||||
|
||||
|
||||
class DDDataRequest(formencode.Schema):
|
||||
"""Validation schema for DDData request."""
|
||||
allow_extra_fields = True
|
||||
filter_extra_fields = False
|
||||
email = formencode.validators.Email(not_empty=True)
|
109
debianmemberportfolio/model/keyfinder.py
Normal file
109
debianmemberportfolio/model/keyfinder.py
Normal file
|
@ -0,0 +1,109 @@
|
|||
# -*- python -*-
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Debian Member Portfolio Service key finder module
|
||||
# Copyright (c) 2009-2014 Jan Dittberner <jan@dittberner.info>
|
||||
#
|
||||
# This file is part of Debian Member Portfolio Service.
|
||||
#
|
||||
# Debian Member Portfolio Service is free software: you can redistribute it
|
||||
# and/or modify it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the License,
|
||||
# or (at your option) any later version.
|
||||
#
|
||||
# Debian Member Portfolio Service 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 Affero
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public
|
||||
# License along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
"""
|
||||
This module provides tools for finding PGP key information from a
|
||||
given keyring.
|
||||
"""
|
||||
import logging
|
||||
import time
|
||||
import sys
|
||||
|
||||
db = None
|
||||
cachetimestamp = 0
|
||||
|
||||
|
||||
def _get_keyring_cache():
|
||||
global db, cachetimestamp
|
||||
if db is None or (time.time() - cachetimestamp) > 86300:
|
||||
import anydbm
|
||||
import pkg_resources
|
||||
import os.path
|
||||
filename = pkg_resources.resource_filename(__name__,
|
||||
'keyringcache')
|
||||
logging.debug('reading cache data from %s', filename)
|
||||
assert os.path.exists(filename) and os.path.isfile(filename)
|
||||
db = anydbm.open(filename, 'r')
|
||||
cachetimestamp = time.time()
|
||||
return db
|
||||
|
||||
|
||||
def _get_cached(cachekey):
|
||||
cache = _get_keyring_cache()
|
||||
logging.debug('cache lookup for %s', cachekey)
|
||||
if cachekey in cache:
|
||||
logging.debug('found entry %s', cache[cachekey])
|
||||
return cache[cachekey]
|
||||
return None
|
||||
|
||||
|
||||
def getFingerprintByEmail(email):
|
||||
"""
|
||||
Gets the fingerprints associated with the given email address if
|
||||
available.
|
||||
"""
|
||||
return _get_cached('fpr:email:%s' % email)
|
||||
|
||||
|
||||
def getRealnameByEmail(email):
|
||||
"""
|
||||
Gets the real names associated with the given email address if
|
||||
available.
|
||||
"""
|
||||
return _get_cached('name:email:%s' % email)
|
||||
|
||||
|
||||
def getLoginByEmail(email):
|
||||
"""
|
||||
Gets the logins associated with the given email address if
|
||||
available.
|
||||
"""
|
||||
return _get_cached('login:email:%s' % email)
|
||||
|
||||
|
||||
def getLoginByFingerprint(fpr):
|
||||
"""
|
||||
Gets the login associated with the given fingerprint if available.
|
||||
"""
|
||||
return _get_cached('login:fpr:%s' % fpr)
|
||||
|
||||
|
||||
def _dump_cache():
|
||||
cache = _get_keyring_cache()
|
||||
fprs = []
|
||||
for key in cache.keys():
|
||||
if key.startswith('email:fpr:'):
|
||||
fpr = key.replace('email:fpr:', '')
|
||||
if not fpr in fprs:
|
||||
fprs.append(fpr)
|
||||
|
||||
for fpr in fprs:
|
||||
login = getLoginByFingerprint(fpr)
|
||||
email = _get_cached('email:fpr:%s' % fpr)
|
||||
name = _get_cached('name:fpr:%s' % fpr)
|
||||
|
||||
print fpr, login, ':'
|
||||
print ' ', name, email
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
logging.basicConfig(stream=sys.stderr, level=logging.WARNING)
|
||||
_dump_cache()
|
182
debianmemberportfolio/model/keyringanalyzer.py
Normal file
182
debianmemberportfolio/model/keyringanalyzer.py
Normal file
|
@ -0,0 +1,182 @@
|
|||
# -*- python -*-
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Debian Member Portfolio service application key ring analyzer tool
|
||||
#
|
||||
# Copyright © 2009-2014 Jan Dittberner <jan@dittberner.info>
|
||||
#
|
||||
# This file is part of the Debian Member Portfolio service.
|
||||
#
|
||||
# Debian Member Portfolio service is free software: you can redistribute it
|
||||
# and/or modify it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of
|
||||
# the License, or (at your option) any later version.
|
||||
#
|
||||
# Debian Member Portfolio service 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 Affero
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public
|
||||
# License along with this program. If not, see
|
||||
# <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
"""
|
||||
This is a tool that analyzes GPG and PGP keyrings and stores the
|
||||
retrieved data in a file database. The tool was inspired by Debian
|
||||
qa's carnivore.
|
||||
"""
|
||||
|
||||
import anydbm
|
||||
import pkg_resources
|
||||
import glob
|
||||
import ConfigParser
|
||||
import os
|
||||
import os.path
|
||||
import logging
|
||||
import subprocess
|
||||
import sys
|
||||
import email.utils
|
||||
|
||||
|
||||
CONFIG = ConfigParser.SafeConfigParser()
|
||||
|
||||
|
||||
def _get_keyrings():
|
||||
"""
|
||||
Gets the available keyring files from the keyring directory
|
||||
configured in ddportfolio.ini.
|
||||
"""
|
||||
keyringdir = os.path.expanduser(CONFIG.get('DEFAULT', 'keyring.dir'))
|
||||
logging.debug("keyring dir is %s", keyringdir)
|
||||
keyrings = glob.glob(os.path.join(keyringdir, '*.gpg'))
|
||||
keyrings.extend(glob.glob(os.path.join(keyringdir, '*.pgp')))
|
||||
keyrings.sort()
|
||||
return keyrings
|
||||
|
||||
|
||||
def _parse_uid(uid):
|
||||
"""
|
||||
Parse a uid of the form 'Real Name <email@example.com>' into email
|
||||
and realname parts.
|
||||
"""
|
||||
|
||||
# First try with the Python library, but it doesn't always catch everything
|
||||
(name, mail) = email.utils.parseaddr(uid)
|
||||
if (not name) and (not mail):
|
||||
logging.warning("malformed uid %s", uid)
|
||||
if (not name) or (not mail):
|
||||
logging.debug("strange uid %s: '%s' - <%s>", uid, name, mail)
|
||||
# Try and do better than the python library
|
||||
if not '@' in mail:
|
||||
uid = uid.strip()
|
||||
# First, strip comment
|
||||
s = uid.find('(')
|
||||
e = uid.find(')')
|
||||
if s >= 0 and e >= 0:
|
||||
uid = uid[:s] + uid[e + 1:]
|
||||
s = uid.find('<')
|
||||
e = uid.find('>')
|
||||
mail = None
|
||||
if s >= 0 and e >= 0:
|
||||
mail = uid[s + 1:e]
|
||||
uid = uid[:s] + uid[e + 1:]
|
||||
uid = uid.strip()
|
||||
if not mail and uid.find('@') >= 0:
|
||||
mail, uid = uid, mail
|
||||
|
||||
name = uid
|
||||
logging.debug("corrected: '%s' - <%s>", name, mail)
|
||||
return (name, mail)
|
||||
|
||||
resultdict = {}
|
||||
|
||||
|
||||
def _get_canonical(key):
|
||||
if not key in resultdict:
|
||||
resultdict[key] = []
|
||||
return key
|
||||
|
||||
|
||||
def _add_to_result(key, newvalue):
|
||||
logging.debug("adding %s: %s", key, newvalue)
|
||||
thekey = _get_canonical(key)
|
||||
if newvalue not in resultdict[thekey]:
|
||||
resultdict[thekey].append(newvalue)
|
||||
|
||||
|
||||
def _handle_mail(mail, fpr):
|
||||
if mail.endswith('@debian.org'):
|
||||
login = mail[0:-len('@debian.org')]
|
||||
_add_to_result('login:email:%s' % mail, login)
|
||||
_add_to_result('login:fpr:%s' % fpr, login)
|
||||
_add_to_result('fpr:login:%s' % login, fpr)
|
||||
_add_to_result('fpr:email:%s' % mail, fpr)
|
||||
_add_to_result('email:fpr:%s' % fpr, mail)
|
||||
|
||||
|
||||
def _handle_uid(uid, fpr):
|
||||
# Do stuff with 'uid'
|
||||
if uid:
|
||||
(uid, mail) = _parse_uid(uid)
|
||||
if mail:
|
||||
_handle_mail(mail, fpr)
|
||||
if uid:
|
||||
_add_to_result('name:fpr:%s' % fpr, uid)
|
||||
if mail:
|
||||
_add_to_result('name:email:%s' % mail, uid)
|
||||
return fpr
|
||||
|
||||
|
||||
def process_gpg_list_keys_line(line, fpr):
|
||||
"""
|
||||
Process a line of gpg --list-keys --with-colon output.
|
||||
"""
|
||||
items = line.split(':')
|
||||
if items[0] == 'pub':
|
||||
return None
|
||||
if items[0] == 'fpr':
|
||||
return items[9].strip()
|
||||
if items[0] == 'uid':
|
||||
if items[1] == 'r':
|
||||
return fpr
|
||||
return _handle_uid(items[9].strip(), fpr)
|
||||
else:
|
||||
return fpr
|
||||
|
||||
|
||||
def process_keyrings():
|
||||
"""Process the keyrings and store the extracted data in an anydbm
|
||||
file."""
|
||||
for keyring in _get_keyrings():
|
||||
logging.debug("get data from %s", keyring)
|
||||
proc = subprocess.Popen([
|
||||
"gpg", "--no-options", "--no-default-keyring",
|
||||
"--homedir", os.path.expanduser(
|
||||
CONFIG.get('DEFAULT', 'gnupghome')),
|
||||
"--no-expensive-trust-checks",
|
||||
"--keyring", keyring, "--list-keys",
|
||||
"--with-colons", "--fixed-list-mode", "--with-fingerprint",
|
||||
"--with-fingerprint"],
|
||||
stdout=subprocess.PIPE)
|
||||
fpr = None
|
||||
for line in proc.stdout.readlines():
|
||||
fpr = process_gpg_list_keys_line(line, fpr)
|
||||
retcode = proc.wait()
|
||||
if retcode != 0:
|
||||
logging.error("subprocess ended with return code %d", retcode)
|
||||
db = anydbm.open(pkg_resources.resource_filename(__name__,
|
||||
'keyringcache'), 'c')
|
||||
for key in resultdict:
|
||||
db[key] = ":".join(resultdict[key])
|
||||
db.close()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
logging.basicConfig(stream=sys.stderr, level=logging.WARNING)
|
||||
CONFIG.readfp(pkg_resources.resource_stream(
|
||||
__name__, 'ddportfolio.ini'))
|
||||
gpghome = os.path.expanduser(CONFIG.get('DEFAULT', 'gnupghome'))
|
||||
if not os.path.isdir(gpghome):
|
||||
os.makedirs(gpghome, 0700)
|
||||
process_keyrings()
|
102
debianmemberportfolio/model/urlbuilder.py
Normal file
102
debianmemberportfolio/model/urlbuilder.py
Normal file
|
@ -0,0 +1,102 @@
|
|||
# -*- python -*-
|
||||
# -*- coding: utf8 -*-
|
||||
#
|
||||
# DDPortfolio service url builder
|
||||
# Copyright © 2009, 2010, 2011, 2012 Jan Dittberner <jan@dittberner.info>
|
||||
#
|
||||
# This file is part of DDPortfolio service.
|
||||
#
|
||||
# DDPortfolio service is free software: you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Affero General Public License
|
||||
# as published by the Free Software Foundation, either version 3 of
|
||||
# the License, or (at your option) any later version.
|
||||
#
|
||||
# DDPortfolio service 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
|
||||
# Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public
|
||||
# License along with this program. If not, see
|
||||
# <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
"""
|
||||
This module provides the function build_urls to build personalized
|
||||
URLs using the given information and the URL patterns defined in
|
||||
ddportfolio.ini.
|
||||
"""
|
||||
|
||||
from ConfigParser import ConfigParser, InterpolationMissingOptionError
|
||||
import pkg_resources
|
||||
from ddportfolioservice.model import keyfinder
|
||||
from urllib import quote_plus
|
||||
from pylons.i18n.translation import _, N_
|
||||
|
||||
|
||||
my_config = ConfigParser()
|
||||
my_config.readfp(pkg_resources.resource_stream(__name__, 'ddportfolio.ini'))
|
||||
|
||||
_FIELDNAMES_MAP = {
|
||||
'email': N_('Email address'),
|
||||
'name': N_('Name'),
|
||||
'gpgfp': N_('GPG fingerprint'),
|
||||
'username': N_('Debian user name'),
|
||||
'nonddemail': N_('Non Debian email address'),
|
||||
'aliothusername': N_('Alioth user name'),
|
||||
}
|
||||
|
||||
|
||||
class DDPortfolioEntry(object):
|
||||
def __init__(self, config, section, key):
|
||||
self.name = key
|
||||
self.optional = config.has_option(section, key + '.optional') and \
|
||||
config.getboolean(section, key + '.optional') or False
|
||||
if config.has_option(section, key + '.type'):
|
||||
self.type = config.get(section, key + '.type')
|
||||
else:
|
||||
self.type = 'url'
|
||||
|
||||
|
||||
def build_urls(fields):
|
||||
"""Build personalized URLs using the developer information in
|
||||
fields."""
|
||||
data = []
|
||||
qfields = {}
|
||||
for key, value in fields.iteritems():
|
||||
if value is not None:
|
||||
if isinstance(value, unicode):
|
||||
qfields[key] = quote_plus(value.encode('utf8'))
|
||||
elif isinstance(value, str):
|
||||
qfields[key] = quote_plus(value)
|
||||
else:
|
||||
qfields[key] = value
|
||||
|
||||
if 'gpgfp' not in qfields:
|
||||
fpr = keyfinder.getFingerprintByEmail(fields['email'].encode('utf8'))
|
||||
if fpr:
|
||||
qfields['gpgfp'] = fpr[0]
|
||||
qfields['firstchar'] = fields['email'][0].encode('utf8')
|
||||
qfields['emailnoq'] = fields['email'].encode('utf8')
|
||||
for section in [section.strip() for section in \
|
||||
my_config.get('DEFAULT',
|
||||
'urlbuilder.sections').split(',')]:
|
||||
data.append(['section', section])
|
||||
if my_config.has_option(section, 'urls'):
|
||||
for entry in ([
|
||||
DDPortfolioEntry(my_config, section, url) for url in \
|
||||
my_config.get(section, 'urls').split(',')]):
|
||||
try:
|
||||
data.append(
|
||||
['url', section, entry,
|
||||
my_config.get(section, entry.name + '.pattern',
|
||||
False, qfields)])
|
||||
except InterpolationMissingOptionError, e:
|
||||
if not entry.optional:
|
||||
if e.reference in _FIELDNAMES_MAP:
|
||||
data.append(['error', section, entry,
|
||||
_('Missing input: %s') % \
|
||||
_(_FIELDNAMES_MAP[e.reference])])
|
||||
else:
|
||||
data.append(['error', section, entry,
|
||||
_('Missing input: %s') % e.reference])
|
||||
return data
|
Loading…
Add table
Add a link
Reference in a new issue