# Path: lib/crypto/packaged.py
# def sign_app(src, dest, ids, reviewer=False, local=False):
#     """
#     Sign a packaged app.
# 
#     If `local` is True, we never copy the signed package to remote storage.
# 
#     """
#     tempname = tempfile.mktemp()
#     try:
#         return _sign_app(src, dest, ids, reviewer, tempname, local)
#     finally:
#         try:
#             os.unlink(tempname)
#         except OSError:
#             # If the file has already been removed, don't worry about it.
#             pass
# 
# class SigningError(Exception):
#     pass


import json
import os.path
import commonware.log
from uuid import UUID
from django.conf import settings
from django.core.urlresolvers import reverse
from django.db import models
from django.utils.functional import lazy
from django_statsd.clients import statsd
from uuidfield.fields import UUIDField
from lib.crypto.packaged import sign_app, SigningError
from mkt.files.models import cleanup_file, nfd_str
from mkt.langpacks.utils import LanguagePackParser
from mkt.translations.utils import to_language
from mkt.site.helpers import absolutify
from mkt.site.models import ModelBase
from mkt.site.storage_utils import private_storage, public_storage
from mkt.site.utils import smart_path
from mkt.webapps.models import get_cached_minifest
                'Trying to upload a file to a destination that already exists')

        self.file_version = self.file_version + 1

        # Because we are only dealing with langpacks generated by Mozilla atm,
        # we can directly sign the file before copying it to its final
        # destination. The filename changes with the version, so when a new
        # file is uploaded we should still be able to serve the old one until
        # the new info is stored in the db.
        self.sign_and_move_file(upload)

    def sign_and_move_file(self, upload):
        ids = json.dumps({
            # 'id' needs to be an unique identifier not shared with anything
            # else (other langpacks, webapps, extensions...), but should not
            # change when there is an update. Since our PKs are uuid it's the
            # best choice.
            'id': self.pk,
            # 'version' should be an integer and should be monotonically
            # increasing.
            'version': self.file_version
        })
        with statsd.timer('langpacks.sign'):
            try:
                # This will read the upload.path file, generate a signature
                # and write the signed file to self.file_path.
                sign_app(private_storage.open(upload.path),
                         self.file_path, ids)
            except SigningError:
                log.info('[LangPack:%s] Signing failed' % self.pk)

# Path: lib/crypto/packaged.py
# def sign_app(src, dest, ids, reviewer=False, local=False):
#     """
#     Sign a packaged app.
# 
#     If `local` is True, we never copy the signed package to remote storage.
# 
#     """
#     tempname = tempfile.mktemp()
#     try:
#         return _sign_app(src, dest, ids, reviewer, tempname, local)
#     finally:
#         try:
#             os.unlink(tempname)
#         except OSError:
#             # If the file has already been removed, don't worry about it.
#             pass
# 
# class SigningError(Exception):
#     pass


# Path: mkt/langpacks/models.py
import json
import os.path
import commonware.log
from uuid import UUID
from django.conf import settings
from django.core.urlresolvers import reverse
from django.db import models
from django.utils.functional import lazy
from django_statsd.clients import statsd
from uuidfield.fields import UUIDField
from lib.crypto.packaged import sign_app, SigningError
from mkt.files.models import cleanup_file, nfd_str
from mkt.langpacks.utils import LanguagePackParser
from mkt.translations.utils import to_language
from mkt.site.helpers import absolutify
from mkt.site.models import ModelBase
from mkt.site.storage_utils import private_storage, public_storage
from mkt.site.utils import smart_path
from mkt.webapps.models import get_cached_minifest

                'Trying to upload a file to a destination that already exists')

        self.file_version = self.file_version + 1

        # Because we are only dealing with langpacks generated by Mozilla atm,
        # we can directly sign the file before copying it to its final
        # destination. The filename changes with the version, so when a new
        # file is uploaded we should still be able to serve the old one until
        # the new info is stored in the db.
        self.sign_and_move_file(upload)

    def sign_and_move_file(self, upload):
        ids = json.dumps({
            # 'id' needs to be an unique identifier not shared with anything
            # else (other langpacks, webapps, extensions...), but should not
            # change when there is an update. Since our PKs are uuid it's the
            # best choice.
            'id': self.pk,
            # 'version' should be an integer and should be monotonically
            # increasing.
            'version': self.file_version
        })
        with statsd.timer('langpacks.sign'):
            try:
                # This will read the upload.path file, generate a signature
                # and write the signed file to self.file_path.
                sign_app(private_storage.open(upload.path),
                         self.file_path, ids)
            except SigningError:
                log.info('[LangPack:%s] Signing failed' % self.pk)

                if public_storage.exists(self.file_path):