Die Anleitung für Plugin-Autoren
Wie du ein Plugin im Plugin-Store von PaperPaw veröffentlichst, mit dem Formular auf dieser Seite. Die Namen auf dieser Seite, von Dateien, Schlüsseln, Feldern und Prüfungen, sind die, die die Seite verwendet.
PaperPaw ist in der Beta, und sein SDK kann sich vor 1.0 noch ändern. Das Changelog nennt jede inkompatible Änderung mit dem, was an ihre Stelle tritt. Das Changelog
Was ein Plugin ist
Ein Plugin ist ein Ordner mit einer Datei plugin.ini ganz oben. Es gibt zwei Arten.
- Daten-Plugins. Dateien, die PaperPaw liest, und sonst nichts: Übersetzungen, Tastenbelegungen, neue Voreinstellungen, Themes, Schriften, ein Stylesheet für Bücher, Bilder. Ein Daten-Plugin läuft auf jedem Gerät, so wie es ist.
- Code-Plugins. Ein Rust-Crate gegen das PaperPaw-SDK, gebaut zu einer Datei,
code.ppn, für jedes Lesegerät, auf dem es läuft: den Xteink X4 und den X4 Pro. Du lädst diese Builds neben dem Ordner hoch, jeden mit deinem Schlüssel signiert, und dazu die Quellen, aus denen sie gebaut sind.
Oder lass die Plugin-Werkstatt es schreiben: Beschreib das Plugin, mit oder ohne Code, und sie baut es, probiert es auf einem nachgebildeten Lesegerät aus und prüft es, auf deinem Computer. Die Plugin-Werkstatt
Ein Code-Plugin läuft als Teil von PaperPaw, mit voller Geschwindigkeit und ohne Sandbox: Es kann alles, was PaperPaw kann, mit den Büchern, Einstellungen und dem Netz des Geräts. Der Store sagt das auf der Seite jedes Code-Plugins, und das Gerät sagt es, bevor es eines installiert. Deshalb zeigt ein Code-Plugin seine Quellen, ist von seinem Autor signiert und wird zum Vergleich aus seinen Quellen neu gebaut.
Jedes Plugin im Store ist für alle kostenlos. Der Store verkauft nichts und nimmt nichts.
Wie man ein Plugin schreibt, mit dem SDK, dem Emulator und den Beispiel-Plugins, steht in der Anleitung von PaperPaw selbst. Plugins schreiben
Die ID
Die ID benennt das Plugin überall: in plugin.ini, im Ordner auf dem Gerät, in seiner Adresse im Store und am Anfang jeder ID in seinem Code (clock.open). Sie besteht aus Kleinbuchstaben, Ziffern und Bindestrichen, höchstens 40, und beginnt und endet nicht mit einem Bindestrich, etwa clock oder large-print. Sie muss frei sein: nicht die ID eines Plugins im Katalog dieser Seite, nicht die eines anderen Autors und nicht eine, die entfernt wurde.
Der Ordner
Der Ordner heißt wie die ID. Ein Ordner store/ darin enthält, was nur der Store braucht: store.ini und die Screenshots. Der Store nimmt ihn aus dem heraus, was Geräte installieren. Die Builds eines Code-Plugins liegen nicht im Ordner: Du lädst sie getrennt hoch.
night-owl/ a data plugin
plugin.ini
settings.ini
i18n/de.ini
store/store.ini for the store only
store/home.png a screenshot
clock/ a code plugin
plugin.ini
i18n/de.ini
store/store.ini
store/home.png
clock-1.0.0-x4.ppn its builds, signed, beside the folder
clock-1.0.0-x4-pro.ppn
plugin.ini benennt das Plugin. Sein Abschnitt [plugin] braucht id, name und version; description ist ein Satz, den der Store als Zusammenfassung nimmt, wenn store.ini keine hat. Zwei vollständige Beispiele:
# night-owl/plugin.ini: what the plugin is. It lies at the top of its folder.
[plugin]
# Lower-case letters, digits and hyphens, at most 40: the id everywhere.
id = night-owl
# The name people see, at most 60 characters.
name = Night owl
# One sentence. The store takes it as the summary when store.ini has none.
description = Dark headers and roomy rows for reading at night.
# Three numbers. A new version needs a higher one.
version = 1.0.0
# The version of the data formats its files are written in: 1 for settings
# and translations, up to 3 (menus.ini, actions.ini); docs/data-files.md.
formats = 1
# clock/plugin.ini: a code plugin's folder has the same file.
[plugin]
id = clock
name = Clock
description = A large clock on the home screen, with the date below it.
# The same version as the manifest in the plugin's code.
version = 1.0.0
# Optional: the most memory it takes while it runs, in KB, as you measured
# it in the emulator. The readers' store shows it, and on the X4 above
# 32 KB it says the plugin is tight on that reader.
heap = 40
Aus der Werkstatt veröffentlichen
Die Plugin-Werkstatt macht eine Datei mit allem, was der Store braucht. So gibt es nur eines hochzuladen. Die Plugin-Werkstatt
Wähle in der Werkstatt im Menü „Publish“ und drücke „Pack“. Sie prüft das Plugin; ein Code-Plugin baut sie für die Lesegeräte und signiert es mit deinem Autorenschlüssel. Dann macht sie
<id>-<version>-store.zip, öffnet das Formular in deinem Browser und zeigt die Datei in ihrem Ordner.Melde dich an und wähle diese eine Datei im ersten Feld des Formulars. Das Formular sagt, was es gefunden hat, etwa „Aus der Werkstatt: Plugin ✓, Build für den X4 ✓, Quellen ✓“, und blendet die anderen Felder aus: Sie werden nicht gebraucht. Ein Plugin veröffentlichen
Drücke „Hochladen und prüfen“ und mach weiter wie bei jedem Upload: Lies die Prüfungen, vervollständige den Eintrag, schick ihn an die Moderatoren. Veröffentlichen mit dem Formular
Lade die Datei hoch, wie sie ist: Pack sie nicht aus. Sie enthält den Ordner des Plugins als ZIP (<id>-<version>-upload.zip), jeden signierten Build (<id>-<version>-x4.ppn), die Quellen als ZIP (<id>-<version>-source.zip) und paperpaw-store.ini, die jeden Teil nennt. Die Seite prüft jeden Teil, als hättest du ihn einzeln hochgeladen, mit denselben Grenzen.
Veröffentlichen mit dem Formular
Das Formular ist der Hauptweg: Du lädst hoch, die Seite prüft sofort, du vervollständigst den Eintrag und schickst ihn an die Moderatoren.
Melde dich an. Gib unter
/account/sign-indeine E-Mail-Adresse ein. Die Seite schickt einen Link, der 30 Minuten gilt und einmal anmeldet: Öffne ihn und drücke „Anmelden“. Beim ersten Mal gibst du den Namen an, den der Store bei deinen Plugins zeigt (höchstens 80 Zeichen), und nimmst die Regeln für Autoren an (unten). Es gibt kein Passwort. Ein Cookie hält dich 30 Tage angemeldet. AnmeldenPack den Ordner des Plugins als ZIP, mit
plugin.iniganz oben oder in einem einzigen Ordner ganz oben. Pack den Ordner selbst, wie unten. Lass versteckte Dateien weg und was dein System hinzufügt (.DS_Store,__MACOSX/,Thumbs.db,desktop.ini): Die Seite lässt sie mit einer Warnung weg, und eine Warnung hält ein Update davon ab, von selbst live zu gehen.# Linux and macOS: zip the folder itself, without hidden files. zip -r night-owl.zip night-owl -x '*/.*' unzip -l night-owl.zip # Windows 10 and 11, in PowerShell or the command prompt (tar comes with Windows). tar -a -c -f night-owl.zip night-owl tar -t -f night-owl.zipDie Liste muss
night-owl/plugin.ini(oderplugin.ini) zeigen und die Dateien vonstore/unter demselben Ordner.Ein Code-Plugin braucht außerdem eine signierte
.ppn-Datei für jedes Lesegerät, auf dem es läuft, und seine Quellen: ein Repository und eine Revision im Abschnitt[source]vonstore.inioder die Quellen als ZIP. Wie du die Builds machst und signierst: Code-PluginsLade unter
/submithoch: das ZIP in das erste Feld (package), jeden Build in das Feld seines Geräts (build-x4,build-x4-pro,build-x4-classic,build-x3) und das ZIP der Quellen, wenn du eines hast, insource-zip. Jede.ppnwird an ihrem Kopf erkannt: Eine im Feld eines anderen Geräts wird für ihr eigenes genommen. Drücke „Hochladen und prüfen“. Kann der Upload nicht gelesen werden, sagt das Formular warum (Prüfunguploadodermanifest). Sonst legt die Seite einen Entwurf an, den nur du siehst, unter/submit/<n>. Ein Plugin veröffentlichenLies die Prüfungen. Jede nennt ihren Code und sagt Passed, Warning oder Failed, mit einem Satz dazu, was falsch ist und was richtig wäre. Was fehlschlug, steht zuerst. Was jeder Code bedeutet und wie du ihn behebst: Die Prüfungen
Vervollständige den Store-Eintrag. Was
plugin.iniundstore.ininannten, ist ausgefüllt. Füll den Rest aus, drücke „Speichern und noch einmal prüfen“, und alle Prüfungen laufen erneut. Was nur ein neuer Upload ändern kann (die Dateien des Ordners, die Builds), änderst du mit einem neuen Upload.Sieh dir die Vorschau an: das Plugin im Regal und seine Seite, wie sie aussehen wird, unter
/submit/<n>/page. Wenn die Seite den Emulator von PaperPaw ausführen kann, zeigt sie auch die Store-Seite des Plugins auf den Geräten, unter/submit/<n>/preview/<device>.png.Schick es ab. Der Knopf „An die Moderatoren senden“ erscheint nur, wenn keine Prüfung fehlschlägt. Bis zur Entscheidung kannst du den Eintrag noch ändern (er wird dann wieder ein Entwurf: schick ihn noch einmal) oder „Zurückziehen“ drücken. Von einem Plugin wartet immer nur eine Version.
Die Moderatoren entscheiden, und du bekommst in jedem Fall eine Mail. Veröffentlicht: Das Plugin ist im Store, auf dieser Seite und auf den Geräten. Abgelehnt: Die Mail und die Seite der Einreichung nennen die Gründe. Lade eine geänderte Version hoch, um es noch einmal zu versuchen, oder antworte auf die Mail, wenn du sie für falsch hältst.
Eine Einreichung ist ein Entwurf (Draft, nur du siehst ihn), wartend (Waiting, auf die Moderatoren), veröffentlicht (Published), abgelehnt (Refused), zurückgezogen (Withdrawn) oder entfernt (Taken down). Deine Kontoseite, /account, listet sie alle.
Die Felder des Formulars
Die Namen der Felder, wie das Formular sie schickt. <lang> ist ein Sprachcode wie de, <file> der Dateiname eines Screenshots wie home.png.
| Feld | Was |
|---|---|
Der Upload, POST /submit | |
package | Pflicht. Der Ordner des Plugins als ZIP, oder die Datei der Werkstatt (<id>-<version>-store.zip) mit allem darin; dann nichts weiter. |
build-x4, build-x4-pro, build-x4-classic, build-x3 | Ein Code-Plugin: die signierte .ppn für jedes Gerät, auf dem es läuft. Jeder angegebene Build lässt es auf diesem Gerät laufen. Ein Build wird für das Gerät genommen, das sein Kopf nennt, in welchem Feld er auch kam. |
source-zip | Optional. Die Quellen als ZIP, nur wenn store.ini kein Repository und keine Revision nennt. |
csrf | Versteckt: das eigene Token der Sitzung, von der Seite selbst geschickt. Ein Formular von einer anderen Seite oder älter als die Sitzung wird abgelehnt. |
Der Eintrag, POST /submit/<n> | |
name | Der Name, höchstens 60 Zeichen. Aus name in plugin.ini. |
summary | Ein Satz, höchstens 160 Zeichen. |
description | Mehr, höchstens 2000 Zeichen, auf der Seite des Plugins. |
group | Eine von reading, formats, library, sync, home, look, notes, learning, news, tools, games, system. |
tags | Bis zu fünf, durch Kommas getrennt. |
licence | Ein SPDX-Bezeichner, etwa MIT. |
source | Wo die Quellen liegen, eine https://-Adresse. |
sdk | Das PaperPaw-SDK, für das es gemacht ist, etwa 0.5. Die Betas einer Version (0.5.0-beta.1) haben ihr SDK: Ein Plugin für sie nennt ebenfalls 0.5. |
devices | Daten-Plugins: ein Kästchen für jedes Gerät, auf dem es läuft (android, x4, x4-pro, x4-classic, x3). Alle angekreuzt heißt jedes Gerät. Ein Code-Plugin läuft auf den Geräten, für die es Builds hat. |
source-repository, source-revision | Code-Plugins: das Repository und der Tag oder Commit, aus dem die Builds gebaut sind. Eine Änderung holt die Quellen neu. |
source-path, source-bin | Code-Plugins, optional: der Ordner des Crates im Repository und das Binary, das gepackt wird. |
i18n-<lang>-name, i18n-<lang>-summary | Name und Zusammenfassung in einer Sprache, die der Eintrag hat. Beide Felder leer nimmt die Sprache weg. |
i18n-new-lang, i18n-new-name, i18n-new-summary | Eine neue Sprache: ihr Code, der Name und die Zusammenfassung. |
screenshot | Neue Screenshots, PNG, JPEG oder WebP, bis zu vier insgesamt. |
alt-<file>, remove-<file> | Was Screenshot <file> zeigt, höchstens 200 Zeichen; ein angekreuztes remove-<file> nimmt ihn weg. |
Die Datei store.ini
store/store.ini gibt dem Store, was plugin.ini nicht hat. Jeder Schlüssel ist optional: Was fehlt, fragt das Formular ab. Mit einer vollständigen store.ini ist der Eintrag schon beim Upload vollständig.
Es ist das INI von PaperPaw: Zeilen [section] und Zeilen key = value. Ein Kommentar ist eine eigene Zeile, die mit # oder ; beginnt. Hinter einem Wert gibt es keine Kommentare: group = look ; meine Gruppe macht die Gruppe zu look ; meine Gruppe, und eine Abschnittszeile mit einem Kommentar dahinter wird gar nicht gelesen. Ein Wert ist eine Zeile; um Leerzeichen zu behalten oder Zeilenumbrüche zu schreiben, setz ihn in Anführungszeichen und schreib \n. Zwei vollständige Beispiele:
# clock/store/store.ini: what the store shows of a code plugin.
# Only the store reads this folder; readers never install store/.
# Every key is optional: the form asks for what is missing.
# Comments go on lines of their own, never after a value.
[store]
# One sentence, at most 160 characters, shown in lists and on the readers.
summary = A large clock on the home screen, with the date below it.
# At most 2000 characters, on the plugin's page. A value is one line:
# put it in quotes and write \n where a new line begins.
description = "The clock shows the time in large figures, and the date below it.\n\nIt adds a widget for the home screen and a setting for 12 or 24 hours."
# One of: reading, formats, library, sync, home, look, notes, learning, news, tools, games, system.
group = home
# At most five, separated by commas: lower-case letters, digits and hyphens.
tags = clock, widget
# An SPDX identifier.
licence = MIT
# Where the source lives: an https address, shown as the plugin's home.
source = https://codeberg.org/your-name/clock
# The PaperPaw SDK it was made for.
sdk = 0.5
[source]
# The exact source the builds were made from: a public repository on
# github.com, codeberg.org or gitlab.com, and a tag or a 40-digit commit.
repository = https://codeberg.org/your-name/clock
revision = v1.0.0
# Only when the plugin's crate is not at the top of the repository:
# path = plugins/clock
# Only when the binary to pack is not named as the crate's package:
# bin = clock
[screenshots]
# A picture in store/, and what it shows, at most 200 characters.
home.png = The home screen with the clock widget, on an Xteink X4.
[i18n.de]
# The name and the summary in another language: both, or neither.
name = Uhr
summary = Eine große Uhr auf der Startseite, mit dem Datum darunter.
# night-owl/store/store.ini: what the store shows of a data plugin.
[store]
summary = Dark headers and roomy rows for reading at night.
description = A theme without code: new defaults for the appearance settings. Anything you choose in Settings still wins.
group = look
tags = theme, dark
licence = CC0-1.0
source = https://github.com/your-name/night-owl
sdk = 0.5
# The devices it runs on: android, x4, x4-pro, x4-classic, x3.
# Leave the key out when it runs on all of them.
devices = android, x4-pro
[screenshots]
home.png = The home screen with dark headers, on a Boox Go 7.
[i18n.de]
name = Nachteule
summary = Dunkle Kopfzeilen und großzügige Zeilen zum Lesen in der Nacht.
| Schlüssel | Was |
|---|---|
[store] | |
summary | Ein Satz, höchstens 160 Zeichen. Fehlt er, nimmt der Store description aus plugin.ini, wenn es passt. |
description | Höchstens 2000 Zeichen. Fehlt sie, nimmt der Store description aus plugin.ini. |
group | Wohin es gehört: reading, formats, library, sync, home (Startseite und Menüs), look, notes (Notizen, Markierungen, Tagebücher), learning (Vokabeln, Sprachen, Lernkarten), news (Nachrichten, Feeds, Artikel, Lesen im Web), tools (Rechner, Timer, Helfer), games oder system. |
tags | Bis zu fünf Wörter, unter denen man es findet, durch Kommas getrennt: Kleinbuchstaben, Ziffern und Bindestriche, je höchstens 24. |
licence | Die Lizenz als SPDX-Bezeichner: MIT, Apache-2.0, GPL-3.0-or-later, CC0-1.0, OFL-1.1. |
source | Wo die Quellen oder die Heimat des Plugins liegen: eine https://-Adresse. |
sdk | Das PaperPaw-SDK, für das es gemacht ist, etwa 0.5, auch für die Betas von 0.5. |
devices | Nur Daten-Plugins: die Geräte, auf denen es läuft, durch Kommas getrennt, aus android, x4, x4-pro, x4-classic, x3. Weggelassen: jedes Gerät. Ein Code-Plugin läuft auf den Geräten, für die es Builds hat, egal was hier steht. |
[source] | |
repository | Code-Plugins: das öffentliche Repository, https:// auf github.com, codeberg.org oder gitlab.com. |
revision | Code-Plugins: der Tag (v1.0.0) oder der volle Commit (40 Hexadezimalziffern), aus dem die Builds gebaut sind. Nie ein Branch: Der bewegt sich. |
path | Optional: der Ordner des Plugin-Crates im Repository, etwa plugins/clock, wenn das Crate nicht ganz oben liegt. |
bin | Optional: das Binary, das gepackt wird, wenn es nicht wie das Paket des Crates heißt. Buchstaben, Ziffern, _ und -. |
[screenshots] | |
<file> | Ein Screenshot in store/ mit seinem Dateinamen, und was er zeigt, höchstens 200 Zeichen, für Menschen, die ihn nicht sehen können. |
[i18n.<lang>] | |
name, summary | Name und Zusammenfassung in der Sprache <lang> (zwei oder drei Kleinbuchstaben, etwa de), beide. Nicht en: Englisch sind Name und Zusammenfassung selbst. |
Die Screenshots sind Dateien in store/, .png, .jpg oder .webp, benannt mit Kleinbuchstaben, Ziffern und Bindestrichen, etwa home.png. Übersetzungen brauchen kein [i18n.<lang>], wenn i18n/<lang>.ini im Ordner die Texte <id>.plugin.name und <id>.plugin.description hat (ein Satz von höchstens 160 Zeichen): Der Store übernimmt sie, und store.ini gewinnt, wo es beide angibt.
Die Prüfungen
Jede Version geht durch diese Prüfungen, jede mit einem Code, der gleich bleibt. Eine Prüfung besteht, warnt oder schlägt fehl, mit einem Satz dazu. Abschicken lässt sich eine Version erst, wenn keine Prüfung fehlschlägt. Warnungen sehen die Moderatoren.
| Code | Was sie prüft | Wenn sie fehlschlägt, und was zu tun ist |
|---|---|---|
upload |
Die Dateien lassen sich lesen: Die Datei des Ordners ist ein ZIP von höchstens 20 MB, 40 MB entpackt, kein Name darin führt aus dem Ordner hinaus, jeder Build hat höchstens 4 MB und die Quellen höchstens 50 MB. Sie warnt, wenn sie Dateien weggelassen hat, die zu keinem Plugin gehören. | Meldet sie "The plugin's file is not a ZIP", "ist größer als 20 MB", "a name outside the folder" (ein Name mit .. oder einem Backslash, wie manche Windows-Programme sie schreiben): Pack den Ordner noch einmal mit den Befehlen oben. "Ausgelassen wurde, was nicht zu einem Plugin gehört: .DS_Store" ist eine Warnung: Pack ohne diese Dateien. |
manifest |
plugin.ini liegt ganz oben im ZIP oder in einem einzigen Ordner ganz oben, und sein [plugin] nennt id, name und version. |
Meldet sie "Im ZIP liegt keine plugin.ini ganz oben": Pack den Ordner des Plugins selbst, nicht den Ordner darum und nicht zwei Ordner. "plugin.ini nennt in ihrem Abschnitt [plugin] nicht: id": Ergänz die genannten Schlüssel. |
id |
Die ID ist frei oder deine: kein Plugin im Katalog dieser Seite, nicht die eines anderen Autors, nicht entfernt, nicht zuerst von einem anderen Autor angeboten. | Meldet sie "belongs to another author", "is one of PaperPaw's own plugins", "was taken down and cannot be used again": Wähl eine andere ID in plugin.ini und in deinem Code und lade neu hoch. |
version |
Die Version besteht aus drei Zahlen wie 1.2.0, gefolgt von einer Vorabversion oder nicht (1.2.0-beta.1, die vor 1.2.0 kommt), wurde noch nie veröffentlicht (entfernte Versionen zählen mit) und ist nicht älter als die neueste. |
Meldet sie "wurde schon veröffentlicht; eine neue Version braucht eine neue Nummer" oder "ist älter als": Erhöh version in plugin.ini und im Manifest deines Codes und lade neu hoch. |
metadata |
Der Store-Eintrag, ein Satz für jede Regel, die er bricht: die Zeichen der ID, ein Name (höchstens 60) und eine Zusammenfassung (ein Satz, höchstens 160), eine Beschreibung von höchstens 2000, eine Lizenz, eine Gruppe der Liste, höchstens fünf Tags, die Sprachen, Name und alt jedes Screenshots, source eine https://-Adresse, sdk wie 0.5; bei einem Code-Plugin auch seine Geräte, sein Schlüssel und die Quellen der Version (repository und revision auf einer bekannten Plattform). |
Vervollständige oder korrigier das Feld, das der Satz nennt, im Formular und drücke „Speichern und noch einmal prüfen“, oder in store.ini für den nächsten Upload. "version 1.0.0: sdk names no PaperPaw SDK" oder "is not like 0.5": Füll sdk aus, etwa 0.5. "source: the revision is a tag or a commit": Füll source-revision aus. |
package |
Der Ordner, den Geräte installieren: ein ZIP aus .ini-, .css-, .ttf-, .otf-, .ttc-, .ppfp-, .txt-, .md- und .png-Dateien; Namen aus Buchstaben, Ziffern, Punkten, Bindestrichen und Unterstrichen, kein Teil beginnt mit einem Punkt, höchstens 100 Bytes; höchstens 64 Dateien, 63 bei einem Code-Plugin; plugin.ini nennt dieselbe ID und Version, eine Zahl in formats; Übersetzungen, die sich lesen lassen. |
Meldet sie "only ini, css, ttf, otf, ttc, ppfp, txt, md, png files belong in a data plugin": Nimm die Datei heraus (eine code.ppn wird als Build hochgeladen, nie im Ordner). "names are letters, digits, dots, hyphens and underscores": Benenn die Datei um. "more than 63 files": weniger Dateien. Eine Übersetzung, die sich nicht lesen lässt, nennt ihre Zeile: Korrigier sie. "Font packs (.ppfp) belong in fonts/": Leg den Font Pack in den Ordner fonts/, nicht in einen Ordner darunter. |
build.x4 build.x4-pro build.x4-classic build.x3 |
Jeder Build, ein Code für jedes Gerät: eine Plugin-Datei von PaperPaw im Format 2, für den Chip dieses Geräts, so lang, wie ihr Kopf sagt, ihr Digest intakt und von ihrem Autor signiert. Den Fingerabdruck liest der Store aus der Datei. | Meldet sie "Die Datei ist nicht signiert": Signier sie mit paperpaw-sign oder im Browser. "Zwei Dateien sind Builds für das Gerät Xteink X4": Du hast den Build desselben Geräts zweimal gewählt; wähl den Build des anderen Geräts oder lass sein Feld leer. "ist kein Build für ein Lesegerät": Die Datei ist keine .ppn; wähl die, die paperpaw-sign pack gemacht hat. "not a PaperPaw plugin file": Das ist das gelinkte Programm; mach die .ppn mit paperpaw-sign pack. "file format 1, from before PaperPaw's plugin interface 2": Bau sie neu mit dem aktuellen PaperPaw-Release. "Changed or damaged": Bau und pack sie neu. "Die Datei dieses Builds fehlt": Lade sie neu hoch. |
signature |
Alle Builds sind mit einem Schlüssel signiert (im Katalog mit dem, den author_key nennt). |
Meldet sie "mit 2 verschiedenen Schlüsseln signiert": Signier jeden Build mit deiner einen Schlüsseldatei. "mit einem anderen Schlüssel signiert, als der Eintrag nennt": Signier mit dem Schlüssel in author_key oder korrigier ihn. |
key |
Der Schlüssel ist der der Versionen davor. Eine erste Version besteht: Geräte merken sich ihren Schlüssel und erwarten ihn bei jedem Update. | Meldet sie "Frühere Versionen sind mit dem Schlüssel": Signier mit dem Schlüssel deiner früheren Versionen. Hast du ihn verloren, veröffentliche das Plugin noch einmal unter einer neuen ID und einem neuen Schlüssel und bitte in deinem Konto („Mein Schlüssel ist verloren“), das alte als das neue weiterzuführen; siehe Updates. |
source |
Die Quellen eines Code-Plugins: aus dem Repository zur Revision geholt oder das hochgeladene ZIP; höchstens 50 MB; ein ZIP mit Cargo.toml ganz oben oder unter path; und eine Cargo.lock. Ohne Cargo.lock warnt sie. |
Meldet sie "Nenn ein Repository und eine Revision": Füll [source] oder die Felder des Formulars aus. "ließen sich nicht von": Push den Tag, mach das Repository öffentlich, prüf die Adresse. "keine Cargo.toml ganz oben": Setz path auf den Ordner des Crates. "fehlt die Cargo.lock": Committe sie und tagge neu. |
how |
Ein Code-Plugin sagt, wie es funktioniert: was es tut, wo man es findet und wie man es benutzt, in mindestens 120 Zeichen, in how/en.txt im Ordner (eine Datei je weiterer Sprache, how/de.txt, wie sein Manifest sie nennt) oder in der Beschreibung. Der Store zeigt es auf der Seite des Plugins als So funktioniert es, und die Reader in ihrem Store. Nur eine Warnung. |
Meldet sie "nothing of how it works" oder "sagt wenig": Leg das So funktioniert es des Plugins, die Dateien, die sein Manifest nennt (Manifest::how), als how/<lang>.txt in den Ordner, oder schreib im Formular eine längere Beschreibung, dann Speichern und erneut prüfen. |
content |
Der Quelltext eines Code-Plugins enthält keine Spiele, BIOS-Dateien oder gekauften Bücher (Dateien wie .gb, .gba, .nes, .azw3): Inhalte, an denen andere die Rechte haben. Nur eine Warnung, für die Moderatoren zum Ansehen. |
Entferne diese Dateien aus dem Repository, oder, wenn sie frei sind (dein eigenes Testspiel, ein gemeinfreies Buch), sag das und woher sie stammen in der Beschreibung. |
screenshots |
Höchstens vier Bilder, jedes ein PNG, JPEG oder WebP von höchstens 500 KB. Sie warnt, wenn es keine gibt. | Meldet sie "at most 500 KB": Mach es kleiner, als PNG mit weniger Farben oder als WebP. "is a PNG, JPEG or WebP picture": Wandle es um. "Keine Screenshots" ist eine Warnung: Füg einen vom Plugin bei der Arbeit hinzu. |
Was die Seite einer Einreichung auflistet, hat die Seite gefunden: die Sätze in ihren eigenen Worten, die diese Tabelle zum Teil zitiert. Sobald du sie abschickst, sehen die Moderatoren außerdem, was PaperPaws eigene Prüfung paperpaw-dev check findet: das Plugin gezeichnet auf dem emulierten X4, X4 Pro und Boox, seine Texte, Erreichbarkeit und Budgets. Sie entscheidet nichts; ein Moderator kann sie dir weitergeben. Ein Code-Plugin wird nur gezeichnet, wenn seine Quellen das Harness aus PaperPaws Vorlage haben (examples/paperpaw-dev.rs, siehe "Checking your plugin" in docs/plugins.md von PaperPaw); führ dieselbe Prüfung vor dem Abschicken selbst aus.
Code-Plugins
Fang mit dem Beispiel von PaperPaw an, einem Code-Plugin in einem eigenen Workspace, wie das eigene Repository eines Plugins: seine Cargo.toml, .cargo/config.toml mit paperpaw-plugin.x daneben (dem Linker-Skript des PaperPaw-Releases, das kein Build-Skript mitbringt), rust-toolchain.toml, plugin/plugin.ini und ein CI-Job, .github/workflows/build.yml. samples/hello-native
Bau für eine Plugin-Schnittstelle. Ein Build läuft auf jedem PaperPaw der Plugin-Schnittstelle, für die er gebaut ist, Beta oder Release, und nur dort, wo derselbe Compiler die Firmware gebaut hat. Sein Fingerabdruck, 16 Hexadezimalziffern im Kopf der Datei, enthält die Schnittstelle. „Über“ auf dem Gerät zeigt seinen Fingerabdruck und den Compiler; jedes Release von PaperPaw nennt sie in seinen Dateien
paperpaw-<reader>-<version>-abi.txt, und der CI-Job des Beispiels nennt die Compiler (RUST_X4,RUST_X4_PRO). Nenn das SDK dieses Releases inCargo.toml:paperpaw-sdk = "0.5.0-beta.1"für die Beta (Cargo nimmt eine Vorabversion nur, wenn sie genannt ist),"0.5"für das Release. Bau neu, wenn ein Release die Plugin-Schnittstelle anhebt; seine Notizen sagen es, und die Plugin-Verwaltung auf dem Gerät auch.Bau eine Datei für jedes Gerät, für den X4 und den X4 Pro. PaperPaw läuft noch nicht auf dem X4 Classic, daher ist sein Feld im Formular für später: Er hat den Chip des X4 Pro, aber eine eigene Firmware, also gib ihm einen Build nur mit dem Fingerabdruck, den sein „Über“ zeigt.
cargo x4 # the X4: riscv32imc-unknown-none-elf cargo +esp x4pro # the X4 Pro: xtensa-esp32s3-none-elf, espup's toolchainMach deinen Schlüssel einmal, mit
paperpaw-signdes Releases:# paperpaw-sign of the release you build for (here the beta 0.5.0-beta.1), # which is also in the emulator's ZIP of the release: cargo install --locked --git https://github.com/hthoene/paperpaw --tag v0.5.0-beta.1 paperpaw-sign # Once: make your key. Keep the file private, with a copy somewhere safe. paperpaw-sign key paperpaw-author.keySignier in deiner CI: Der Job des Beispiels baut das Plugin bei jedem Tag
v*, packt und signiert eine Datei für den X4 und den X4 Pro und hängt sie mit ihren SHA-256 an das Release des Tags. Leg den Inhalt deiner Schlüsseldatei im SecretPAPERPAW_PLUGIN_KEYdes Repositorys ab und setzPLUGINauf den Namen deines Binarys.Oder pack und signier auf deinem eigenen Computer:
# Pack and sign in one step, for each reader: paperpaw-sign pack target/riscv32imc-unknown-none-elf/release/clock clock-1.0.0-x4.ppn --key paperpaw-author.key paperpaw-sign pack target/xtensa-esp32s3-none-elf/release/clock clock-1.0.0-x4-pro.ppn --key paperpaw-author.key # Or sign a file packed without --key: paperpaw-sign sign-plugin clock-1.0.0-x4.ppn --key paperpaw-author.key # What a file holds: its chip, its fingerprint and its signer. paperpaw-sign plugin clock-1.0.0-x4.ppnOder signier im Browser: Pack mit
paperpaw-sign packohne--key, öffne die Signierseite, wähl deine Schlüsseldatei (oder mach dort eine, gespeichert alspaperpaw-author.key) und deine.ppn-Dateien, signier sie und speichere jede. Dein Schlüssel und deine Dateien verlassen nie deinen Computer. Es braucht einen Browser, der mit Ed25519 signiert: Firefox 129, Chrome und Edge 137, Safari 17 oder neuer. Im Browser signierenNenn die Quellen. Tagge den Commit, aus dem du gebaut hast, und push den Tag. In
store.ininennt[source]das öffentliche Repository (github.com,codeberg.orgodergitlab.com) und den Tag oder Commit alsrevision; die Seite holt das ZIP dieser Revision selbst von der Plattform. Liegt das Crate nicht ganz oben im Repository, nenntpathseinen Ordner; heißt das Binary nicht wie das Paket des Crates, nenntbines (das Paket des Beispiels heißtpaperpaw-sample-hello-nativeund sein Binaryhello, also braucht esbin = hello). Quellen anderswo gehen als ZIP insource-ziphoch, mitCargo.tomlganz oben oder in einem einzigen Ordner ganz oben.
Die Schlüsseldatei ist eine Zeile aus 64 Hexadezimalziffern, dein Geheimnis. Ihr öffentlicher Schlüssel, ebenfalls 64 Hexadezimalziffern, ist, was der Store als deinen zeigt und was Geräte sich merken. Dieselbe Datei signiert mit paperpaw-sign und im Browser. Halte sie geheim und bewahre eine Kopie getrennt auf: Wer sie hat, kann in deinem Namen signieren, und ohne sie lässt sich auf keinem Gerät, das das Plugin hat, ein Update von dir installieren. Committe sie nie, lade sie nie hoch.
Pfade landen in einem Build, also bau mit dem build.sh des Beispiels: Es schreibt sie so wie der Neubau (unten), das oberste Verzeichnis deiner Quellen als /plugin, das Verzeichnis von cargo als /cargo und für den X4 Pro die Toolchain als /rust (--remap-path-prefix). So unter Linux oder macOS gebaut, in einem beliebigen Ordner, passt dein Build zu seinem Neubau; ohne das weicht er vielleicht allein wegen seiner Pfade ab. Unter Windows behalten Pfade ihr \, also bau in WSL oder mit dem CI-Job des Beispiels.
Committe Cargo.lock und bau mit --locked: Ohne sie lassen sich die Quellen nicht zum Vergleich neu bauen, und die Prüfung source warnt.
Updates
Gib der neuen Version eine höhere Nummer in
plugin.ini(und im Manifest deines Codes), neuer als die letzte. Eine Nummer, die einmal veröffentlicht war, auch eine entfernte, wird nie wieder verwendet.Lade den neuen Ordner unter
/submitmit dem Konto hoch, das das Plugin veröffentlicht hat, bei einem Code-Plugin mit neuen Builds und den neuen Quellen. Was der Upload weglässt, kommt aus deiner zuletzt veröffentlichten Version: Zusammenfassung, Beschreibung, Gruppe, Lizenz, Quellen, SDK, Tags, Übersetzungen, Screenshots sowiepathundbin.Signier es mit demselben Schlüssel. Geräte merken sich den Schlüssel eines Plugins bei der ersten Installation und lehnen ein Update ab, das von einem anderen signiert ist, deshalb nimmt das Formular keinen anderen Schlüssel (Prüfung
key). Hast du deinen Schlüssel verloren, lässt sich kein Update dieses Plugins mehr auf einem Gerät installieren, das es hat, und der Store kann das nicht ändern: Ein Gerät nimmt für ein Plugin nie einen neuen Schlüssel. Veröffentliche das Plugin also noch einmal unter einer neuen ID und einem neuen Schlüssel und bitte in deinem Konto („Mein Schlüssel ist verloren“), das alte Plugin als das neue weiterzuführen. Die Bitte ist auf der Seite des alten Plugins öffentlich und wartet 14 Tage; ein Update, das mit dem alten Schlüssel signiert ist, zieht sie zurück, denn dann ist der Schlüssel nicht verloren. Dann genehmigt sie ein Moderator, und die Seite des alten Plugins sagt, dass es als das neue weitergeführt wird. Geräte werden nicht umgestellt: Sie sehen sich das neue Plugin an und installieren es selbst, mit eigenen Einstellungen. Die KontaktadresseJedes Update wartet auf die Moderatoren, wie ein neues Plugin: Nichts geht live, bevor ein Mensch es angesehen hat. Du bekommst eine Mail, wenn sie entschieden haben.
Im Katalog ist ein Update ein neuer Block [[versions]] in der TOML des Plugins, neben den früheren, die bleiben.
Eine neue PaperPaw-Version
Ein Code-Plugin läuft auf jedem PaperPaw der Plugin-Schnittstelle, für die es gebaut wurde, deshalb braucht es einen neuen Build nur, wenn ein Release diese Schnittstelle anhebt. Vor einem Release und vor jeder Beta baut der Store die neueste Version deines Plugins aus ihren Quellen gegen den Release Candidate, prüft sie mit dem paperpaw-dev dieser Version und schreibt dir per Mail, ob sie baut und die Prüfungen besteht, mit dem Protokoll und dem Build; hat sie nicht bestanden, folgt eine Woche später eine Erinnerung. Hebt ein Release die Schnittstelle an, wartet, wer dein Plugin nutzt, mit dem Update auf seinen neuen Build und sieht, dass er wartet.
Probier es selbst: Nimm das SDK des Release Candidates (das ändert auch
Cargo.lock) und bau. Was das Protokoll des Store-Builds zeigt, siehst du hier auch.# Against the release candidate the mail names (here v0.6.0-rc.1): cargo add paperpaw-sdk --git https://github.com/hthoene/paperpaw --tag v0.6.0-rc.1 ./build.sh # Then commit Cargo.toml and Cargo.lock together.Sobald es baut, ändere drei Zeilen im CI-Job des Beispiels und zwei in deinen Quellen und setz ein Tag: Der Job baut, packt und signiert beide Dateien mit deinem Schlüssel und hängt sie mit dem Katalog-Ausschnitt an das Release.
# .github/workflows/build.yml, the sample's job: the new release and its # compilers, as its versions.env and shells/xteink/rust-toolchain.toml name them. env: PAPERPAW: "0.6.0" RUST_X4: "<the release's X4 compiler>" RUST_X4_PRO: "<the release's X4 Pro compiler>" # Cargo.toml: the release's SDK. plugin/plugin.ini: a higher version. Then: git commit -am "PaperPaw 0.6" && git tag v1.1.0 && git push --tagsOhne den CI-Job baut und signiert ein Befehl, oder er signiert eine ohne Schlüssel gepackte Datei. Der Build des Stores ist nicht signiert: Ein Gerät führt nur aus, was sein Autor signiert hat, und der Store hat keinen Schlüssel von dir. Signier ihn nur, wenn deine eingecheckten Quellen das sind, woraus er gebaut wurde, die SDK-Zeile in
Cargo.tomlundCargo.lockeingeschlossen.# Build, pack and sign both files in one step: ./build.sh --key paperpaw-author.key # Or sign files packed without a key, such as the store's build: paperpaw-sign sign-plugin clock-1.1.0-x4.ppn --key paperpaw-author.keyReich die Version unter
/submitein wie jedes Update, signiert mit demselben Schlüssel. Behält die Version die Plugin-Schnittstelle und die Compiler ihres Release Candidates, ist der Fingerabdruck derselbe und du kannst sie vor der Version einreichen; sonst reich sie ein, sobald die Version erschienen ist.
Was der Store zeigt
Die Seite bewahrt eine Kopie der Quellen jeder Version eines Code-Plugins auf und zeigt sie allen, Datei für Datei, unter /plugins/<id>/<version>/source, mit einem Link auf die Revision in deinem Repository. Wer ein Plugin installiert, kann lesen, was er installiert.
Die Dateien eines Daten-Plugins werden ebenso gezeigt, unter /plugins/<id>/<version>/files.
Jeder Build eines Code-Plugins wird aus den hier aufbewahrten Quellen neu gebaut, in einem abgeschotteten Container ohne Netz, mit der Toolchain, die sein Fingerabdruck nennt, und Byte für Byte mit deiner Datei ohne ihre Signatur verglichen.
Die Seite des Plugins zeigt dann „Geprüft: stimmt mit seinen Quellen überein“, oder „Nicht neu gebaut“, solange er wartet, wenn für seinen Fingerabdruck keine Toolchain bekannt ist oder wenn er sich nicht neu bauen ließ, oder „Neu gebaut, stimmt aber nicht mit seinen Quellen überein“. Der Neubau hält nie ein Plugin zurück, und Geräte bekommen immer die Datei, die du signiert hast: Er ist eine Prüfung, kein Build-Dienst. Builds für den X4 Classic werden noch nicht neu gebaut.
Jeder kann die Prüfung wiederholen. Sie holt den Build und die aufbewahrten Quellen von der Seite, prüft beide gegen die SHA-256, die die Seite nennt, baut neu und vergleicht. Nur die neueste Version eines Plugins ist gelistet und damit prüfbar.
# From a copy of the paperpaw.org repository, with Docker:
cargo run -- verify clock 1.0.0 --device x4
paperpaw-website verify <id> <version> [--device x4|x4-pro] [--site https://paperpaw.org]
# Or with bash, curl, sha256sum and Docker alone:
rebuild/verify.sh <id> <version> [x4|x4-pro] [site]
Sie gibt MATCHES oder DIFFERS mit beiden Hashes aus und endet mit 0, wenn sie passen, 1, wenn sie sich unterscheiden, und 2, wenn sie es nicht sagen konnte.
Das öffentliche Versionsprotokoll nennt jede Version, die hier je veröffentlicht wurde, und jede entfernte, auf beiden Wegen, mit der SHA-256 ihres Pakets und jedes Builds, dem Schlüssel ihres Autors und der Revision ihrer Quellen. Nichts darin wird je geändert oder entfernt, und jeder Eintrag nennt den Hash des vorigen. Als JSON: /api/v1/log.json?after=<n>. Das Versionsprotokoll
Die Regeln für Autoren
Diese Regeln nimmst du an, wenn du dein Konto anlegst. Sie gelten für jedes Plugin und jede Version.
Veröffentliche nur, was du veröffentlichen darfst: deine eigene Arbeit oder Arbeit, deren Lizenz das Weitergeben erlaubt, mit ihren Urhebern so genannt, wie ihre Lizenz es verlangt. Das gilt auch für Schriften, Bilder und Übersetzungen.
Liefere keine Spiele, BIOS-Dateien, Bücher oder andere Werke mit, an denen andere die Rechte haben, außer ihre Lizenz erlaubt das Weitergeben, und nichts, was Kopierschutz (DRM) entfernt oder zu Raubkopien führt. Ein Emulator oder ein Reader für ein Format ist in Ordnung: Die Spiele und Bücher sind die eigenen der Leser.
Gib ihm eine Lizenz als SPDX-Bezeichner, die allen erlaubt, es zu installieren und zu nutzen, und leg die Lizenzen dessen bei, was es mitbringt, etwa die Lizenz einer Schrift als
.txt.Sei ehrlich in Name, Zusammenfassung, Beschreibung und Screenshots: Sag, was es tut und was nicht, zeig das Plugin selbst bei der Arbeit, und nutze keine Namen oder Logos anderer, die nahelegen, es sei ihres.
Keine Schadsoftware und nichts, was Geräten oder ihren Besitzern schadet: keine versteckten Funktionen, nichts, was ein Gerät absichtlich beschädigt, sperrt oder verlangsamt, nichts, was Bücher, Dateien oder Konten nimmt.
Kein verstecktes Sammeln von Daten und kein verstecktes Senden.
Sag in der Beschreibung, was das Plugin über das Netz sendet, an wen und warum. Anderes sendet es nicht.
Personenbezogene Daten: Sammle nur, was das Plugin zum Arbeiten braucht, sag es in der Beschreibung und halte dich an das Recht, das für dich gilt, in der EU die DSGVO. Leg niemandes personenbezogene Daten in das Plugin, seine Screenshots oder seinen Eintrag.
Die Builds kommen aus den Quellen, die du nennst: Jeder Build ist unverändert aus dieser Revision gebaut, damit jeder lesen und neu bauen kann, was er installiert.
Es ist kostenlos: Jeder darf es installieren und nutzen, ohne zu bezahlen.
Wenn ein Plugin gemeldet wird
Jeder kann ein Plugin von seiner Seite aus melden, unter /plugins/<id>/report, ohne Konto: illegale Inhalte, Schaden für Geräte oder ihre Besitzer, verletzte Rechte oder Lizenzen, offengelegte personenbezogene Daten oder eine andere gebrochene Regel. Die Moderatoren sehen sich jede Meldung an.
Die Moderatoren entscheiden. Sie können die Meldung abweisen, eine Version entfernen, das Plugin entfernen oder das Konto des Autors sperren. Was entfernt ist, verlässt den Store und den Store der Geräte; seine ID und seine Versionsnummern werden nicht wieder verwendet, und das Versionsprotokoll behält es. Du erfährst per Mail, was sie entschieden haben und warum: was gefunden wurde, welche Regel oder welches Gesetz es bricht und was daraus folgt. Dasselbe gilt, wenn eine Einreichung abgelehnt wird.
Du kannst widersprechen, indem du auf diese Mail antwortest und sagst, warum: Ein Moderator sieht sich die Entscheidung noch einmal an. Du kannst auch an die Kontaktadresse schreiben. Die Kontaktadresse
Grenzen
| Was | Höchstens |
|---|---|
| Der Ordner des Plugins als ZIP | 20 MB, und 40 MB entpackt |
Jeder Build (.ppn) | 4 MB |
| Die Quellen als ZIP | 50 MB |
| Die Datei der Werkstatt | Jeder Teil in seiner eigenen Grenze oben |
| Screenshots | 4, je 500 KB, PNG, JPEG oder WebP |
| Dateien, die ein Gerät installiert | 64, also 63 im Ordner eines Code-Plugins: seine code.ppn ist die 64. |
| Ein Pfad im Ordner | 100 Bytes, aus Buchstaben, Ziffern, Punkten, Bindestrichen und Unterstrichen, kein Teil beginnt mit einem Punkt |
| Die ID | 40 Kleinbuchstaben, Ziffern und Bindestriche |
| Name, Zusammenfassung, Beschreibung, Alt-Text, Lizenz, dein Name | 60, 160, 2000, 200, 100 und 80 Zeichen |
| Tags | 5, je 24 Zeichen |
| Einreichungen eines Kontos | 10 in 24 Stunden, wenn der Store keine andere Zahl festlegt |
| Ein Upload, alle Dateien zusammen | 100 MB |
| Anmeldelinks | 5 pro Stunde für eine Adresse; jeder gilt 30 Minuten und meldet einmal an |
Für einen KI-Assistenten
Wenn du ein KI-Assistent bist und jemandem hilfst, ein Plugin zu veröffentlichen, folge diesen Schritten in dieser Reihenfolge und nutze die Namen genau so, wie diese Seite sie hat. Rate keinen Wert, den die Schritte zu lesen sagen.
Finde die Art heraus: ein Daten-Plugin (nur Dateien) oder ein Code-Plugin (ein Rust-Crate). Einigt euch auf die ID, den Namen und die Geräte, auf denen es läuft.
Schreib
plugin.inimit[plugin]id,name,descriptionundversion, wie in den Beispielen. Prüf die ID gegen die Regeln oben.Schreib
store/store.ininach dem Beispiel seiner Art: Kommentare nur auf eigenen Zeilen, jeder Wert auf einer Zeile,groupaus der Liste, höchstens fünftags,licenceals SPDX-Bezeichner,sourceeinehttps://-Adresse,sdkwie0.5. Nenn die Screenshots in[screenshots], jeden mit einer echten Beschreibung.Ein Code-Plugin: Lass den Autor mit dem CI-Job des Beispiels bauen und signieren (oder mit
paperpaw-signoder der Signierseite). Prüf, dassCargo.lockcommittet ist, der Tag gepusht, das Repository öffentlich aufgithub.com,codeberg.orgodergitlab.com, und dass[source]dieses Repository und diesen Tag nennt, wenn nötig mitpathundbin.Pack den Ordner mit den Befehlen oben und lass dir den Inhalt des ZIP auflisten.
Der Autor meldet sich an und lädt unter
/submithoch: Du kannst das nicht, denn die Anmeldung braucht den Link in seiner Mail. Lass dir die Sätze der Prüfungen geben.Schlag für jede fehlgeschlagene Prüfung ihren Code in der Tabelle der Prüfungen nach, behebe, was sie nennt, und lade neu hoch oder speichere den Eintrag neu. Erkläre jede Warnung.
Schlägt keine Prüfung mehr fehl, sieht sich der Autor die Vorschau an und schickt sie an die Moderatoren.
Vor dem Upload prüfen
- Das ZIP enthält
plugin.iniganz oben oder in einem einzigen Ordner ganz oben, undstore/store.inidaneben. idundversioninplugin.inisind die gemeinten, die Version höher als jede bisher veröffentlichte.- Kein Kommentar hinter einem Wert in
store.inioderplugin.ini, und jede Abschnittszeile für sich. - Jede Datei im Ordner außerhalb von
store/ist.ini,.css,.ttf,.otf,.ttc,.ppfp,.txt,.mdoder.png(ein Font Pack,.ppfp, nur direkt infonts/), jeder Pfad höchstens 100 Bytes, nicht mehr als 64 Dateien (63 bei Code), und keinecode.ppn. - Kein
.DS_Store,__MACOSX/,Thumbs.db,desktop.iniund keine anderen versteckten Dateien. - Code: eine
.ppnfür jedes Gerät, undpaperpaw-sign plugin <file>zeigt für alle denselben Signierer und für jede den richtigen Chip. - Code: Jeder Fingerabdruck ist der, den „Über“ auf dem Gerät zeigt, oder der aus
paperpaw-<reader>-<version>-abi.txtdes Releases. - Code: Der Tag in
revisionexistiert im öffentlichen Repository, am Commit, aus dem die Builds gebaut sind, mitCargo.lock. - Frag nie nach der Schlüsseldatei, schreib sie nie in eine Datei, die der Autor teilt, und erfinde nie einen Fingerabdruck, einen Schlüssel oder eine SHA-256: Lies sie mit
paperpaw-sign pluginundsha256sumaus.