def write_plugin(plugin):
    """Write a plugin"""
    data = OrderedDict(zip(DEFAULT_ORDER, [None] * len(DEFAULT_ORDER)))
    with open(plugin["plugin"], "rb") as inp:
        data.update(json.loads(inp.read().decode("utf-8")))

    # remove unset values
    for key, value in list(data.items()):
        if value is None:
            del data[key]

    # import scripts
    for fun in ("process", "resolve"):
        if fun not in plugin:
            continue
        try:
            with open(plugin[fun]) as src:
                data[fun] = src.read()
        except IOError as ex:
            print("Could not open {0} file {1}: {2}".format(fun, plugin[fun], ex), file=sys.stderr)

    # generate JSON
    data = json.dumps(data, indent=4, separators=(",", ": "))
    count = 1
    while count > 0:
        data, count = RE_INDENT.subn("\\1\t", data)

    # write plugin file
    with open(plugin["plugin"], "wb") as outp:
        outp.write(data.encode("utf-8"))
def create_signed_url(file, expires=60, secure=False, private_cloudfront=False, expires_at=None):
    if not private_cloudfront:
        generator = QueryStringAuthGenerator(
            settings.AWS_ACCESS_KEY_ID,
            settings.AWS_SECRET_ACCESS_KEY,
            calling_format=getattr(settings, "AWS_CALLING_FORMAT", CallingFormat.SUBDOMAIN),
            is_secure=secure,
        )
        generator.set_expires_in(expires)
        return generator.generate_url("GET", settings.AWS_STORAGE_BUCKET_NAME, file)

    url = settings.MEDIA_URL
    if not isinstance(settings.MEDIA_URL, CloudFrontURLs):
        url = CloudFrontURLs(settings.MEDIA_URL)
    url = url.get_url(file, force_https=True if secure else False)

    if url.startswith("//"):
        # A protocol is needed for correct signing
        if secure:
            url = "https:" + url
        else:
            url = "http:" + url

    if expires_at is None:
        expires = int(time.time() + expires)
    else:
        expires = expires_at

    # Use OrderedDict to keep things predictable and testable
    policy = OrderedDict()
    policy["Resource"] = url
    policy["Condition"] = {"DateLessThan": {"AWS:EpochTime": expires}}
    policy = {"Statement": [policy]}
    policy = json.dumps(policy, separators=(",", ":"))

    key = settings.CUDDLYBUDDLY_STORAGE_S3_KEY_PAIR
    dig = SHA.new()
    dig.update(policy.encode("utf-8"))
    sig = PKCS1_v1_5.new(RSA.importKey(key[1]))
    sig = sig.sign(dig)
    sig = base64.b64encode(sig).decode("utf-8")
    sig = sig.replace("+", "-").replace("=", "_").replace("/", "~")

    return "%s%sExpires=%s&Signature=%s&Key-Pair-Id=%s" % (url, "&" if "?" in url else "?", expires, sig, key[0])