Esempio n. 1
0
def write_to_package_job(control, path, callback_version_id):
    # copy to temporary
    """
    This job will be called when any field in .deb file control part
    has been edited.
    
    :param control: New Control Dict
    :type control: dict
    :param path: Original Package Path
    :type path: str
    :param callback_version_id: Callback Version ID, for callback query
    :type callback_version_id: int
    """
    abs_path = os.path.join(settings.MEDIA_ROOT, path)
    temp_path = os.path.join(settings.TEMP_ROOT, str(uuid.uuid1()) + '.deb')
    shutil.copyfile(abs_path, temp_path)
    # read new package
    temp_package = DebianPackage(temp_path)
    temp_package.control = control
    # save new package
    temp_package.save()
    t_version = Version.objects.get(id=callback_version_id)
    t_version.write_callback(temp_package.path)
Esempio n. 2
0
def handle_uploaded_package(path):
    """
    :param path: Package Uploaded Path
    :type path: str
    :return: Result Dict
    :rtype: dict
    """
    result_dict = {}
    try:
        uploaded_package = DebianPackage(path)
        control = uploaded_package.control
        version_dir = os.path.join(settings.MEDIA_ROOT, 'versions')
        if not os.path.isdir(version_dir):
            mkdir_p(version_dir)
        target_dir = os.path.join(version_dir, str(uuid.uuid1()))
        if not os.path.isdir(target_dir):
            mkdir_p(target_dir)
        target_path = os.path.join(
            target_dir,
            control.get('Package', 'undefined') + '_' +
            control.get('Version', 'undefined') + '_' +
            control.get('Architecture', 'undefined') + '.deb')
        with transaction.atomic():
            p_section = Section.objects.filter(
                name=control.get('Section', None)).last()
            if p_section:
                pass
            else:
                # create a new section
                p_section_name = control.get('Section', None)
                if p_section_name:
                    p_section = Section(name=p_section_name)
                    p_section.save()
            # search version
            p_version = Version.objects.filter(
                c_package=control.get('Package', None),
                c_version=control.get('Version', None)).last()
            if p_version:
                # version conflict
                result_dict.update({
                    "success":
                    False,
                    "exception":
                    _("Version Conflict: %s") % p_version.c_version
                })
            else:
                # os.rename(path, target_path)
                shutil.move(path, target_path)
                p_version = Version()
                p_version.c_package = control.get('Package', None)
                p_version.c_version = control.get('Version', None)
                p_version.storage = os.path.relpath(target_path,
                                                    settings.MEDIA_ROOT)
                p_version.maintainer_name = DebianPackage.value_for_field(
                    control.get('Maintainer', None))
                p_version.maintainer_email = DebianPackage.detail_for_field(
                    control.get('Maintainer', None))
                p_version.c_description = control.get('Description', "")
                p_version.c_section = p_section
                p_version.c_tag = control.get('Tag', None)
                p_version.c_architecture = control.get('Architecture', None)
                p_version.c_name = control.get('Name', None)
                p_version.author_name = DebianPackage.value_for_field(
                    control.get('Author', None))
                p_version.author_email = DebianPackage.detail_for_field(
                    control.get('Author', None))
                p_version.sponsor_name = DebianPackage.value_for_field(
                    control.get('Sponsor', None))
                p_version.sponsor_site = DebianPackage.detail_for_field(
                    control.get('Sponsor', None))
                p_version.c_depiction = control.get('Depiction', None)
                p_version.c_homepage = control.get('Homepage', None)
                p_version.c_priority = control.get('Priority', None)
                p_version.c_installed_size = control.get(
                    'Installed-Size', None)
                p_version.c_essential = control.get('Essential', None)
                p_version.c_depends = control.get('Depends', None)
                p_version.c_pre_depends = control.get('Pre-Depends', None)
                p_version.c_recommends = control.get('Recommends', None)
                p_version.c_suggests = control.get('Suggests', None)
                p_version.c_breaks = control.get('Breaks', None)
                p_version.c_conflicts = control.get('Conflicts', None)
                p_version.c_replaces = control.get('Replaces', None)
                p_version.c_provides = control.get('Provides', None)
                p_version.c_build_essential = control.get(
                    'Build-Essential', None)
                p_version.c_origin = control.get('Origin', None)
                p_version.c_bugs = control.get('Bugs', None)
                p_version.c_multi_arch = control.get('Multi-Arch', None)
                p_version.c_source = control.get('Source', None)
                p_version.c_subarchitecture = control.get(
                    'Subarchitecture', None)
                p_version.c_kernel_version = control.get(
                    'Kernel-Version', None)
                p_version.c_installer_menu_item = control.get(
                    'Installer-Menu-Item', None)
                p_version.c_built_using = control.get('Built-Using', None)
                p_version.c_built_for_profiles = control.get(
                    'Built-For-Profiles', None)
                p_version.c_icon = control.get('Icon', None)
                p_version.update_hash()
                p_version.save()
                # move resource
                result_dict.update({"success": True, "version": p_version.id})
    except Exception as e:
        # error handler
        result_dict.update({
            "success": False,
            # TODO: fix unicode bug
            "exception": str(e)
        })
    return result_dict
Esempio n. 3
0
def build_procedure(conf):
    """
    This is the main package list building procedure.
    """
    
    if not conf["build_p_diff"]:
        # Build Package file
        build_all_versions_enabled = conf["build_all"]
        
        # Get Package List QuerySet
        if build_all_versions_enabled:
            version_set = Version.objects.filter(enabled=True).order_by('-id')
            version_count = version_set.count()
        else:
            version_set = Version.objects.raw(
                "SELECT * FROM `WEIPDCRM_version` "
                "WHERE `enabled` = TRUE "
                "GROUP BY `c_package` "
                "ORDER BY `c_package`, `id` DESC"
            )
            version_count = 0
            for version in version_set:
                version_count += 1
        
        # Check Empty
        if version_count == 0:
            raise ValueError(_("No enabled package available."))

        # Preparing Temp Directory
        build_temp_path = os.path.join(settings.TEMP_ROOT, str(conf["build_uuid"]))
        if not os.path.exists(build_temp_path):
            mkdir_p(build_temp_path)

        # Create Temp Package file
        build_temp_package = open(os.path.join(build_temp_path, "Packages"), "wb+")
        
        # Generate Control List
        depiction_url = ""
        if preferences.Setting.advanced_mode:
            site = Site.objects.get(id=settings.SITE_ID)
            scheme = "http"
            if settings.SECURE_SSL is True:
                scheme = "https"
            depiction_url = "%s://%s" % (scheme, site.domain)
        for version_instance in version_set:
            # !!! HERE WE SHOULD USE ADVANCED CONTROL DICT !!!
            control_dict = version_instance.get_advanced_control_dict()
            if (not version_instance.custom_depiction) and len(depiction_url) != 0:
                control_dict["Depiction"] = depiction_url + version_instance.get_absolute_url()
            if version_instance.online_icon is not None and len(str(version_instance.online_icon)) > 0:
                control_dict["Icon"] = depiction_url + os.path.join(str(preferences.Setting.resources_alias), version_instance.online_icon.name)
            DebianPackage.get_control_content(control_dict, build_temp_package)
            build_temp_package.write("\n".encode("utf-8"))
        
        # Compression Gzip
        build_temp_package.seek(0)
        if conf["build_compression"] == 1 \
                or conf["build_compression"] == 2 \
                or conf["build_compression"] == 5 \
                or conf["build_compression"] == 6:
            build_temp_package_gz = gzip.open(os.path.join(build_temp_path, "Packages.gz"), mode="wb")
            while True:
                cache = build_temp_package.read(16 * 1024)  # 16k cache
                if not cache:
                    break
                build_temp_package_gz.write(cache)
            build_temp_package_gz.close()
        
        # Compression Bzip
        build_temp_package.seek(0)
        if conf["build_compression"] == 3 \
                or conf["build_compression"] == 4 \
                or conf["build_compression"] == 5 \
                or conf["build_compression"] == 6:
            build_temp_package_bz2 = bz2.BZ2File(os.path.join(build_temp_path, "Packages.bz2"), mode="wb")
            while True:
                cache = build_temp_package.read(16 * 1024)  # 16k cache
                if not cache:
                    break
                build_temp_package_bz2.write(cache)
            build_temp_package_bz2.close()
        
        # Close original Package file
        build_temp_package.close()

        # Release
        active_release = Release.objects.get(id=conf["build_release"])
        active_release_control_dict = active_release.get_control_field()
        build_temp_release = open(os.path.join(build_temp_path, "Release"), mode="wb")
        DebianPackage.get_control_content(active_release_control_dict, build_temp_release)
        
        # Checksum
        if conf["build_secure"] is True:
            def hash_file(hash_obj, file_path):
                with open(file_path, "rb") as f:
                    for block in iter(lambda: f.read(65535), b""):
                        hash_obj.update(block)

            checksum_list = [
                "Packages",
                "Packages.gz",
                "Packages.bz2"
            ]
            build_validation_titles = [
                "MD5Sum", "SHA1", "SHA256", "SHA512"
            ]
            build_validation_methods = [
                hashlib.md5, hashlib.sha1, hashlib.sha256, hashlib.sha512
            ]
            
            # Using a loop to iter different validation methods
            for build_validation_index in range(0, 3):
                if conf["build_validation"] > build_validation_index:
                    build_temp_release.write((build_validation_titles[build_validation_index] + ":\n").encode("utf-8"))
                    for checksum_instance in checksum_list:
                        checksum_path = os.path.join(build_temp_path, checksum_instance)
                        if os.path.exists(checksum_path):
                            m2 = build_validation_methods[build_validation_index]()
                            hash_file(m2, checksum_path)
                            p_hash = m2.hexdigest()
                            p_size = os.path.getsize(checksum_path)
                            build_temp_release.write(
                                (" " + p_hash +
                                 " " + str(p_size) +
                                 " " + checksum_instance +
                                 "\n").encode("utf-8")
                            )
        
        build_temp_release.close()

        if conf["build_secure"] is True:
            # GPG Signature
            """
            Use 'gpg --gen-key' to generate GnuPG key before using this function.
            """
            password = preferences.Setting.gpg_password
            if password is not None and len(password) > 0:
                subprocess.check_call(
                    ["gpg", "-abs", "--homedir", os.path.join(settings.BASE_DIR, '.gnupg'), "--batch", "--yes", "--pinentry-mode=loopback", "--passphrase", password, "-o",
                     os.path.join(build_temp_path, "Release.gpg"),
                     os.path.join(build_temp_path, "Release"),
                     ]
                )
            else:
                subprocess.check_call(
                    ["gpg", "-abs", "--homedir", os.path.join(settings.BASE_DIR, '.gnupg'), "--batch", "--yes", "-o",
                     os.path.join(build_temp_path, "Release.gpg"),
                     os.path.join(build_temp_path, "Release"),
                     ]
                )
        # Preparing Directory
        release_root = os.path.join(
            settings.MEDIA_ROOT,
            "releases",
            str(active_release.id),
        )
        build_path = os.path.join(
            release_root,
            "builds",
            str(conf["build_uuid"])
        )
        if not os.path.isdir(build_path):
            mkdir_p(build_path)
        
        # Publish
        rename_list = [
            "Release",
            "Release.gpg",
            "Packages",
            "Packages.gz",
            "Packages.bz2"
        ]
        for rename_instance in rename_list:
            rename_path = os.path.join(build_temp_path, rename_instance)
            rename_to_path = os.path.join(build_path, rename_instance)
            active_path = os.path.join(release_root, rename_instance)
            if os.path.exists(rename_path):
                if os.path.exists(active_path):
                    os.unlink(active_path)
                shutil.copyfile(rename_path, active_path)
                os.chmod(active_path, 0o755)
                # os.rename(rename_path, rename_to_path)
                shutil.move(rename_path, rename_to_path)
                os.chmod(rename_to_path, 0o755)
            else:
                if os.path.exists(rename_to_path):
                    os.unlink(rename_to_path)
                if os.path.exists(active_path):
                    os.unlink(active_path)

        def thumb_png(png_path):
            img = Image.open(png_path)
            img.thumbnail((60, 60), Image.ANTIALIAS)
            img.save(png_path)
                
        # Cydia Icon
        cydia_icon_path = os.path.join(release_root, "CydiaIcon.png")
        if os.path.exists(cydia_icon_path):
            os.unlink(cydia_icon_path)
        if active_release.icon is not None and len(str(active_release.icon)) > 0:
            src_path = os.path.join(settings.MEDIA_ROOT, active_release.icon.name)
            if os.path.exists(src_path):
                shutil.copyfile(
                    src_path,
                    cydia_icon_path
                )
        else:
            src_path = os.path.join(settings.STATIC_ROOT, "img/CydiaIcon.png")
            if os.path.exists(src_path):
                shutil.copyfile(
                    src_path,
                    cydia_icon_path
                )
        if os.path.exists(cydia_icon_path):
            thumb_png(cydia_icon_path)
            os.chmod(cydia_icon_path, 0o755)

        build_instance = Build.objects.get(uuid=str(conf["build_uuid"]))
        if build_instance is not None:
            build_instance.is_finished = True
            build_instance.save()
    else:
        # TODO: Pdiffs Feature
        pass