def parse_submission(fms_id, lines, usk_hash): """ Parse a single submission from raw fms message lines and returns a submission tuple of the form: (fms_id, usk_hash, base_version, chk, length) Returns None if no submission could be parsed. """ print "LINES:" print lines for line in lines: if not line.startswith('W:'): continue # 0 1 2 3 4 # W:<repo_hash>:<base_version>:<chk><length> fields = line.strip().split(':') if not is_hex_string(fields[1]) or not is_hex_string(fields[2]): continue if fields[1] != usk_hash: continue if (not fields[3].startswith('CHK@') or len(fields[3]) != ENCODED_CHK_SIZE): continue try: length = int(fields[4]) except ValueError: continue # (fms_id, usk_hash, base_version, chk, length) return (fms_id, fields[1], fields[2], fields[3], length) return None
def to_msg_string(updates, announcements=None, separator='\n'): """ Dump updates and announcements in a format which can be read by parse. """ if updates is None: updates = [] if announcements is None: announcements = [] # Make sure we always get the same string rep. updates = list(updates) updates.sort() announcements = list(announcements) announcements.sort() # Hmmm... extra loops for assert paranoia. for value in announcements: assert is_usk_file(value) for update in updates: assert is_hex_string(update[0], 12) assert update[1] >= 0 tmp = [ separator.join(["A:%s" % value for value in announcements]), separator.join( ["U:%s:%i" % (update[0], update[1]) for update in updates]) ] while '' in tmp: tmp.remove('') return separator.join(tmp)
def to_msg_string(updates, announcements=None, separator='\n'): """ Dump updates and announcements in a format which can be read by parse. """ if updates is None: updates = [] if announcements is None: announcements = [] # Make sure we always get the same string rep. updates = list(updates) updates.sort() announcements = list(announcements) announcements.sort() # Hmmm... extra loops for assert paranoia. for value in announcements: assert is_usk_file(value) for update in updates: assert is_hex_string(update[0], 12) assert update[1] >= 0 tmp = [separator.join(["A:%s" % value for value in announcements]), separator.join(["U:%s:%i" % (update[0], update[1]) for update in updates])] while '' in tmp: tmp.remove('') return separator.join(tmp)
def trust_id_for_repo(trust_map, fms_id, repo_hash): """ Accept index updates from an fms id for a repo.""" assert is_fms_id(fms_id) assert is_hex_string(repo_hash) hashes = trust_map.get(fms_id, ()) if repo_hash in hashes: return False hashes = list(hashes) hashes.append(repo_hash) trust_map[fms_id] = tuple(hashes) return True
def validate_trust_map_entry(cls, cfg, fields): """ INTERNAL: Raise a ValueError for invalid trust map entries. """ if not is_fms_id(fields[0]): raise ValueError("%s doesn't look like an fms id." % fields[0]) if len(fields) < 2: raise ValueError("No USK hashes for fms id: %s?" % fields[0]) for value in fields[1:]: if not is_hex_string(value): raise ValueError("%s doesn't look like a repo hash." % value) if fields[0] in cfg.fmsread_trust_map: raise ValueError(("%s appears more than once in the " + "[fmsread_trust_map] section.") % fields[0])
def parse_updates(fields, updates): """ Helper function parses updates. """ if fields[0] != 'U' or len(fields) < 3: return False while len(fields) > 0 and fields[0] == 'U' and len(fields) >= 3: try: if is_hex_string(fields[1]): updates.add((fields[1], int(fields[2]))) fields = fields[3:] else: break except ValueError: break # Doesn't imply success, just that we tried. return True
def unpack_info(info_text): """ INTERNAL: Validate and unpack __INFO__ contents from 7-bit ASCII. """ try: info_text = info_text.decode('ascii') except UnicodeError: raise SubmitError("Non-ASCII characters in info file.", True) if len(info_text) > MAX_INFO_LEN: raise SubmitError("Info file too big.", True) fields = info_text.splitlines(False) if len(fields) != 2: raise SubmitError("Format error in info file.", True) if not is_hex_string(fields[0], 40): raise SubmitError("Version isn't a 40 digit hex string: %s" % repr(fields[0]), True) # Hmmmm... empty submitter is ok return fields[0], fields[1].strip()
def pack_info(version, submitter): """ INTERNAL: Validate and pack __INFO__ contents into 7-bit ASCII. """ try: submitter.encode('ascii') except UnicodeError: raise SubmitError("Non-ASCII characters in submitter name: %s" % repr(submitter), True) if not is_hex_string(version, 40): raise SubmitError("Version isn't a 40 digit hex string: %s" % repr(version), True) try: ret = ("%s\n%s\n" % (version, submitter)).encode('ascii') except UnicodeError: # Impossible? raise SubmitError("Unexpected error packing info???", True) if len(ret) > MAX_INFO_LEN: raise SubmitError("Info file too big.", True) return ret
def parse_trust_args(params, opts): """ INTERNAL: Helper function to parse --hash and --fmsid. """ if not opts.get('hash', []): raise util.Abort("Use --hash to set the USK hash.") if len(opts['hash']) != 1: raise util.Abort("Only one --hash value is allowed.") if not is_hex_string(opts['hash'][0]): raise util.Abort("[%s] doesn't look like a USK hash." % opts['hash'][0]) if not opts.get('fmsid', []): raise util.Abort("Use --fmsid to set the FMS id.") if len(opts['fmsid']) != 1: raise util.Abort("Only one --fmsid value is allowed.") if not is_fms_id(opts['fmsid'][0]): raise util.Abort("[%s] doesn't look like an FMS id." % opts['fmsid'][0]) params['FMSREAD_HASH'] = opts['hash'][0] params['FMSREAD_FMSID'] = opts['fmsid'][0]
def parse_trust_args(params, opts): """ INTERNAL: Helper function to parse --hash and --fmsid. """ if opts.get('hash', []) == []: raise util.Abort("Use --hash to set the USK hash.") if len(opts['hash']) != 1: raise util.Abort("Only one --hash value is allowed.") if not is_hex_string(opts['hash'][0]): raise util.Abort("[%s] doesn't look like a USK hash." % opts['hash'][0]) if opts.get('fmsid', []) == []: raise util.Abort("Use --fmsid to set the FMS id.") if len(opts['fmsid']) != 1: raise util.Abort("Only one --fmsid value is allowed.") if not is_fms_id(opts['fmsid'][0]): raise util.Abort("[%s] doesn't look like an FMS id." % opts['fmsid'][0]) params['FMSREAD_HASH'] = opts['hash'][0] params['FMSREAD_FMSID'] = opts['fmsid'][0]
def untrust_id_for_repo(trust_map, fms_id, repo_hash): """ Stop accepting index updates from an fms id for a repo.""" assert is_fms_id(fms_id) assert is_hex_string(repo_hash) if not fms_id in trust_map: return False hashes = list(trust_map[fms_id]) # Paranoia. There shouldn't be duplicates. count = 0 while repo_hash in hashes: hashes.remove(repo_hash) count += 1 if len(hashes) == 0: del trust_map[fms_id] return True trust_map[fms_id] = tuple(hashes) return count > 0