Beispiel #1
0
def task_create(project_name: str, title: str, description: str = None):
    """Create new task."""
    project_data = database.get_project_by_name(name=project_name)
    project = Project(id=project_data[0][0],
                      name=project_data[0][1],
                      description=project_data[0][2])
    task = Task(id=None,
                title=title,
                description=description,
                status=TaskStatusE.OPEN,
                project_id=project.id)
    database.create_task(task)
    typer.echo(f"Task created: {title} in project {project.name}")
Beispiel #2
0
def project_list():
    """List of the available projects."""
    projects = [
        Project(id=row[0], name=row[1], description=row[2])
        for row in database.get_project_list()
    ]
    if not projects:
        typer.echo("No projects defined.")
        return
    for project in projects:
        typer.echo(
            f"Project: {project.name}, description: {project.description}, ID: {project.id}"
        )
Beispiel #3
0
def task_show(task_id: int):
    """Show the task details with task_id."""
    task_data = database.get_task_by_id(task_id=task_id)
    task = Task(id=task_data[0][0],
                title=task_data[0][1],
                description=task_data[0][2],
                status=task_data[0][3],
                project_id=task_data[0][4])
    project_data = database.get_project_by_id(project_id=task.project_id)
    project = Project(id=project_data[0][0],
                      name=project_data[0][1],
                      description=project_data[0][2])
    typer.echo(
        f"Task: {task.title}, status: {task.get_display_status()}, description: {task.description}, "
        f"project: {project.name}/{project.id}")
Beispiel #4
0
def task_list(project_name: str):
    """List of the available tasks in given project."""
    project_data = database.get_project_by_name(name=project_name)
    project = Project(id=project_data[0][0],
                      name=project_data[0][1],
                      description=project_data[0][2])
    tasks = [
        Task(id=row[0],
             title=row[1],
             description=row[2],
             status=row[3],
             project_id=row[4])
        for row in database.get_task_list(project_id=project.id)
    ]
    if not tasks:
        typer.echo(f"No tasks defined for project {project.name}.")
        return
    for task in tasks:
        typer.echo(
            f"Task: {task.title}, status: {task.get_display_status()}, description: {task.description}, "
            f"project: {project.name}/{project.id}")
Beispiel #5
0
    def __init__(self):
        QtGui.QMainWindow.__init__(self)
        self.setAcceptDrops(True)
        self.dropped.connect(self.importAsLayer)
        
        self.project = Project(self)
        self.toolsWidget = ToolsWidget(self.project)
        self.optionsWidget = OptionsWidget(self.project)
        self.paletteWidget = PaletteWidget(self.project)
        self.onionSkinWidget = OnionSkinWidget(self.project)
        self.timelineWidget = TimelineWidget(self.project)
        self.scene = Scene(self.project)
        
        self.updateTitle()
        self.project.updateTitleSign.connect(self.updateTitle)

        ### layout #####################################################
        self.setDockNestingEnabled(True)
        self.setCentralWidget(self.scene)
        
        QtGui.QApplication.setOrganizationName("pixeditor")
        QtGui.QApplication.setApplicationName("pixeditor")
        settings = QtCore.QSettings()
        settings.beginGroup("mainWindow")
        try:
            lock = bool(int(settings.value("lock")))
        except TypeError:
            lock = True
        
        toolsDock = Dock(self.toolsWidget, "tools", lock)
        toolsDock.setObjectName("toolsDock")
        self.addDockWidget(QtCore.Qt.LeftDockWidgetArea, toolsDock)
        self.scene.coords=toolsDock.widget().coords

        optionsDock = Dock(self.optionsWidget, "options", lock)
        optionsDock.setObjectName("optionsDock")
        self.addDockWidget(QtCore.Qt.RightDockWidgetArea, optionsDock)

        paletteDock = Dock(self.paletteWidget, "palette", lock)
        paletteDock.setObjectName("paletteDock")
        self.addDockWidget(QtCore.Qt.RightDockWidgetArea, paletteDock)
        
        onionSkinDock = Dock(self.onionSkinWidget, "onion skin", lock)
        onionSkinDock.setObjectName("onionSkinDock")
        self.addDockWidget(QtCore.Qt.RightDockWidgetArea, onionSkinDock)
        
        timelineDock = Dock(self.timelineWidget, "timeline", lock)
        timelineDock.setObjectName("timelineDock")
        self.addDockWidget(QtCore.Qt.BottomDockWidgetArea, timelineDock)

        ### File menu ###
        menubar = self.menuBar()
        openAction = QtGui.QAction('Open', self)
        openAction.triggered.connect(self.openAction)
        saveAsAction = QtGui.QAction('Save as', self)
        saveAsAction.triggered.connect(self.saveAsAction)
        saveAction = QtGui.QAction('Save', self)
        saveAction.triggered.connect(self.saveAction)
        saveAction.setShortcut('Ctrl+S')
        
        importNewAction = QtGui.QAction('Import as new', self)
        importNewAction.triggered.connect(self.importAsNewAction)
        importLayerAction = QtGui.QAction('Import as layer', self)
        importLayerAction.triggered.connect(self.importAsLayerAction)
        exportAction = QtGui.QAction('Export', self)
        exportAction.triggered.connect(self.exportAction)
        exportAction.setShortcut('Ctrl+E')
        
        exitAction = QtGui.QAction('Exit', self)
        exitAction.triggered.connect(self.close)
        exitAction.setShortcut('Ctrl+Q')
        
        fileMenu = menubar.addMenu('File')
        fileMenu.addAction(openAction)
        fileMenu.addAction(saveAsAction)
        fileMenu.addAction(saveAction)
        fileMenu.addSeparator()
        fileMenu.addAction(importNewAction)
        fileMenu.addAction(importLayerAction)
        fileMenu.addAction(exportAction)
        fileMenu.addSeparator()
        fileMenu.addAction(exitAction)
        
        ### Edit menu ###
        undoAction = QtGui.QAction('Undo', self)
        undoAction.triggered.connect(self.project.undo)
        undoAction.setShortcut('Ctrl+Z')
        redoAction = QtGui.QAction('Redo', self)
        redoAction.triggered.connect(self.project.redo)
        redoAction.setShortcut('Ctrl+Y')
        
        cutAction = QtGui.QAction('Cut', self)
        cutAction.triggered.connect(self.timelineWidget.cut)
        cutAction.setShortcut('Ctrl+X')
        copyAction = QtGui.QAction('Copy', self)
        copyAction.triggered.connect(self.timelineWidget.copy)
        copyAction.setShortcut('Ctrl+C')
        pasteAction = QtGui.QAction('Paste', self)
        pasteAction.triggered.connect(self.timelineWidget.paste)
        pasteAction.setShortcut('Ctrl+V')
        
        editMenu = menubar.addMenu('Edit')
        editMenu.addAction(undoAction)
        editMenu.addAction(redoAction)
        editMenu.addSeparator()
        editMenu.addAction(cutAction)
        editMenu.addAction(copyAction)
        editMenu.addAction(pasteAction)
        
        ### project menu ###
        newAction = QtGui.QAction('New', self)
        newAction.triggered.connect(self.newAction)
        cropAction = QtGui.QAction('Crop', self)
        cropAction.triggered.connect(self.cropAction)
        resizeAction = QtGui.QAction('Resize', self)
        resizeAction.triggered.connect(self.resizeAction)
        replacePaletteAction = QtGui.QAction('replace palette', self)
        replacePaletteAction.triggered.connect(self.replacePaletteAction)
        prefAction = QtGui.QAction('Background', self)
        prefAction.triggered.connect(self.backgroundAction)
        
        projectMenu = menubar.addMenu('Project')
        projectMenu.addAction(newAction)
        projectMenu.addAction(cropAction)
        projectMenu.addAction(resizeAction)
        projectMenu.addAction(replacePaletteAction)
        projectMenu.addAction(prefAction)

        ### resources menu ###
        savePaletteAction = QtGui.QAction('save  current palette', self)
        savePaletteAction.triggered.connect(self.savePaletteAction)
        savePenAction = QtGui.QAction('save custom pen', self)
        savePenAction.triggered.connect(self.savePenAction)
        reloadResourcesAction = QtGui.QAction('reload resources', self)
        reloadResourcesAction.triggered.connect(self.reloadResourcesAction)
        
        resourcesMenu = menubar.addMenu('Resources')
        resourcesMenu.addAction(savePaletteAction)
        resourcesMenu.addAction(savePenAction)
        resourcesMenu.addAction(reloadResourcesAction)
        
        ### view menu ###
        viewMenu = menubar.addMenu('View')
        dockWidgets = self.findChildren(QtGui.QDockWidget)
        for dock in dockWidgets:
            viewMenu.addAction(dock.toggleViewAction())
        viewMenu.addSeparator()
        self.lockLayoutWidget = QtGui.QAction('Lock Layout', self)
        self.lockLayoutWidget.setCheckable(True)
        self.lockLayoutWidget.setChecked(lock)
        self.lockLayoutWidget.toggled.connect(self.lockLayoutAction)
        viewMenu.addAction(self.lockLayoutWidget)
        
        ### shortcuts ###
        QtGui.QShortcut(QtCore.Qt.Key_Left, self, lambda : self.selectFrame(-1))
        QtGui.QShortcut(QtCore.Qt.Key_Right, self, lambda : self.selectFrame(1))
        QtGui.QShortcut(QtCore.Qt.Key_Up, self, lambda : self.selectLayer(-1))
        QtGui.QShortcut(QtCore.Qt.Key_Down, self, lambda : self.selectLayer(1))
        QtGui.QShortcut(QtCore.Qt.Key_Space, self, self.timelineWidget.playPauseClicked)
        QtGui.QShortcut(QtCore.Qt.Key_1, self, toolsDock.widget().penClicked)
        QtGui.QShortcut(QtCore.Qt.Key_2, self, toolsDock.widget().pipetteClicked)
        QtGui.QShortcut(QtCore.Qt.Key_3, self, toolsDock.widget().fillClicked)
        QtGui.QShortcut(QtCore.Qt.Key_4, self, toolsDock.widget().moveClicked)
        QtGui.QShortcut(QtCore.Qt.Key_5, self, toolsDock.widget().selectClicked)
        self.hiddenDock = []
        QtGui.QShortcut(QtCore.Qt.Key_Tab, self, self.hideDock)
        QtGui.QShortcut(QtCore.Qt.Key_E, self, self.project.changeColor)
        
        ### settings ###
        try:
            self.restoreGeometry(settings.value("geometry"))
        except TypeError:
            pass # no geometry to restore so leave as is
        try:
            self.restoreState(settings.value("windowState"))
        except TypeError:
            pass # no state to restore so leave as is
        settings.endGroup()
        self.show()
Beispiel #6
0
 def __init__(self, workingDir):
     self.workingDir = workingDir
     self.project = Project()
Beispiel #7
0
def project_create(project_name: str, description: str = None):
    """Create the new project."""
    project = Project(id=None, name=project_name, description=description)
    database.create_project(project)
    typer.echo(f"Project `{project_name}` created.")
Beispiel #8
0
def disassemble_and_make_project(INPUT_PATH, project_dir: Path,
                                 disassembler_db: DisassemblerDb):
    build_dir = project_dir / "build"
    gen_asm_dir = project_dir / "gen-asm"

    # create output directories
    # TODO: gen_asm_dir should be emptied, since cluster boundaries can change between runs
    for dir in {project_dir, build_dir, gen_asm_dir}:
        dir.mkdir(parents=True, exist_ok=True)

    prj = Project(INPUT_PATH,
                  project_dir,
                  disassembler_db_snapshot=deepcopy(disassembler_db))

    pe = pefile.PE(INPUT_PATH)
    exe_patch_offset = pe.sections[0].PointerToRawData

    clusters = data_io.load_clusters(project_dir / "tmp-clusters")
    labels_db = data_io.load_labels(project_dir, suffix=".tmp")

    print(f"Disassembling {len(clusters)} clusters...")

    for cluster in clusters:
        filename = gen_asm_dir / f"{cluster.section_name[1:]}_{cluster.start:08X}.s"
        print(f" - {filename} : {len(cluster.chunks)} chunks")

        if cluster.start < MIN_OFFSET:
            continue

        total_length = sum([len(chunk.bytes) for chunk in cluster.chunks])
        cluster_end = cluster.start + total_length

        with open(filename, 'wt') as f:
            if AS == "gas":
                print(f"""\
.intel_syntax
.section {cluster.section_name}
""",
                      file=f)

                # export labels
                for label in sorted(labels_db.values()):
                    if label.address >= cluster_end:
                        break
                    elif label.address >= cluster.start:
                        print(
                            f".global {gnuas_escape_label(label.name):40s} /* {label} */",
                            file=f)

                print(file=f)
                disassembly_gas.disassemble_for_GAS(
                    cluster.chunks,
                    f,
                    disassembler_db=disassembler_db,
                    labels_db=labels_db,
                    use_labels=True)

            if AS == "nasm":
                print(f"""\
section {cluster.section_name}
""", file=f)

                analysis.disassemble_for_nasm(cluster.chunks,
                                              f,
                                              labels_db=labels_db,
                                              use_labels=True)

        prj.add_asm_source(filename, cluster.start, total_length)

    # Generate MinGW project

    def relpath(path_to, path_from):
        path_to = Path(path_to).resolve()
        path_from = Path(path_from).resolve()
        try:
            for p in (*reversed(path_from.parents), path_from):
                head, tail = p, path_to.relative_to(p)
        except ValueError:  # Stop when the paths diverge.
            pass
        return Path(
            '../' *
            (len(path_from.parents) - len(head.parents))).joinpath(tail)

    def generate_project(prj: Project):
        # generate project Makefile

        project_makefile = project_dir / "Makefile"

        P = PurePosixPath
        makefile_cwd = project_dir
        # relative_source_dir = Path().relative_to(self.output_dir)

        build_dir_rel = relpath(build_dir, makefile_cwd)

        input_exe_path = relpath(prj.exe_path, makefile_cwd)
        prj.output_path = relpath(project_dir / prj.exe_path.name,
                                  makefile_cwd)
        ldscript = relpath("i386pe.x", makefile_cwd)

        with open(project_makefile, "wt", newline='\n') as f:
            all_obj = []

            for src in prj.sources:
                obj_path = relpath(build_dir / src.path.stem,
                                   makefile_cwd).with_suffix(".o")
                all_obj.append(obj_path)

            # link objects
            obj_paths = " ".join([str(P(obj_path)) for obj_path in all_obj])

            # FIXME: un-hardcode!
            text_start = 0x10001000

            print(f"""
#PREFIX=i686-w64-mingw32-
AS=$(PREFIX)as
LD=$(PREFIX)ld
OBJCOPY=$(PREFIX)objcopy
OBJDUMP=$(PREFIX)objdump

ALLCODE_BIN={P(build_dir_rel)}/allcode.bin
ALLCODE_O={P(build_dir_rel)}/allcode.o
ALLCODE_S={P(build_dir_rel)}/allcode.s
OUTPUT_EXE={P(prj.output_path)}
OUTPUT_S={P(build_dir_rel)}/output.s
COPY_WITH_PATCH={P(relpath("copy_with_patch.py", project_dir))}

all: input.s $(OUTPUT_EXE) $(OUTPUT_S)

input.s: {P(input_exe_path)}
\t$(OBJDUMP) -M intel -D -h $< | tail -n +3 >$@

$(ALLCODE_O): {obj_paths} {P(ldscript)}
\tar rcs {P(build_dir_rel)}/allcode.a {obj_paths}
\t$(LD) -T  {P(ldscript)} -Ttext=0x{text_start:08x} {obj_paths} -o $@
\t$(OBJDUMP) -M intel -D -h $(ALLCODE_O) >$(ALLCODE_S)

$(ALLCODE_BIN): $(ALLCODE_O)
\t$(OBJCOPY) --only-section=.text -O binary $< $@

$(OUTPUT_EXE): $(ALLCODE_BIN) {P(input_exe_path)}
\t$(COPY_WITH_PATCH) {P(input_exe_path)} $@ {exe_patch_offset} $(ALLCODE_BIN)
\t#cp {P(input_exe_path)} $@
\t#dd if=$(ALLCODE_BIN) of=$@ obs=1 seek={exe_patch_offset} conv=notrunc 2>&1

$(OUTPUT_S): $(OUTPUT_EXE)
\t$(OBJDUMP) -M intel -D -h $< | tail -n +3 >$@

""",
                  file=f)

            for src in prj.sources:
                src_path = relpath(src.path, makefile_cwd)
                obj_path = relpath(build_dir / src.path.stem,
                                   makefile_cwd).with_suffix(".o")  # TODO DRY

                print(f"{P(obj_path)}: {P(src_path)}", file=f)
                if AS == "gas":
                    print(f"\t$(AS) $< -o $@", file=f)
                print(file=f)

            # all_obj = []
            #
            # for src in prj.sources:
            #     if src.offset < MIN_OFFSET: continue
            #
            #     # patch_offset = src.offset + prj.text_vma_to_file_offset
            #     # print(f"makeproject: {src.path} @ {src.offset:08X}h")
            #
            #     # strategy: compile asm source to .o, export as flat binary, patch exe file (diff in the end)
            #     src_path = relpath(src.path, makefile_cwd)
            #     obj1_path = relpath(prj.output_dir / (src.path.stem + "a"), makefile_cwd).with_suffix(".o")
            #     obj_path = relpath(prj.output_dir / src.path.stem, makefile_cwd).with_suffix(".o")
            #     dasm_path = relpath(prj.output_dir / src.path.stem, makefile_cwd).with_suffix(".s")
            #     bin_path = relpath(prj.output_dir / src.path.stem, makefile_cwd).with_suffix(".bin")
            #
            #     # print(f"# cluster {src.offset:08X}h: {src.length:6} bytes @ {patch_offset:X}h", file=f)
            #
            #     if AS == "nasm":
            #         print(f"nasm {P(src_path)} -f elf32 -o {P(obj_path)}", file=f)
            #     #print(f"$LD -Ttext=0x{src.offset:08X} {P(obj1_path)} -o {P(obj_path)}", file=f)
            #     # print(f"$OBJDUMP -M intel -D {P(obj_path)} >{P(dasm_path)}", file=f)
            #     # print(f"$OBJCOPY --only-section=.text -O binary {P(obj_path)} {P(bin_path)}", file=f)
            #     # print(f"dd if={P(bin_path)} of={P(prj.output_path)} obs=1 seek={patch_offset} conv=notrunc", file=f)
            #
            #     print(file=f)
            #
            #     all_obj.append(obj_path)

            #break

    #         print(f"""
    # # post-diff
    # cmp -l {P(input_exe_path)} {P(prj.output_path)} | gawk '{{printf "%08X %02X %02X\\n", $1, strtonum(0$2), strtonum(0$3)}}'
    # """, file=f)

    # generate linker script

    # ndisasm bigobj & compare
    # print(f"ndisasm bigobj.bin -b 32 -o 0x401000 >bigobj.asm", file=f)

    generate_project(prj)

    return prj