Beispiel #1
0
    def index(self):
        ''' Print up an index of the available trackers
        '''
        keys = list(self.TRACKER_HOMES.keys())
        if len(keys) == 1:
            self.send_response(302)
            self.send_header('Location', urllib_.quote(keys[0]) + '/index')
            self.end_headers()
        else:
            self.send_response(200)

        self.send_header('Content-Type', 'text/html')
        self.end_headers()
        w = self.wfile.write

        if self.CONFIG and self.CONFIG['TEMPLATE']:
            template = open(self.CONFIG['TEMPLATE']).read()
            pt = PageTemplate()
            pt.write(template)
            extra = { 'trackers': self.TRACKERS,
                'nothing' : None,
                'true' : 1,
                'false' : 0,
            }
            w(s2b(pt.pt_render(extra_context=extra)))
        else:
            w(s2b(_('<html><head><title>Roundup trackers index</title></head>\n'
                    '<body><h1>Roundup trackers index</h1><ol>\n')))
            keys.sort()
            for tracker in keys:
                w(s2b('<li><a href="%(tracker_url)s/index">%(tracker_name)s</a>\n'%{
                    'tracker_url': urllib_.quote(tracker),
                    'tracker_name': html_escape(tracker)}))
            w(b'</ol></body></html>')
Beispiel #2
0
    def close(self):
        file, ext = os.path.splitext(self.filename)

        if ext in sgml_file_types:
            self.file.write(s2b("<!-- SHA: %s -->\n" % (self.digest.hexdigest(),)))
        elif ext in hash_file_types:
            self.file.write(s2b("#SHA: %s\n" % (self.digest.hexdigest(),)))
        elif ext in slast_file_types:
            self.file.write(s2b("/* SHA: %s */\n" % (self.digest.hexdigest(),)))

        self.file.close()
Beispiel #3
0
    def __call__(self, environ, start_response):
        """Initialize with `apache.Request` object"""
        request = RequestHandler(environ, start_response)

        if environ['REQUEST_METHOD'] == 'OPTIONS':
            if environ["PATH_INFO"][:5] == "/rest":
                # rest does support options
                # This I hope will result in self.form=None
                environ['CONTENT_LENGTH'] = 0
            else:
                code = 501
                message, explain = BaseHTTPRequestHandler.responses[code]
                request.start_response([('Content-Type', 'text/html')], code)
                request.wfile.write(s2b(DEFAULT_ERROR_MESSAGE % locals()))
                return []

        # need to strip the leading '/'
        environ["PATH_INFO"] = environ["PATH_INFO"][1:]
        if self.timing:
            environ["CGI_SHOW_TIMING"] = self.timing

        if environ['REQUEST_METHOD'] in ("OPTIONS", "DELETE"):
            # these methods have no data. When we init tracker.Client
            # set form to None to get a properly initialized empty
            # form.
            form = None
        else:
            form = BinaryFieldStorage(fp=environ['wsgi.input'],
                                      environ=environ)

        if "cache_tracker" in self.feature_flags:
            client = self.tracker.Client(self.tracker, request, environ, form,
                                         self.translator)
            try:
                client.main()
            except roundup.cgi.client.NotFound:
                request.start_response([('Content-Type', 'text/html')], 404)
                request.wfile.write(
                    s2b('Not found: %s' % html_escape(client.path)))
        else:
            with self.get_tracker() as tracker:
                client = tracker.Client(tracker, request, environ, form,
                                        self.translator)
                try:
                    client.main()
                except roundup.cgi.client.NotFound:
                    request.start_response([('Content-Type', 'text/html')],
                                           404)
                    request.wfile.write(
                        s2b('Not found: %s' % html_escape(client.path)))

        # all body data has been written using wfile
        return []
    def __call__(self, environ, start_response):
        """Initialize with `apache.Request` object"""
        self.environ = environ
        request = RequestDispatcher(self.home, self.debug, self.timing)
        request.__start_response = start_response

        request.wfile = Writer(request)
        request.__wfile = None
        request.headers = Headers(environ)

        if environ['REQUEST_METHOD'] == 'OPTIONS':
            if environ["PATH_INFO"][:5] == "/rest":
                # rest does support options
                # This I hope will result in self.form=None
                environ['CONTENT_LENGTH'] = 0
            else:
                code = 501
                message, explain = BaseHTTPRequestHandler.responses[code]
                request.start_response([('Content-Type', 'text/html'),
                                        ('Connection', 'close')], code)
                request.wfile.write(s2b(DEFAULT_ERROR_MESSAGE % locals()))
                return []

        tracker = roundup.instance.open(self.home, not self.debug)

        # need to strip the leading '/'
        environ["PATH_INFO"] = environ["PATH_INFO"][1:]
        if request.timing:
            environ["CGI_SHOW_TIMING"] = request.timing

        form = BinaryFieldStorage(fp=environ['wsgi.input'], environ=environ)

        if environ['REQUEST_METHOD'] in ("OPTIONS", "DELETE"):
            # these methods have no data. When we init tracker.Client
            # set form to None and request.rfile to None to get a
            # properly initialized empty form.
            form = None
            request.rfile = None

        client = tracker.Client(tracker, request, environ, form,
                                request.translator)
        try:
            client.main()
        except roundup.cgi.client.NotFound:
            request.start_response([('Content-Type', 'text/html')], 404)
            request.wfile.write(s2b('Not found: %s' %
                                    html_escape(client.path)))

        # all body data has been written using wfile
        return []
Beispiel #5
0
def encodePassword(plaintext, scheme, other=None, config=None):
    """Encrypt the plaintext password.
    """
    if plaintext is None:
        plaintext = ""
    if scheme == "PBKDF2":
        if other:
            rounds, salt, raw_salt, digest = pbkdf2_unpack(other)
        else:
            raw_salt = random_.token_bytes(20)
            salt = h64encode(raw_salt)
            if config:
                rounds = config.PASSWORD_PBKDF2_DEFAULT_ROUNDS
            else:
                rounds = 10000
        if rounds < 1000:
            raise PasswordValueError("invalid PBKDF2 hash (rounds too low)")
        raw_digest = pbkdf2(plaintext, raw_salt, rounds, 20)
        return "%d$%s$%s" % (rounds, salt, h64encode(raw_digest))
    elif scheme == 'SSHA':
        if other:
            raw_other = b64decode(other)
            salt = raw_other[20:]
        else:
            # new password
            # variable salt length
            salt_len = random_.randbelow(52 - 36) + 36
            salt = random_.token_bytes(salt_len)
        s = ssha(s2b(plaintext), salt)
    elif scheme == 'SHA':
        s = sha1(s2b(plaintext)).hexdigest()  # nosec
    elif scheme == 'MD5':
        s = md5(s2b(plaintext)).hexdigest()  # nosec
    elif scheme == 'crypt':
        if crypt is None:
            raise PasswordValueError('Unsupported encryption scheme %r' %
                                     scheme)
        if other is not None:
            salt = other
        else:
            saltchars = './0123456789' + string.ascii_letters
            salt = random_.choice(saltchars) + random_.choice(saltchars)
        s = crypt.crypt(plaintext, salt)
    elif scheme == 'plaintext':
        s = plaintext
    else:
        raise PasswordValueError('Unknown encryption scheme %r' % scheme)
    return s
    def find(self, wordlist):
        '''look up all the words in the wordlist.
        If none are found return an empty dictionary
        * more rules here
        '''
        if not wordlist:
            return {}

        database = self._get_database()

        enquire = xapian.Enquire(database)
        stemmer = xapian.Stem("english")
        terms = []
        for term in [
                word.upper() for word in wordlist
                if self.minlength <= len(word) <= self.maxlength
        ]:
            if not self.is_stopword(term):
                terms.append(stemmer(s2b(term.lower())))
        query = xapian.Query(xapian.Query.OP_AND, terms)

        enquire.set_query(query)
        matches = enquire.get_mset(0, database.get_doccount())

        return [tuple(b2s(m.document.get_data()).split(':')) for m in matches]
Beispiel #7
0
class memorydbSessionTest(memorydbOpener, SessionTest, unittest.TestCase):
    s2b = lambda x, y: strings.s2b(y)

    def setUp(self):
        self.db = self.module.Database(config, 'admin')
        setupSchema(self.db, 1, self.module)
        self.sessions = self.db.sessions

    # doesn't work for memory as it uses a mock for session db.
    def testUpdateTimestamp(self):
        self.skipTest("This test does is not implemented for memorydb.")
Beispiel #8
0
 def run_cgi(self):
     """ Execute the CGI command. Wrap an innner call in an error
         handler so all errors can be caught.
     """
     try:
         self.inner_run_cgi()
     except client.NotFound:
         self.send_error(404, self.path)
     except client.Unauthorised as message:
         self.send_error(403, '%s (%s)' % (self.path, message))
     except:
         exc, val, tb = sys.exc_info()
         if hasattr(socket, 'timeout') and isinstance(val, socket.timeout):
             self.log_error('timeout')
         else:
             # it'd be nice to be able to detect if these are going to have
             # any effect...
             self.send_response(400)
             self.send_header('Content-Type', 'text/html')
             self.end_headers()
             if self.DEBUG_MODE:
                 try:
                     reload(cgitb)
                     self.wfile.write(s2b(cgitb.breaker()))
                     self.wfile.write(s2b(cgitb.html()))
                 except:
                     s = StringIO()
                     traceback.print_exc(None, s)
                     self.wfile.write(b"<pre>")
                     self.wfile.write(s2b(cgi.escape(s.getvalue())))
                     self.wfile.write(b"</pre>\n")
             else:
                 # user feedback
                 self.wfile.write(s2b(cgitb.breaker()))
                 ts = time.ctime()
                 self.wfile.write(
                     s2b('''<p>%s: An error occurred. Please check
                 the server log for more information.</p>''' % ts))
                 # out to the logfile
                 print('EXCEPTION AT', ts)
                 traceback.print_exc()
Beispiel #9
0
def h64decode(data):
    """decode using variant of base64"""
    data = s2b(data)
    off = len(data) % 4
    if off == 0:
        return b64decode(data, b"./")
    elif off == 1:
        raise ValueError("Invalid base64 input")
    elif off == 2:
        return b64decode(data + b"==", b"./")
    else:
        return b64decode(data + b"=", b"./")
    def add_text(self, identifier, text, mime_type='text/plain'):
        ''' "identifier" is  (classname, itemid, property) '''
        if mime_type != 'text/plain':
            return
        if not text: text = ''

        # open the database and start a transaction if needed
        database = self._get_database()

        # XXX: Xapian now supports transactions,
        #  but there is a call to save_index() missing.
        #if not self.transaction_active:
        #database.begin_transaction()
        #self.transaction_active = True

        # TODO: allow configuration of other languages
        stemmer = xapian.Stem("english")

        # We use the identifier twice: once in the actual "text" being
        # indexed so we can search on it, and again as the "data" being
        # indexed so we know what we're matching when we get results
        identifier = s2b('%s:%s:%s' % identifier)

        # create the new document
        doc = xapian.Document()
        doc.set_data(identifier)
        doc.add_term(identifier, 0)

        for match in re.finditer(
                r'\b\w{%d,%d}\b' % (self.minlength, self.maxlength),
                text.upper(), re.UNICODE):
            word = match.group(0)
            if self.is_stopword(word):
                continue
            term = stemmer(s2b(word.lower()))
            doc.add_posting(term, match.start(0))

        database.replace_document(identifier, doc)
Beispiel #11
0
    def __call__(self, environ, start_response):
        """Initialize with `apache.Request` object"""
        self.environ = environ
        request = RequestDispatcher(self.home, self.debug, self.timing)
        request.__start_response = start_response

        request.wfile = Writer(request)
        request.__wfile = None
        request.headers = Headers(environ)

        if environ ['REQUEST_METHOD'] == 'OPTIONS':
            code = 501
            message, explain = BaseHTTPRequestHandler.responses[code]
            request.start_response([('Content-Type', 'text/html'),
                ('Connection', 'close')], code)
            request.wfile.write(s2b(DEFAULT_ERROR_MESSAGE % locals()))
            return []

        tracker = roundup.instance.open(self.home, not self.debug)

        # need to strip the leading '/'
        environ["PATH_INFO"] = environ["PATH_INFO"][1:]
        if request.timing:
            environ["CGI_SHOW_TIMING"] = request.timing

        form = cgi.FieldStorage(fp=environ['wsgi.input'], environ=environ)

        client = tracker.Client(tracker, request, environ, form,
            request.translator)
        try:
            client.main()
        except roundup.cgi.client.NotFound:
            request.start_response([('Content-Type', 'text/html')], 404)
            request.wfile.write(s2b('Not found: %s'%html_escape(client.path)))

        # all body data has been written using wfile
        return []
Beispiel #12
0
class anydbmSessionTest(anydbmOpener, SessionTest, unittest.TestCase):
    s2b = lambda x, y: strings.s2b(y)

    # this only works for dbm. other backends don't change the __timestamp
    # value, they have a separate column for the timestamp so they can
    # update it with SQL.
    def testUpdateTimestamp(self):
        # make sure timestamp is older than one minute so update will work
        timestamp = time.time() - 62
        self.sessions.set('random_session',
                          text='hello, world!',
                          __timestamp=timestamp)
        self.sessions.updateTimestamp('random_session')
        self.assertNotEqual(self.sessions.get('random_session', '__timestamp'),
                            timestamp)
Beispiel #13
0
def write_csv(klass, data):
    props = klass.getprops()
    if not os.path.exists('/tmp/imported'):
        os.mkdir('/tmp/imported')
    f = open('/tmp/imported/%s.csv'%klass.classname, 'w')
    writer = csv.writer(f, colon_separated)
    propnames = klass.export_propnames()
    propnames.append('is retired')
    writer.writerow(propnames)
    for entry in data:
        row = []
        for name in propnames:
            if name == 'is retired':
                continue
            prop = props[name]
            if name in entry:
                if isinstance(prop, hyperdb.Date) or \
                        isinstance(prop, hyperdb.Interval):
                    row.append(repr(entry[name].get_tuple()))
                elif isinstance(prop, hyperdb.Password):
                    row.append(repr(str(entry[name])))
                else:
                    row.append(repr(entry[name]))
            elif isinstance(prop, hyperdb.Multilink):
                row.append('[]')
            elif name in ('creator', 'actor'):
                row.append("'1'")
            elif name in ('created', 'activity'):
                row.append(repr(today.get_tuple()))
            else:
                row.append('None')
        row.append(entry.get('is retired', False))
        writer.writerow(row)

        if isinstance(klass, hyperdb.FileClass) and entry.get('content'):
            fname = klass.exportFilename('/tmp/imported/', entry['id'])
            support.ensureParentsExist(fname)
            c = open(fname, 'wb')
            if isinstance(entry['content'], bytes):
                c.write(entry['content'])
            else:
                c.write(s2b(us2s(entry['content'])))
            c.close()

    f.close()
    f = open('/tmp/imported/%s-journals.csv'%klass.classname, 'w')
    f.close()
Beispiel #14
0
def checkDigest(filename):
    """Read file, check for valid fingerprint, return TRUE if ok"""
    # open and read file
    inp = open(filename, "rb")
    lines = inp.readlines()
    inp.close()

    fingerprint = extractFingerprint(lines)
    if fingerprint is None:
        return 0
    del lines[-1]

    # calculate current digest
    digest = sha1()
    for line in lines:
        digest.update(line)

    # compare current to stored digest
    return fingerprint == s2b(digest.hexdigest())
Beispiel #15
0
def pbkdf2(password, salt, rounds, keylen):
    """pkcs#5 password-based key derivation v2.0

    :arg password: passphrase to use to generate key (if unicode, converted to utf-8)
    :arg salt: salt bytes to use when generating key
    :param rounds: number of rounds to use to generate key
    :arg keylen: number of bytes to generate

    If hashlib supports pbkdf2, uses it's implementation as backend.

    :returns:
        raw bytes of generated key
    """
    password = s2b(us2s(password))
    if keylen > 40:
        #NOTE: pbkdf2 allows up to (2**31-1)*20 bytes,
        # but m2crypto has issues on some platforms above 40,
        # and such sizes aren't needed for a password hash anyways...
        raise ValueError("key length too large")
    if rounds < 1:
        raise ValueError("rounds must be positive number")
    return _pbkdf2(password, salt, rounds, keylen)
Beispiel #16
0
 def linereader(file=file, lnum=[lnum]):
     line = s2b(linecache.getline(file, lnum[0]))
     lnum[0] = lnum[0] + 1
     return line
Beispiel #17
0
def unpack_timestamp(s):
    try:
        timestamp = struct.unpack("i", base64.b64decode(s2b(s)))[0]
    except (struct.error, binascii.Error, TypeError):
        raise FormError(_("Form is corrupted."))
    return timestamp
Beispiel #18
0
 def storefile(self, classname, nodeid, property, content):
     if isinstance(content, str):
         content = s2b(content)
     self.tx_files[classname, nodeid, property] = content
     self.transactions.append(
         (self.doStoreFile, (classname, nodeid, property)))
Beispiel #19
0
 def __setitem__(self, key, value):
     return super(cldb, self).__setitem__(s2b(key), value)
Beispiel #20
0
 def __delitem__(self, key):
     return super(BasicDatabase, self).__delitem__(s2b(key))
Beispiel #21
0
 def __setitem__(self, key, value):
     return super(BasicDatabase, self).__setitem__(s2b(key), value)
Beispiel #22
0
 def __getitem__(self, key):
     if key not in self:
         d = self[key] = {}
         return d
     return super(BasicDatabase, self).__getitem__(s2b(key))
Beispiel #23
0
 def __init__(self, **values):
     super(BasicDatabase, self).__init__()
     for k, v in values.items():
         super(BasicDatabase, self).__setitem__(s2b(k), v)
Beispiel #24
0
 def __delitem__(self, key):
     return super(cldb, self).__delitem__(s2b(key))
Beispiel #25
0
 def __contains__(self, key):
     return super(BasicDatabase, self).__contains__(s2b(key))
Beispiel #26
0
 def __contains__(self, key):
     return super(cldb, self).__contains__(s2b(key))
Beispiel #27
0
 def __init__(self, **values):
     super(cldb, self).__init__()
     for key, value in values.items():
         super(cldb, self).__setitem__(s2b(key), value)