diff --git a/.gitignore b/.gitignore index c6bba59..579267b 100644 --- a/.gitignore +++ b/.gitignore @@ -128,3 +128,8 @@ dist .yarn/build-state.yml .yarn/install-state.gz .pnp.* + +*.exe +resources/rpv-web.ico +resources/rpv-web.rc +resources/rpv-web.res diff --git a/CHANGELOG.md b/CHANGELOG.md index dd90a1e..1eb97d5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,21 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## v1.3.0 - July 29, 2024 + +### Added + +* Add RPC interface filter +* Add support for negative filters +* Add RPC interface version in interface pane +* Add module base address to interface details + +### Changed + +* Make process filter persistent when tab is changed +* MIDL view now jumps to selected method + + ## v1.2.1 - July 19, 2024 ### Changed diff --git a/README.md b/README.md index 31e2f94..3d642d5 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ [![](https://github.com/qtc-de/rpv-web/actions/workflows/build.yml/badge.svg?branch=main)](https://github.com/qtc-de/rpv-web/actions/workflows/build.yml) [![](https://github.com/qtc-de/rpv-web/actions/workflows/build.yml/badge.svg?branch=dev)](https://github.com/qtc-de/rpv-web/actions/workflows/build.yml) -[![](https://img.shields.io/badge/version-1.2.1-blue)](https://github.com/qtc-de/rpv-web/releases) +[![](https://img.shields.io/badge/version-1.3.0-blue)](https://github.com/qtc-de/rpv-web/releases) [![](https://img.shields.io/badge/language-v%20%26%20vue-blue)](https://vlang.io/) [![](https://img.shields.io/badge/license-GPL%20v3.0-blue)](https://github.com/qtc-de/rpv-web/blob/master/LICENSE) [![](https://img.shields.io/badge/Pages-fa6b05)](https://qtc-de.github.io/rpv-web/) diff --git a/frontend/Dockerfile.dev b/frontend/Dockerfile.dev new file mode 100644 index 0000000..fd695f0 --- /dev/null +++ b/frontend/Dockerfile.dev @@ -0,0 +1,19 @@ +FROM node:lts-alpine + +WORKDIR /app +COPY package*.json . + +RUN adduser --gecos '' --disabled-password rpv \ + && chown -R rpv:rpv /app \ + && su rpv -c "npm install" \ + && su rpv -c "npm install http-server" + +COPY . . + +RUN chown -R rpv:rpv /app \ + && su rpv -c "npm run build" + +USER rpv:rpv +EXPOSE 5173 + +CMD ["npm", "run", "dev", "--", "--host"] diff --git a/frontend/dev.sh b/frontend/dev.sh new file mode 100755 index 0000000..62e1cf7 --- /dev/null +++ b/frontend/dev.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +podman image exists rpv-web-dev + +if [ $? -ne 0 ]; then + echo '[+] Building rpv-web-dev image.' + podman build -t rpv-web-dev -f Dockerfile.dev . +else + echo '[+] rpv-web-dev image already exists.' +fi + +echo '[+] Starting rpv-web-dev container.' +podman run -v ${PWD}/src/:/app/src:Z -it -p 5173:5173 rpv-web-dev diff --git a/frontend/src/components/Headline.vue b/frontend/src/components/Headline.vue index f06b0ab..1b5ca89 100644 --- a/frontend/src/components/Headline.vue +++ b/frontend/src/components/Headline.vue @@ -374,7 +374,7 @@

WEB

-

v1.1.0

+

v1.3.0

diff --git a/frontend/src/components/InterfaceDetailPane.vue b/frontend/src/components/InterfaceDetailPane.vue index 63c85f3..b549e6b 100644 --- a/frontend/src/components/InterfaceDetailPane.vue +++ b/frontend/src/components/InterfaceDetailPane.vue @@ -107,9 +107,13 @@ v-on:blur="changeInterfaceName($event)"/> - DLL + Module {{ selectedInterface.location }} + + Module Base + {{ selectedInterface.module_base }} + Description {{ selectedInterface.description }} diff --git a/frontend/src/components/InterfacePane.vue b/frontend/src/components/InterfacePane.vue index 65451d0..d3365e6 100644 --- a/frontend/src/components/InterfacePane.vue +++ b/frontend/src/components/InterfacePane.vue @@ -16,11 +16,12 @@ setup() { const store = processStore(); - const { selectedProcess, selectedInterface } = storeToRefs(store); - return { store, selectedProcess, selectedInterface } + const { interfaceFilter, selectedProcess, selectedInterface } = storeToRefs(store); + return { store, interfaceFilter, selectedProcess, selectedInterface } }, - components: { + components: + { VueSimpleContextMenu, }, @@ -31,6 +32,114 @@ this.selectedInterface = intf; }, + casualFilter(intf, filter) + { + let inverse = false; + + if (filter.startsWith('!')) + { + filter = filter.substring(1); + inverse = true; + } + + return (intf.id.toLowerCase().includes(filter) || intf.location.toLowerCase().includes(filter) || + intf.description.toLowerCase().includes(filter) || intf.name.toLowerCase().includes(filter) || + intf.annotation.toLowerCase().includes(filter)) != inverse; + }, + + getInterfaces: function*(filter) + { + for (const intf of this.selectedProcess.rpc_info.interface_infos) + { + if (filter) + { + let match = true; + filter = filter.toLowerCase(); + + if (!filter.includes(':') && !this.casualFilter(intf, filter)) + { + match = false; + } + + else + { + const filterArray = filter.split(/\s*\|\s*/); + + for (const entry of filterArray) + { + let key, value; + let inverse = false; + + [key, value] = entry.split(':', 2); + + if (key === 'uuid') + { + key = 'id'; + } + + if (value === undefined) + { + if (!this.casualFilter(intf, key)) + { + match = false; + break; + } + + continue; + } + + if (value.startsWith('!')) + { + value = value.substring(1); + inverse = true; + } + + if (Object.hasOwn(intf, key)) + { + const propValue = intf[key]; + + if (Array.isArray(propValue)) + { + let found = false; + + for (const item of propValue) + { + if (String(item).toLowerCase().includes(value)) + { + found = true; + break; + } + } + + if (!found != inverse) + { + match = false; + break; + } + } + + else + { + if (String(propValue).toLowerCase().includes(value) == inverse) + { + match = false; + break; + } + } + } + } + } + + if (!match) + { + continue; + } + } + + yield intf; + } + }, + interfaceClick(e, item) { if (item.typ != 'rpc') @@ -63,11 +172,15 @@