[or-cvs] r20777: {projects} First round of re-organizing GetTor (in projects/gettor: . gettor)
kaner at seul.org
kaner at seul.org
Sun Oct 11 16:58:48 UTC 2009
Author: kaner
Date: 2009-10-11 12:58:48 -0400 (Sun, 11 Oct 2009)
New Revision: 20777
Added:
projects/gettor/gettor/constants.py
projects/gettor/gettor/utils.py
Modified:
projects/gettor/GetTor.py
projects/gettor/gettor/blacklist.py
projects/gettor/gettor/config.py
projects/gettor/gettor/gtlog.py
projects/gettor/gettor/packages.py
projects/gettor/gettor/requests.py
projects/gettor/gettor/responses.py
Log:
First round of re-organizing GetTor
Modified: projects/gettor/GetTor.py
===================================================================
--- projects/gettor/GetTor.py 2009-10-11 12:33:01 UTC (rev 20776)
+++ projects/gettor/GetTor.py 2009-10-11 16:58:48 UTC (rev 20777)
@@ -1,53 +1,10 @@
#!/usr/bin/python2.5
# -*- coding: utf-8 -*-
-"""
- gettor.py by Jacob Appelbaum <jacob at appelbaum.net>,
- Christian Fromme <kaner at strace.org>
- This program will hand out Tor via email to supported systems.
- This program is Free Software, see LICENSE for details.
-
- It is intended to be used in a .forward file as part of a pipe like so:
-
- cat <<'EOF'> .forward
- |/usr/local/bin/gettor.py
- EOF
-
- You should have a dist/current/ mirror in a directory that gettor can read.
- Such a mirror can be created like so:
-
- cd /usr/local/
- rsync -av rsync://rsync.torproject.org/tor/dist/current tor-dist-current/
-
- You can keep it updated with a cronjob like so:
-
- MirrorDir=/usr/local/tor-dist-current/
- 0 3 * * * rsync -a rsync://rsync.torproject.org/tor/dist/current/ $MirrorDir
-
- You should ensure that for each file and signature pair you wish to
- distribute, you have created a zip file containing both.
-
- While this program isn't written in a threaded manner per se, it is designed to function
- as if it will be called as a pipe many times at once. There is a slight
- desynchronization with blacklist entry checking and may result in false
- negatives. This isn't perfect but it is designed to be lightweight. It could
- be fixed easily with a shared locking system but this isn't implemented yet.
-
- To clean out the blacklist on a daily basis, install the following cronjob:
-
- # m h dom mon dow command
- 1 1 * * * /bin/rm -rf /var/lib/gettor/bl/*
-
- You'll probably want a directory structure like this owned by uid/gid 'gettor':
- /var/lib/gettor/{bl,pkg}
-
-"""
-
-__program__ = 'gettor.py'
-__version__ = '20090621.01'
+__program__ = 'GetTor.py'
__url__ = 'https://tor-svn.freehaven.net/svn/tor/trunk/contrib/gettor/'
__author__ = 'Jacob Appelbaum <jacob at appelbaum.net>, Christian Fromme <kaner at strace.org>'
-__copyright__ = 'Copyright (c) 2008, Jacob Appelbaum, Christian Fromme'
+__copyright__ = 'Copyright (c) 2008, 2009, The Tor Project'
__license__ = 'See LICENSE for licensing information'
try:
@@ -56,375 +13,81 @@
antigravity = None
import sys
-import os
-import subprocess
-import gettext
-import re
-import gettor.blacklist
-import gettor.requests
-import gettor.responses
+
import gettor.gtlog
-import gettor.config
import gettor.opt
-import gettor.packages
+import gettor.config
+import gettor.requests
+import gettor.responses
+import gettor.utils
-# Global logger
-log = None
+log = gettor.gtlog.getLogger()
-# XXX Move this into a utils class or something
-def createDir(path):
- try:
- log.info("Creating directory %s.." % path)
- os.makedirs(path)
- except OSError, e:
- log.error("Failed to create directory %s: %s" % (path, e))
- return False
- return True
+def processMail(conf):
+ """All mail processing happens here. Processing goes as follows:
+ - Parse request. This means: Find out everything we need to reply in
+ an appropriate manner. Reply address, language, package name.
+ Also try to find out if the user wants split packages and if he has
+ a valid signature on his mail.
+ - Send reply. Use all information gathered from the request and pass
+ it on to the reply class/method to decide what to do."""
+
+ log.info("Processing mail..")
+ # Retrieve request from stdin
+ request = gettor.requests.requestMail(conf)
+ replyTo, lang, pack, split, sig = request.parseMail()
+ log.info("Request from %s package %s, lang %s, split %s" \
+ % (replyTo, pack, lang, split))
+ log.info("Signature is %s" % sig)
-# Switch language to 'newlocale'. Return default if language is not supported.
-def switchLocale(newlocale, localedir):
- trans = gettext.translation("gettor",
- localedir,
- [newlocale],
- fallback=True)
- trans.install()
-
-def runTests():
- # XXX: Implement me
- return True
-
-def installMo(poFile, targetDir):
- global log
- args = os.getcwd() + "/" + poFile + " -o " + targetDir + "/gettor.mo"
+ # Ok, information aquired. Initiate reply sequence
try:
- ret = subprocess.call("msgfmt" + " " + args, shell=True)
- if ret < 0:
- log.error("Error in msgfmt execution: %s" % ret)
- return False
- except OSError, e:
- log.error("Comilation failed: " % e)
- return False
- return True
+ reply = gettor.responses.Response(conf, replyTo, lang, pack, split, sig)
+ reply.sendReply()
+ except:
+ log.error("Sending the reply failed. See previous errors for reasons.")
+ # XXX Error handling???
+ raise
-def installTrans(config, localeSrcdir):
- global log
- hasDirs = None
-
- if config is None:
- log.error("Bad arg.")
- return False
- if not os.path.isdir(localeSrcdir):
- log.info("Not a directory: %s" % localeSrcdir)
- if not createDir(localeSrcdir):
- log.error(_("Giving up on %s" % localeSrcdir))
- return False
- localeDir = config.getLocaleDir()
- if not os.path.isdir(localeDir):
- log.info("Not a directory: %s" % localeDir)
- if not createDir(localeDir):
- log.error(_("Giving up on %s" % localeDir))
- return False
-
- for root, dirs, files in os.walk(localeSrcdir):
- # Python lacks 'depth' feature for os.walk()
- if root != localeSrcdir:
- continue
- for dir in dirs:
- hasDirs = True
- if dir.startswith("."):
- continue
- # We ignore the templates dir for now
- if dir.startswith("templates"):
- continue
- try:
- poFile = os.path.join(root, dir) + "/gettor.po"
- # Construct target dir
- targetDir = localeDir + "/" + dir + "/LC_MESSAGES"
- if not os.path.isdir(targetDir):
- log.info("Not a directory: %s" % targetDir)
- if not createDir(targetDir):
- log.error(_("Giving up on %s" % targetDir))
- return False
- if installMo(poFile, targetDir) == False:
- log.error("Installing .mo files failed.")
- return False
- except Exception:
- log.error("Error accessing translation files.")
- return False
- if hasDirs is None:
- log.errpr("Empty locale dir: " % localeSrcdir)
- return False
-
- return True
-
-def installCron():
- # XXX: Check if cron is installed and understands our syntax?
- currentCronTab = getCurrentCrontab()
- gettorPath = os.getcwd() + "/" + os.path.basename(sys.argv[0])
- gettorArgs = " --clear-blacklist --fetch-packages --prep-packages"
- newCronTab = currentCronTab + '\n' + '3 2 * * * ' + gettorPath + gettorArgs
- echoCmd = ['echo', newCronTab ]
- cronCmd = ['crontab', '-']
- echoProc = subprocess.Popen(echoCmd, stdout=subprocess.PIPE)
- cronProc = subprocess.Popen(cronCmd, stdin=echoProc.stdout)
- cronProc.communicate()[0]
- return cronProc.returncode
-
-def getCurrentCrontab():
- # This returns our current crontab
- savedTab = "# This crontab has been tampered with by gettor.py\n"
- currentTab = os.popen("crontab -l")
- for line in currentTab:
- savedTab += line
- return savedTab
-
-def processMail(conf, logLang, packs, blackList, whiteList):
- global log
-
- packageList = packs.getPackageList()
- if packageList is None or len(packageList) < 1:
- log.error(_("Sorry, your package list is unusable."))
- log.error(_("Try running with --fetch-packages --prep-packages."))
- return False
-
- # Receive mail from stdin
- rmail = gettor.requests.requestMail(packageList)
- rawMessage = rmail.getRawMessage()
- if not rawMessage:
- log.error(_("No raw message. Something went wrong."))
- return False
- parsedMessage = rmail.getParsedMessage()
- if not parsedMessage:
- log.error(_("No parsed message. Dropping message."))
- return False
- replyTo = rmail.getReplyTo()
- if not replyTo:
- log.error(_("No help dispatched. Invalid reply address for user."))
- return False
- replyLang = rmail.getLocale()
- if not replyLang:
- replyLang = logLang
-
- # Initialize response
- srcEmail = conf.getSrcEmail()
- # Bail out if someone tries to be funny
- # XXX TODO: Implement a blacklist check here
- if (srcEmail == replyTo):
- log.error(_("Won't send myself emails."))
- return False
-
- delayAlert = conf.getDelayAlert()
- resp = gettor.responses.gettorResponse(conf, replyLang, logLang)
- signature = rmail.hasVerifiedSignature()
- log.info(_("Signature is: %s") % str(signature))
- # Addresses from whitelist can pass without DKIM signature
-## XXX Hack below while yahoo.cn and yahoo.com have dkim headers that
-## our dkim py thinks always fail. -RD
- if not signature and not whiteList.lookupListEntry(replyTo) and not re.compile(".*@yahoo.com.cn").match(replyTo) and not re.compile(".*@yahoo.cn").match(replyTo) and not re.compile(".*@gmail.com").match(replyTo):
- # Check to see if we've helped them to understand that they need DKIM
- # in the past
- previouslyHelped = blackList.lookupListEntry(replyTo)
- if previouslyHelped:
- log.info(_("Unsigned messaged to gettor by blacklisted user dropped."))
- return False
- else:
- # Reply with some help and bail out
- blackList.createListEntry(replyTo)
- resp.sendHelp(srcEmail, replyTo)
- log.info(_("Unsigned messaged to gettor. We issued some help."))
- return True
- else:
- log.info(_("Good message to gettor."))
- package = rmail.getPackage()
- if package != None:
- log.info(_("Package: %s selected.") % str(package))
- log.info(_("Sending delay alert email: %s") % str(delayAlert))
- if delayAlert == True:
- message = _("""
- Hello, This is the "gettor" robot.
-
- Thank you for your request. It was successfully understood. Your request is
- currently being processed. Your package should arrive within the next ten
- minutes.
-
- If it doesn't arrive, the package might be too big for your mail provider.
- Try resending the mail from a gmail.com or yahoo.cn account. Also,
- try asking for tor-browser-bundle rather than tor-im-browser-bundle,
- since it's smaller.
-
- If you have any questions or it doesn't work, you can contact a
- human at this support email address: tor-assistants at torproject.org
-
- """)
- status = resp.sendGenericMessage(srcEmail, replyTo, message)
- if status != True:
- log.info(_("Failed to send delay alert"))
- if (rmail.getSplitDelivery()):
- status = resp.sendSplitPackage(srcEmail, replyTo, conf.getPackDir() + "/" + package + ".split")
- else:
- status = resp.sendPackage(srcEmail, replyTo, packageList[package])
- if status != True:
- log.info(_("Failed at attempt to send package: %s") % str(package))
- return False
- else:
- log.info(_("Package sent: %s") % str(package))
- else:
- resp.sendPackageHelp(packageList, srcEmail, replyTo)
- log.info(_("We issued some help about proper email formatting."))
-
- return True
-
-def main():
- global log
- success = None
-
- # Parse command line, setup config, logging and language
- options, arguments = gettor.opt.parseOpts()
- conf = gettor.config.gettorConf(options.configfile)
- gettor.gtlog.initialize()
- log = gettor.gtlog.getLogger()
-
- # Setup locale
- logLang = conf.getLocale()
- localeDir = conf.getLocaleDir()
- # We need to do this first
+def processOptions(options, conf):
+ """Do everything that's not part of parsing a mail. Prepare GetTor usage,
+ install files, fetch packages, do some black/whitelist voodoo and so on"""
+ print "Options: ", options
+ # Order matters!
if options.insttrans:
- if installTrans(conf, options.i18ndir):
- log.info("Installing translation files done.")
- success = True
- else:
- log.error("Installing translation files failed.")
- return False
- # Just check for the english .mo file, because that's the fallback
- englishMoFile = localeDir + "/en/LC_MESSAGES/gettor.mo"
- if not os.path.isfile(englishMoFile):
- log.error("Sorry, %s is not a file we can access." % englishMoFile)
- return False
- switchLocale(logLang, localeDir)
-
- distDir = conf.getDistDir()
- if not os.path.isdir(distDir):
- log.info(_("Sorry, %s is not a directory.") % distDir)
- if not createDir(distDir):
- log.error(_("Giving up on %s", distDir))
- return False
- try:
- packs = gettor.packages.gettorPackages(options.mirror, conf)
- except IOError:
- log.error(_("Error initiating package list."))
- return False
- try:
- whiteList = gettor.blacklist.BWList(conf.getWlStateDir())
- blackList = gettor.blacklist.BWList(conf.getBlStateDir())
- except IOError, e:
- log.error(_("White/Black list error: %s") % e)
- return False
-
+ gettor.utils.installTrans(conf, options.i18ndir)
if options.fetchpackages:
- if packs.syncWithMirror() != 0:
- log.error(_("Syncing Tor packages failed."))
- return False
- else:
- log.info(_("Syncing Tor packages done."))
- success = True
+ gettor.utils.fetchPackages(conf, options.mirror)
if options.preppackages:
- if not packs.buildPackages():
- log.error(_("Building packages failed."))
- return False
- else:
- log.info(_("Building packages done."))
- success = True
- if options.runtests:
- if not runTests():
- log.error(_("Tests failed."))
- return False
- else:
- log.info(_("Tests passed."))
- success = True
+ gettor.utils.prepPackages(conf)
if options.installcron:
- if installCron() != 0:
- log.error(_("Installing cron failed"))
- return False
- else:
- log.info(_("Installing cron done."))
- success = True
+ gettor.utils.installCron()
if options.whitelist:
- if not whiteList.createListEntry(options.whitelist):
- log.error(_("Creating whitelist entry failed."))
- return False
- else:
- log.info(_("Creating whitelist entry ok."))
- success = True
+ gettor.utils.addWhitelistEntry(options.whitelist)
if options.blacklist:
- if not blackList.createListEntry(options.blacklist):
- log.error(_("Creating blacklist entry failed."))
- return False
- else:
- log.info(_("Creating blacklist entry ok."))
- success = True
+ gettor.utils.addBlacklistEntry(options.blacklist)
if options.lookup:
- if whiteList.lookupListEntry(options.lookup):
- log.info(_("Present in whitelist."))
- success = True
- if blackList.lookupListEntry(options.lookup):
- log.info(_("Present in blacklist."))
- success = True
- if not success:
- log.info(_("Address neither in blacklist or whitelist."))
- success = True
+ gettor.utils.lookupAddress(options.lookup)
if options.clearwl:
- if not whiteList.removeAll():
- log.error(_("Deleting whitelist failed."))
- return False
- else:
- log.info(_("Deleting whitelist done."))
- success = True
+ gettor.utils.clearWhitelist()
if options.clearbl:
- if not blackList.removeAll():
- log.error(_("Deleting blacklist failed."))
- return False
- else:
- log.info(_("Deleting blacklist done."))
- success = True
+ gettor.utils.clearBlacklist()
- # Break here if preparation work has been done
- if success is not None:
- return success
-
- # Main loop
- if not processMail(conf, logLang, packs, blackList,
- whiteList):
- log.error(_("Processing mail failed."))
- return False
+def main():
+ # Parse command line, setup config and logging
+ options, arguments = gettor.opt.parseOpts()
+ config = gettor.config.Config(options.configfile)
+ gettor.gtlog.initialize()
- return True
+ if sys.stdin.isatty():
+ # We separate this because we need a way to know how we reply to the
+ # caller: Send mail or just dump to stdout/stderr.
+ processOptions(options, config)
+ else:
+ # We've got mail
+ processMail(config)
-if __name__ == "__main__":
- if not main():
- generalerror = """
- An error occured while processing your request to GetTor. Most likely
- this happened because we are too busy at the moment.
+ log.info("Done.")
- Please try again later, sorry for the inconvenience.
-
- Please note that currently, we can't process HTML emails. You will need
- to send plain text.
-
- Best,
- Your GetTor robot
- """
- # XXX This is a heavy cludge to prevent the mail user to see
- # "Main loop exited with errors." when something bad happened.
- # Instead, 'generalerror' is send back to the user.
- # If GetTor runs from the command line (indicator: args are present),
- # we presume the "Main loop exited with errors." is more
- # appropriate. However, this should go soon and be replaced by real
- # error handling (and mail user informing)
- # -- kaner
- if len(sys.argv) == 1:
- print >> sys.stderr, generalerror
- else:
- print >> sys.stderr, "Main loop exited with errors."
- exit(1)
- else:
- exit(0)
+if __name__ == "__main__":
+ main()
Modified: projects/gettor/gettor/blacklist.py
===================================================================
--- projects/gettor/gettor/blacklist.py 2009-10-11 12:33:01 UTC (rev 20776)
+++ projects/gettor/gettor/blacklist.py 2009-10-11 16:58:48 UTC (rev 20777)
@@ -12,7 +12,7 @@
log = gettor.gtlog.getLogger()
-conf = gettor.config.gettorConf()
+conf = gettor.config.Config()
stateDir = conf.getStateDir()
blStateDir = conf.getBlStateDir()
Modified: projects/gettor/gettor/config.py
===================================================================
--- projects/gettor/gettor/config.py 2009-10-11 12:33:01 UTC (rev 20776)
+++ projects/gettor/gettor/config.py 2009-10-11 16:58:48 UTC (rev 20777)
@@ -66,9 +66,9 @@
import sys
import ConfigParser
-__all__ = ["gettorConf"]
+__all__ = ["Config"]
-class gettorConf:
+class Config:
'''
Initialize gettor with default values if one or more values are missing
from the config file. This will return entirely default values if the
@@ -175,6 +175,6 @@
return self.useConf["delayAlert"][0]
if __name__ == "__main__" :
- c = gettorConf()
+ c = Config()
print "# This is a suitable default configuration. Tune to fit your needs."
c.printConfiguration()
Added: projects/gettor/gettor/constants.py
===================================================================
--- projects/gettor/gettor/constants.py (rev 0)
+++ projects/gettor/gettor/constants.py 2009-10-11 16:58:48 UTC (rev 20777)
@@ -0,0 +1,165 @@
+#!/usr/bin/python2.5
+# -*- coding: utf-8 -*-
+"""
+ constants.py
+
+ Copyright (c) 2008, Jacob Appelbaum <jacob at appelbaum.net>,
+ Christian Fromme <kaner at strace.org>
+
+ This is Free Software. See LICENSE for license information.
+
+ This library implements all of the email replying features needed for gettor.
+"""
+
+import gettext
+
+_ = gettext.gettext
+
+helpmsg = _("""
+ Hello! This is the "gettor" robot.
+
+ Unfortunately, we won't answer you at this address. You should make
+ an account with GMAIL.COM or YAHOO.CN and send the mail from
+ one of those.
+
+ We only process requests from email services that support "DKIM",
+ which is an email feature that lets us verify that the address in the
+ "From" line is actually the one who sent the mail.
+
+ (We apologize if you didn't ask for this mail. Since your email is from
+ a service that doesn't use DKIM, we're sending a short explanation,
+ and then we'll ignore this email address for the next day or so.)
+
+ Please note that currently, we can't process HTML emails or base 64
+ mails. You will need to send plain text.
+
+ If you have any questions or it doesn't work, you can contact a
+ human at this support email address: tor-assistants at torproject.org
+ """)
+
+packagehelpmsg = _("""
+ Hello, This is the "gettor" robot.
+
+ I will mail you a Tor package, if you tell me which one you want.
+ Please select one of the following package names:
+
+ tor-browser-bundle
+ macosx-universal-bundle
+ panther-bundle
+ tor-im-browser-bundle
+ source-bundle
+
+ Please reply to this mail (to gettor at torproject.org), and tell me
+ a single package name anywhere in the body of your email.
+
+ Please note that currently we can't process HTML emails or base64
+ emails. You will need to send plain text.
+
+ If you have any questions or it doesn't work, you can contact a
+ human at this support email address: tor-assistants at torproject.org
+
+ """)
+
+packagemsg = _("""
+ Hello! This is the "gettor" robot.
+
+ Here's your requested software as a zip file. Please unzip the
+ package and verify the signature.
+
+ Hint: If your computer has GnuPG installed, use the gpg
+ commandline tool as follows after unpacking the zip file:
+
+ gpg --verify <packagename>.asc <packagename>
+
+ The output should look somewhat like this:
+
+ gpg: Good signature from "Roger Dingledine <arma at mit.edu>"
+
+ If you're not familiar with commandline tools, try looking for
+ a graphical user interface for GnuPG on this website:
+
+ http://www.gnupg.org/related_software/frontends.html
+
+ If your Internet connection blocks access to the Tor network, you
+ may need a bridge relay. Bridge relays (or "bridges" for short)
+ are Tor relays that aren't listed in the main directory. Since there
+ is no complete public list of them, even if your ISP is filtering
+ connections to all the known Tor relays, they probably won't be able
+ to block all the bridges.
+
+ You can acquire a bridge by sending an email that contains "get bridges"
+ in the body of the email to the following email address:
+ bridges at torproject.org
+
+ It is also possible to fetch bridges with a web browser at the following
+ url: https://bridges.torproject.org/
+
+ If you have any questions or it doesn't work, you can contact a
+ human at this support email address: tor-assistants at torproject.org
+
+ """)
+
+splitpackagemsg = _("""
+ Hello! This is the "gettor" robot.
+
+ Here's your requested software as a zip file. Please unzip the
+ package and verify the signature.
+
+ IMPORTANT NOTE:
+ Since this is part of a split-file request, you need to wait for
+ all split files to be received by you before you can save them all
+ into the same directory and unpack them by double-clicking the
+ first file.
+
+ Packages might come out of order! Please make sure you received
+ all packages before you attempt to unpack them!
+
+ Hint: If your computer has GnuPG installed, use the gpg
+ commandline tool as follows after unpacking the zip file:
+
+ gpg --verify <packagename>.asc <packagename>
+
+ The output should look somewhat like this:
+
+ gpg: Good signature from "Roger Dingledine <arma at mit.edu>"
+
+ If you're not familiar with commandline tools, try looking for
+ a graphical user interface for GnuPG on this website:
+
+ http://www.gnupg.org/related_software/frontends.html
+
+ If your Internet connection blocks access to the Tor network, you
+ may need a bridge relay. Bridge relays (or "bridges" for short)
+ are Tor relays that aren't listed in the main directory. Since there
+ is no complete public list of them, even if your ISP is filtering
+ connections to all the known Tor relays, they probably won't be able
+ to block all the bridges.
+
+ You can acquire a bridge by sending an email that contains "get bridges"
+ in the body of the email to the following email address:
+ bridges at torproject.org
+
+ It is also possible to fetch bridges with a web browser at the following
+ url: https://bridges.torproject.org/
+
+ If you have any questions or it doesn't work, you can contact a
+ human at this support email address: tor-assistants at torproject.org
+
+ """)
+
+delayalertmsg = _("""
+ Hello, This is the "gettor" robot.
+
+ Thank you for your request. It was successfully understood. Your request is
+ currently being processed. Your package should arrive within the next ten
+ minutes.
+
+ If it doesn't arrive, the package might be too big for your mail provider.
+ Try resending the mail from a gmail.com or yahoo.cn account. Also,
+ try asking for tor-browser-bundle rather than tor-im-browser-bundle,
+ since it's smaller.
+
+ If you have any questions or it doesn't work, you can contact a
+ human at this support email address: tor-assistants at torproject.org
+
+ """)
Modified: projects/gettor/gettor/gtlog.py
===================================================================
--- projects/gettor/gettor/gtlog.py 2009-10-11 12:33:01 UTC (rev 20776)
+++ projects/gettor/gettor/gtlog.py 2009-10-11 16:58:48 UTC (rev 20777)
@@ -41,7 +41,7 @@
# Don't add handlers twice
if initialized == True:
return
- conf = gettor.config.gettorConf()
+ conf = gettor.config.Config()
logger = logging.getLogger('gettor')
logger.setLevel(loglevel)
logSubSystem = conf.getLogSubSystem()
Modified: projects/gettor/gettor/packages.py
===================================================================
--- projects/gettor/gettor/packages.py 2009-10-11 12:33:01 UTC (rev 20776)
+++ projects/gettor/gettor/packages.py 2009-10-11 16:58:48 UTC (rev 20777)
@@ -1,7 +1,7 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
'''
- gettor_packages.py: Package related stuff
+ packages.py: Package related stuff
Copyright (c) 2008, Jacob Appelbaum <jacob at appelbaum.net>,
Christian Fromme <kaner at strace.org>
@@ -18,7 +18,7 @@
import gettor.config
import re
-__all__ = ["gettorPackages"]
+__all__ = ["Packages"]
log = gettor.gtlog.getLogger()
@@ -32,7 +32,7 @@
return False
return True
-class gettorPackages:
+class Packages:
# "bundle name": ("single file regex", "split file regex")
packageRegex = { "windows-bundle": ("vidalia-bundle-.*.exe$", "vidalia-bundle-.*_split"),
"panther-bundle": ("vidalia-bundle-.*-ppc.dmg$", "vidalia-bundle-.*-ppc_split"),
@@ -44,14 +44,13 @@
#"torbutton": "torbutton-current.xpi$",
}
- def __init__(self, mirror, config, silent=False):
- self.mirror = mirror
+ def __init__(self, config):
self.packageList = {}
self.distDir = config.getDistDir()
try:
entry = os.stat(self.distDir)
except OSError, e:
- if not createDir(self.Distdir):
+ if not createDir(self.distDir):
log.error("Bad dist dir %s: %s" % (self.distDir, e))
raise IOError
self.packDir = config.getPackDir()
@@ -61,14 +60,6 @@
if not createDir(self.packDir):
log.error("Bad pack dir %s: %s" % (self.packDir, e))
raise IOError
- self.rsync = ["rsync"]
- self.rsync.append("-a")
- # Don't download dotdirs
- self.rsync.append("--exclude='.*'")
- if not silent:
- self.rsync.append("--progress")
- self.rsync.append("rsync://%s/tor/dist/current/" % self.mirror)
- self.rsync.append(self.distDir)
def getPackageList(self):
# Build dict like 'name': 'name.z'
@@ -76,14 +67,15 @@
for filename in os.listdir(self.packDir):
self.packageList[filename[:-2]] = self.packDir + "/" + filename
except OSError, (strerror):
- log.error(_("Failed to build package list: %s") % strerror)
+ log.error("Failed to build package list: %s" % strerror)
return None
# Check sanity
for key, val in self.packageList.items():
# Remove invalid packages
if not os.access(val, os.R_OK):
- log.info(_("Warning: %s not accessable. Removing from list.") % val)
+ log.info("Warning: %s not accessable. Removing from list." \
+ % val)
del self.packageList[key]
return self.packageList
@@ -98,13 +90,17 @@
if not os.access(packSplitDir, os.R_OK):
os.mkdir(packSplitDir)
except OSError, e:
- log.error(_("Could not create dir %s: %s" % (packSplitDir, e)))
- # Loop through split dir, look if every partXX.ZZZ has a matching signature,
- # pack them together in a .z
+ log.error("Could not create dir %s: %s" \
+ % (packSplitDir, e))
+ # Loop through split dir, look if every partXX.ZZZ has a
+ # matching signature, pack them together in a .z
splitdir = self.distDir + "/" + filename
for splitfile in os.listdir(splitdir):
+ # Skip signature files
+ if splitfile.endswith(".asc"):
+ continue
if re.compile(".*split.part.*").match(splitfile):
- ascfile = splitdir + "/signatures/" + splitfile + ".asc"
+ ascfile = splitdir + "/" + splitfile + ".asc"
file = splitdir + "/" + splitfile
zipFileName = packSplitDir + "/" + splitfile + ".z"
if os.access(ascfile, os.R_OK) and os.access(file, os.R_OK):
@@ -114,7 +110,7 @@
zip.write(ascfile, os.path.basename(ascfile))
zip.close()
else:
- log.error(_("Uhm, no signature for %s found" % splitfile))
+ log.error("Uhm, expected signature file for %s to be: %s" % (file, ascfile))
return False
if re.compile(regex_single).match(filename):
file = self.distDir + "/" + filename
@@ -131,21 +127,37 @@
if len(self.packageList) > 0:
return True
else:
- log.error(_("Failed at building packages"))
+ log.error("Failed to build packages")
return False
- def syncWithMirror(self):
- process = subprocess.Popen(self.rsync)
+ def syncWithMirror(self, mirror, silent):
+ rsync = ["rsync"]
+ rsync.append("-a")
+ # Don't download dotdirs
+ rsync.append("--exclude='.*'")
+ if not silent:
+ rsync.append("--progress")
+ rsync.append("rsync://%s/tor/dist/current/" % mirror)
+ rsync.append(self.distDir)
+ process = subprocess.Popen(rsync)
process.wait()
return process.returncode
- def getCommandToStr(self):
+ def getCommandToStr(self, mirror, silent):
"""This is useful for cronjob installations
"""
+ rsync = ["rsync"]
+ rsync.append("-a")
+ # Don't download dotdirs
+ rsync.append("--exclude='.*'")
+ if not silent:
+ rsync.append("--progress")
+ rsync.append("rsync://%s/tor/dist/current/" % mirror)
+ rsync.append(self.distDir)
return ''.join(self.rsync)
if __name__ == "__main__" :
- c = gettor_config.gettorConf()
+ c = gettor_config.Config()
p = gettorPackages("rsync.torproject.org", c)
print "Building packagelist.."
if p.syncwithMirror() != 0:
Modified: projects/gettor/gettor/requests.py
===================================================================
--- projects/gettor/gettor/requests.py 2009-10-11 12:33:01 UTC (rev 20776)
+++ projects/gettor/gettor/requests.py 2009-10-11 16:58:48 UTC (rev 20777)
@@ -17,6 +17,7 @@
import re
import gettor.gtlog
+import gettor.packages
__all__ = ["requestMail"]
@@ -25,13 +26,13 @@
class requestMail:
defaultLang = "en"
+ # XXX
supportedLangs = { "en": "English",
"de": "Deutsch" }
- def __init__(self, packages):
+ def __init__(self, config):
+ """ Read message from stdin, parse all the stuff we want to know
"""
- Read message from stdin, parse all the stuff we want to know
- """
self.rawMessage = sys.stdin.read()
self.parsedMessage = email.message_from_string(self.rawMessage)
self.signature = False
@@ -47,44 +48,52 @@
# TODO XXX:
# Scrub this data
- self.replyToAddress = None
self.replytoAddress = self.parsedMessage["from"]
# If no package name could be recognized, use 'None'
self.returnPackage = None
self.splitDelivery = False
+ self.replyLocale = "en"
+ packager = gettor.packages.Packages(config)
+ self.packages = packager.getPackageList()
+
+ def parseMail(self):
# Parse line by line
for line in email.Iterators.body_line_iterator(self.parsedMessage):
- # Remove comments
+ # Remove quotes
if line.startswith(">"):
continue
- for package in packages.keys():
+ # XXX This is a bit clumsy, but i cant think of a better way
+ # currently. A map also doesnt really help i think. -kaner
+ for package in self.packages.keys():
matchme = ".*" + package + ".*"
match = re.match(matchme, line)
if match:
self.returnPackage = package
- log.info(_("User requested package %s") % self.returnPackage)
- # If we find 'split' somewhere in the mail, we assume that the user wants
- # a split delivery
+ log.info("User requested package %s" % self.returnPackage)
+ # If we find 'split' somewhere in the mail, we assume that the user
+ # wants a split delivery
match = re.match(".*split.*", line)
if match:
- log.info(_("User requested a split delivery"))
self.splitDelivery = True
-
- self.replyLocale = None
- pattern = re.compile("^Lang:\s+(.*)$")
- for line in email.Iterators.body_line_iterator(self.parsedMessage):
- match = pattern.match(line)
+ log.info("User requested a split delivery")
+ # Default locale is english
+ match = re.match(".*[Ll]ang:\s+(.*)$", line)
if match:
self.replyLocale = match.group(1)
- log.info(_("User requested locale %s") % self.replyLocale)
+ log.info("User requested locale %s" % self.replyLocale)
+ # Actually use a map here later XXX
for (key, lang) in self.supportedLangs.items():
if self.replyLocale == key:
break
else:
- log.info(_("Requested language %s not supported. Falling back to %s") % (self.replyLocale, self.defaultLang))
+ log.info("Requested language %s not supported. Falling back to %s" \
+ % (self.replyLocale, self.defaultLang))
self.replyLocale = self.defaultLang
+ return (self.replytoAddress, self.replyLocale, \
+ self.returnPackage, self.splitDelivery, self.signature)
+
def getRawMessage(self):
return self.rawMessage
@@ -106,33 +115,6 @@
def getSplitDelivery(self):
return self.splitDelivery
-if __name__ == "__main__" :
- """ Give us an email to understand what we think of it. """
- packageList = {
- "windows-bundle": "/var/lib/gettor/pkg/windows-bundle.z",
- "macosx-bundle": "/var/lib/gettor/pkg/macosx-bundle.z",
- "linux-bundle": "/var/lib/gettor/pkg/linux-bundle.z",
- "source-bundle": "/var/lib/gettor/pkg/source-bundle.z"
- }
-
- rmail = requestMail(packageList)
- print "Fetching raw message."
- rawMessage = rmail.getRawMessage()
- # This doesn't work without DNS ( no wifi on board current airplane )
- print "Verifying signature of message."
- signature = rmail.hasVerifiedSignature()
- print "Parsing Message."
- parsedMessage = rmail.getParsedMessage()
- print "Parsing reply."
- parsedReply = rmail.getReplyTo()
- print "Parsing package request."
- package = rmail.getRequestPackage()
- if package == None:
- packageFile = "help"
- else:
- packageFile = packageList[package]
-
- print "The signature status of the email is: %s" % str(signature)
- print "The email requested the following reply address: %s" % parsedReply
- print "It looks like the email requested the following package: %s" % package
- print "We would select the following package file: %s" % packageFile
+ def getAll(self):
+ return (self.replytoAddress, self.replyLocale, \
+ self.returnPackage, self.splitDelivery, self.signature)
Modified: projects/gettor/gettor/responses.py
===================================================================
--- projects/gettor/gettor/responses.py 2009-10-11 12:33:01 UTC (rev 20776)
+++ projects/gettor/gettor/responses.py 2009-10-11 16:58:48 UTC (rev 20777)
@@ -17,62 +17,114 @@
import StringIO
import base64
import gettext
+import re
import gettor.gtlog
+import gettor.blacklist
+import gettor.constants
-__all__ = ["gettorResponse"]
+__all__ = ["Response"]
log = gettor.gtlog.getLogger()
-class gettorResponse:
+class Response:
- def __init__(self, config, mailLang="en", logLang="en"):
- self.mailLang = mailLang
- self.logLang = logLang
+ def __init__(self, config, replyto, lang, package, split, signature):
self.config = config
-
- def setLang(self, language):
- # XXX: Sorta hack, have nothing better on my mind right now
- # On every entry to a translation-needing function, call this with
- # lang=maillang
- # On every exit of a translation-needing function, call this with
- # lang=loglang
- # :-/
- if self.config:
- trans = gettext.translation("gettor", self.config.getLocaleDir(), [language])
+ self.srcEmail = "GetTor <gettor at torproject.org>"
+ self.replyTo = replyto
+ self.mailLang = lang
+ self.package = package
+ self.splitsend = split
+ self.signature = signature
+ self.whiteList = gettor.blacklist.BWList(config.getWlStateDir())
+ try:
+ trans = gettext.translation("gettor", config.getLocaleDir(), [lang])
trans.install()
+ except IOError:
+ log.error("Translation fail. Trying running with -r.")
+ raise
- def sendHelp(self, source, destination):
- """ Send a helpful message to the user interacting with us """
- self.setLang(self.mailLang)
- message = _("""
- Hello! This is the "gettor" robot.
+ def sendReply(self):
+ """All routing decisions take place here."""
+ if not self.signature \
+ and not self.whiteList.lookupListEntry(self.replyTo) \
+ and not re.compile(".*@yahoo.com.cn").match(self.replyTo) \
+ and not re.compile(".*@yahoo.cn").match(self.replyTo) \
+ and not re.compile(".*@gmail.com").match(self.replyTo):
+ blackListed = blackList.lookupListEntry(self.replyTo)
+ if blackListed:
+ log.info("Unsigned messaged to gettor by blacklisted user dropped.")
+ return False
+ else:
+ # Reply with some help and bail out
+ blackList.createListEntry(self.replyTo)
+ sendHelp()
+ log.info("Unsigned messaged to gettor. We issued some help.")
+ return True
+ else:
+ print "Sending mail.."
+ delayAlert = self.config.getDelayAlert()
+ if self.splitsend:
+ print "Sending split packages"
+ self.sendSplitPackage()
+ else:
+ print "Sending non-split package"
+ self.sendPackage()
- Unfortunately, we won't answer you at this address. You should make
- an account with GMAIL.COM or YAHOO.CN and send the mail from
- one of those.
+ def sendPackage(self):
+ """ Send a message with an attachment to the user"""
+ packages = gettor.packages.Packages(self.config)
+ packageList = packages.getPackageList()
+ filename = packageList[self.package]
+ message = gettor.constants.packagemsg
+ package = self.constructMessage(message, "", filename)
+ try:
+ status = self.sendMessage(package)
+ except:
+ log.error("Could not send package to user")
+ status = False
- We only process requests from email services that support "DKIM",
- which is an email feature that lets us verify that the address in the
- "From" line is actually the one who sent the mail.
+ return status
- (We apologize if you didn't ask for this mail. Since your email is from
- a service that doesn't use DKIM, we're sending a short explanation,
- and then we'll ignore this email address for the next day or so.)
+ def sendSplitPackage(self):
+ """XXX XXX XXX alpha state XXX XXX XXX"""
+ splitdir = self.config.getPackDir() + "/" + self.package + ".split"
+ try:
+ entry = os.stat(splitdir)
+ except OSError, e:
+ log.error("Not a valid directory: %s" % splitdir)
+ return False
+ files = os.listdir(splitdir)
+ # Sort the files, so we can send 01 before 02 and so on..
+ files.sort()
+ nFiles = len(files)
+ num = 0
+ for filename in files:
+ fullPath = splitdir + "/" + filename
+ num = num + 1
+ subj = "[GetTor] Split package [%02d / %02d] " % (num, nFiles)
+ message = gettor.constants.splitpackagemsg
+ package = self.constructMessage(message, subj, fullPath)
+ try:
+ status = self.sendMessage(package)
+ except:
+ log.error("Could not send package %s to user" % filename)
+ # XXX What now? Keep on sending? Bail out? Use might have
+ # already received 10 out of 12 packages..
+ status = False
- Please note that currently, we can't process HTML emails or base 64
- mails. You will need to send plain text.
-
- If you have any questions or it doesn't work, you can contact a
- human at this support email address: tor-assistants at torproject.org
- """)
- help = self.constructMessage(message, source, destination, "")
+ return status
+
+ def sendHelp(self):
+ """ Send a helpful message to the user interacting with us """
+ message = gettor.constants.helpmsg
+ help = self.constructMessage(message, "")
try:
- status = self.sendMessage(help, source, destination)
+ status = self.sendMessage(help)
except:
log.error(_("Could not send help message to user"))
status = False
- self.setLang(self.logLang)
return status
@@ -83,192 +135,40 @@
## Somebody should figure out how to automate yet sort. -RD
## """ + "".join([ "\t%s\n" % key for key in packageList.keys()]) + """
- def sendPackageHelp(self, packageList, source, destination):
+ def sendPackageHelp(self, packageList):
""" Send a helpful message to the user interacting with us """
- self.setLang(self.mailLang)
- message = _("""
- Hello, This is the "gettor" robot.
-
- I will mail you a Tor package, if you tell me which one you want.
- Please select one of the following package names:
-
- tor-browser-bundle
- macosx-universal-bundle
- panther-bundle
- tor-im-browser-bundle
- source-bundle
-
- Please reply to this mail (to gettor at torproject.org), and tell me
- a single package name anywhere in the body of your email.
-
- Please note that currently we can't process HTML emails or base64
- emails. You will need to send plain text.
-
- If you have any questions or it doesn't work, you can contact a
- human at this support email address: tor-assistants at torproject.org
-
- """)
- help = self.constructMessage(message, source, destination, "")
+ message = gettor.constants.packagehelpmsg
+ help = self.constructMessage(message, "")
try:
- status = self.sendMessage(help, source, destination)
+ status = self.sendMessage(help)
except:
status = False
log.error(_("Could not send package help message to user"))
- self.setLang(self.logLang)
return status
- def sendGenericMessage(self, source, destination, message):
+ def sendGenericMessage(self, message):
""" Send a helpful message of some sort """
- self.setLang(self.mailLang)
- help = self.constructMessage(message, source, destination, "")
+ help = self.constructMessage(message, "")
try:
- status = self.sendMessage(help, source, destination)
+ status = self.sendMessage(help)
except:
- log.error(_("Could not send generic help message to user"))
+ log.error("Could not send generic help message to user")
status = False
- self.setLang(self.logLang)
return status
- def sendPackage(self, source, destination, filename):
- """ Send a message with an attachment to the user interacting with us """
- self.setLang(self.mailLang)
- message = _("""
- Hello! This is the "gettor" robot.
-
- Here's your requested software as a zip file. Please unzip the
- package and verify the signature.
-
- Hint: If your computer has GnuPG installed, use the gpg
- commandline tool as follows after unpacking the zip file:
-
- gpg --verify <packagename>.asc <packagename>
-
- The output should look somewhat like this:
-
- gpg: Good signature from "Roger Dingledine <arma at mit.edu>"
-
- If you're not familiar with commandline tools, try looking for
- a graphical user interface for GnuPG on this website:
-
- http://www.gnupg.org/related_software/frontends.html
-
- If your Internet connection blocks access to the Tor network, you
- may need a bridge relay. Bridge relays (or "bridges" for short)
- are Tor relays that aren't listed in the main directory. Since there
- is no complete public list of them, even if your ISP is filtering
- connections to all the known Tor relays, they probably won't be able
- to block all the bridges.
-
- You can acquire a bridge by sending an email that contains "get bridges"
- in the body of the email to the following email address:
- bridges at torproject.org
-
- It is also possible to fetch bridges with a web browser at the following
- url: https://bridges.torproject.org/
-
- If you have any questions or it doesn't work, you can contact a
- human at this support email address: tor-assistants at torproject.org
-
- """)
- package = self.constructMessage(message, source, destination, "", filename)
- try:
- status = self.sendMessage(package, source, destination)
- except:
- log.error(_("Could not send package to user"))
- status = False
- self.setLang(self.mailLang)
-
- return status
-
- def sendSplitPackage(self, source, destination, splitdir):
- message = _("""
- Hello! This is the "gettor" robot.
-
- Here's your requested software as a zip file. Please unzip the
- package and verify the signature.
-
- IMPORTANT NOTE:
- Since this is part of a split-file request, you need to wait for
- all split files to be received by you before you can save them all
- into the same directory and unpack them by double-clicking the
- first file.
-
- Packages might come out of order! Please make sure you received
- all packages before you attempt to unpack them!
-
- Hint: If your computer has GnuPG installed, use the gpg
- commandline tool as follows after unpacking the zip file:
-
- gpg --verify <packagename>.asc <packagename>
-
- The output should look somewhat like this:
-
- gpg: Good signature from "Roger Dingledine <arma at mit.edu>"
-
- If you're not familiar with commandline tools, try looking for
- a graphical user interface for GnuPG on this website:
-
- http://www.gnupg.org/related_software/frontends.html
-
- If your Internet connection blocks access to the Tor network, you
- may need a bridge relay. Bridge relays (or "bridges" for short)
- are Tor relays that aren't listed in the main directory. Since there
- is no complete public list of them, even if your ISP is filtering
- connections to all the known Tor relays, they probably won't be able
- to block all the bridges.
-
- You can acquire a bridge by sending an email that contains "get bridges"
- in the body of the email to the following email address:
- bridges at torproject.org
-
- It is also possible to fetch bridges with a web browser at the following
- url: https://bridges.torproject.org/
-
- If you have any questions or it doesn't work, you can contact a
- human at this support email address: tor-assistants at torproject.org
-
- """)
- print splitdir
- try:
- entry = os.stat(splitdir)
- except OSError, e:
- log.error(_("Not a valid directory: %s" % splitdir))
- return False
- files = os.listdir(splitdir)
- # Sort the files, so we can send 01 before 02 and so on..
- files.sort()
- nFiles = len(files)
- num = 0
- for filename in files:
- fullPath = splitdir + "/" + filename
- num = num + 1
- subj = "[gettor] Split package [%02d / %02d] " % (num, nFiles)
- package = self.constructMessage(message, source, destination, subj, fullPath)
- try:
- status = self.sendMessage(package, source, destination)
- except:
- log.error(_("Could not send package %s to user" % filename))
- # XXX What now? Keep on sending? Bail out? Use might have
- # already received 10 out of 12 packages..
- status = False
- self.setLang(self.mailLang)
-
- return status
-
-
- def constructMessage(self, messageText, ourAddress, recipient, subj, fileName=None):
+ def constructMessage(self, messageText, subj, fileName=None):
""" Construct a multi-part mime message, including only the first part
with plaintext."""
if subj == "":
- subj =_('Re: Your "gettor" request')
+ subj =_('[GetTor] Your request')
message = StringIO.StringIO()
mime = MimeWriter.MimeWriter(message)
mime.addheader('MIME-Version', '1.0')
mime.addheader('Subject', subj)
- mime.addheader('To', recipient)
- mime.addheader('From', ourAddress)
+ mime.addheader('To', self.replyTo)
+ mime.addheader('From', self.srcEmail)
mime.startmultipartbody('mixed')
firstPart = mime.nextpart()
@@ -286,10 +186,10 @@
mime.lastpart()
return message
- def sendMessage(self, message, src, dst, smtpserver="localhost:25"):
+ def sendMessage(self, message, smtpserver="localhost:25"):
try:
smtp = smtplib.SMTP(smtpserver)
- smtp.sendmail(src, dst, message.getvalue())
+ smtp.sendmail(self.srcEmail, self.replyTo, message.getvalue())
smtp.quit()
status = True
except smtplib.SMTPAuthenticationError:
@@ -324,7 +224,3 @@
return False
return status
-
-if __name__ == "__main__" :
- print "This is the response handling code. You probably do not want to call it by hand."
-
Added: projects/gettor/gettor/utils.py
===================================================================
--- projects/gettor/gettor/utils.py (rev 0)
+++ projects/gettor/gettor/utils.py 2009-10-11 16:58:48 UTC (rev 20777)
@@ -0,0 +1,247 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+'''
+ utils.py: Useful helper routines
+
+ Copyright (c) 2008, Jacob Appelbaum <jacob at appelbaum.net>,
+ Christian Fromme <kaner at strace.org>
+
+ This is Free Software. See LICENSE for license information.
+
+ This module handles all package related functionality
+'''
+
+import os
+
+import gettor.gtlog
+import gettor.blacklist
+import gettor.packages
+
+log = gettor.gtlog.getLogger()
+
+def createDir(path):
+ """Helper routine that creates a given directory"""
+ try:
+ log.info("Creating directory %s.." % path)
+ os.makedirs(path)
+ except OSError, e:
+ log.error("Failed to create directory %s: %s" % (path, e))
+ return False
+ return True
+
+def installTrans(conf, dir):
+ """Install all translation files to 'dir'"""
+ log.info("Installing translation files..")
+ hasDirs = None
+
+ if conf is None:
+ log.error("Bad arg.")
+ return False
+ if not os.path.isdir(localeSrcdir):
+ log.info("Not a directory: %s" % localeSrcdir)
+ if not createDir(localeSrcdir):
+ log.error(_("Giving up on %s" % localeSrcdir))
+ return False
+ localeDir = conf.getLocaleDir()
+ if not os.path.isdir(localeDir):
+ log.info("Not a directory: %s" % localeDir)
+ if not createDir(localeDir):
+ log.error(_("Giving up on %s" % localeDir))
+ return False
+
+ # XXX: Warn if there is no translation files anywhere..
+ for root, dirs, files in os.walk(localeSrcdir):
+ # Python lacks 'depth' feature for os.walk()
+ if root != localeSrcdir:
+ continue
+ for dir in dirs:
+ hasDirs = True
+ if dir.startswith("."):
+ continue
+ # We ignore the templates dir for now
+ if dir.startswith("templates"):
+ continue
+ try:
+ poFile = os.path.join(root, dir) + "/gettor.po"
+ # Construct target dir
+ targetDir = localeDir + "/" + dir + "/LC_MESSAGES"
+ if not os.path.isdir(targetDir):
+ log.info("Not a directory: %s" % targetDir)
+ if not createDir(targetDir):
+ log.error(_("Giving up on %s" % targetDir))
+ return False
+ if installMo(poFile, targetDir) == False:
+ log.error("Installing .mo files failed.")
+ return False
+ except Exception:
+ log.error("Error accessing translation files.")
+ return False
+ if hasDirs is None:
+ log.errpr("Empty locale dir: " % localeSrcdir)
+ return False
+
+ return True
+
+def fetchPackages(conf, mirror):
+ """Fetch Tor packages from a mirror"""
+ log.info("Fetching package files..")
+ try:
+ packs = gettor.packages.Packages(conf)
+ except IOError:
+ log.error("Error initiating package list.")
+ return False
+ if packs.syncWithMirror(mirror, False) != 0:
+ log.error("Syncing Tor packages failed.")
+ return False
+ else:
+ log.info("Syncing Tor packages done.")
+ return True
+
+def prepPackages(conf):
+ """Prepare the downloaded packages in a way so GetTor can work with them"""
+ log.info("Preparing package files..")
+ try:
+ packs = gettor.packages.Packages(conf)
+ except IOError:
+ log.error("Error initiating package list.")
+ return False
+ if not packs.buildPackages():
+ log.error("Building packages failed.")
+ return False
+ else:
+ log.info("Building packages done.")
+ return True
+
+def installCron():
+ log.info("Installing cronjob..")
+ # XXX: Check if cron is installed and understands our syntax?
+ currentCronTab = getCurrentCrontab()
+ path = os.getcwd() + "/" + os.path.basename(sys.argv[0])
+ args = " --clear-blacklist --fetch-packages --prep-packages"
+ newCronTab = currentCronTab + '\n' + '3 2 * * * ' + path + args
+ echoCmd = ['echo', newCronTab ]
+ cronCmd = ['crontab', '-']
+ echoProc = subprocess.Popen(echoCmd, stdout=subprocess.PIPE)
+ cronProc = subprocess.Popen(cronCmd, stdin=echoProc.stdout)
+ cronProc.communicate()[0]
+ return cronProc.returncode
+
+def addWhitelistEntry(address):
+ log.info("Adding address to whitelist: %s" % address)
+ try:
+ whiteList = gettor.blacklist.BWList(conf.getWlStateDir())
+ except IOError, e:
+ log.error("Whitelist error: %s" % e)
+ return False
+ if not whiteList.createListEntry(options.whitelist):
+ log.error("Creating whitelist entry failed.")
+ return False
+ else:
+ log.info("Creating whitelist entry ok.")
+ return True
+
+def addBlacklistEntry(address):
+ log.info("Adding address to blacklist: %s" % address)
+ try:
+ blackList = gettor.blacklist.BWList(conf.getBlStateDir())
+ except IOError, e:
+ log.error("Blacklist error: %s" % e)
+ return False
+ if not blackList.createListEntry(options.whitelist):
+ log.error("Creating blacklist entry failed.")
+ return False
+ else:
+ log.info("Creating whitelist entry ok.")
+ return True
+
+def lookupAddress(address):
+ log.info("Lookup address: %s" % address)
+ found = False
+ try:
+ whiteList = gettor.blacklist.BWList(conf.getWlStateDir())
+ blackList = gettor.blacklist.BWList(conf.getBlStateDir())
+ except IOError, e:
+ log.error("White/Blacklist error: %s" % e)
+ return False
+ if whiteList.lookupListEntry(address):
+ log.info("Address '%s' is present in the whitelist." % address)
+ found = True
+ if blackList.lookupListEntry(address):
+ log.info("Address '%s' is present in the blacklist." % address)
+ found = True
+ if not success:
+ log.info("Address '%s' neither in blacklist or whitelist." % address)
+ found = True
+
+ return found
+
+def clearWhitelist():
+ try:
+ whiteList = gettor.blacklist.BWList(conf.getWlStateDir())
+ except IOError, e:
+ log.error("Whitelist error: %s" % e)
+ return False
+ log.info("Clearing whitelist..")
+ if not whiteList.removeAll():
+ log.error("Deleting whitelist failed.")
+ return False
+ else:
+ log.info("Deleting whitelist done.")
+ return True
+
+def clearBlacklist():
+ log.info("Clearing blacklist..")
+ try:
+ blackList = gettor.blacklist.BWList(conf.getBlStateDir())
+ except IOError, e:
+ log.error("Blacklist error: %s" % e)
+ return False
+ if not blackList.removeAll():
+ log.error("Deleting blacklist failed.")
+ return False
+ else:
+ log.info("Deleting blacklist done.")
+ return True
+
+# Helper routines go here ####################################################
+
+def installMo(poFile, targetDir):
+ global log
+ args = os.getcwd() + "/" + poFile + " -o " + targetDir + "/gettor.mo"
+ try:
+ ret = subprocess.call("msgfmt" + " " + args, shell=True)
+ if ret < 0:
+ log.error("Error in msgfmt execution: %s" % ret)
+ return False
+ except OSError, e:
+ log.error("Comilation failed: " % e)
+ return False
+ return True
+
+def installTrans(config, localeSrcdir):
+ global log
+ hasDirs = None
+
+ if config is None:
+ log.error("Bad arg.")
+ return False
+ if not os.path.isdir(localeSrcdir):
+ log.info("Not a directory: %s" % localeSrcdir)
+ if not createDir(localeSrcdir):
+ log.error(_("Giving up on %s" % localeSrcdir))
+ return False
+ localeDir = config.getLocaleDir()
+ if not os.path.isdir(localeDir):
+ log.info("Not a directory: %s" % localeDir)
+ if not createDir(localeDir):
+ log.error(_("Giving up on %s" % localeDir))
+ return False
+
+def getCurrentCrontab():
+ # This returns our current crontab
+ savedTab = "# This crontab has been tampered with by gettor.py\n"
+ currentTab = os.popen("crontab -l")
+ for line in currentTab:
+ savedTab += line
+ return savedTab
+
More information about the tor-commits
mailing list