Replaces %%%NAMESPACE%%% for all files and ___NAMESPACE___ in all
        filenames in the zip with the either '' if no namespace is provided
        or 'namespace__' if provided.

def zip_inject_namespace(
    zip_src,
    namespace=None,
    managed=None,
    filename_token=None,
    namespace_token=None,
    namespaced_org=None,
    logger=None,
):
    """ Replaces %%%NAMESPACE%%% for all files and ___NAMESPACE___ in all
        filenames in the zip with the either '' if no namespace is provided
        or 'namespace__' if provided.
    """

    # Handle namespace and filename tokens
    if not filename_token:
        filename_token = "___NAMESPACE___"
    if not namespace_token:
        namespace_token = "%%%NAMESPACE%%%"
    if managed is True and namespace:
        namespace_prefix = namespace + "__"
    else:
        namespace_prefix = ""

    # Handle tokens %%%NAMESPACED_ORG%%% and ___NAMESPACED_ORG___
    namespaced_org_token = "%%%NAMESPACED_ORG%%%"
    namespaced_org_file_token = "___NAMESPACED_ORG___"
    namespaced_org = namespace_prefix if namespaced_org else ""

    # Handle token %%%NAMESPACE_OR_C%%% for lightning components
    namespace_or_c_token = "%%%NAMESPACE_OR_C%%%"
    namespace_or_c = namespace if managed and namespace else "c"

    # Handle token %%%NAMESPACED_ORG_OR_C%%%
    namespaced_org_or_c_token = "%%%NAMESPACED_ORG_OR_C%%%"
    namespaced_org_or_c = namespace if namespaced_org else "c"

    zip_dest = zipfile.ZipFile(io.BytesIO(), "w", zipfile.ZIP_DEFLATED)

    for name in zip_src.namelist():
        orig_name = str(name)
        content = zip_src.read(name)
        try:
            content = content.decode("utf-8")
        except UnicodeDecodeError:
            # if we cannot decode the content, don't try and replace it.
            pass
        else:
            prev_content = content
            content = content.replace(namespace_token, namespace_prefix)
            if logger and content != prev_content:
                logger.info(
                    '  {}: Replaced %%%NAMESPACE%%% with "{}"'.format(name, namespace)
                )

            prev_content = content
            content = content.replace(namespace_or_c_token, namespace_or_c)
            if logger and content != prev_content:
                logger.info(
                    '  {}: Replaced %%%NAMESPACE_OR_C%%% with "{}"'.format(
                        name, namespace_or_c
                    )
                )

            prev_content = content
            content = content.replace(namespaced_org_token, namespaced_org)
            if logger and content != prev_content:
                logger.info(
                    '  {}: Replaced %%%NAMESPACED_ORG%%% with "{}"'.format(
                        name, namespaced_org
                    )
                )

            prev_content = content
            content = content.replace(namespaced_org_or_c_token, namespaced_org_or_c)
            if logger and content != prev_content:
                logger.info(
                    '  {}: Replaced %%%NAMESPACED_ORG_OR_C%%% with "{}"'.format(
                        name, namespaced_org_or_c
                    )
                )

            content = content.encode("utf-8")

        # Replace namespace token in file name
        name = name.replace(filename_token, namespace_prefix)
        name = name.replace(namespaced_org_file_token, namespaced_org)
        if logger and name != orig_name:
            logger.info("  {}: renamed to {}".format(orig_name, name))
        zip_dest.writestr(name, content)

    return zip_dest