Inhalt
Entwicklerhandbuch
Informationen für Hubzilla-Entwickler
Wer ist ein Hubzilla-Entwickler? Sollte ich das lesen?
Jeder, der dazu beiträgt, Hubzilla besser zu machen, ist ein Entwickler. Es gibt viele verschiedene und wichtige Möglichkeiten, wie Sie zu dieser erstaunlichen Technologie beitragen können, auch wenn Sie nicht wissen, wie man Code schreibt. Die Software selbst ist nur ein Teil des Hubzilla-Projekts. Sie können beitragen durch
- den Text in Ihre Sprache übersetzen, damit Menschen auf der ganzen Welt die Möglichkeit haben, Hubzilla zu nutzen
- für Hubzilla werben und das Bewusstsein für die Plattform durch Blogbeiträge, Artikel und Mundpropaganda verbreiten
- Erstellung von Kunstwerken und Grafiken für Projektressourcen wie Icons und Marketingmaterial
- Unterstützung der Projektinfrastruktur wie der Projektwebsite und der Demoserver
Softwareentwickler sind natürlich willkommen; es gibt so viele großartige Ideen, die umgesetzt werden können, und nicht genug Leute, um sie alle zu verwirklichen! Die Hubzilla-Codebasis ist ein fortschrittliches und ausgereiftes System, aber die Plattform ist immer noch sehr flexibel und offen für neue Ideen.
Wir sind ziemlich entspannt, wenn es um Entwickler geht. Bei uns gibt es nicht viele Regeln. Einige von uns sind überlastet, und wenn Sie helfen wollen, lassen wir Sie gerne helfen. Wenn Sie sich jedoch an ein paar Richtlinien halten, wird der Prozess reibungsloser und die Zusammenarbeit einfacher. Von allen Entwicklern wird erwartet, dass sie sich an unseren Verhaltenskodex halten. Wir haben Entwickler aus der ganzen Welt mit unterschiedlichen Fähigkeiten, unterschiedlichen kulturellen Hintergründen und unterschiedlich viel Geduld. Unsere oberste Regel ist es, andere zu respektieren. Manchmal ist das schwierig, und manchmal haben wir sehr unterschiedliche Ansichten darüber, wie die Dinge funktionieren sollten, aber wenn sich jeder bemüht, werden wir gut miteinander auskommen.
Dieses Dokument wird Ihnen dabei helfen, Hubzilla kennenzulernen und mitzugestalten.
Sie möchten Code beisteuern?
...und wissen nicht, wie Sie anfangen sollen...
- Hubzilla debuggen (php auf dem Webserver),
- Code für das Projekt beisteuern,
- optional - das alles von einer virtuellen Maschine aus zu tun
Diese Anleitung wurde für Debian (Wheezy) als virtuelle Maschine auf Lubuntu (Ubuntu 14.0) als Host getestet.
Installation einer virtuellen Maschine (KVM)
Hier die Installationsanleitung für Linux Debian. Die Zusammenfassung:
- KVM installieren
# apt-get install qemu-kvm libvirt-bin
- füge dich der Gruppe libvirt hinzu
# adduser <deinBenutzer> libvirt
- Installieren Sie die Benutzeroberfläche zur Verwaltung der virtuellen Maschinen
# apt-get install virt-manager
- Laden Sie ein Betriebssystem herunter, das in der virtuellen Maschine laufen soll (mini.iso)
- Starten Sie den Virt-Manager
- Erstellen Sie eine neue virtuelle Maschine (klicken Sie auf das Symbol)
- Wählen Sie Ihr Iso-Image (soeben heruntergeladen) als Installationsquelle
- optional: konfigurieren Sie die neue vm: ram, cpu's,...
- Virtuelle Maschine starten > Ergebnis: Linux Debian startet in einem neuen Fenster.
- (optional) Vermeiden Sie Netzwerkfehler nach dem Neustart des Host-Betriebssystems
# virsh net-start default
# virsh net-autostart standard
Apache-Webserver installieren
Öffnen Sie ein Terminal und machen Sie sich zum root
su -l
Erstellen Sie die Standardgruppe für den Apache-Webserver
groupadd www-data
könnte bereits existieren
usermod -a -G www-data www-data
Prüfen Sie, ob das System wirklich auf dem neuesten Stand ist
apt-get update
apt-get upgrade
Optionaler Neustart der Dienste nach der Installation
reboot
Wenn Sie neu gestartet haben, machen Sie sich zum root
su -l
Installieren Sie Apache:
apt-get install apache2 apache2-doc apache2-utils
Öffnen Sie den Webbrowser auf dem PC und überprüfen Sie localhost Sollte Ihnen eine Seite wie „It works“ anzeigen (Quelle http://www.manfred-steger.de/tuts/20-der-eigene-webserver-mit-dem-raspberry-pi#)
PHP, MySQL und phpMyAdmin installieren
PHP, MySQL
su -l
apt-get install libapache2-mod-php8.2 php8.2 php-pear php8.2-xcache php8.2-curl php8.2-mcrypt php8.2-xdebug
apt-get install php8.2-mysql
apt-get install mysql-server mysql-client
das mysql-Passwort eingeben und notieren Optional, da es bereits während der phpmyadmin-Einrichtung aktiviert wurde
phpenmod mcrypt
phpMyAdmin
phpMyAdmin installieren
apt-get install phpmyadmin
Konfigurieren von phpmyadmin
- Wählen Sie apache2 aus (Tipp: benutzen Sie die Tabulator-Taste zum Auswählen)
- Datenbank für phpmyadmin mit dbconfig-common? konfigurieren: Wählen Sie Ja
(Quelle http://www.manfred-steger.de/tuts/20-der-eigene-webserver-mit-dem-raspberry-pi#)
Aktivieren Sie Rewrite
Bei der Standardinstallation von Apache2 ist mod_rewrite bereits installiert. Um zu prüfen, ob dies der Fall ist, überprüfen Sie die Existenz von /etc/apache2/mods-available/rewrite.load
nano /etc/apache2/mods-available/rewrite.load
(Sie sollten den Inhalt finden: LoadModule rewrite_module
/usr/lib/apache2/modules/mod_rewrite.so
) Um mod_rewrite zu aktivieren und zu laden, führen Sie die restlichen Schritte aus. Erstellen Sie einen symbolischen Link in /etc/apache2/mods-enabled
cd /var/www
a2enmod rewrite
Öffnen Sie dann die folgende Datei und ersetzen Sie jedes Vorkommen von „AllowOverride None
“ durch „AllowOverride all
“.
nano /etc/apache2/apache2.conf
oder
gedit /etc/apache2/sites-enabled/000-default
Starten Sie schließlich Apache2 neu.
service apache2 restart
Testen Sie die Installation
cd /var/www
Erstellen Sie eine php-Datei, um die php-Installation zu testen
nano phpinfo.php
In die Datei einfügen:
<?php
phpinfo();
?>
(STRG+0, ENTER, STRG+X speichern)
Webbrowser auf dem PC öffnen und http://localhost/phpinfo.php
ausprobieren (Seite zeigt Infos zu php)
phpMyAdmin mit der MySQL-Datenbank verbinden
nano /etc/apache2/apache2.conf
- CTRL+V... bis zum Ende der Datei
- Am Ende der Datei einfügen: (CTRL+0, ENTER, CTRL+X speichern)
Einfügen von /etc/phpmyadmin/apache.conf
Apache neu starten
/etc/init.d/apache2 neu starten
apt-get update
apt-get upgrade
reboot
phpMyAdmin
Webbrowser auf dem PC öffnen und http://localhost/phpmyadmin
ausprobieren
(Quelle http://www.manfred-steger.de/tuts/20-der-eigene-webserver-mit-dem-raspberry-pi#)
Erstelle eine leere Datenbank... die später von Hubzilla verwendet wird
öffne den Webbrowser auf dem PC und probiere http://localhost/phpmyadmin
Erstelle eine leere Datenbank, zum Beispiel mit dem Namen „red“. Erstelle einen Datenbankbenutzer, z.B. „red“. Erteile dem Benutzer „red“ alle Rechte für die Datenbank „red“.
Notieren Sie sich die Zugangsdaten (Hostname, Benutzername, Passwort, Datenbankname).
Forken Sie das Projekt auf github
Bitte folgen Sie den Anweisungen in der offiziellen Dokumentation von git. Es ist eine gute Idee, das gesamte Handbuch zu lesen! Git unterscheidet sich in vielerlei Hinsicht von anderen Versionskontrollsystemen. Jetzt sollten Sie
- ein Konto bei github.com erstellen
- fork
https://framagit.org/hubzilla/core
- fork
https://framagit.org/hubzilla/addons
Wenn Sie GIT nicht von der Kommandozeile aus benutzen wollen - es gibt ein nützliches Eclipse-Plugin namens „Eclipse Mylyn to GitHub connector“.
Installieren Sie Hubzilla und seine Addons
Git auf Ihrem Computer / vm
Sie sollten ein Konto auf GitHub erstellt und die Projekte geforkt haben, bevor Sie fortfahren. Löschen Sie das Verzeichnis www
rm -R www/
Installieren Sie git (und optional git-gui, eine Client-Gui)
apt-get install git git-gui
Hubzilla und Addons herunterladen
Laden Sie das Hauptprojekt hubzilla und hubzilla-addons herunter
git clone https://github.com/yourname/hubzilla www
cd www/
git clone https://github.com/yourname/hubzilla-addons addon
Erstelle diesen zusätzlichen Ordner
mkdir -p „store/[data]/smarty3“
Erstellen Sie .htconfig.php und machen Sie sie für den Webserver schreibbar
touch .htconfig.php
chmod ou+w .htconfig.php
Machen Sie den Benutzer www-data (Webserver) zum Eigentümer aller Projektdateien
cd ..
chown -R www-data:www-data www/
Fügen Sie sich selbst („surfer“ in diesem Beispiel) zur Gruppe www-data hinzu. Warum das? Wenn Sie später Dateien in eclipse oder einem anderen Editor bearbeiten wollen. Dann machen Sie alle Dateien für die Gruppe www-data, in der Sie jetzt Mitglied sind, schreibbar.
cd www/
usermod -G www-data surfer
chmod -R g+w www/
Starten Sie den Computer (oder vm) neu Wenn Sie immer noch nicht in der Lage sind, die Projektdateien zu ändern, können Sie die Mitglieder der Gruppe www-data überprüfen mit
cat /etc/group
Melden Sie sich als Admin an
Öffnen Sie http://localhost
und starten Sie die Matrix
Bevor Sie einen ersten Benutzer registrieren, schalten Sie die Registrierungsmails aus. Öffnen Sie /var/www/.htconfig.php
und stellen Sie sicher, dass in dieser Zeile „0“ gesetzt ist
App::$config['system']['verify_email'] = 0;
Sie sollten in der Lage sein, die Datei als „Sie selbst“ zu ändern (anstelle von root oder www-data).
Cron und der Poller
Wichtig! Lassen Sie den Poller laufen, um die jüngsten „öffentlichen“ Beiträge Ihrer Freunde zu erfassen. Richten Sie einen Cron-Job oder eine geplante Aufgabe ein, um den Poller alle 5-10 Minuten laufen zu lassen, um die jüngsten „öffentlichen“ Beiträge Ihrer Freunde zu erfassen
crontab -e
Fügen Sie hinzu.
*/10 * * * * cd /var/www/; /usr/bin/php include/poller.php
Wenn du den Pfad zu PHP nicht kennst, gib ein
which php
Debuggen Sie den Server über eclipse
Überprüfen Sie die Konfiguration von xdebug
Sie sollten xdebug bereits in den vorhergehenden Schritten installiert haben
apt-get install php-xdebug
Xdebug konfigurieren Öffnen Sie Ihr Terminal und geben Sie als root (su -l)
gedit /etc/php/mods-available/xdebug.ini
Wenn die Datei leer ist, versuchen Sie es an dieser Stelle
gedit /etc/php/conf.d/xdebug.ini
Dieser Befehl sollte den Texteditor gedit mit der Xdebug-Konfigurationsdatei öffnen Am Ende des Dateiinhalts fügen Sie den folgenden Text ein
xdebug.remote_enable=on
xdebug.remote_handler=dbgp
xdebug.remote_host=localhost
xdebug.remote_port=9000
Speichern Sie die Änderungen und schließen Sie den Editor. Geben Sie in Ihr Terminal ein, um den Webserver neu zu starten.
service apache2 neustart
Eclipse installieren und Debugging starten
Installieren Sie Eclipse. Starten Sie Eclipse mit dem Standard-Arbeitsbereich (oder wie Sie möchten) Installieren Sie das PHP-Plugin Menü > Hilfe > Neue Software installieren... Installieren Sie „PHP-Entwicklungswerkzeuge ...“ Optional - Installieren Sie das GitHub Connector Plugin Menü > Hilfe > Neue Software installieren... Installieren Sie „Eclipse Mylyn zu GitHub Connector“. Konfigurieren Sie das PHP-Plugin Menü > Fenster > Präferenzen...
Allgemein > Webbrowser > Ändern Sie auf „Externen Webbrowser verwenden“ PHP > Debug > Debug-Einstellungen > PHP Debugger > Ändern Sie auf „XDebug“.
Erstellen Sie ein neues PHP-Projekt Menü > Datei > Neues Projekt > Wählen Sie PHP > „PHP-Projekt“.
Wählen Sie „Projekt an bestehendem Ort erstellen“ und „/var/www“.
Debugging starten Öffnen Sie index.php und „Debuggen als...“. Wählen Sie als Start-URL: „http://localhost/
“
Erwartet:
- Der Webbrowser startet
- Der Debugger wird bei der ersten php-Zeile anhalten
Stellen Sie Ihre Änderungen über github zur Verfügung
Vorbereitungen
Es gibt eine entsprechende Seite in dieser Dokumentation: [zrl=[baseurl]/help/git_for_non_developers]Git for Non-Developers[/zrl]. Wie bereits erwähnt, ist es empfehlenswert, die offizielle Dokumentation GitHub-Contributing-to-a-Project von Git zu lesen. Eclipse hat ein nützliches Plugin für GIT: „Eclipse Mylyn to GitHub connector“. Stellen Sie sicher, dass Sie Ihre Daten eingestellt haben
git config --global user.name „Ihr Name“
git config --global user.email „your@mail.com“
Dein erster Beitrag
Erstelle einen beschreibenden Themenzweig
git checkout -b dev_beginning
Stellen Sie sicher, dass Ihr lokales Repository mit dem Hauptprojekt auf dem neuesten Stand ist. Fügen Sie das ursprüngliche Repository als Remote-Repository mit dem Namen „upstream“ hinzu, falls noch nicht geschehen
git remote add upstream https://framagit.org/hubzilla/core/
Holen Sie sich die neueste Arbeit von dieser Remote
git fetch upstream
git merge upstream/master
Tipp: Sie können die Zweige auflisten
git branch -v
Nehmen Sie Ihre Änderungen vor. In diesem Beispiel ist es eine neue Doc-Datei. Prüfen Sie Ihre Änderungen
git status
Fügen Sie die neue Datei hinzu (stage)
git add doc/dev_beginner.bb
Übertragen Sie die Änderungen in Ihren lokalen Zweig. Dadurch wird ein Editor geöffnet, um eine Nachricht zu übermitteln.
git commit -a
Pushen Sie online zurück in den gleichen Themenzweig
git push
Nun können Sie zu Ihrem (Online-)Konto bei github gehen und den Pull Request erstellen.
Folgende Beiträge
Für den Fall, dass die Hauptentwickler wollen, dass du etwas änderst. Holen Sie sich die neueste Arbeit aus dem entfernten Upstream/Master, um sicher zu sein, dass Sie die neuesten Änderungen haben.
git fetch upstream
git merge upstream/master
Nehmen Sie Ihre Änderungen vor, testen Sie sie, committen Sie (in das lokale Repository), pushen Sie (in das Online-Repository)
git status
git commit -a -m „Änderung des Zweigs hinzugefügt“
git push
Versionen und Releases
Hubzilla verwendet derzeit eine Standard-Versionsnummerierungssequenz von $x.$y(.$z), zum Beispiel '1.12' oder '1.12.1'. Die erste Ziffer ist die Hauptversionsnummer. Hauptversionen werden „ungefähr“ einmal pro Jahr veröffentlicht, oft im Dezember.
Die zweite Ziffer ist die Nummer der Nebenversion. Wenn diese Zahl ungerade ist, handelt es sich um eine Entwicklungsversion. Ist die Zahl gerade, handelt es sich um eine freigegebene Version. Nebenversionen werden in der Regel einmal pro Monat freigegeben (von der Entwicklungs- in die Hauptversion verschoben), wenn die Entwicklung „stabil“ ist, aber das wird wahrscheinlich zunehmen. Zukünftig werden kleinere Versionen zwischen einem und drei Monaten veröffentlicht; das entspricht einem stabilen Codepunkt und wenn es einen allgemeinen Konsens in der Gemeinschaft gibt, dass die aktuelle Codebasis stabil genug ist, um eine Veröffentlichung in Betracht zu ziehen.
Die letzte Ziffer ist eine Schnittstellen- oder Patch-Kennung.
Der Freigabeprozess beinhaltet die Änderung der Versionsnummer (per Definition ist die Minor-Versionsnummer ungerade, und die Minor-Nummer wird erhöht). Einmal im Jahr wird bei einer Hauptversion die Hauptversionsnummer erhöht und die Nebenversionsnummer auf 0 zurückgesetzt.
Der Versionskandidat wird in einen neuen Zweig verschoben und die Tests beginnen bzw. werden für einen Zeitraum von 1-2 Wochen fortgesetzt, oder bis alle wichtigen Probleme behoben sind. Dieser Zweig wird in der Regel mit RC (Release Candidate) bezeichnet; beispielsweise steht 1.8RC für die bevorstehende Veröffentlichung der Version 1.8. Zu diesem Zeitpunkt wird die Versionsnummer des Entwicklungszweigs auf die nächsthöhere ungerade Zahl erhöht. (Zum Beispiel 1.9). Neue Entwicklungen können dann im Entwicklungszweig stattfinden.
Fehlerkorrekturen sollten immer auf „dev“ angewendet werden und von dort aus (in der Regel mit git cherry-pick) auf den RC-Zweig und, falls erforderlich, auf den Master- oder offiziellen Release-Zweig übertragen werden.
Zum Zeitpunkt der Erstellung eines Release Candidate wird die Sprachstring-Datei eingefroren, bis eine neue Version veröffentlicht wird. Die Übersetzungsarbeit kann fortgesetzt werden, aber alle Übersetzungen sollten an „dev“ übermittelt und in RC zusammengeführt werden.
Sobald die RC-Tests abgeschlossen sind, wird RC mit 'master' zusammengeführt und der RC-Versionsbezeichner entfernt; dies führt zu einem letzten Checkin, um die Versionsnummer zu ändern. Die CHANGELOG-Datei sollte ebenfalls zu diesem Zeitpunkt oder kurz davor aktualisiert werden. Wenn es während dieser letzten Zusammenführung Konflikte gibt, wird die Zusammenführung abgebrochen und „git merge -s ours“ angewendet. Dies führt dazu, dass der Master-Zweig durch den Inhalt des RC-Zweigs ersetzt wird. Konflikte entstehen oft durch String-Updates, die nach der letzten Veröffentlichung an master vorgenommen wurden und nicht einfach ohne manuelle Bearbeitung gelöst werden können. Da es sich hier um eine Veröffentlichung von getesteten Code handelt, wird von einer manuellen Bearbeitung abgeraten und stattdessen sollte die Strategie des Replacement Merge verwendet werden. Es wird davon ausgegangen, dass RC nun den neuesten, gut getesteten Code enthält.
Sobald die Veröffentlichung live ist und in den Master-Zweig überführt wurde, kann der RC-Zweig entfernt werden.
Nach der Veröffentlichung können Korrekturen an Master vorgenommen werden. Wenn möglich, sollten diese in dev vorgenommen werden und „git cherry-pick“ zum Zusammenführen verwendet werden; dadurch bleiben die Commit-Informationen erhalten und Konflikte beim Zusammenführen im nächsten Zyklus werden vermieden. Nur selten gilt ein Patch nur für den Master-Zweig. Falls nötig, kann das gemacht werden. Wenn die Änderung schwerwiegend ist, sollte die Versionsnummer der Schnittstelle erhöht werden. Dies liegt im Ermessen der Gemeinschaft. In jedem Fall sollte ein „git pull“ des Master-Zweigs immer zur neuesten Version führen, auf die alle Patches nach der Veröffentlichung angewendet werden.
Die Schnittstellennummer (das $z in $x.$y.$z) sollte in dev immer dann erhöht werden, wenn eine Änderung vorgenommen wird, die die Schnittstellen oder die API in inkompatibler Weise verändert, so dass alle externen Pakete (insbesondere Addons und API-Clients), die sich auf das aktuelle Verhalten verlassen, ihre eigenen Schnittstellen an dem Punkt, an dem es sich geändert hat, entdecken und entsprechend ändern können.
Git-Repository-Zweige
Es gibt zwei offizielle Zweige des Hubzilla-Git-Projektarchivs.
- Die stabile Version wird im Master-Zweig gepflegt. Die letzte Übertragung in diesem Zweig gilt als geeignet für Produktions-Hubs.
- Die experimentelle Entwicklung findet im dev-Zweig statt, der in den master-Zweig überführt wird, sobald er als getestet und stabil genug erachtet wird.
Git für Nicht-Entwickler
Sie kümmern sich um eine Übersetzung oder tragen zu einem Thema bei, und jedes Mal, wenn Sie eine Pull-Anfrage stellen, müssen Sie mit einem der Entwickler sprechen, bevor Ihre Änderungen eingefügt werden können? Wahrscheinlich haben Sie noch keine Kurzanleitung gefunden, die erklärt, wie Sie die Dinge auf Ihrer Seite synchronisieren können. Es ist wirklich sehr einfach. Nachdem Sie einen Fork des Repo erstellt haben (klicken Sie einfach auf „fork“ bei github), müssen Sie Ihre eigene Kopie klonen. Für das Beispiel nehmen wir an, dass du an einem Thema namens redexample arbeitest (das nicht existiert).
git clone https://github.com/username/red.git
Wechseln Sie anschließend in das Verzeichnis und fügen Sie einen Upstream hinzu.
cd rot
git remote add upstream https://framagit.org/hubzilla/core/
Von nun an können Sie Änderungen im Upstream mit dem Befehl
git fetch upstream
Bevor Ihre Änderungen automatisch zusammengeführt werden können, müssen Sie oft Änderungen im Upstream zusammenführen.
git merge upstream/master
Sie sollten Upstream-Änderungen immer zusammenführen, bevor Sie sie veröffentlichen, und Sie müssen Upstream-Änderungen mit allen Pull-Requests zusammenführen, damit sie automatisch zusammengeführt werden können. In 99% der Fälle wird das alles gut gehen. Das einzige Mal, dass es nicht klappt, ist, wenn jemand anderes die gleichen Dateien wie Sie bearbeitet hat - und oft nur, wenn sie die gleichen Zeilen der gleichen Dateien bearbeitet haben. In diesem Fall wäre es ein guter Zeitpunkt, um Hilfe zu bitten, bis Sie den Umgang mit Ihren eigenen Konflikten beim Zusammenführen in den Griff bekommen haben. Dann müssen Sie nur noch Ihre Änderungen hinzufügen
git add view/theme/redexample/
Dadurch werden alle Dateien in view/theme/redexample und alle Unterverzeichnisse hinzugefügt. Wenn Ihre speziellen Dateien über den gesamten Code verteilt sind, sollten Sie eine nach der anderen hinzufügen. Versuchen Sie nicht, git add -a auszuführen, da dies alles hinzufügt, einschließlich temporärer Dateien (wir fangen diese meist, aber nicht immer, mit .gitignore ab) und lokaler Änderungen, die Sie haben, aber nicht übertragen wollten. Wenn Sie alle Dateien, die Sie geändert haben, hinzugefügt haben, müssen Sie sie übertragen.
git commit
Daraufhin öffnet sich ein Editor, in dem Sie die vorgenommenen Änderungen beschreiben können. Speichern Sie diese Datei und beenden Sie den Editor. Zum Schluss pushen Sie die Änderungen auf Ihr eigenes Git
git push
Und das war's, Ihr Projektarchiv ist auf dem neuesten Stand! Alles, was Sie jetzt noch tun müssen, ist die Pull-Anfrage zu erstellen. Es gibt zwei Möglichkeiten, dies zu tun. Der einfache Weg, wenn Sie Github benutzen, ist, einfach auf den grünen Button oben in Ihrer eigenen Kopie des Repositorys zu klicken, eine Beschreibung der Änderungen einzugeben und auf „create pull request“ zu klicken. Das Haupt-Repository, Themes und Addons haben alle ihren Hauptzweig bei Github, so dass diese Methode meistens verwendet werden kann. Die meisten Leute können hier aufhören. Einige Projekte in der erweiterten RedMatrix-Ökosphäre haben keine Github-Präsenz, um für diese eine Pull-Anfrage zu stellen, ist es etwas anders - Sie müssen Ihre Pull-Anfrage manuell erstellen. Glücklicherweise ist das nicht viel schwieriger.
git request-pull -p <start> <url>
Start ist der Name eines Commits, mit dem begonnen werden soll. Dieser muss stromaufwärts existieren. Normalerweise wollen Sie nur master.
URL ist die URL Ihres Repos.
Man kann auch <end>
angeben. Die Voreinstellung ist HEAD.
Beispiel:
git request-pull master https://example.com/project
Und senden Sie die Ausgabe einfach an den Projektbetreuer.
Tools und Arbeitsabläufe für Entwickler
Hub-Snapshots
Die Seite mit den Hub-Snapshots enthält Anweisungen und Skripte für die Erstellung vollständiger Snapshots eines Hubs, um den Wechsel zwischen konsistenten und vollständig bekannten Zuständen zu unterstützen. Dies ist nützlich, um Situationen zu vermeiden, in denen der Inhalt oder das Datenbankschema mit dem Code inkompatibel sein könnte.
Dokumentation erstellen
Um eine Dokumentation zu erstellen, müssen Sie nur ein paar Wörter in eine geschickte Reihenfolge bringen und ihre Existenz einem Entwickler bekannt geben. Sie können dies buchstäblich überall tun, solange ein Entwickler es sehen kann. Sobald Sie es bekannt gemacht haben, wird es jemand für Sie einchecken. Sie sollten versuchen, proprietäre Formate oder Orte, die eine Authentifizierung mit anderen Methoden als Nomad erfordern, zu vermeiden, um einem Entwickler den Zugang zu erleichtern, aber selbst das ist keine strikte Voraussetzung. Wenn Sie direkt beitragen wollen, ist das auch in Ordnung. Um direkt beizutragen, sollte die Dokumentation in einem der folgenden Formate vorliegen:
- Markdown
- BBCode
- HTML
- Einfacher Text
- Andere Formate sind ebenfalls erlaubt, aber die Unterstützung für das Format muss zuerst zu mod/help.php hinzugefügt werden.
Wenn Sie eine reine Textdatei bearbeiten, halten Sie bitte die Spaltenbreite auf 80. Dies liegt daran, dass reiner Text in Fällen verwendet wird, in denen wir keine funktionierende Installation haben - zum Beispiel die Installationsdokumentation - und es sollte einfach sein, diese mit einem CLI-Texteditor zu lesen. Der Vorteil von Markdown ist, dass es für Menschen lesbar ist.
Der Vorteil von BBCode ist, dass es identitätsbewusst ist.
Wenn Sie also BBCode verwenden, versuchen Sie, das Beste daraus zu machen:
- Verwenden Sie gegebenenfalls ZRL-Links, um sicherzustellen, dass ein Link zu einer anderen Website die Authentifizierung beibehält und die identitätsbasierte Dokumentation funktioniert
- Verwenden Sie baseurl- oder observer.baseurl-Tags, wo es angebracht ist, anstelle von example.com für authentifizierte Betrachter.
- Unterstützen Sie nicht-authentifizierte Benutzer mit observer=0-Tags. Aufgrund historischer Versäumnisse tun wir dies derzeit nicht. Dies muss überall hinzugefügt werden.
Übersetzungen Um die Dokumentation zu übersetzen oder in anderen Sprachen als Englisch bereitzustellen:
- Erstellen Sie ein Verzeichnis in doc/ mit Ihrem zweistelligen Ländercode, falls es noch nicht existiert (z.B. doc/de/ für Deutsch oder doc/fr/ für Französisch)
- Erstellen Sie ein Dokument mit demselben Dateinamen wie die englische Version, aber mit dem Inhalt in Ihrer eigenen Sprache. So können wir auf die englische Version zurückgreifen, wenn die Übersetzung für eine bestimmte Seite nicht vorhanden ist.
Um eine Dokumentation zu erstellen, für die es keine gleichwertige Datei auf Englisch gibt, können Sie eine neue Datei mit einem Namen Ihrer Wahl erstellen - allerdings müssen Sie auch eine lokalisierte Version der Indexseite (main.bb auf Englisch) bereitstellen, damit sie über das Menü zugänglich ist.
Übersetzungen
Unsere Übersetzungen werden über Transifex verwaltet. Wenn Sie bei der Übersetzung von Hubzilla in eine andere Sprache helfen möchten, melden Sie sich auf transifex.com an, besuchen Sie Transifex und beantragen Sie die Mitgliedschaft in einem der bestehenden Sprachteams oder erstellen Sie ein neues. Benachrichtigen Sie einen der Hauptentwickler, wenn Sie ein Übersetzungsupdate haben, das zusammengeführt werden muss, oder fragen Sie, ob Sie es selbst zusammenführen können, wenn Sie mit Git und PHP vertraut sind. Wir haben eine Zeichenkettendatei namens 'messages.po', die gettext-kompatibel ist, und eine Handvoll E-Mail-Vorlagen, aus denen wir automatisch die Sprachdateien der Anwendung generieren.
Der Übersetzungsprozess
Die in der Benutzeroberfläche von Hubzilla verwendeten Strings werden bei Transifex übersetzt und dann in das Git-Repository auf github aufgenommen. Wenn Sie bei der Übersetzung helfen möchten einer Sprache helfen wollen, sei es bei der Korrektur von Begriffen oder bei der Übersetzung von Hubzilla in eine derzeit nicht unterstützte Sprache übersetzen möchten, registrieren Sie bitte ein Konto auf transifex.com und kontaktieren Sie dort das Übersetzungsteam.
Hubzilla zu übersetzen ist ganz einfach. Verwenden Sie einfach das Online-Tool auf transifex. Wenn Sie Wenn Sie sich nicht mit Git & Co. herumschlagen wollen, ist das kein Problem, wir überprüfen den Status der Übersetzungen regelmäßig und importieren sie in den Quellbaum auf github, damit andere sie nutzen können.
Wir nehmen nicht jede Übersetzung von transifex in den Quellbaum auf, um eine eine verstreute und gestörte Gesamterfahrung zu vermeiden. Als ungefähre Schätzung haben wir eine Untergrenze von 50% übersetzter Strings, bevor wir die Sprache einbeziehen. Diese Grenze richtet sich nur nach der Menge der übersetzten Zeichenfolgen, wobei wir davon ausgehen dass die wichtigsten Zeichenfolgen für die Benutzeroberfläche zuerst von einem Übersetzungsteam übersetzt Team übersetzt werden. Wenn Sie der Meinung sind, dass Ihre Übersetzung vor dieser Grenze brauchbar ist, kontaktieren Sie uns bitte und wir werden die Arbeit Ihres Teams wahrscheinlich in den Quellbaum aufnehmen.
Wenn Sie Ihre Arbeit selbst in den Quellbaum aufnehmen möchten, können Sie dies gerne tun und kontaktieren Sie uns bei allen Fragen, die sich ergeben. Der Prozess ist einfach und Hubzilla wird mit allen notwendigen Werkzeugen geliefert.
Der Speicherort der übersetzten Dateien im Quellbaum ist
/view/LNG-CODE/
wobei LNG-CODE der Code der verwendeten Sprache ist, z. B. de für Deutsch oder fr für Französisch. Für die E-Mail-Vorlagen (die *.tpl-Dateien) legen Sie sie einfach in das Verzeichnis und Sie sind fertig. Die übersetzten Strings kommen als „hmessages.po“-Datei von Transifex, die in die PHP-Datei übersetzt werden muss, die Hubzilla verwendet. Dazu Sie die Datei in das oben genannte Verzeichnis und verwenden Sie das Dienstprogramm „po2php“ aus dem aus dem Verzeichnis util Ihrer Hubzilla-Installation.
Angenommen, Sie möchten die deutsche Lokalisierung konvertieren, die sich in view/de/hmessages.po steht, würden Sie wie folgt vorgehen.
- Navigieren Sie an der Eingabeaufforderung in das Basisverzeichnis Ihrer
Hubzilla-Installation
- Führen Sie das po2php-Skript aus, das die Übersetzung
in die Datei hstrings.php einfügt, die von Hubzilla verwendet wird.
$> php util/po2php.php view/de/hmessages.po
Die Ausgabe des Skripts wird in der Datei view/de/hstrings.php platziert, wo froemdoca es erwartet, so dass Sie Ihre Übersetzung sofort testen können.
- Besuchen Sie Ihre Hubzilla-Seite und überprüfen Sie, ob sie in der Sprache ist, die Sie gerade übersetzt haben. Wenn nicht, versuchen Sie, den Fehler zu finden, wahrscheinlich gibt PHP Ihnen einen Hinweis im Log/Warnings.über den Fehler.
Zur Fehlersuche können Sie auch versuchen, die Datei mit PHP „auszuführen“. Dies sollte keine Ausgabe geben, wenn die Datei in Ordnung ist, aber vielleicht einen Hinweis für die Fehler in der Datei zu finden.
$> php view/de/hstrings.php
- Übertragen Sie die beiden Dateien mit einer aussagekräftigen Commit-Nachricht in Ihr Git Repository, pushen Sie es zu Ihrem Fork des Hubzilla Repository auf github und stellen einen Pull Request für diesen Commit.
Dienstprogramme
Zusätzlich zum po2php-Skript gibt es einige weitere Hilfsprogramme für die Übersetzung im Verzeichnis „util“ des Hubzilla-Quellbaums. Wenn Sie nur Hubzilla in eine andere Sprache übersetzen wollen, werden Sie wahrscheinlich keines dieser Werkzeuge aber es gibt Ihnen eine Vorstellung davon, wie der Übersetzungsprozess von Hubzilla funktioniert.
Weitere Informationen finden Sie in der Datei utils/README.
Bekannte Probleme
Hubzilla verwendet die Spracheinstellung des Browsers des Besuchers, um die Sprache für die Benutzeroberfläche. Meistens funktioniert dies, aber es gibt einige bekannte Macken.
Die frühen Übersetzungen basieren auf den Friendica-Übersetzungen, wenn Sie einige grobe Übersetzungen finden, lassen Sie es uns bitte wissen oder korrigieren Sie sie bei Transifex.
Lizenzvergabe
Der gesamte zum Projekt beigetragene Code unterliegt der MIT-Lizenz, sofern nicht anders angegeben. Wir akzeptieren Code von Drittanbietern, der unter MIT, BSD und LGPL fällt, aber Copyleft-Lizenzen (GPL und AGPL) sind nur in Addons erlaubt. Es muss möglich sein, den GPL-(Copyleft-)Code vollständig aus dem Hauptprojekt zu entfernen, ohne etwas zu zerstören.
Codierungsstil
Im Interesse der Konsistenz verwenden wir den folgenden Code-Stil. Wir akzeptieren auch Patches, die andere Stile verwenden, aber bitte versuchen Sie, wenn möglich, einen einheitlichen Code-Stil zu verwenden. Wir werden nicht über die Vorzüge dieses Stils streiten oder diskutieren, und es ist irrelevant, was Projekt „xyz“ verwendet. Dies ist nicht Projekt „xyz“. Dies ist eine Grundlinie, um zu versuchen, den Code jetzt und in Zukunft lesbar zu halten.
- Alle Kommentare sollten in Englisch sein.
- Wir verwenden Doxygen, um Dokumentation zu erstellen. Dies wurde nicht konsequent angewandt, aber es wird dringend empfohlen, es zu lernen und zu benutzen.
- Die Einrückung erfolgt hauptsächlich durch Tabulatoren mit einer Tabulatorbreite von 4.
- String-Verkettungen und Operatoren sollten durch Leerzeichen getrennt werden. z.B.
$foo = $bar . 'abc';
anstelle von$foo=$bar.‘abc';
- Im Allgemeinen verwenden wir einfache Anführungszeichen für String-Variablen und doppelte Anführungszeichen für SQL-Anweisungen. „Hier Dokumente“ sollten vermieden werden. Manchmal ist die Verwendung von Strings in doppelten Anführungszeichen mit Variablenersetzung das effizienteste Mittel zur Erstellung des Strings. In den meisten Fällen sollten Sie einfache Anführungszeichen verwenden.
- Verwenden Sie Leerzeichen großzügig, um die Lesbarkeit zu verbessern. Bei der Erstellung von Arrays mit vielen Elementen wird oft ein Schlüssel/Wert-Paar pro Zeile gesetzt, das entsprechend von der übergeordneten Zeile eingerückt wird. Das Aneinanderreihen der Zuweisungsoperatoren erfordert etwas mehr Arbeit, erhöht aber auch die Lesbarkeit.
- Im Allgemeinen werden öffnende geschweifte Klammern in dieselbe Zeile gesetzt wie das, was die Klammer öffnet. Sie sind das letzte Zeichen in der Zeile. Schließende Klammern stehen in einer eigenen Zeile.
- Einige Funktionen nehmen Argumente im argc/argv-Stil entgegen, wie main() in C oder Funktions-Args in Bash oder Perl. Urls werden innerhalb eines Moduls aufgeteilt. z.B. bei
http://example.com/module/arg1/arg2
ist $this->argc 3 (integer) und $this->argv enthält: [0] => 'module', [1] => 'arg1', [2] => 'arg2'. Es wird immer nur ein Argument angegeben. Wenn eine nackte Domain-URL angegeben wird, wird $this->argv[0] auf „home“ gesetzt.
Erstellen von Plugins/Addons für Hubzilla
Sie möchten also, dass Hubzilla etwas tut, was es noch nicht tut. Da gibt es viele Möglichkeiten. Aber lass uns lernen, wie man ein Plugin oder Addon schreibt. In deinem Hubzilla-Ordner/Verzeichnis wirst du wahrscheinlich ein Unterverzeichnis namens 'addon' finden. Wenn Sie noch keins haben, erstellen Sie es einfach.
mkdir addon
Überlegen Sie sich dann einen Namen für Ihr Addon. Wahrscheinlich haben Sie zumindest eine vage Vorstellung davon, was es tun soll. Für unser Beispiel werde ich ein Plugin mit dem Namen „randplace“ erstellen, das einen zufälligen Speicherort für jeden Ihrer Beiträge angibt. Der Name Ihres Plugins wird verwendet, um die Funktionen zu finden, auf die wir zugreifen müssen, und ist Teil des Funktionsnamens, also verwenden Sie zur Sicherheit nur einfache Textzeichen. Sobald Sie einen Namen gewählt haben, erstellen Sie ein Verzeichnis unterhalb von 'addon', um Ihre Arbeitsdatei(en) zu speichern.
mkdir addon/randplace
Erstellen Sie nun Ihre Plugin-Datei. Sie muss den gleichen Namen haben und ist ein PHP-Skript. Erstellen Sie also mit Ihrem Lieblingseditor die Datei
addon/randplace/randplace.php
Die allererste Zeile dieser Datei muss lauten
<?php
Dann werden wir einen Kommentarblock erstellen, der das Plugin beschreibt. Hierfür gibt es ein spezielles Format. Wir verwenden /* ... */ Kommentar-Stil und einige markierte Zeilen, die aus
/**
*
* Name: Random Place (here you can use better descriptions than you could in the filename)
* Description: Sample Hubzilla plugin, Sets a random place when posting.
* Version: 1.0
* Author: Mike Macgirvin <mike@zothub.com>
*
*/
Diese Tags sind für den Website-Administrator sichtbar, wenn er Plugins über die Verwaltungskonsole installiert oder verwaltet. Es kann mehr als einen Autor geben. Fügen Sie einfach eine weitere Zeile hinzu, die mit „Autor:“ beginnt. Ein typisches Plugin hat mindestens die folgenden Funktionen:
- pluginname_load()
- pluginname_unload()
In unserem Fall werden wir sie randplace_load() und randplace_unload() nennen, da dies der Name unseres Plugins ist. Diese Funktionen werden immer dann aufgerufen, wenn wir das Plugin entweder initialisieren oder von der aktuellen Webseite entfernen wollen. Auch wenn Ihr Plugin Dinge wie die Änderung des Datenbankschemas erfordert, bevor es zum ersten Mal ausgeführt werden kann, würden Sie diese Anweisungen wahrscheinlich in den Funktionen namens
- pluginname_install()
- pluginname_uninstall()
Als nächstes werden wir über Hooks sprechen. Hooks sind Stellen im Hubzilla-Code, an denen wir Plugins erlauben, etwas zu tun. Es gibt eine Menge davon, und jedes hat einen Namen. Normalerweise verwenden wir die Funktion pluginname_load(), um eine „Handler-Funktion“ für alle Hooks zu registrieren, an denen Sie interessiert sind. Wenn dann einer dieser Hooks ausgelöst wird, wird Ihr Code aufgerufen. Wir registrieren Hook-Handler mit der Funktion 'register_hook()'. Sie benötigt 3 Argumente. Das erste ist der Hook, den wir abfangen wollen, das zweite ist der Dateiname der Datei, in der sich unsere Handler-Funktion befindet (relativ zur Basis Ihrer Hubzilla-Installation), und das dritte ist der Funktionsname Ihrer Handler-Funktion. Lassen Sie uns also jetzt unsere randplace_load()-Funktion erstellen.
function randplace_load() {
register_hook('post_local', 'addon/randplace/randplace.php', 'randplace_post_hook');
register_hook('feature_settings', 'addon/randplace/randplace.php', 'randplace_settings');
register_hook('feature_settings_post', 'addon/randplace/randplace.php', 'randplace_settings_post');
}
Wir werden also drei Ereignisse abfangen: „post_local“, das ausgelöst wird, wenn ein Beitrag im lokalen System erstellt wird, „feature_settings“, um einige Einstellungen für unser Plugin festzulegen, und „feature_settings_post“, um diese Einstellungen zu speichern.
Als nächstes erstellen wir eine unload-Funktion. Das ist ganz einfach, denn sie hebt nur die Registrierung unserer Hooks auf. Sie nimmt genau die gleichen Argumente entgegen.
function randplace_unload() {
unregister_hook('post_local', 'addon/randplace/randplace.php', 'randplace_post_hook');
unregister_hook('feature_settings', 'addon/randplace/randplace.php', 'randplace_settings');
unregister_hook('feature_settings_post', 'addon/randplace/randplace.php', 'randplace_settings_post');
}
Hooks werden mit zwei Argumenten aufgerufen. Das erste ist immer $a, das unsere globale App-Struktur ist und eine riesige Menge an Informationen über den Zustand der Web-Anfrage enthält, die wir gerade verarbeiten, sowie darüber, wer der Betrachter ist, und was unser Login-Status ist, und der aktuelle Inhalt der Webseite, die wir wahrscheinlich aufbauen.
Das zweite Argument ist spezifisch für den Hook, den Sie aufrufen. Es enthält Informationen, die für diese bestimmte Stelle im Programm relevant sind, und ermöglicht es Ihnen oft, sie anzusehen und sogar zu ändern. Um sie zu ändern, müssen Sie dem Variablennamen ein '&' hinzufügen, damit sie als Referenz an Ihre Funktion übergeben wird. Andernfalls wird eine Kopie erstellt, und alle Änderungen, die Sie vornehmen, gehen verloren, wenn der Hook-Prozess zurückkehrt. Normalerweise (aber nicht immer) ist das zweite Argument ein benanntes Array von Datenstrukturen. Bitte lesen Sie die „Hook-Referenz“ (zu diesem Zeitpunkt noch nicht geschrieben) für Details zu jedem spezifischen Hook. Gelegentlich müssen Sie sich den Programmcode ansehen, um genau zu sehen, wie ein bestimmter Hook aufgerufen wird und wie die Ergebnisse verarbeitet werden.
Fügen wir nun etwas Code hinzu, um unseren post_local-Hook-Handler zu implementieren.
function randplace_post_hook($a, &$item) {
/**
*
* An item was posted on the local system.
* We are going to look for specific items:
* - A status post by a profile owner
* - The profile owner must have allowed our plugin
*
*/
logger('randplace invoked');
if(! local_channel()) /* non-zero if this is a logged in user of this system */
return;
if(local_channel() != $item['uid']) /* Does this person own the post? */
return;
if(($item['parent']) || (! is_item_normal($item))) {
/* If the item has a parent, or isn't "normal", this is a comment or something else, not a status post. */
return;
}
/* Retrieve our personal config setting */
$active = get_pconfig(local_channel(), 'randplace', 'enable');
if(! $active)
return;
/**
*
* OK, we're allowed to do our stuff.
* Here's what we are going to do:
* load the list of timezone names, and use that to generate a list of world cities.
* Then we'll pick one of those at random and put it in the "location" field for the post.
*
*/
$cities = array();
$zones = timezone_identifiers_list();
foreach($zones as $zone) {
if((strpos($zone,'/')) && (! stristr($zone,'US/')) && (! stristr($zone,'Etc/')))
$cities[] = str_replace('_', ' ',substr($zone,strpos($zone,'/') + 1));
}
if(! count($cities))
return;
$city = array_rand($cities,1);
$item['location'] = $cities[$city];
return;
}
Fügen wir nun unsere Funktionen zum Erstellen und Speichern von Einstellungswerten hinzu.
/**
*
* Callback from the settings post function.
* $post contains the global $_POST array.
* We will make sure we've got a valid user account
* and that only our own submit button was clicked
* and if so set our configuration setting for this person.
*
*/
function randplace_settings_post($a,$post) {
if(! local_channel())
return;
if($_POST['randplace-submit'])
set_pconfig(local_channel(),'randplace','enable',intval($_POST['randplace']));
}
/**
*
* Called from the Feature Setting form.
* The second argument is a string in this case, the HTML content region of the page.
* Add our own settings info to the string.
*
* For uniformity of settings pages, we use the following convention
* <div class="settings-block">
* <h3>title</h3>
* .... settings html - many elements will be floated...
* <div class="clear"></div> <!-- generic class which clears all floats -->
* <input type="submit" name="pluginnname-submit" class="settings-submit" ..... />
* </div>
*/
function randplace_settings(&$a,&$s) {
if(! local_channel())
return;
/* Add our stylesheet to the page so we can make our settings look nice */
head_add_css('/addon/randplace/randplace.css');
/* Get the current state of our config variable */
$enabled = get_pconfig(local_channel(),'randplace','enable');
$checked = (($enabled) ? ' checked="checked" ' : '');
/* Add some HTML to the existing form */
$s .= '<div class="settings-block">';
$s .= '<h3>' . t('Randplace Settings') . '</h3>';
$s .= '<div id="randplace-enable-wrapper">';
$s .= '<label id="randplace-enable-label" for="randplace-checkbox">' . t('Enable Randplace Plugin') . '</label>';
$s .= '<input id="randplace-checkbox" type="checkbox" name="randplace" value="1" ' . $checked . '/>';
$s .= '</div><div class="clear"></div>';
/* provide a submit button */
$s .= '<div class="settings-submit-wrapper" ><input type="submit" name="randplace-submit" class="settings-submit" value="' . t('Submit') . '" /></div></div>';
}
Erweiterte Plugins
Manchmal möchten Ihre Plugins eine Reihe neuer Funktionen bereitstellen, die gar nicht oder nur umständlich über Hooks bereitgestellt werden können. In diesem Fall kann Ihr Plugin auch als „Modul“ fungieren. Ein Modul ist in unserem Fall ein strukturierter Webpage-Handler, der auf eine bestimmte URL reagiert. Dann wird alles, was auf diese URL zugreift, vollständig von Ihrem Plugin behandelt. Der Schlüssel dazu ist die Erstellung einer einfachen Funktion namens pluginname_module(), die nichts tut.
function randplace_module() { return; }
Sobald diese Funktion existiert, wird die URL https://yoursite/randplace
auf Ihr Plugin als Modul zugreifen. Dann können Sie Funktionen definieren, die an verschiedenen Stellen aufgerufen werden, um eine Webseite aufzubauen, genau wie die Module im mod/-Verzeichnis. Die typischen Funktionen und die Reihenfolge, in der sie aufgerufen werden, sind
modulename_init($a) // (e.g. randplace_init($a);) called first - if you wish to emit json or xml,
// you should do it here, followed by killme() which will avoid the default action of building a webpage
modulename_aside($a) // Often used to create sidebar content
modulename_post($a) // Called whenever the page is accessed via the "post" method
modulename_content($a) // called to generate the central page content. This function should return a string
// consisting of the central page content.
Ihre Modulfunktionen haben Zugriff auf den URL-Pfad, als ob sie eigenständige Programme im Unix-Betriebssystem wären. Wenn Sie zum Beispiel die Seite
https://yoursite/randplace/something/somewhere/whatever
besuchen, erstellen wir eine argc/argv-Liste zur Verwendung durch Ihre Modulfunktionen
$x = argc(); $x will be 4, the number of path arguments after the sitename
for($x = 0; $x < argc(); $x ++)
echo $x . ' ' . argv($x);
0 randplace
1 something
2 somewhere
3 whatever
Portierung von Friendica-Plugins
Hubzilla verwendet eine ähnliche Plugin-Architektur wie das Friendica-Projekt. Die Authentifizierungs-, Identitäts- und Rechtesysteme sind jedoch völlig unterschiedlich. Viele Friendica-Plugins können relativ einfach portiert werden, indem man ein paar Funktionen umbenennt - und dann sicherstellt, dass das Berechtigungsmodell befolgt wird. Die Funktionen, die umbenannt werden müssen, sind:
- Friendica's pluginname_install() wird zu pluginname_load()
- Friendicas pluginname_uninstall() wird zu pluginname_unload()
Hubzilla hat _install und _uninstall Funktionen, aber diese werden unterschiedlich benutzt.
- Friendicas „plugin_settings“-Haken wird „feature_settings“ genannt
- Friendicas „plugin_settings_post“-Haken wird „feature_settings_post“ genannt
Wenn Sie diese ändern, wird Ihr Plugin oft funktionieren, aber bitte überprüfen Sie Ihren gesamten Berechtigungs- und Identitätscode, da die Konzepte dahinter in Hubzilla völlig anders sind. Viele strukturierte Datennamen (insbesondere DB-Schema-Spalten) sind auch ganz anders.
Testen
Hubzilla verwendet [PHPUnit] für automatisierte Tests, oft auch Unit-Tests oder Integrationstests genannt.
Die Tests werden als PHP-Klassen geschrieben und befinden sich im Unterverzeichnis tests/unit
des Hubzilla-Hauptrepositorys. In diesem Leitfaden wird erklärt, wie man die Tests ausführt, wie die Tests strukturiert sind und wie Sie Ihre eigenen Tests schreiben können.
Ausführen der Testsuite
Installieren der Abhängigkeiten
Um die Tests ausführen zu können, müssen Sie die Entwickler-Abhängigkeiten installieren, die in der composer.json-Datei
aufgeführt sind. Stellen Sie sicher, dass Sie [composer installiert] auf Ihrem Entwicklungssystem haben, und führen Sie dann aus:
% composer install
Dies wird phpunit und einige andere Abhängigkeiten installieren. Es wird auch einige Dateien im Unterverzeichnis vendor/composer
aktualisieren. Dies mag ein wenig laut erscheinen, aber es ist wichtig, dass diese Änderungen nicht in das Repository übertragen werden!
Warnung! Übertragen Sie die Änderungen an den Dateien im Verzeichnis vendor/composer
nicht in Ihr Projektarchiv!
Einrichten der Testdatenbank
Wir haben ein Skript (tests/create_test_db.sh
) beigefügt, das Ihnen hilft, die Testdatenbank einzurichten. Sie können es wie folgt ausführen:
% HZ_TEST_DB_TYPE=mysql ./tests/create_test_db.sh
Wenn Sie stattdessen PostgreSQL verwenden, erstellen Sie die Testdatenbank wie folgt:
% HZ_TEST_DB_TYPE=postgres ./tests/create_test_db.sh
Das Skript macht einige Annahmen über Ihre Einrichtung, aber alles ist über Umgebungsvariablen konfigurierbar. Falls Sie Anpassungen benötigen, finden Sie die Details im Quelltext des Skripts.
Ausführen der Tests
Sobald Sie die Entwicklerabhängigkeiten installiert und die Testdatenbank eingerichtet haben, können Sie die Tests wie folgt ausführen:
% ./vendor/bin/phpunit -c tests/phpunit.xml
Auch hier macht die Konfiguration in tests/phpunit.xml
standardmäßig einige Annahmen über Ihre Einrichtung, die mit Hilfe von Umgebungsvariablen außer Kraft gesetzt werden können. Siehe tests/phpunit.xml
für die Details.
Sie können auch einen bestimmten Test oder eine bestimmte Gruppe von Tests ausführen, indem Sie das Argument --filter
in PHPUnit verwenden:
% ./vendor/bin/phpunit -c tests/phpunit.xml --filter Autoname
Führt jeden Test mit der Bezeichnung „Autoname“ aus.
Erzeugen von Abdeckungsberichten
Um Abdeckungsberichte zu generieren, benötigen Sie einen Treiber, der in der Lage ist, die Abdeckungsinformationen zu generieren, die PHPUnit sammelt. Wir empfehlen [Xdebug], aber sehen Sie sich die PHPUnit Seite zur Codeabdeckungsanalyse für Alternativen und Details an.
Wenn Xdebug richtig eingestellt ist, können Sie den Abdeckungsbericht wie folgt erzeugen:
% XDEBUG_MODE=coverage ./vendor/bin/phpunit -c ./tests/phpunit.xml
Dies erzeugt eine Reihe von HTML-Dateien in den Verzeichnissen des Unterverzeichnisses tests/results/coverage/
.
Öffnen Sie die Datei „index.php“ in Ihrem Webbrowser, um die Statistiken zu sehen.
Fehlersuche
Wenn Xdebug installiert ist, können Sie auch Step-Debugging und eine Reihe anderer Dinge tun, um die Tests zu debuggen und Informationen über ihre Ausführung zu erhalten. Lesen Sie auf den [Xdebug]-Seiten und in Ihrem bevorzugten Editor nach, wie Sie dies einrichten können.
Teststruktur und Organisation
Die Tests befinden sich im Unterverzeichnis tests/unit
und in weiteren Unterverzeichnissen, die mehr oder weniger das Verzeichnislayout des Core Code Repository widerspiegeln.
Tests werden als PHP-Klassen geschrieben, die die UnitTestCase-Klasse erweitern (zu finden in tests/unit/UnitTestcase.php
). Der Dateiname und die darin enthaltene Testklasse sollten gleich lauten und müssen mit Test.php
enden.
Beispiele sind:
tests/unit/includes/AccountTest.php
tests/unit/Lib/ActivityTest.php
Die Testklassen enthalten eine oder mehrere Testfunktionen, diese müssen öffentlich sein und mit dem Präfix test
versehen werden.
Hier ist ein Beispiel:
use Zotlabs\Tests\Unit\UnitTestCase;
class AccountTest extends UnitTestCase {
public function test_get_account_by_id_returns_existing_account() {
$Konto = get_account_by_id(42);
$this->assertNotFalse($account);
$this->assertEquals(
$this->fixtures['account'][0]['account_email'],
$account['account_email']
);
}
Beachten Sie, dass wir versuchen, den Namen der Testfunktion so aussagekräftig wie möglich zu gestalten.
Die Klasse kann auch eine beliebige Anzahl anderer Funktionen enthalten, um die Dinge ordentlich und übersichtlich zu halten. Diese können je nach Bedarf des Testcodes privat, geschützt oder öffentlich sein.
Die Ergebnisse und Artefakte der Testläufe werden im Verzeichnis tests/results/
abgelegt. Dazu gehören in der Regel das Testprotokoll, der Code Coverage Report usw.
Hubzilla-spezifische Funktionen
Testdatenbankzugriff:
Idealerweise sollte es in der Lage sein, jeden Teil des Codes isoliert zu testen, wobei alle Abhängigkeiten durch Stubs, Mocks oder Fakes ersetzt werden sollten.
Dies ist bei einer Legacy-Codebasis wie Hubzilla, die nicht im Hinblick auf Testbarkeit geschrieben wurde, nicht möglich. Aus diesem Grund verwenden wir eine separate Testdatenbank und stellen sie dem zu testenden Code mit denselben Mechanismen zur Verfügung, die auch Hubzilla normalerweise verwendet. Das bedeutet, dass jeder Code, der Datenbankabfragen ausführt, sich normal verhält, wenn er von einem Test aufgerufen wird.
Damit dies funktioniert, stellen wir vor der Ausführung jeder Testfunktion eine Verbindung zur Datenbank her. Wir laden auch einige anfängliche Daten in die Datenbank, um sicherzustellen, dass die Dinge wie erwartet funktionieren und dass wir einen bekannten Zustand der Datenbank haben, wenn der Test läuft. Nach Beendigung des Tests wird die Testdatenbank gelöscht, so dass bei der nächsten Testdurchführung derselbe konsistente Zustand vorliegt.
All dies wird von der Basisklasse UnitTestCase
gehandhabt.
Datenbank-Fixtures:
Wir benötigen einige vorhersehbare Inhalte in der Datenbank, um Dinge wie die Protokollierung und andere Inhalte, die für die Tests im Allgemeinen nützlich sind, einzurichten. Dies sind Datenbank-Fixtures, die für jeden Testlauf in die Datenbank geladen werden.
Die Datenbankfixtures befinden sich im Verzeichnis tests/unit/include/dba/_files
und bestehen aus YAML-Dateien, wobei jede Datei den Inhalt einer Datenbanktabelle mit dem gleichen Namen wie die Datei selbst darstellt.
Obwohl Datenbank-Fixtures sehr nützlich sind, versuchen wir, die Anzahl der Fixtures so gering wie möglich zu halten. In der Regel ist es besser, alle für einen bestimmten Test benötigten Inhalte im Test selbst hinzuzufügen.
Fakes:
Fakes sind Klassen, die wir an den zu testenden Code übergeben können und die genauso aussehen und sich genauso verhalten wie die Originalklasse (für den zu testenden Code). Sie sind nützlich, wenn wir Objekte an den zu testenden Code übergeben können, da wir sie vom Testcode aus vollständig kontrollieren können.
Fakes befinden sich im Verzeichnis tests/fakes
.
Erstellen von Protokoll- Föderationsdiensten
Es gibt drei Hauptkomponenten beim Schreiben von Föderations-Plugins. Diese sind:
- Kanalerkennung und Verbindungsaufbau
- Senden von Beiträgen/Nachrichten
- Empfangen von Beiträgen/Nachrichten
Darüber hinaus müssen Verbundtreiber Folgendes bewältigen
- Unterschiede in den Datenschutzrichtlinien (und Inhaltsformaten)
Herstellen von Verbindungen
Die Kernanwendung bietet eine Kanalerkennung in der folgenden Reihenfolge:
- Nomad-Kanal-Erkennung
- Webfinger (channel@hub) Lookup 2.1 RFC7033 Webfinger 2.2 XRD basierter Webfinger (alter Stil)
- URL-Ermittlung (derzeit nur zur Ermittlung von RSS-Feeds verwendet)
- Wenn alle diese Methoden fehlschlagen, ist das Netzwerk „unbekannt“ und wir sind nicht in der Lage, mit dem Kanal zu kommunizieren oder eine Verbindung zu ihm herzustellen. Ein „xchan“-Datensatz kann dennoch erstellt werden, wenn genügend Informationen bekannt sind, um einen eindeutigen Kanal zu identifizieren.
Jeder der Lookup-Dienste kann an ein Plugin gebunden und erweitert werden. Wenn ein Kanal entdeckt wird, erstellen wir einen „xchan“-Datensatz, der eine plattformneutrale Darstellung der Kanalidentität ist. Wenn wir Informationen an den Kanal senden müssen, ist in der Regel auch ein „hubloc“-Datensatz (Standort des Hubs) erforderlich. Ein 'follow'-Plugin-Hook wird bereitgestellt, um Webfinger und diese Erkennungssequenz vollständig zu umgehen.
Der letzte Schritt, um dies alles zusammenzufügen, ist die Erstellung eines „abook“-Datensatzes, der einen xchan in einer Beziehung zu einem lokalen Kanal mit einem bestimmten Satz von Berechtigungen anlegt. Bei Netzwerken, die keine nomadische Identität unterstützen, muss Ihr Plugin auch „abook_instance“ setzen, eine durch Kommata getrennte Liste von lokalen URLs, mit denen der entfernte Kanal verbunden ist. Wenn Ihr Mitglied zum Beispiel mit meinem Channel-Klon unter https://example.com verbunden war, würde die abook_instance für diese Verbindung'https://example.com' lauten. Wenn Sie sich auch mit meinem Klon unter https://abc.example.com verbunden haben, würde die Zeichenfolge in„https://example.com,https://abc.example.com“ geändert werden. Dies ermöglicht es den lokalen Kanälen zu unterscheiden, mit welcher Instanz ein bestimmter entfernter Kanal verbunden ist und vermeidet Zustellungsfehler an diese Kanäle von anderen Kloninstanzen.
Ein Föderations-Plugin für ein Webfinger-basiertes System muss nur die Webfinger- oder XRD-Ergebnisse untersuchen und einen Protokoll-Stack identifizieren, der für die Verbindung oder Kommunikation verwendet werden kann. Dann erstellt es einen xchan-Datensatz mit dem angegebenen 'xchan_network'-Typ und einen hubloc-Datensatz mit demselben 'hubloc_network' mit den angegebenen Informationen. Derzeit muss das Plugin den gesamten Datensatz erstellen, aber in Zukunft wird dies erweitert, so dass das Plugin nur einen Netzwerknamen identifizieren muss und der Datensatz mit allen anderen bekannten Werten gefüllt wird.
Ein xchan-Datensatz ist immer erforderlich, um eine Verbindung herzustellen. Um eine Verbindung herzustellen, erstellen Sie einen abook-Eintrag mit den gewünschten Berechtigungen. Zusätzliche Informationen, die Ihr Plugin für die Kommunikation benötigt, können in der xconfig-Tabelle und/oder abconfig-Tabelle gespeichert werden, wenn es in den xchan- oder hubloc-Tabellen keine passende Tabellenspalte gibt.
Wenn eine Verbindung hergestellt wird, rufen wir normalerweise den Notifier (include/notifier.php) auf, um eine Nachricht an den entfernten Kanal zu senden. Dies ist an den Hook 'permissions_create' gebunden. Ihr Plugin muss dies verarbeiten, um eine „Follow“- oder „Make Friends“-Nachricht an das andere Netzwerk zu senden.
Anmerkungen: Die erste Stufe des Nomad lookup wird durch einen webfinger lookup ersetzt. Diese Arbeit ist in Arbeit. Ursprünglich war ein separater Lookup erforderlich, da Webfinger keine Nicht-SSL-Verbindungen zulässt. Um diese Einschränkung zu umgehen, werden wir Nomad-Lookups, die nicht auf SSL basieren (in der Regel Test- und Entwicklungsseiten), über den „alten“ XRD-basierten Webfinger anbieten.
Die Kernanwendung wird versuchen, xchan-Einträge für Projekte zu erstellen, die als Mitglieder des „offenen Webs“ identifiziert wurden; derzeit Hubzilla, Friendica, Diaspora, GNU-Social und Pump.io. Dies geschieht, damit Kommentare zwischen den Projektseiten weitergegeben werden können und das Netzwerk korrekt identifiziert werden kann. Ein Föderations-Plugin ist erforderlich, um eine vollständige Verbindung mit anderen Netzwerken herzustellen, aber Kommentare können auch an Seiten weitergeleitet werden, auf denen ein solches Plugin nicht installiert ist, damit es keine unerklärlichen Löcher in den Unterhaltungen gibt.
Die Kernanwendung muss auch die Möglichkeit bieten, Diaspora-Kommentare zu signieren, da diese ein spezielles Signierformat erfordern und vom Verfasser des Kommentars signiert werden müssen, unabhängig davon, ob dieser Kanal mit Diaspora föderiert ist. Der Eigentümer der Konversation kann mit Diaspora föderieren, so dass die Kommentare signiert werden müssen. Dies ist bedauerlich, aber notwendig.
Versenden von Nachrichten
Jedes Mal, wenn eine Nachricht gesendet wird (mit der einzigen Ausnahme der Verzeichniskommunikation), rufen wir den Notifier (include/notifier.php) auf und übergeben ihm die Art der Nachricht und im Allgemeinen einen Identifikator, um die Informationen, die gesendet werden, aus der Datenbank abzurufen (Artikel oder Konversationsdinge, private E-Mails, Aktualisierungen von Berechtigungen usw.). Der Notifier verfügt über mehrere Hooks, die von Plugins auf unterschiedliche Weise verwendet werden können, je nachdem, wie ihre Zustellschleife funktioniert. Für verschiedene Nachrichtentypen und komplexe Zustellungssituationen müssen Sie möglicherweise mehrere Hooks verwenden. Der „permissions_create“-Hook wurde bereits im ersten Abschnitt erwähnt. Es gibt auch eine „permissions_update“-Nachricht, wenn sich die Berechtigungen geändert haben und das andere Ende der Verbindung darüber informiert werden muss. Nur wenige Dienste werden dies bereitstellen oder handhaben (da ihre Berechtigungen statisch sind), aber es wird z. B. auch verwendet, um Nachrichten zur Aktualisierung von Profilen und Profilfotos zu senden, und Sie möchten dies vielleicht handhaben. Der nächste Plugin-Hook ist 'notifier_process'. Ihm wird ein Array übergeben, das den kompletten Status des Notifizierers enthält und einmal pro Notifiziereraufruf aufgerufen wird. Er enthält die vollständige Liste der Empfänger (mit jeweils gesetztem xchan_network).
Es gibt auch 'notifier_hub', dem wie 'notifier_process' der komplette Status des Antragstellers übergeben wird, aber der Unterschied besteht darin, dass er für jede einzelne Hub- oder eindeutige URL-Zustellung aufgerufen wird und auf den Typ hubloc_network abgestimmt werden kann. Die Hub-Zustellung ist wesentlich effizienter als die Empfängerzustellung, eignet sich aber möglicherweise nicht für alle Protokollstacks.
Ihr Plugin muss den Nachrichtenstatus und die Empfänger verstehen und das gesendete Element in das gewünschte Format übersetzen. Sie müssen auch den Datenschutz prüfen und die Kommunikation an alle außer den vorgesehenen Empfängern blockieren - wenn es sich um eine private Kommunikation handelt. Das Plugin wird an dieser Stelle die Nachricht oft in die Warteschlange stellen und die Warteschlangen-ID an den Melder zurückgeben.
Es gibt bereits Warteschlangen-Handler für einfache gepostete Daten. Wenn Sie einen Warteschlangeneintrag vom Typ 'post' erstellen, öffnen wir eine HTTP-POST-Anfrage und senden die bereitgestellten Daten und bestätigen den Erfolg oder Misserfolg. Sie können andere Kommunikationsformen erstellen, indem Sie einen anderen outq_driver-Typ angeben und die Verarbeitung von Warteschlangenanfragen selbst übernehmen. Wenn Sie verschiedene Fehlerzustände oder etwas anderes als Erfolg/Misserfolg bestätigen möchten, ist eine Zustellungsmeldung verfügbar. Für erweiterte Zustellungsberichte ist ebenfalls ein eigener Warteschlangentyp erforderlich. Der Basistyp „post“ behandelt nur Erfolg (erfolgreiche Kommunikation mit der Gegenstelle) und Misserfolg.
Empfang von Nachrichten
Für den Empfang von Nachrichten aus dem entfernten Netz ist wahrscheinlich ein „Empfangs“-Endpunkt oder -Modul erforderlich, der bzw. das für Ihr Netzwerk-Kommunikationsprotokoll vorgesehen ist. Dabei handelt es sich um eine URL-Route, die Ihr Plugin möglicherweise mit dem Hook 'module_loaded' registrieren muss. Ihr Modul übernimmt dann die Verantwortung für den Import aller Daten, die an diesem Endpunkt ankommen, und die Übersetzung in das für dieses Projekt erforderliche Format sowie die Speicherung der resultierenden Daten. Die von uns verwendete Grundstruktur ist ein erweiterbares Activitystream-Element, jedoch mit leicht abweichenden Feldnamen und mehreren optionalen Feldern. Sie kann leicht auf einen Activitystream abgebildet werden. Zusätzliche Daten können in der Tabelle „iconfig“ gespeichert werden. item_store() und item_store_update() werden im Allgemeinen verwendet, um die Daten zu speichern und entsprechende Benachrichtigungen zu senden. Ähnliche Möglichkeiten gibt es für private Post und Profilinformationen.
Verhaltenskodex für Mitwirkende
Unser Versprechen
Im Interesse der Förderung eines offenen und einladenden Umfelds verpflichten wir uns als Mitwirkende und Betreuer, die Teilnahme an unserem Projekt und unserer Gemeinschaft zu einer belästigungsfreien Erfahrung für jeden zu machen, unabhängig von Alter, Körpergröße, Behinderung, ethnischer Zugehörigkeit, Geschlechtsidentität und -ausdruck, Erfahrungsniveau, Nationalität, persönlichem Aussehen, Ethnie, Religion oder sexueller Identität und Orientierung.
Unsere Standards
Beispiele für Verhaltensweisen, die zur Schaffung eines positiven Umfelds beitragen umfassen:
Eine einladende und integrative Sprache verwenden
Respekt vor unterschiedlichen Standpunkten und Erfahrungen
Konstruktive Kritik anständig annehmen
Sich auf das konzentrieren, was für die Gemeinschaft am besten ist
Einfühlungsvermögen gegenüber anderen Mitgliedern der Gemeinschaft zeigen
Beispiele für inakzeptables Verhalten von Teilnehmern sind:
- Die Verwendung sexualisierter Sprache oder Bilder und unerwünschte sexuelle Aufmerksamkeit oder Annäherungsversuche
- Trolling, beleidigende/abwertende Kommentare und persönliche oder politische Angriffe
- Öffentliche oder private Belästigung
- Veröffentlichung privater Informationen anderer, wie z. B. einer physischen oder elektronischen Adresse, ohne ausdrückliche Erlaubnis
- sonstiges Verhalten, das in einem beruflichen Umfeld als unangemessen angesehen werden könnte
Unsere Verantwortlichkeiten
Die Projektbetreuer sind dafür verantwortlich, die Standards für akzeptables Verhalten zu klären, und es wird von ihnen erwartet, dass sie angemessene und faire Korrekturmaßnahmen ergreifen, wenn ein inakzeptables Verhalten festgestellt wird. Die Projektbetreuer haben das Recht und die Verantwortung, Kommentare, Commits, Code, Wiki-Edits, Issues und andere Beiträge, die nicht mit diesem Verhaltenskodex übereinstimmen, zu entfernen, zu bearbeiten oder abzulehnen, oder Beiträge, die sie als unangemessen, bedrohlich, beleidigend oder schädlich erachten, vorübergehend oder dauerhaft zu verbieten.
Geltungsbereich
Dieser Verhaltenskodex gilt sowohl innerhalb der Projektbereiche als auch im öffentlichen Umfeld, wenn eine Person das Projekt oder seine Gemeinschaft vertritt. Beispiele für das Repräsentieren eines Projekts oder einer Gemeinschaft sind die Verwendung einer offiziellen Projekt-E-Mail-Adresse, das Posten über ein offizielles Social-Media-Konto oder das Handeln als ernannter Vertreter bei einer Online- oder Offline-Veranstaltung. Die Repräsentation eines Projekts kann von den Projektbetreuern weiter definiert und präzisiert werden.
Durchsetzung
Fälle von beleidigendem, belästigendem oder anderweitig inakzeptablem Verhalten können beim Projektteam unter project@hubzilla.org gemeldet werden. Alle Beschwerden werden geprüft und untersucht und führen zu einer Reaktion, die als notwendig und den Umständen angemessen erachtet wird. Das Projektteam ist zur Vertraulichkeit gegenüber der Person, die einen Vorfall meldet, verpflichtet. Weitere Einzelheiten zu spezifischen Durchsetzungsrichtlinien können separat veröffentlicht werden.
Projektbetreuer, die den Verhaltenskodex nicht in gutem Glauben befolgen oder durchsetzen, können mit vorübergehenden oder dauerhaften Konsequenzen rechnen, die von anderen Mitgliedern der Projektleitung festgelegt werden.
Namensnennung
Dieser Verhaltenskodex ist eine Anpassung des Contributor Covenant, Version 1.4, verfügbar unter http://contributor-covenant.org/version/1/4.
Das Nomad Protokoll
Was ist Nomad?
Nomad ist das revolutionäre Protokoll, das Hubzilla antreibt und die Kommunikation, das Identitätsmanagement und die Zugangskontrolle in einem vollständig dezentralisierten Netzwerk unabhängiger Websites, oft als „das Grid“ bezeichnet, ermöglicht. Die daraus resultierende Plattform ist ein robustes System, das den Datenschutz und die Sicherheit unterstützt und gleichzeitig die Art von umfangreichen Webdiensten ermöglicht, die normalerweise nur in zentralisierten, proprietären Lösungen zu finden sind.
Betrachten Sie dieses typische Szenario:
Jaquelina möchte Fotos von ihrem Blog unter jaquelina.org mit Roberto teilen, aber mit niemandem sonst. Roberto unterhält seinen eigenen Familien-Hub unter roberto.net auf einem völlig unabhängigen Server. Nomad erlaubt Jaquelina, ihre Fotos mit einer Zugriffskontrollliste (ACL) zu veröffentlichen, die nur Roberto einschließt. Das bedeutet, dass Roberto die Fotos zwar sehen kann, wenn er ihren Blog besucht, sein Bruder Marco jedoch nicht, und auch kein anderes Familienmitglied, das ein Konto auf roberto.net hat.
Der Clou an diesem Szenario ist die Tatsache, dass Roberto sich nie auf Jaquelinas Website angemeldet hat. Stattdessen musste er sich nur einmal mit seinem Passwort auf seiner eigenen Website roberto.net anmelden. Wenn Roberto jaquelina.org besucht, wird er von ihrem Hub nahtlos authentifiziert, indem sein Server im Hintergrund abgefragt wird.
Es ist nicht ungewöhnlich, dass Server technische Probleme haben oder aus verschiedenen Gründen unzugänglich werden. Nomad bietet Robustheit für Robertos Online-Aktivitäten, indem es ihm erlaubt, Klone seiner Online-Identität oder seines Kanals auf mehreren unabhängigen Hubs zu haben. Stellen Sie sich vor, dass Robertos Server aus irgendeinem Grund zusammenbricht und er sich dort nicht mehr einloggen kann. Er meldet sich einfach bei einem seiner Klone auf gadfly.com an, einer Website, die von seinem Freund Peter betrieben wird. Sobald er sich bei gadfly.com authentifiziert hat, kann Roberto Jaquelinas Blog wie zuvor ansehen, ohne dass Jaquelina zusätzlichen Zugang gewähren muss!
Kommunikation
Kommunikation und soziale Netzwerke sind ein wesentlicher Bestandteil des Grids. Jeder Kanal (und jeder Dienst, der von diesem Kanal bereitgestellt wird) kann die funktionsreiche soziale Kommunikation auf globaler Ebene in vollem Umfang nutzen. Diese Kommunikation kann öffentlich oder privat sein - und private Kommunikation umfasst nicht nur einen vollständig verschlüsselten Transport, sondern auch eine verschlüsselte Speicherung zum Schutz vor versehentlichem Schnüffeln und Offenlegung durch unseriöse Systemadministratoren und Internetdienstanbieter.
Nomad unterstützt eine breite Palette von Hintergrunddiensten im Grid, von Freundschaftsvorschlägen bis hin zu Verzeichnisdiensten. Neue Inhalte und Datenaktualisierungen werden im Hintergrund zwischen den Hubs im gesamten Grid gemäß den Zugriffskontrolllisten und den von den Sender- und Empfängerkanälen festgelegten Berechtigungen weitergegeben. Die Daten werden auch zwischen einer beliebigen Anzahl von Kanalklonen synchronisiert, so dass Hub-Mitglieder auch dann auf Daten zugreifen und nahtlos weiter zusammenarbeiten können, wenn ihr primärer Hub nicht erreichbar oder offline ist.
Identität
Die Identitätsschicht von Nomad ist einzigartig. Sie bietet ein unsichtbares Single Sign-On für alle Standorte im Grid.
Sie bietet auch eine nomadische Identität, so dass Ihre Kommunikation mit Freunden, Familie oder anderen Personen, mit denen Sie kommunizieren, nicht durch den Verlust Ihres primären Kommunikationsknotens beeinträchtigt wird - weder vorübergehend noch dauerhaft.
Die wichtigen Teile Ihrer Identität und Ihrer Beziehungen können auf einem USB-Stick oder Ihrem Laptop gesichert werden und jederzeit an einem beliebigen Knoten im Netz erscheinen - mit all Ihren Freunden und Vorlieben.
Entscheidend ist, dass diese nomadischen Instanzen synchron gehalten werden, so dass jede Instanz übernehmen kann, wenn eine andere gefährdet oder beschädigt ist. Dies schützt Sie nicht nur vor größeren Systemausfällen, sondern auch vor vorübergehender Überlastung der Website und staatlicher Manipulation oder Zensur.
Wir sind der Meinung, dass die nomadische Identität, die einmalige Anmeldung und die Dezentralisierung von Hubzilla ein hohes Maß an Widerstandsfähigkeit und Beständigkeit in die Internetkommunikation einbringen, die angesichts der weltweiten Tendenzen zur Zentralisierung von Unternehmen sowie der massenhaften und wahllosen staatlichen Überwachung und Zensur dringend benötigt werden.
Beim Durchsuchen des Netzes, beim Anzeigen von Kanälen und deren einzigartigen Inhalten, werden Sie nahtlos authentifiziert, sogar über völlig unterschiedliche Server-Hubs hinweg. Sie müssen keine Passwörter eingeben. Sie müssen nichts eintippen. Sie werden auf jeder neuen Seite, die Sie besuchen, einfach mit Ihrem Namen begrüßt.
Wie funktioniert das bei Nomad? Wir nennen es „magic-auth“, weil Hubzilla die Details der Komplexität von Single-Sign-On-Logins und nomadischen Identitäten vor dem Surfen im Netz verbirgt. Dies ist eines der Designziele von Hubzilla: die Privatsphäre und die Freiheit im Internet zu erhöhen und gleichzeitig die Komplexität und die Langeweile zu reduzieren, die durch die Notwendigkeit entstehen, für jeden Besuch im Internet neue Passwörter und Anmeldenamen einzugeben. Sie melden sich nur einmal auf Ihrem Home-Hub (oder einem von Ihnen gewählten nomadischen Backup-Hub) an. Dadurch können Sie auf alle authentifizierten Dienste zugreifen, die überall im Netz angeboten werden - wie Einkaufen, Blogs, Foren und Zugang zu privaten Informationen. Ihr Passwort wird nicht auf tausend verschiedenen Websites gespeichert, sondern auf Servern, die Sie kontrollieren oder denen Sie vertrauen.
Sie können nicht zum Schweigen gebracht werden. Sie können nicht aus dem Netz entfernt werden, es sei denn, Sie selbst entscheiden sich dafür, es zu verlassen.
Zugangskontrolle
Die Identitätsschicht von Nomad ermöglicht es Ihnen, fein abgestufte Berechtigungen für jeden Inhalt zu vergeben, den Sie veröffentlichen möchten - und diese Berechtigungen erstrecken sich über das gesamte Grid. Das ist so, als hätte man eine riesige Website, die aus einer Armee kleiner individueller Websites besteht - und bei der jeder Kanal im Grid seine Datenschutz- und Freigabepräferenzen für alle von ihm erstellten Webressourcen vollständig kontrollieren kann.
Derzeit unterstützt Hubzilla die Zugriffskontrolle für viele Datentypen, darunter Diskussionsbeiträge und -kommentare, Fotoalben, Veranstaltungen, Cloud-Dateien, Webseiten, Wikis und mehr. Jedes Objekt und die Art und Weise, wie und mit wem es geteilt wird, unterliegt vollständig Ihrer Kontrolle.
Diese Art der Kontrolle ist bei großen Unternehmensanbietern trivial, da sie die Benutzerdatenbank besitzen. Im Grid brauchen Sie keine riesige Benutzerdatenbank auf Ihrem Rechner - denn das Grid ist Ihre Benutzerdatenbank. Sie verfügt über eine im Grunde unendliche Kapazität (begrenzt durch die Gesamtzahl der Hubs, die im Internet online sind) und ist auf Hunderte, möglicherweise sogar Millionen von Computern verteilt.
Der Zugang kann für jede Ressource, jeden Kanal oder jede Gruppe von Kanälen gewährt oder verweigert werden - überall im Grid. Andere können auf Ihre Inhalte zugreifen, wenn Sie es ihnen erlauben, und sie müssen nicht einmal ein Konto in Ihrem Hub haben.
Magic Auth
Der so genannte „magic auth“ erfolgt durch einen speziellen Austausch. Auf dem entfernten Computer wird eine Umleitung zum Nomad-Endpunkt mit speziellen GET-Parametern vorgenommen.
Endpunkt: https://example.com/post/name
wobei 'name' die linke Seite des Kanal-Webbies ist, zum Beispiel 'mike', wenn der Webbie 'mike@zothub.com' ist.
Zusätzlich werden vier Parameter übergeben:
- auth => die Webbie der Person, die den Zugang beantragt
- dest => die gewünschte Ziel-URL (urlencodiert)
- sec => eine zufällige Zeichenkette, die auch lokal gespeichert wird, um sie während der Verifizierungsphase zu verwenden.
- version => die Zot-Revision
Wenn dieses Paket empfangen wird, wird eine Nomad-Nachricht an die auth-Identität gesendet:
{
"type":"auth_check",
"sender":{
"guid":"kgVFf_1_SSbyqH-BNWjWuhAvJ2EhQBTUdw-Q1LwwssAntr8KTBgBSzNVzUm9_RwuDpxI6X8me_QQhZMf7RfjdA",
"guid_sig":"PT9-TApzpm7QtMxC63MjtdK2nUyxNI0tUoWlOYTFGke3kNdtxSzSvDV4uzq_7SSBtlrNnVMAFx2_1FDgyKawmqVtRPmT7QSXrKOL2oPzL8Hu_nnVVTs_0YOLQJJ0GYACOOK-R5874WuXLEept5-KYg0uShifsvhHnxnPIlDM9lWuZ1hSJTrk3NN9Ds6AKpyNRqf3DUdz81-Xvs8I2kj6y5vfFtm-FPKAqu77XP05r74vGaWbqb1r8zpWC7zxXakVVOHHC4plG6rLINjQzvdSFKCQb5R_xtGsPPfvuE24bv4fvN4ZG2ILvb6X4Dly37WW_HXBqBnUs24mngoTxFaPgNmz1nDQNYQu91-ekX4-BNaovjDx4tP379qIG3-NygHTjFoOMDVUvs-pOPi1kfaoMjmYF2mdZAmVYS2nNLWxbeUymkHXF8lT_iVsJSzyaRFJS1Iqn7zbvwH1iUBjD_pB9EmtNmnUraKrCU9eHES27xTwD-yaaH_GHNc1XwXNbhWJaPFAm35U8ki1Le4WbUVRluFx0qwVqlEF3ieGO84PMidrp51FPm83B_oGt80xpvf6P8Ht5WvVpytjMU8UG7-js8hAzWQeYiK05YTXk-78xg0AO6NoNe_RSRk05zYpF6KlA2yQ_My79rZBv9GFt4kUfIxNjd9OiV1wXdidO7Iaq_Q",
"url":"http:\/\/podunk.edu",
"url_sig":"T8Bp7j5DHHhQDCFcAHXfuhUfGk2P3inPbImwaXXF1xJd3TGgluoXyyKDx6WDm07x0hqbupoAoZB1qBP3_WfvWiJVAK4N1FD77EOYttUEHZ7L43xy5PCpojJQmkppGbPJc2jnTIc_F1vvGvw5fv8gBWZvPqTdb6LWF6FLrzwesZpi7j2rsioZ3wyUkqb5TDZaNNeWQrIEYXrEnWkRI_qTSOzx0dRTsGO6SpU1fPWuOOYMZG8Nh18nay0kLpxReuHCiCdxjXRVvk5k9rkcMbDBJcBovhiSioPKv_yJxcZVBATw3z3TTE95kGi4wxCEenxwhSpvouwa5b0hT7NS4Ay70QaxoKiLb3ZjhZaUUn4igCyZM0h6fllR5I6J_sAQxiMYD0v5ouIlb0u8YVMni93j3zlqMWdDUZ4WgTI7NNbo8ug9NQDHd92TPmSE1TytPTgya3tsFMzwyq0LZ0b-g-zSXWIES__jKQ7vAtIs9EwlPxqJXEDDniZ2AJ6biXRYgE2Kd6W_nmI7w31igwQTms3ecXe5ENI3ckEPUAq__llNnND7mxp5ZrdXzd5HHU9slXwDShYcW3yDeQLEwAVomTGSFpBrCX8W77n9hF3JClkWaeS4QcZ3xUtsSS81yLrp__ifFfQqx9_Be89WVyIOoF4oydr08EkZ8zwlAsbZLG7eLXY"
},
"recipients":{
{
"guid":"ZHSqb3yGar3TYV_o9S-JkD-6o_V4DhUcxtv0VeyX8Kj_ENHPI_M3SyAUucU835-mIayGMmTpqJz3ujPkcavVhA",
"guid_sig":"JsAAXigNghTkkbq8beGMJjj9LBKZn28hZ-pHSsoQuwYWvBJ2lSnfc4r9l--WgO6sucH-SR6RiBo78eWn1cZrh_cRMu3x3LLx4y-tjixg-oOOgtZakkBg4vmOhkKPkci0mFtzvUrpY4YHySqsWTuPwRx_vOlIYIGEY5bRXpnkNCoC8J4EJnRucDrgSARJvA8QQeQQL0H4mWEdGL7wlsZp_2VTC6nEMQ48Piu6Czu5ThvLggGPDbr7PEMUD2cZ0jE4SeaC040REYASq8IdXIEDMm6btSlGPuskNh3cD0AGzH2dMciFtWSjmMVuxBU59U1I6gHwcxYEV6BubWt_jQSfmA3EBiPhKLyu02cBMMiOvYIdJ3xmpGoMY1Cn__vhHnx_vEofFOIErb6nRzbD-pY49C28AOdBA5ffzLW3ss99d0A-6GxZmjsyYhgJu4tFUAa7JUl84tMbq28Tib0HW6qYo6QWw8K1HffxcTpHtwSL5Ifx0PAoGMJsGDZDD1y_r9a4vH5pjqmGrjL3RXJJUy-m4eLV5r7xMWXsxjqu3D8r04_dcw4hwwexpMT1Nwf8CTB0TKb8ElgeOpDFjYVgrqMYWP0XdhatcFtAJI7gsS-JtzsIwON9Kij66-VAkqy_z1IXI0ziyqV1yapSVYoUV1vMScRZ_nMqwiB5rEDx-XLfzko"
}
}
"callback":"\/post",
"version":1,
"secret":"1eaa6613699be6ebb2adcefa5379c61a3678aa0df89025470fac871431b70467",
"secret_sig":"eKV968b1sDkOVdSMi0tLRtOhQw4otA8yFKaVg6cA4I46_zlAQGbFptS-ODiZlSAqR7RiiZQv4E2uXCKar52dHo0vvNKbpOp_ezWYcwKRu1shvAlYytsflH5acnDWL-FKOOgz5zqLLZ6cKXFMoR1VJGG_Od-DKjSwajyV9uVzTry58Hz_w0W2pjxwQ-Xv11rab5R2O4kKSW77YzPG2R5E6Q7HN38FrLtyWD_ai3K9wlsFOpwdYC064dk66X7BZtcIbKtM6zKwMywcfJzvS5_0U5yc5GGbIY_lY6SViSfx9shOKyxkEKHfS29Ynk9ATYGnwO-jnlMqkJC7t149H-sI9hYWMkLuCzaeLP56k2B2TmtnYvE_vHNQjzVhTwuHCIRVr-p6nplQn_P3SkOpYqPi3k_tnnOLa2d3Wtga8ClEY90oLWFJC3j2UkBf_VEOBNcg-t5XO3T-j9O4Sbk96k1Qoalc-QlznbGx4bOVsGkRBBMiH4YUqiiWB_OkFHtdqv7dqGeC-u-B4u9IxzYst46vvmyA3O-Q4APSZ1RY8ITUH0jLTbh6EAV7Oki8pIbOg0t56p-8RlanOZqmFvR-grVSc7Ak1ZcD8NACmvidUpa1B7WEvRcOeffx9lype0bt5XenDnMyx6szevwxZIiM8qGM2lsSk4fu8HI9cW0mLywzZT0"
}
auth_check-Nachrichten MÜSSEN verschlüsselt werden. Diese Nachricht wird an die Herkunftsseite gesendet, die prüft, ob das „secret“ mit dem „sec“ übereinstimmt, das sie ursprünglich übermittelt hat. Sie prüft auch secret_sig, das mit dem privaten Schlüssel des Zielkanals signiert und mit base64url kodiert ist. Wenn alles in Ordnung ist, wird ein json-Paket zurückgegeben:
{
"success":1,
"confirm":"q0Ysovd1uQRsur2xG9Tg6bC23ynzw0191SkVd7CJcYoaePy6e_v0vnmPg2xBUtIaHpx_aSuhgAkd3aVjPeaVBmts6aakT6a_yAEy7l2rBydntu2tvrHhoVqRNOmw0Q1tI6hwobk1BgK9Pm0lwOeAo8Q98BqIJxf47yO9pATa0wktOg6a7LMogC2zkkhwOV5oEqjJfeHeo27TiHr1e2WaphfCusjmk27V_FAYTzw05HvW4SPCx55EeeTJYIwDfQwjLfP4aKV-I8HQCINt-2yxJvzH7Izy9AW-7rYU0Il_gW5hrhIS5MTM12GBXLVs2Ij1CCLXIs4cO0x6e8KEIKwIjf7iAu60JPmnb_fx4QgBlF2HLw9vXMwZokor8yktESoGl1nvf5VV5GHWSIKAur3KPS2Tb0ekNh-tIk9u-xob4d9eIf6tge_d3aq1LcAtrDBDLk8AD0bho5zrVuTmZ9k-lBVPr_DRHSV_dlpu088j3ThaBsuV1olHK3vLFRhYCDIO0CqqK5IuhqtRNnRaqhlNN6fQUHpXk2SwHiJ2W36RCYMTnno6ezFk_tN-RA2ly-FomNZoC5FPA9gFwoJR7ZmVFDmUeK3bW-zYTA5vu15lpBPnt7Up_5rZKkr0WQVbhWJmylqOuwuNWbn3SrMQ8rYFZ23Tv300cOfKVgRBaePWQb4"
}
"confirm“ ist in diesem Fall die base64url-kodierte RSA-Signatur der Verkettung von ‚secret‘ mit dem base64url-kodierten Whirlpool-Hash der Quellguid und guid_sig; signiert mit dem privaten Schlüssel des Quellkanals. Dies verhindert, dass ein Manin-the-Middle ein betrügerisches Erfolgspaket einfügt. Nach Empfang und erfolgreicher Überprüfung dieses Pakets wird die Zielseite zur ursprünglichen Ziel-URL umgeleitet und zeigt eine erfolgreiche Fernanmeldung an.
Nomad-Strukturen
Nomad-Signaturen
Alle signierten Daten in Nomad werden durch eine RSA-Signaturoperation mit dem privaten Schlüssel des Initiators erzeugt. Das binäre Ergebnis wird dann für den Transport mit base64url kodiert.
Nomad-Verschlüsselung
Die Verschlüsselung erfolgt derzeit mit AES256CTR. Weitere Algorithmen KÖNNEN unterstützt werden. Ein 32-Oktett-Schlüssel und ein 16-Oktett-Initialisierungsvektor werden nach dem Zufallsprinzip erzeugt. Die gewünschten Daten werden dann mit diesen generierten Zeichenketten verschlüsselt und das Ergebnis base64url-kodiert. Dann wird ein Array erstellt:
data
Die base64url-kodierten verschlüsselten Daten
alg
Der gewählte Algorithmus, in diesem Fall die Zeichenkette „aes256ctr“.
key
Der zufällig erzeugte Schlüssel, RSA-verschlüsselt mit dem öffentlichen Schlüssel des Empfängers, und das Ergebnis base64url-kodiert
iv
Der zufällig erzeugte Initialisierungsvektor, RSA-verschlüsselt mit dem öffentlichen Schlüssel des Empfängers, und das Ergebnis base64url-kodiert
Grundlegendes Nomad-Paket
Wird verwendet, um einen Dialog mit einer anderen Nomad-Site einzuleiten. Dieses Paket KANN verschlüsselt sein. Das Vorhandensein eines Array-Elements 'iv' zeigt an, dass eine Verschlüsselung vorgenommen wurde. Beim Senden eines 'auth_check'-Pakets MUSS dieses Paket verschlüsselt werden, wobei der öffentliche Schlüssel der Zielsite (der Site-Schlüssel, im Gegensatz zu einem Absenderschlüssel) verwendet wird.
{
"type":"notify",
"sender":{
"guid":"kgVFf_1_SSbyqH-BNWjWuhAvJ2EhQBTUdw-Q1LwwssAntr8KTBgBSzNVzUm9_RwuDpxI6X8me_QQhZMf7RfjdA",
"guid_sig":"PT9-TApzpm7QtMxC63MjtdK2nUyxNI0tUoWlOYTFGke3kNdtxSzSvDV4uzq_7SSBtlrNnVMAFx2_1FDgyKawmqVtRPmT7QSXrKOL2oPzL8Hu_nnVVTs_0YOLQJJ0GYACOOK-R5874WuXLEept5-KYg0uShifsvhHnxnPIlDM9lWuZ1hSJTrk3NN9Ds6AKpyNRqf3DUdz81-Xvs8I2kj6y5vfFtm-FPKAqu77XP05r74vGaWbqb1r8zpWC7zxXakVVOHHC4plG6rLINjQzvdSFKCQb5R_xtGsPPfvuE24bv4fvN4ZG2ILvb6X4Dly37WW_HXBqBnUs24mngoTxFaPgNmz1nDQNYQu91-ekX4-BNaovjDx4tP379qIG3-NygHTjFoOMDVUvs-pOPi1kfaoMjmYF2mdZAmVYS2nNLWxbeUymkHXF8lT_iVsJSzyaRFJS1Iqn7zbvwH1iUBjD_pB9EmtNmnUraKrCU9eHES27xTwD-yaaH_GHNc1XwXNbhWJaPFAm35U8ki1Le4WbUVRluFx0qwVqlEF3ieGO84PMidrp51FPm83B_oGt80xpvf6P8Ht5WvVpytjMU8UG7-js8hAzWQeYiK05YTXk-78xg0AO6NoNe_RSRk05zYpF6KlA2yQ_My79rZBv9GFt4kUfIxNjd9OiV1wXdidO7Iaq_Q",
"url":"http:\/\/podunk.edu",
"url_sig":"T8Bp7j5DHHhQDCFcAHXfuhUfGk2P3inPbImwaXXF1xJd3TGgluoXyyKDx6WDm07x0hqbupoAoZB1qBP3_WfvWiJVAK4N1FD77EOYttUEHZ7L43xy5PCpojJQmkppGbPJc2jnTIc_F1vvGvw5fv8gBWZvPqTdb6LWF6FLrzwesZpi7j2rsioZ3wyUkqb5TDZaNNeWQrIEYXrEnWkRI_qTSOzx0dRTsGO6SpU1fPWuOOYMZG8Nh18nay0kLpxReuHCiCdxjXRVvk5k9rkcMbDBJcBovhiSioPKv_yJxcZVBATw3z3TTE95kGi4wxCEenxwhSpvouwa5b0hT7NS4Ay70QaxoKiLb3ZjhZaUUn4igCyZM0h6fllR5I6J_sAQxiMYD0v5ouIlb0u8YVMni93j3zlqMWdDUZ4WgTI7NNbo8ug9NQDHd92TPmSE1TytPTgya3tsFMzwyq0LZ0b-g-zSXWIES__jKQ7vAtIs9EwlPxqJXEDDniZ2AJ6biXRYgE2Kd6W_nmI7w31igwQTms3ecXe5ENI3ckEPUAq__llNnND7mxp5ZrdXzd5HHU9slXwDShYcW3yDeQLEwAVomTGSFpBrCX8W77n9hF3JClkWaeS4QcZ3xUtsSS81yLrp__ifFfQqx9_Be89WVyIOoF4oydr08EkZ8zwlAsbZLG7eLXY"
"sitekey":"-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxTeIwXZWrw/S+Ju6gewh
LgkKnNNe2uCUqCqMZoYgJar3T5sHCDhvXc4dDCbDkxVIaA/+V1mURtBV60a3IGjn
OAO0W0XGGLe2ED7G5o9U8T9mVGq8Mauv0v1oQ5wIR1gEAhBavkQ2OUGuF/YKn2nj
HlKsv9HzUAHpcDMUe3Uklc2RhQbMcnJxEgkyjCkDyrTtCZzISkTAocHvpCG1KSog
njUZdiz9UWxvM4rCFkCJvQU4RwRZJb7GA9ul+9JrF7NvUQTx8csRP2weBk1E9yyj
wbe187E0eVj9RXX2Mx3mYhgrTdodxLOVMSXZLg1/SMpeFFl7QBhuM0SiOPg8a7Et
e2iNA/RD4WiUFqCDfafasRa1TOozOm7LA+08lkAh5PeQPJsJbrX0wVVft++Y+5/z
BvcUOP73vcbz7j5hJ7HLsbQtye/UUCfODBFybuDqRM84Aet8rjZohX7vukXdMD4I
2HuB7pjR4uIfyYr0J63ANkvbsn8LR+RnirmHrK5H/OgxxjXcfYbGEQgFxvxhF6lA
FpMu6Do4dx3CIb6pRmZ8bjSImXexJ0BSo9n3gtrz0XYLecsYFlQ9+QQjm83qxyLb
M23in0xqMVsyQvzjNkpImrO/QdbEFRIIMee83IHq+adbyjQR49Z2hNEIZhkLPc3U
2cJJ2HkzkOoF2K37qwIzk68CAwEAAQ==
-----END PUBLIC KEY-----
"
},
"recipients":{
{
"guid":"lql-1VnxtiO4-WF0h72wLX1Fu8szzHDOXgQaTbELwXW77k8AKFfh-hYr70vqMrc3SSvWN-Flrc5HFhRTWB7ICw",
"guid_sig":"PafvEL0VpKfxATxlCqDjfOeSIMdmpr3iU7X-Sysa1h5LzDpjSXsjO37tYZL-accb1M5itLlfnW5epkTa5I4flsW21zSY1A2jCuBQUTLLGV7rNyyBy7lgqJUFvAMRx0TfXzP9lcaPqlM9T1tA6jfWOsOmkdzwofGeXBnsjGfjsO2xdGYe6vwjOU0DSavukvzDMnOayB9DekpvDnaNBTxeGLM45Skzr7ZEMcNF7TeXMbnvpfLaALYEKeQs9bGH-UgAG8fBWgzVAzeBfx_XSR1rdixjyiZGP0kq0h35SlmMPcEjliodOBFwMXqpXFB7Ibp4F6o6te2p2ErViJccQVG8VNKB6SbKNXY6bhP5zVcVsJ-vR-p4xXoYJJvzTN7yTDsGAXHOLF4ZrXbo5yi5gFAlIrTLAF2EdWQwxSGyLRWKxG8PrDkzEzX6cJJ0VRcLh5z6OI5QqQNdeghPZbshMFMJSc_ApCPi9_hI4ZfctCIOi3T6bdgTNKryLm5fhy_eqjwLAZTGP-aUBgLZpb1mf2UojBn6Ey9cCyq-0T2RWyk-FcIcbV4qJ-p_8oODqw13Qs5FYkjLr1bGBq82SuolkYrXEwQClxnrfKa4KYc2_eHAXPL01iS9zVnI1ySOCNJshB97Odpooc4wk7Nb2Fo-Q6THU9zuu0uK_-JbK7IIl6go2qA"
},
},
"callback":"\/post",
"version":"1.2",
"encryption":{
"aes256ctr"
},
"secret":"1eaa6613699be6ebb2adcefa5379c61a3678aa0df89025470fac871431b70467",
"secret_sig":"0uShifsvhHnxnPIlDM9lWuZ1hSJTrk3NN9Ds6AKpyNRqf3DUdz81-Xvs8I2kj6y5vfFtm-FPKAqu77XP05r74vGaWbqb1r8zpWC7zxXakVVOHHC4plG6rLINjQzvdSFKCQb5R_xtGsPPfvuE24bv4fvN4ZG2ILvb6X4Dly37WW_HXBqBnUs24mngoTxFaPgNmz1nDQNYQu91-ekX4-BNaovjDx4tP379qIG3-NygHTjFoOMDVUvs-pOPi1kfaoMjmYF2mdZAmVYS2nNLWxbeUymkHXF8lT_iVsJSzyaRFJS1Iqn7zbvwH1iUBjD_pB9EmtNmnUraKrCU9eHES27xTwD-yaaH_GHNc1XwXNbhWJaPFAm35U8ki1Le4WbUVRluFx0qwVqlEF3ieGO84PMidrp51FPm83B_oGt80xpvf6P8Ht5WvVpytjMU8UG7-js8hAzWQeYiK05YTXk-78xg0AO6NoNe_RSRk05zYpF6KlA2yQ_My79rZBv9GFt4kUfIxNjd9OiV1wXdidO7Iaq_Q"
}
type
Der Nachrichtentyp: notify, purge, refresh, force_refresh, auth_check, ping oder pickup. Der Inhalt der Pakete variiert je nach Nachrichtentyp. Hier wird das notify-Paket beschrieben.
callback
Eine Zeichenkette, die an die URL angehängt wird und den Nomad-Kommunikationsendpunkt auf diesem System identifiziert. In der Regel ist dies die Zeichenfolge „/post“.
version
Die Kennung des Nomad-Protokolls, damit künftige Protokollrevisionen nebeneinander bestehen können.
encryption
Array der unterstützten Verschlüsselungsalgorithmen, geordnet nach abnehmender Präferenz. Wenn keine kompatiblen Verschlüsselungsmethoden angegeben sind, MÜSSEN Anwendungen „aes256cbc“ verwenden.
secret
Eine 64-stellige Zeichenkette, die von der sendenden Seite zufällig generiert wird.
secret_sig
Die RSA-Signatur des Geheimnisses, signiert mit dem privaten Schlüssel des Absenders.
sender
Ein Array aus vier Komponenten, die eine tragbare Identität liefern. Wir können die angegebene URL kontaktieren und ein Nomad-Infopaket herunterladen, um den öffentlichen Schlüssel des Absenders zu erhalten, und diesen zur Überprüfung der Absender-Guid und der Signaturen der Entsende-URL verwenden.
guid
In der Regel eine 64 Zeichen lange base64url-kodierte Zeichenfolge. Sie wird erzeugt, wenn eine Identität erstellt wird, und es wird versucht, dass sie eindeutig ist; dies ist jedoch nicht erforderlich.
guid_sig
Die RSA-Signatur der guid, signiert mit dem privaten Schlüssel des Absenders und base64url-kodiert.
url
Die Basis-URL des Ortes, von dem dieser Beitrag stammt.
url_sig
Die RSA-Signatur der url, signiert mit dem privaten Schlüssel des Absenders und base64url kodiert.
sitekey
Der öffentliche Schlüssel der in der Url angegebenen Website
recipients
Wird nur für private Nachrichten verwendet. Ein Array von Umschlag-Empfängern. Jeder Empfänger wird durch ein Array aus guid und guid_sig dargestellt. Wenn Empfänger angegeben sind, wird das gesamte Paket auch mit einem ausgehandelten kryptografischen Algorithmus oder 'aes256cbc' gekapselt, wenn keiner ausgehandelt werden konnte.
guid
Die guid eines privaten Empfängers.
guid_sig
Die RSA-Signatur der guid, signiert mit dem privaten Schlüssel des Empfängers und base64url-kodiert
Zot API
Many existing social applications and tools can interface directly using the Twitter/StatusNet API, which is available using the 'twitter_api' addon.
This document describes the native API; which allows direct programmatic access to several internal data structures and libraries extending beyond the basic social interface.
The API endpoints detailed below are relative to api/z/1.0
, meaning that if an API is listed as channel/stream
the full API URL is https://hub.hubzilla.hu/api/z/1.0/channel/stream
.
channel/export/basic
Export basic channel data
Options: - sections comma-separated list of data types to export
- posts if true, return default sections plus 3 months of posts
If no sections are requested, the following sections are returned: channel, connections, config, apps, chatrooms, events, webpages, mail, wikis
Files and large collections of posts may run into memory limits; these must generally be requested separately.
channel/stream
Fetch channel conversation items
network/stream
Fetch network conversation items
files
List file storage (attach DB)
GET /api/z/1.0/files
Options:
- filehash return only entries matching hash (exactly)
- filename return only entries matching filename (substring)
- filetype return only entries matching filetype/mimetype (substring)
- start start at record (default 0)
- records number of records to return or 0 for unlimited
Example:
curl -u mychannel:mypassword https://xyz.macgirvin.com/api/z/1.0/files -d filetype=multipart/mixed
Returns:
{
"success": true,
"results": [
{
"id": "1",
"aid": "1",
"uid": "2",
"hash": "44ee8b2a1a7f36dea07b93b7747a2383a1bc0fdd08339e8928bfcbe45f65d939",
"filename": "Profile Photos",
"filetype": "multipart/mixed",
"filesize": "0",
"revision": "0",
"folder": "",
"os_storage": "1",
"is_dir": "1",
"is_photo": "0",
"flags": "0",
"created": "2016-01-02 21:51:17",
"edited": "2016-01-02 21:51:17",
"allow_cid": "",
"allow_gid": "",
"deny_cid": "",
"deny_gid": ""
},
{
"id": "12",
"aid": "1",
"uid": "2",
"hash": "71883f1fc64af33889229cbc79c5a056deeec5fc277d765f182f19073e1b2998",
"filename": "Cover Photos",
"filetype": "multipart/mixed",
"filesize": "0",
"revision": "0",
"folder": "",
"os_storage": "1",
"is_dir": "1",
"is_photo": "0",
"flags": "0",
"created": "2016-01-15 00:24:33",
"edited": "2016-01-15 00:24:33",
"allow_cid": "",
"allow_gid": "",
"deny_cid": "",
"deny_gid": ""
},
{
"id": "16",
"aid": "1",
"uid": "2",
"hash": "f48f7ec3278499d1dd86b72c3207beaaf4717b07df5cc9b373f14d7aad2e1bcd",
"filename": "2016-01",
"filetype": "multipart/mixed",
"filesize": "0",
"revision": "0",
"folder": "",
"os_storage": "1",
"is_dir": "1",
"is_photo": "0",
"flags": "0",
"created": "2016-01-22 03:24:55",
"edited": "2016-01-22 03:26:57",
"allow_cid": "",
"allow_gid": "",
"deny_cid": "",
"deny_gid": ""
}
]
}
filemeta
Export file metadata for any uploaded file
filedata
Provides the ability to download a file from cloud storage in chunks
GET /api/z/1.0/filedata
Required:
- file_id attach.hash of desired file ('begins with' match)
Optional:
- start starting byte of returned data in file (counting from 0)
- length length (prior to base64 encoding) of chunk to download
Returns:
attach (DB) structure with base64 encoded 'content' comprised of the desired chunk
Example:
https://xyz.macgirvin.com/api/z/1.0/filedata?f=&file_id=9f5217770fd&start=0&length=48
Returns:
{
"attach": {
"id": "107",
"aid": "1",
"uid": "2",
"hash": "9f5217770fd55d563bd77f84d534d8e119a187514bbd391714626cd9c0e60207",
"creator": "pgcJx1IQjuPkx8aI9qheJlBMZzJz-oTPjHy3h5pWlOVOriBO_cSiUhhqwhuZ74TYJ8_ECO3pPiRMWC0q8YPCQg",
"filename": "pcxtopbm.c",
"filetype": "application/octet-stream",
"filesize": "3934",
"revision": "0",
"folder": "",
"flags": "0",
"is_dir": "0",
"is_photo": "0",
"os_storage": "1",
"os_path": "",
"display_path": "",
"content": "LyogcGN4dG9wYm0uYyAtIGNvbnZlcnQgUEMgcGFpbnRicnVzaCAoLnBjeCkgZmls",
"created": "2016-07-24 23:13:01",
"edited": "2016-07-24 23:13:01",
"allow_cid": "",
"allow_gid": "",
"deny_cid": "",
"deny_gid": "",
"start": 0,
"length": 48
}
}
file/export
file
albums
Description: list photo albums
GET /api/z/1.0/albums
Output:
text - textual name
total - number of photos in this album
url - web URL
urlencode - textual name, urlencoded
bin2hex - textual name using bin2hex (which is used in the web URL link)
Example:
{
"success": true,
"albums": [
{
"text": "/",
"total": "2",
"url": "https://xyz.macgirvin.com/photos/hubzilla/album/",
"urlencode": "",
"bin2hex": ""
},
{
"text": "2016-01",
"total": "6",
"url": "https://xyz.macgirvin.com/photos/hubzilla/album/323031362d3031",
"urlencode": "2016-01",
"bin2hex": "323031362d3031"
},
{
"text": "2016-02",
"total": "7",
"url": "https://xyz.macgirvin.com/photos/hubzilla/album/323031362d3032",
"urlencode": "2016-02",
"bin2hex": "323031362d3032"
},
{
"text": "Cover Photos",
"total": "5",
"url": "https://xyz.macgirvin.com/photos/hubzilla/album/436f7665722050686f746f73",
"urlencode": "Cover+Photos",
"bin2hex": "436f7665722050686f746f73"
},
{
"text": "Profile Photos",
"total": "26",
"url": "https://xyz.macgirvin.com/photos/hubzilla/album/50726f66696c652050686f746f73",
"urlencode": "Profile+Photos",
"bin2hex": "50726f66696c652050686f746f73"
}
]
}
photos
list photo metadata
photo
group
GET /api/z/1.0/group
Description: list privacy groups
Returns: DB tables of all privacy groups.
To use with API group_members, provide either 'group_id' from the id element returned in this call, or 'group_name' from the gname returned in this call.
[
{
"id": "1",
"hash": "966c946394f3e2627bbb8a55026b5725e582407098415c02f85232de3f3fde76Friends",
"uid": "2",
"visible": "0",
"deleted": "0",
"gname": "Friends"
},
{
"id": "2",
"hash": "852ebc17f8c3ed4866f2162e384ded0f9b9d1048f93822c0c84196745f6eec66Family",
"uid": "2",
"visible": "1",
"deleted": "0",
"gname": "Family"
},
{
"id": "3",
"hash": "cc3cb5a7f9818effd7c7c80a58b09a189b62efa698a74319117babe33ee30ab9Co-workers",
"uid": "2",
"visible": "0",
"deleted": "0",
"gname": "Co-workers"
}
]
group_members
GET /api/z/1.0/group_members
Required:
group_id or group_name
Returns:
group_member+abook+xchan (DB join) for each member of the privacy group
[
{
"id": "1",
"uid": "2",
"gid": "1",
"xchan": "pgcJx1IQjuPkx8aI9qheJlBMZzJz-oTPjHy3h5pWlOVOriBO_cSiUhhqwhuZ74TYJ8_ECO3pPiRMWC0q8YPCQg",
"abook_id": "2",
"abook_account": "1",
"abook_channel": "2",
"abook_xchan": "pgcJx1IQjuPkx8aI9qheJlBMZzJz-oTPjHy3h5pWlOVOriBO_cSiUhhqwhuZ74TYJ8_ECO3pPiRMWC0q8YPCQg",
"abook_my_perms": "218555",
"abook_their_perms": "0",
"abook_closeness": "0",
"abook_created": "2016-01-02 21:16:26",
"abook_updated": "2016-01-02 21:16:26",
"abook_connected": "0000-00-00 00:00:00",
"abook_dob": "0000-00-00 00:00:00",
"abook_flags": "0",
"abook_blocked": "0",
"abook_ignored": "0",
"abook_hidden": "0",
"abook_archived": "0",
"abook_pending": "0",
"abook_unconnected": "0",
"abook_self": "1",
"abook_feed": "0",
"abook_profile": "",
"abook_incl": "",
"abook_excl": "",
"abook_instance": "",
"xchan_hash": "pgcJx1IQjuPkx8aI9qheJlBMZzJz-oTPjHy3h5pWlOVOriBO_cSiUhhqwhuZ74TYJ8_ECO3pPiRMWC0q8YPCQg",
"xchan_guid": "lql-1VnxtiO4-WF0h72wLX1Fu8szzHDOXgQaTbELwXW77k8AKFfh-hYr70vqMrc3SSvWN-Flrc5HFhRTWB7ICw",
"xchan_guid_sig": "PafvEL0VpKfxATxlCqDjfOeSIMdmpr3iU7X-Sysa1h5LzDpjSXsjO37tYZL-accb1M5itLlfnW5epkTa5I4flsW21zSY1A2jCuBQUTLLGV7rNyyBy7lgqJUFvAMRx0TfXzP9lcaPqlM9T1tA6jfWOsOmkdzwofGeXBnsjGfjsO2xdGYe6vwjOU0DSavukvzDMnOayB9DekpvDnaNBTxeGLM45Skzr7ZEMcNF7TeXMbnvpfLaALYEKeQs9bGH-UgAG8fBWgzVAzeBfx_XSR1rdixjyiZGP0kq0h35SlmMPcEjliodOBFwMXqpXFB7Ibp4F6o6te2p2ErViJccQVG8VNKB6SbKNXY6bhP5zVcVsJ-vR-p4xXoYJJvzTN7yTDsGAXHOLF4ZrXbo5yi5gFAlIrTLAF2EdWQwxSGyLRWKxG8PrDkzEzX6cJJ0VRcLh5z6OI5QqQNdeghPZbshMFMJSc_ApCPi9_hI4ZfctCIOi3T6bdgTNKryLm5fhy_eqjwLAZTGP-aUBgLZpb1mf2UojBn6Ey9cCyq-0T2RWyk-FcIcbV4qJ-p_8oODqw13Qs5FYkjLr1bGBq82SuolkYrXEwQClxnrfKa4KYc2_eHAXPL01iS9zVnI1ySOCNJshB97Odpooc4wk7Nb2Fo-Q6THU9zuu0uK_-JbK7IIl6go2qA",
"xchan_pubkey": "-----BEGIN PUBLIC KEY-----\nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA18JB76lyP4zzL/y7BCej\neJnfZIWZNtM3MZvI1zEVMWmmwOS+u/yH8oPwyaDk4Y/tnj8GzMPj1lCGVRcd8EJa\nNrCMd50HODA5EsJtxpsOzRcILYjOcTtIAG1K4LtKqELi9ICAaFp0fNfa+Jf0eCek\nvPusx2/ORhy+o23hFoSMhL86o2gmaiRnmnA3Vz4ZMG92ieJEDMXt9IA1EkIqS4y5\nBPZfVPLD1pv8iivj+dtN1XjwplgjUbtxmU0/Ej808nHppscRIqx/XJ0XZU90oNGw\n/wYoK2EzJlPbRsAkwNqoFrAYlr5HPpn4BJ2ebFYQgWBUraD7HwS5atsQEaxGfO21\nlUP0+lDg9t3CXvudDj0UG1jiEKbVIGA+4aG0GN2DSC5AyRq/GRxqyay5W2vQbAZH\nyvxPGrZFO24I65g3pjhpjEsLqZ4ilTLQoLMs0drCIcRm5RxMUo4s/LMg16lT4cEk\n1qRtk2X0Sb1AMQQ2uRXiVtWz77QHMONEYkf6OW4SHbwcv5umvlv69NYEGfCcbgq0\nAV7U4/BWztUz/SWj4r194CG43I9I8dmaEx9CFA/XMePIAXQUuABfe1QMOR6IxLpq\nTHG1peZgHQKeGz4aSGrhQkZNNoOVNaZoIfcvopxcHDTZLigseEIaPPha4WFYoKPi\nUPbZ5o8gTLc750uzrnb2jwcCAwEAAQ==\n-----END PUBLIC KEY-----\n",
"xchan_photo_mimetype": "image/png",
"xchan_photo_l": "https://xyz.macgirvin.com/photo/profile/l/2",
"xchan_photo_m": "https://xyz.macgirvin.com/photo/profile/m/2",
"xchan_photo_s": "https://xyz.macgirvin.com/photo/profile/s/2",
"xchan_addr": "teller@xyz.macgirvin.com",
"xchan_url": "https://xyz.macgirvin.com/channel/teller",
"xchan_connurl": "https://xyz.macgirvin.com/poco/teller",
"xchan_follow": "https://xyz.macgirvin.com/follow?f=&url=%s",
"xchan_connpage": "",
"xchan_name": "Teller",
"xchan_network": "zot",
"xchan_instance_url": "",
"xchan_flags": "0",
"xchan_photo_date": "2016-10-19 01:26:50",
"xchan_name_date": "2016-01-02 21:16:26",
"xchan_hidden": "0",
"xchan_orphan": "0",
"xchan_censored": "0",
"xchan_selfcensored": "0",
"xchan_system": "0",
"xchan_pubforum": "0",
"xchan_deleted": "0"
},
{
"id": "12",
"uid": "2",
"gid": "1",
"xchan": "xuSMUYxw1djBB97qXsbrBN1nzJH_gFwQL6pS4zIy8fuusOfBxNlMiVb4h_q5tOEvpE7tYf1EsryjNciMuPIj5w",
"abook_id": "24",
"abook_account": "1",
"abook_channel": "2",
"abook_xchan": "xuSMUYxw1djBB97qXsbrBN1nzJH_gFwQL6pS4zIy8fuusOfBxNlMiVb4h_q5tOEvpE7tYf1EsryjNciMuPIj5w",
"abook_my_perms": "218555",
"abook_their_perms": "218555",
"abook_closeness": "80",
"abook_created": "2016-01-27 00:48:43",
"abook_updated": "2016-12-04 17:16:58",
"abook_connected": "2016-12-04 17:16:58",
"abook_dob": "0001-01-01 00:00:00",
"abook_flags": "0",
"abook_blocked": "0",
"abook_ignored": "0",
"abook_hidden": "0",
"abook_archived": "0",
"abook_pending": "0",
"abook_unconnected": "0",
"abook_self": "0",
"abook_feed": "0",
"abook_profile": "debb5236efb1626cfbad33ccb49892801e5f844aa04bf81f580cfa7d13204819",
"abook_incl": "",
"abook_excl": "",
"abook_instance": "",
"xchan_hash": "xuSMUYxw1djBB97qXsbrBN1nzJH_gFwQL6pS4zIy8fuusOfBxNlMiVb4h_q5tOEvpE7tYf1EsryjNciMuPIj5w",
"xchan_guid": "d5EMLlt1tHHZ0dANoA7B5Wq9UgXoWcFS9-gXOkL_AAejcPApoQRyxfHTuu8DoTbUaO-bYmX5HPuWuK9PHyqNmA",
"xchan_guid_sig": "CVWEMRPtzI1YcHfnnWHTuv3H964OAmSElgUfxMoX6RdQdxNpqb_POirpVuyP8s3W17mVCfO5V9IAjkg5iKcqCk6YcvOD_egmMy-AnM9TC1kKndQHw55CunD82Q8K_xBNSXkSROizcNkKh9DVLjJPFjW1AqtI4njkZ3EMgrWqnbFRM1qPToUoCY9zM3tEMHoAD9YX1zP90wl40LzfN-dtcNWpSBbiz9owou62uzLbN7mrCwKOMlXLjwwGswRnxIsEnb3O-FXOs8hs0mArKe9snq1-BKeD16LyzxgwlpVLElzIJZGEZGtMdIJgeRzKuBvPjsOIpQ1yAkuOpFJ3nGCM-IPOIIjAmyVl5zD3xPVcxxpZlJRn5fG1Y-gnqTgsrEQCA7M6XPWQdrdHU4akZfyUyFJDhv3uM-jon9VzrYTBw68R0WA-1Z8WafEHA4qh5OWAj85lUarwhr7iTiEckH51ypPCPs6VbT6Pw7yMaxfjFOcipashQagx0tfOlDhE5dQANOXKASFtH1J9-CZY2MQdLPQ6u54d5whuHKMGaJ0V68pnmZ2rOn7g344Ah2WCJrm17jj60QsRMorqRFj7GMdPIA1XB8Wrk88MuYOe3Dhyuu6ZWKI7YTWJS690ZVkKUqAiNHqj0W86DtaiPUc_mmGR0fHl4Gksnko3WmCFv9q2X2E",
"xchan_pubkey": "-----BEGIN PUBLIC KEY-----\nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAoj2xCJktBA8Ww7Hp+ZNL\nrNuQpo8UB/bfvRkIy+yua3xpF1TuXcnAH61kyRz8vXgOu/l2CyxQbIoaGslCV5Sy\n8JKeNXe+IilUdSSEjMIwCPfSPsYnMHsSnHWmPmclvJwEtQUKOZmW5mMuVBvXy7D2\njomFwc69AYphdyys6eQ7Dcn6+FRBiQbyMprZ5lxyVW+O4DuXVNa3ej2ebx0gCJZ4\ntTIlBoKwEey91dY+FyKVFjdwfNczpmL7LgmZXqcVx+MG3mYgibwdVMiXVj5X06cs\nV9hJ5Xi+Aklsv/UWJtjw9FVt7y9TLptnhh4Ra6T/MDmnBBIAkOR7P/X8cRv078MT\nl0IMsP0RJcDEtTLtwHFVtDs6p52KDFqclKWbqmxmxqV3OTPVYtArRGIzgnJi/5ur\nHRr5G6Cif7QY3UowsIOf78Qvy28LwSbdymgBAWwPPKIviXWxGO+9kMWdmPSUQrWy\nK0+7YA9P9fBUFfn9Hc+p8SJQmQ6OAqLwrDGiPSOlGaNrbEqwqLGgIpXwK+lEFcFJ\n3SPOjJRWdR2whlMxvpwX+39+H7dWN3vSa3Al4/Sq7qW8yW2rYwf+eGyp4Z0lRR+8\nJxFMCwZkSw5g14YdlikAPojv5V1c6KuA5ieg8G1hwyONV7A4JHPyEdPt0W0TZi6C\nCOVkPaC3xGrguETZpJfVpwUCAwEAAQ==\n-----END PUBLIC KEY-----\n",
"xchan_photo_mimetype": "image/png",
"xchan_photo_l": "https://xyz.macgirvin.com/photo/9da63aa910ea14e1501ee1a749d181a6-4",
"xchan_photo_m": "https://xyz.macgirvin.com/photo/9da63aa910ea14e1501ee1a749d181a6-5",
"xchan_photo_s": "https://xyz.macgirvin.com/photo/9da63aa910ea14e1501ee1a749d181a6-6",
"xchan_addr": "cloner@xyz.macgirvin.com",
"xchan_url": "http://abc.macgirvin.com/channel/cloner",
"xchan_connurl": "http://abc.macgirvin.com/poco/cloner",
"xchan_follow": "https://xyz.macgirvin.com/follow?f=&url=%s",
"xchan_connpage": "",
"xchan_name": "Karen",
"xchan_network": "zot",
"xchan_instance_url": "",
"xchan_flags": "0",
"xchan_photo_date": "2016-03-31 19:59:20",
"xchan_name_date": "2016-01-26 23:23:42",
"xchan_hidden": "0",
"xchan_orphan": "0",
"xchan_censored": "0",
"xchan_selfcensored": "0",
"xchan_system": "0",
"xchan_pubforum": "0",
"xchan_deleted": "0"
}
]
xchan
An xchan is a global location independent channel and is the primary record for a network identity. It may refer to channels on other websites, networks, or services.
GET /api/z/1.0/xchan
Required: one of [ address, hash, guid ] as GET parameters
Returns a portable xchan structure
Example: https://xyz.macgirvin.com/api/z/1.0/xchan?f=&address=mike@macgirvin.com
Returns:
{
"hash": "jr54M_y2l5NgHX5wBvP0KqWcAHuW23p1ld-6Vn63_pGTZklrI36LF8vUHMSKJMD8xzzkz7s2xxCx4-BOLNPaVA",
"guid": "sebQ-IC4rmFn9d9iu17m4BXO-kHuNutWo2ySjeV2SIW1LzksUkss12xVo3m3fykYxN5HMcc7gUZVYv26asx-Pg",
"guid_sig": "Llenlbl4zHo6-g4sa63MlQmTP5dRCrsPmXHHFmoCHG63BLq5CUZJRLS1vRrrr_MNxr7zob_Ykt_m5xPKe5H0_i4pDj-UdP8dPZqH2fqhhx00kuYL4YUMJ8gRr5eO17vsZQ3XxTcyKewtgeW0j7ytwMp6-hFVUx_Cq08MrXas429ZrjzaEwgTfxGnbgeQYQ0R5EXpHpEmoERnZx77VaEahftmdjAUx9R4YKAp13pGYadJOX5xnLfqofHQD8DyRHWeMJ4G1OfWPSOlXfRayrV_jhnFlZjMU7vOdQwHoCMoR5TFsRsHuzd-qepbvo3pzvQZRWnTNu6oPucgbf94p13QbalYRpBXKOxdTXJrGdESNhGvhtaZnpT9c1QVqC46jdfP0LOX2xrVdbvvG2JMWFv7XJUVjLSk_yjzY6or2VD4V6ztYcjpCi9d_WoNHruoxro_br1YO3KatySxJs-LQ7SOkQI60FpysfbphNyvYMkotwUFI59G08IGKTMu3-GPnV1wp7NOQD1yzJbGGEGSEEysmEP0SO9vnN45kp3MiqbffBGc1r4_YM4e7DPmqOGM94qksOcLOJk1HNESw2dQYWxWQTBXPfOJT6jW9_crGLMEOsZ3Jcss0XS9KzBUA2p_9osvvhUKuKXbNztqH0oZIWlg37FEVsDs_hUwUJpv2Ar09k4",
"pubkey": "-----BEGIN PUBLIC KEY-----\nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA7QCwvuEIwCHjhjbpz3Oc\ntyei/Pz9nDksNbsc44Cm8jxYGMXsTPFXDZYCcCB5rcAhPPdZSlzaPkv4vPVcMIrw\n5cdX0tvbwa3rNTng6uFE7qkt15D3YCTkwF0Y9FVZiZ2Ko+G23QeBt9wqb9dlDN1d\nuPmu9BLYXIT/JXoBwf0vjIPFM9WBi5W/EHGaiuqw7lt0qI7zDGw77yO5yehKE4cu\n7dt3SakrXphL70LGiZh2XGoLg9Gmpz98t+gvPAUEotAJxIUqnoiTA8jlxoiQjeRK\nHlJkwMOGmRNPS33awPos0kcSxAywuBbh2X3aSqUMjcbE4cGJ++/13zoa6RUZRObC\nZnaLYJxqYBh13/N8SfH7d005hecDxWnoYXeYuuMeT3a2hV0J84ztkJX5OoxIwk7S\nWmvBq4+m66usn6LNL+p5IAcs93KbvOxxrjtQrzohBXc6+elfLVSQ1Rr9g5xbgpub\npSc+hvzbB6p0tleDRzwAy9X16NI4DYiTj4nkmVjigNo9v2VPnAle5zSam86eiYLO\nt2u9YRqysMLPKevNdj3CIvst+BaGGQONlQalRdIcq8Lin+BhuX+1TBgqyav4XD9K\nd+JHMb1aBk/rFLI9/f2S3BJ1XqpbjXz7AbYlaCwKiJ836+HS8PmLKxwVOnpLMbfH\nPYM8k83Lip4bEKIyAuf02qkCAwEAAQ==\n-----END PUBLIC KEY-----\n",
"photo_mimetype": "image/jpeg",
"photo_l": "https://xyz.macgirvin.com/photo/350b74555c04429148f2e12775f6c403-4",
"photo_m": "https://xyz.macgirvin.com/photo/350b74555c04429148f2e12775f6c403-5",
"photo_s": "https://xyz.macgirvin.com/photo/350b74555c04429148f2e12775f6c403-6",
"address": "mike@macgirvin.com",
"url": "https://macgirvin.com/channel/mike",
"connurl": "https://macgirvin.com/poco/mike",
"follow": "https://macgirvin.com/follow?f=&url=%s",
"connpage": "https://macgirvin.com/connect/mike",
"name": "Mike Macgirvin",
"network": "zot",
"instance_url": "",
"flags": "0",
"photo_date": "2012-12-06 05:06:11",
"name_date": "2012-12-06 04:59:13",
"hidden": "1",
"orphan": "0",
"censored": "0",
"selfcensored": "0",
"system": "0",
"pubforum": "0",
"deleted": "0"
}
item/update
Create or update an item (post, activity, webpage, etc.)
Usage: POST /api/z/1.0/item/update
Description: item/update posts an item (typically a conversation item or post, but can be any item) using form input.
Required:
- body
text/bbcode contents by default.
Optional:
- $_FILES['media']
uploaded media file to include with post
- title
title of post/item
- contact_allow
array of xchan.xchan_hash allowed to view this item
- group_allow
array of group.hash allowed to view this item
- contact_deny
array of xchan.xchan_hash not allowed to view this item
- group_deny
array of group.hash not allowed to view this item
- coord
geographic coordinates
- location
freefrom location
- expire
datetime this post will expire or be removed
- mimetype
mimetype if not text/bbcode
- parent
item.id of parent to this post (makes it a comment)
- parent_mid
alternate form of parent using message_id
- remote_xchan
xchan.xchan_hash of this message author if not the channel owner
- consensus
boolean set to true if this is a consensus or voting item (default false)
- nocomment
boolean set to true if comments are to be disabled (default false)
- origin
do not use this without reading the code
- namespace
persistent identity for a remote network or service
- remote_id
message_id of this resource on a remote network or service
- message_id
message_id of this item (leave unset to generate one)
- created
datetime of message creation
- post_id
existing item.id if this is an edit operation
- app
application or network name to display with item
- category
comma separated categories for this item
- webpage
item.page_type if not 0
- pagetitle
for webpage and design elements, the 'page name'
- layout_mid
item.mid of layout for this design element
- plink
permalink for this item if different than the default
- verb
activitystream verb for this item/activity
- obj_type
activitystream object type for this item/activity
Example:
curl -u mychannel:mypassword https://xyz.macgirvin.com/api/z/1.0/item/update -d body="hello world"
Returns:
{
"success": true,
"item_id": "2245",
"item": {
"id": "2245",
"mid": "14135cdecf6b8e3891224e4391748722114da6668eebbcb56fe4667b60b88249@xyz.macgirvin.com",
"aid": "1",
"uid": "2",
"parent": "2245",
"parent_mid": "14135cdecf6b8e3891224e4391748722114da6668eebbcb56fe4667b60b88249@xyz.macgirvin.com",
"thr_parent": "14135cdecf6b8e3891224e4391748722114da6668eebbcb56fe4667b60b88249@xyz.macgirvin.com",
"created": "2016-12-03 20:00:12",
"edited": "2016-12-03 20:00:12",
"expires": "0001-01-01 00:00:00",
"commented": "2016-12-03 20:00:12",
"received": "2016-12-03 20:00:12",
"changed": "2016-12-03 20:00:12",
"comments_closed": "0001-01-01 00:00:00",
"owner_xchan": "pgcJx1IQjuPkx8aI9qheJlBMZzJz-oTPjHy3h5pWlOVOriBO_cSiUhhqwhuZ74TYJ8_ECO3pPiRMWC0q8YPCQg",
"author_xchan": "pgcJx1IQjuPkx8aI9qheJlBMZzJz-oTPjHy3h5pWlOVOriBO_cSiUhhqwhuZ74TYJ8_ECO3pPiRMWC0q8YPCQg",
"source_xchan": "",
"mimetype": "text/bbcode",
"title": "",
"body": "hello world",
"html": "",
"app": "",
"lang": "",
"revision": "0",
"verb": "http://activitystrea.ms/schema/1.0/post",
"obj_type": "http://activitystrea.ms/schema/1.0/note",
"obj": "",
"tgt_type": "",
"target": "",
"layout_mid": "",
"postopts": "",
"route": "",
"llink": "https://xyz.macgirvin.com/display/14135cdecf6b8e3891224e4391748722114da6668eebbcb56fe4667b60b88249@xyz.macgirvin.com",
"plink": "https://xyz.macgirvin.com/channel/mychannel/?f=&mid=14135cdecf6b8e3891224e4391748722114da6668eebbcb56fe4667b60b88249@xyz.macgirvin.com",
"resource_id": "",
"resource_type": "",
"attach": "",
"sig": "sa4TOQNfHtV13HDZ1tuQGWNBpZp-nWhT2GMrZEmelXxa_IvEepD2SEsCTWOBqM8OKPJLfNy8_i-ORXjrOIIgAa_aT8cw5vka7Q0C8L9eEb_LegwQ_BtH0CXO5uT30e_8uowkwzh6kmlVg1ntD8QqrGgD5jTET_fMQOIw4gQUBh40GDG9RB4QnPp_MKsgemGrADnRk2vHO7-bR32yQ0JI-8G-eyeqGaaJmIwkHoi0vXsfjZtU7ijSLuKEBWboNjKEDU89-vQ1c5Kh1r0pmjiDk-a5JzZTYShpuhVA-vQgEcADA7wkf4lJZCYNwu3FRwHTvhSMdF0nmyv3aPFglQDky38-SAXZyQSvd7qlABHGCVVDmYrYaiq7Dh4rRENbAUf-UJFHPCVB7NRg34R8HIqmOKq1Su99bIWaoI2zuAQEVma9wLqMoFsluFhxX58KeVtlCZlro7tZ6z619-dthS_fwt0cL_2dZ3QwjG1P36Q4Y4KrCTpntn9ot5osh-HjVQ01h1I9yNCj6XPgYJ8Im3KT_G4hmMDFM7H9RUrYLl2o9XYyiS2nRrf4aJHa0UweBlAY4zcQG34bw2AMGCY53mwsSArf4Hs3rKu5GrGphuwYX0lHa7XEKMglwBWPWHI49q7-oNWr7aWwn1FnfaMfl4cQppCMtKESMNRKm_nb9Dsh5e0",
"diaspora_meta": "",
"location": "",
"coord": "",
"public_policy": "",
"comment_policy": "contacts",
"allow_cid": "",
"allow_gid": "",
"deny_cid": "",
"deny_gid": "",
"item_restrict": "0",
"item_flags": "0",
"item_private": "0",
"item_origin": "1",
"item_unseen": "0",
"item_starred": "0",
"item_uplink": "0",
"item_consensus": "0",
"item_wall": "1",
"item_thread_top": "1",
"item_notshown": "0",
"item_nsfw": "0",
"item_relay": "0",
"item_mentionsme": "0",
"item_nocomment": "0",
"item_obscured": "0",
"item_verified": "1",
"item_retained": "0",
"item_rss": "0",
"item_deleted": "0",
"item_type": "0",
"item_hidden": "0",
"item_unpublished": "0",
"item_delayed": "0",
"item_pending_remove": "0",
"item_blocked": "0"
}
}
item/full
Get all data associated with an item
abook
Connections
abconfig
Connection metadata (such as permissions)
perm_allowed
Check a permission for a given xchan
Hooks
Hooks ermöglichen es Plugins/Addons, sich an vielen Stellen in den Code „einzuhaken“ und das Verhalten zu ändern oder anderweitig unabhängige Aktionen durchzuführen, wenn eine Aktivität stattfindet oder auf bestimmte Datenstrukturen zugegriffen wird. Es gibt viele Hooks, die es Ihnen ermöglichen, sich an fast jeder Stelle in die Software einzuklinken und etwas anderes zu tun als das, was standardmäßig vorgesehen ist. Diesen Hooks werden zwei Variablen übergeben. Die erste ist die App-Struktur, die Details über den gesamten Zustand der Seitenanforderung enthält, während wir die resultierende Seite aufbauen. Die zweite ist eindeutig für den spezifischen Hook, der aufgerufen wird, und liefert spezifische Details darüber, was in der Software zum Zeitpunkt des Aufrufs des Hooks passiert.
Erstellter Index aller Hooks und der Dateien, die sie aufrufen
module_mod_aftercontent Allgemeiner Hook für jedes Modul, ausgeführt nach mod_content(). Ersetzen Sie „module“ durch den Namen des Moduls, z. B. „photos_mod_aftercontent“.
module_mod_content Allgemeiner Hook für ein beliebiges Modul, wird vor mod_content() ausgeführt. Ersetzen Sie 'module' durch den Modulnamen, z. B. 'photos_mod_content'.
module_mod_init Allgemeiner Hook für ein beliebiges Modul, wird vor mod_init() ausgeführt. Ersetzen Sie 'module' durch den Modulnamen, z. B. 'photos_mod_init'.
module_mod_post Allgemeiner Hook für ein beliebiges Modul, der vor mod_post() ausgeführt wird. Ersetzen Sie 'module' durch den Namen des Moduls, z. B. 'photos_mod_post'.
about_hook Aufgerufen von der Seite siteinfo
accept_follow Wird aufgerufen, wenn eine Verbindung akzeptiert wird (Freundschaftsanfrage)
account_downgrade Wird aufgerufen, wenn ein Konto abgelaufen ist, was auf eine mögliche Herabstufung auf die Serviceklasse „basic“ hinweist
Konto_Einstellungen Wird bei der Erstellung des Formulars für die Kontoeinstellungen aufgerufen
account_settings_post Wird bei der Buchung aus dem Kontoeinstellungsformular aufgerufen
tätigkeit_filter Wird bei der Erstellung der Liste der Filter für die Netzwerkseite aufgerufen
activity_mapper Wird bei der Bestimmung der Vorgangsart für die Übertragung aufgerufen.
activity_decode_mapper Wird aufgerufen, wenn die Vorgangsart für die Übertragung bestimmt wird.
activity_obj_mapper Wird aufgerufen, wenn der Objekttyp für die Übertragung bestimmt wird.
activity_obj_decode_mapper Wird bei der Bestimmung des Objekttyps für die Übertragung aufgerufen.
activity_order Wird bei der Generierung der Liste der Bestelloptionen für die Netzseite aufgerufen
addon_app_installed_filter Wird aufgerufen, wenn festgestellt wird, ob eine addon_app installiert ist
activity_received Wird aufgerufen, wenn eine Aktivität (Beitrag, Kommentar, Like, etc.) von einer Nomad-Quelle empfangen wurde
admin_aside Wird aufgerufen, wenn das Seitenleisten-Widget der Verwaltungsseite erzeugt wird
affinity_labels Wird verwendet, um alternative Beschriftungen für den Affinitätsslider zu generieren.
api_perm_is_allowed Wird aufgerufen, wenn perm_is_allowed() von einem API-Aufruf ausgeführt wird.
app_destroy Wird aufgerufen, wenn eine App gelöscht wird.
app_installed_filter Wird aufgerufen, wenn festgestellt wird, ob eine App installiert ist
app_menu Wird bei der Erstellung des app_menu Dropdowns aufgerufen (kann veraltet sein)
attach_delete Wird aufgerufen, wenn Anhänge aus der Tabelle attach gelöscht werden
atom_author Wird aufgerufen, wenn ein Autor- oder Eigentümer-Element für einen Atom ActivityStream-Feed erzeugt wird
atom_entry Wird bei der Erzeugung jedes Eintrags eines Atom ActivityStreams Feeds aufgerufen
atom_feed Wird bei der Generierung eines Atom ActivityStreams Feeds aufgerufen
atom_feed_end Wird aufgerufen, wenn die Erzeugung eines Atom ActivityStreams Feeds abgeschlossen ist
attach_upload_file Wird beim Hochladen einer Datei aufgerufen
authentifizieren Kann alternative Authentifizierungsmechanismen bereitstellen
author_is_pmable Wird aus dem Aktionsmenü des Threads aufgerufen, um festzustellen, ob wir dem Verfasser des Beitrags eine private E-Mail schicken können
bb2diaspora Wird bei der Umwandlung von bbcode in Markdown aufgerufen
bbcode Wird am Ende der Konvertierung von bbcode in HTML aufgerufen
bbcode_filter Wird zu Beginn der Umwandlung von bbcode in HTML aufgerufen
bb_translate_video Wird aufgerufen, wenn eingebettete Dienste aus bbcode-Videoelementen extrahiert werden (wird selten verwendet)
build_pagehead Wird bei der Erstellung des HTML-Seitenkopfes aufgerufen
can_comment_on_post Wird aufgerufen, wenn entschieden wird, ob ein Kommentarfeld für einen Beitrag angezeigt werden soll oder nicht
change_channel Wird aufgerufen, wenn man sich bei einem Channel anmeldet (entweder während des Logins oder danach über den Channelmanager)
channel_remove Wird aufgerufen, wenn ein Channel entfernt wird
channel_links Wird bei der Generierung des Link: HTTP-Header für einen Kanal
channel_settings Wird aufgerufen, wenn die Seite mit den Channel-Einstellungen angezeigt wird
chat_message Wird aufgerufen, um eine Chat-Nachricht zu erstellen.
chat_post Wird aufgerufen, wenn eine Chat-Nachricht gepostet wurde.
check_account_email Überprüft die bei einer Kontoregistrierung angegebene E-Mail
check_account_invite Validierung eines Einladungscodes bei der Verwendung von Website-Einladungen
check_account_password Dient der Kontrolle von Kontopasswörtern (Mindestlänge, Einbeziehung von Zeichensätzen usw.)
check_channelallowed Wird verwendet, um die Sperrlisten für schwarze und weiße Kanäle außer Kraft zu setzen oder zu umgehen.
check_siteallowed Wird verwendet, um die schwarzen/weißen Sperrlisten für Websites außer Kraft zu setzen oder zu umgehen.
collect_public_recipients Wird verwendet, um eine Liste von Empfängern zu erstellen, an die eine öffentliche Nachricht gesendet werden soll.
comment_buttons Wird aufgerufen, wenn die Bearbeitungsschaltflächen für Kommentare angezeigt werden.
comments_are_now_closed Wird aufgerufen, wenn entschieden wird, ob ein Kommentarfeld für einen Beitrag angezeigt werden soll oder nicht
connect_premium Wird aufgerufen, wenn eine Verbindung zu einem Premium-Kanal hergestellt wird
connection_remove Wird aufgerufen, wenn eine Verbindung gelöscht/entfernt wird
connector_settings Wird aufgerufen, wenn die Seite mit den Features/Addon-Einstellungen aufgerufen wird
construct_page Allgemeiner Hook zur Bereitstellung von Inhalten für bestimmte Seitenbereiche. Wird aufgerufen, wenn die Comanche-Seite erstellt wird.
kontakt_block_ende Wird bei der Erstellung des „Connections“-Widgets in der Seitenleiste aufgerufen
kontakt_edit Wird bei der Bearbeitung einer Verbindung über connedit aufgerufen
kontakt_edit_post Wird aufgerufen, wenn ein Beitrag an connedit gesendet wird
Kontakt_Auswahl_Optionen Veraltet/unbenutzt
content_security_policy Wird vor der Ausgabe des Content-Security-Policy-Headers aufgerufen
conversation_start Wird zu Beginn des Renderns einer Konversation (Nachricht oder Nachrichtensammlung oder Stream) aufgerufen
cover_photo_content_end Wird aufgerufen, nachdem ein Titelbild hochgeladen wurde
create_identity Wird bei der Erstellung eines Channels aufgerufen
cron Wird aufgerufen, wenn eine geplante Aufgabe (Poller) ausgeführt wird
cron_daily Wird aufgerufen, wenn täglich geplante Aufgaben ausgeführt werden
cron_weekly Wird aufgerufen, wenn wöchentlich geplante Aufgaben ausgeführt werden
crypto_methods Wird aufgerufen, wenn eine Liste von Kryptoalgorithmen in der lokal bevorzugten Reihenfolge erstellt wird
daemon_addon Wird aufgerufen, wenn der erweiterbare Hintergrund-Daemon aufgerufen wird
daemon_master_release Wird zu Beginn der Verarbeitung von \Zotlabs\Daemon\Master::Release() aufgerufen
directory_item Wird beim Erzeugen einer Verzeichnisliste für die Anzeige aufgerufen
discover_channel_webfinger Wird aufgerufen, wenn ein Webfinger-Lookup durchgeführt wird
display_item Wird für jedes Element aufgerufen, das in einem Gesprächsfaden angezeigt wird
display_settings Wird vom Einstellungsmodul aufgerufen, wenn der Abschnitt 'Anzeigeeinstellungen' angezeigt wird
display_settings_post Wird aufgerufen, wenn ein Beitrag aus dem Formular „Einstellungen anzeigen“ des Einstellungsmoduls angezeigt wird
donate_contributors Wird vom 'donate'-Addon aufgerufen, wenn eine Liste von Spendenempfängern erstellt wird
donate_plugin wird vom 'donate'-Addon aufgerufen
donate_sponsoren aufgerufen durch das 'donate'-Addon
dreport_ist_storable wird vor dem Speichern eines Dreport-Datensatzes aufgerufen, um festzustellen, ob er gespeichert werden soll
dreport_process wird für jeden gültigen Lieferbericht aufgerufen
dropdown_extras Hinzufügen zusätzlicher Elemente zum Dropdown-Menü, wenn Element/Threads angezeigt werden.
drop_item wird aufgerufen, wenn ein 'item' entfernt wird
encode_object wird aufgerufen, wenn ein Objekt für die Übertragung kodiert wird.
enotify wird vor jeder Benachrichtigung aufgerufen
enotify_mail wird aufgerufen, wenn eine Benachrichtigungs-E-Mail gesendet wird
enotify_store wird beim Speichern eines Benachrichtigungsdatensatzes aufgerufen
enotify_store_end wird aufgerufen, nachdem ein Benachrichtigungsdatensatz gespeichert wurde
event_created wird aufgerufen, wenn ein Ereignisdatensatz erstellt wird
event_store_event wird aufgerufen, wenn ein Ereignisdatensatz erstellt oder aktualisiert wird
event_updated wird aufgerufen, wenn ein Ereignisdatensatz geändert wird
externals_url_select wird aufgerufen, wenn eine Liste mit zufälligen Websites erstellt wird, von denen öffentliche Beiträge abgerufen werden sollen
feature_enabled wird aufgerufen, wenn 'feature_enabled()' verwendet wird
merkmal_settings wird von der Einstellungsseite aufgerufen, wenn man 'addon/feature settings' besucht
feature_settings_post wird von der Einstellungsseite aufgerufen, wenn von 'addon/feature settings' aus gepostet wird
fetch_and_store wird aufgerufen, um das Filtern von 'entschlüsselten' Elementen vor der Speicherung zu ermöglichen.
file_thumbnail wird aufgerufen, wenn Miniaturbilder für die Wolkenseite im Modus „Kacheln anzeigen“ erzeugt werden
folgen wird aufgerufen, wenn eine Follow-Operation stattfindet
follow_from_feed wird aufgerufen, wenn eine Follow-Operation in einem RSS-Feed stattfindet
follow_allow wird aufgerufen, bevor die Ergebnisse einer Follow-Operation gespeichert werden
gender_selector wird bei der Erstellung der Dropdown-Liste „Geschlecht“ aufgerufen (erweitertes Profil)
gender_selector_min wird bei der Erstellung der Dropdown-Liste „Geschlecht“ aufgerufen (normales Profil)
generate_map wird aufgerufen, um den HTML-Code für die Anzeige eines Orts auf der Karte nach Koordinaten zu erzeugen
generate_named_map wird aufgerufen, um die HTML-Datei für die Anzeige eines Kartenorts anhand eines Textes zu erzeugen
get_all_api_perms Wird aufgerufen, wenn die Berechtigungen für API-Verwendungen abgerufen werden
get_all_perms wird aufgerufen, wenn get_all_perms() verwendet wird
get_best_language wird aufgerufen, wenn die bevorzugte Sprache für die Seite ausgewählt wird
get_default_export_sections Wird aufgerufen, um die Standardliste der zu exportierenden Funktionsdatengruppen in identity_basic_export() zu erhalten
get_features Wird aufgerufen, wenn get_features() aufgerufen wird
get_photo Wird aufgerufen, wenn Fotoinhalte (außer Profilfotos) in mod_photo abgerufen werden
get_profile_photo Wird aufgerufen, wenn der Inhalt des lokalen Profilfotos in mod_photo abgerufen wird
get_role_perms Wird aufgerufen, wenn get_role_perms() aufgerufen wird, um Berechtigungen für benannte Berechtigungsrollen zu erhalten
global_permissions Wird aufgerufen, wenn die globale Berechtigungsliste erstellt wird
home_content Wird von mod_home aufgerufen, um den Inhalt der Home-Seite zu ersetzen
home_init Wird von der Funktion home_init() der Homepage aufgerufen
hostxrd Wird bei der Erzeugung von .well-known/hosts-meta für „old webfinger“ aufgerufen (wird vom Diaspora-Protokoll verwendet)
html2bb_video Wird aufgerufen, wenn die html2bbcode-Übersetzung verwendet wird, um eingebettete Medien zu behandeln
html2bbcode Wird bei der Verwendung der html2bbcode-Übersetzung aufgerufen
identität_basic_export Wird aufgerufen, wenn die Basisinformationen eines Channels zur Sicherung oder Übertragung exportiert werden.
import_autor_xchan Wird aufgerufen, wenn ein Autor eines Beitrags mit xchan_hash gesucht wird, um sicherzustellen, dass er einen xchan-Eintrag auf unserer Website hat
import_channel Wird aufgerufen, wenn ein Kanal aus einer Datei oder einer API-Quelle importiert wird
import_directory_profile Wird aufgerufen, wenn die Lieferung einer Profilstruktur aus einer externen Quelle verarbeitet wird (normalerweise für die Speicherung in Verzeichnissen)
import_xchan Wird bei der Verarbeitung des Ergebnisses von zot_finger() aufgerufen, um das Ergebnis zu speichern
item_photo_menu Wird aufgerufen, wenn die Liste der Aktionen erzeugt wird, die mit einem angezeigten Konversationselement verbunden sind
item_store Wird aufgerufen, wenn item_store() einen Datensatz vom Typ item speichert
item_stored Wird aufgerufen, nachdem item_store() einen Datensatz des Typs item in der Datenbank gespeichert hat.
item_custom Wird aufgerufen, bevor item_store() einen Datensatz des Typs item speichert (damit Addons ITEM_TYPE_CUSTOM-Elemente verarbeiten können).
item_store_update Wird aufgerufen, wenn item_store_update() aufgerufen wird, um einen gespeicherten Eintrag zu aktualisieren.
item_stored_update Wird aufgerufen, nachdem item_store_update() ein gespeichertes Element aktualisiert hat.
item_translate Wird von item_store und item_store_update aufgerufen, nachdem die Sprache des Beitrags automatisch erkannt wurde.
jot_networks Wird aufgerufen, um die Liste der zusätzlichen Post-Plugins zu generieren, die aus dem ACL-Formular aktiviert werden sollen
jot_tool Veraltet und möglicherweise überflüssig. Ermöglicht das Hinzufügen von Aktionsschaltflächen zum Beitragseditor.
jot_tpl_filter Wird aufgerufen, um Vorlagenvariablen vor der Ersetzung in jot.tpl zu filtern.
jot_header_tpl_filter Wird aufgerufen, um Vorlagenvariablen vor der Ersetzung in jot_header.tpl zu filtern.
legal_webbie Wird aufgerufen, um eine Kanaladresse zu validieren
legal_webbie_text Bietet eine Erklärung der Text-/Zeichenbeschränkungen für legal_webbie()
load_pdl Wird aufgerufen, wenn wir eine PDL-Datei oder eine Beschreibung laden
local_dir_update Wird aufgerufen, wenn eine Verzeichnisaktualisierung von einem Channel auf dem Verzeichnisserver verarbeitet wird
location_move Wird aufgerufen, wenn einem UNO-Channel ein neuer Standort mitgeteilt wurde (was auf eine Verschiebung und nicht auf einen Klon hinweist)
protokolliert Wird aufgerufen, wenn die Authentifizierung auf irgendeine Weise erfolgreich war
Logger Wird aufgerufen, wenn ein Eintrag in die Logdatei der Anwendung gemacht wird
logging_out Wird bei der Abmeldung aufgerufen
login_hook Wird bei der Generierung des Anmeldeformulars aufgerufen
magic_auth Wird bei der Verarbeitung einer magic-auth-Sequenz aufgerufen
markdown_to_bb Wird bei der Verarbeitung der Markdown-Konvertierung aufgerufen
match_webfinger_location Wird bei der Verarbeitung von Webfinger-Anfragen aufgerufen
magic_auth_openid_success Wird aufgerufen, wenn ein magic-auth aufgrund von openid-Anmeldedaten erfolgreich war
magic_auth_success Wird aufgerufen, wenn ein magic-auth erfolgreich war
main_slider Wird bei der Generierung des Affinitätswerkzeugs aufgerufen
marital_selector Wird aufgerufen, wenn die Auswahlliste für das Dropdown-Menü des Profils „Familienstand“ erstellt wird (erweitertes Profil)
marital_selector_min Wird bei der Erstellung der Auswahlliste für das Dropdown-Profil „Familienstand“ aufgerufen (normales Profil)
module_loaded Wird aufgerufen, wenn ein Modul erfolgreich für eine URL-Anfrage auf dem Server lokalisiert wurde.
mood_verbs Wird bei der Erstellung der Liste der Stimmungen aufgerufen
nav Wird bei der Erstellung der Navigationsleiste aufgerufen
network_content_init Wird beim Laden des Inhalts für die Netzwerkseite aufgerufen
netzwerk_ping Wird bei einer Ping-Anfrage aufgerufen
netzwerk_zu_name Veraltet
notifier_end Wird aufgerufen, wenn eine Zustellschleife abgeschlossen ist
notifier_hub Wird aufgerufen, wenn ein Hub zugestellt wurde
notifier_normal Wird aufgerufen, wenn der Notifizierer für eine 'normale' Zustellung aufgerufen wird
notifier_process Wird aufgerufen, wenn der Notifizierende eine Nachricht/Ereignis verarbeitet
obj_verbs Wird bei der Erstellung der Liste der für das Profil „Dinge“ verfügbaren Verben aufgerufen.
oembed_action Wird aufgerufen, wenn entschieden wird, ob eine Oembed-Url gefiltert, blockiert oder genehmigt werden soll
oembed_probe Wird aufgerufen, wenn eine Suche nach Oembed-Inhalten durchgeführt wird.
other_encapsulate Wird aufgerufen, wenn Inhalte verschlüsselt werden, für die der Algorithmus unbekannt ist (siehe auch crypto_methods)
other_unencapsulate Wird aufgerufen, wenn Inhalte entschlüsselt werden, deren Algorithmus unbekannt ist (siehe auch crypto_methods)
page_content_top Wird aufgerufen, wenn wir eine Webseite generieren (vor dem Aufruf der Modul-Content-Funktion)
page_end Wird aufgerufen, nachdem wir den Seiteninhalt generiert haben
page_header Wird bei der Generierung der Navigationsleiste aufgerufen
page_meta Wird bei der Generierung der Metadaten im Seitenkopf aufgerufen.
parse_atom Wird aufgerufen, wenn ein Atom/RSS-Feed-Element geparst wird.
parse_link Wird aufgerufen, wenn eine URL abgefragt wird, um daraus einen Beitrag zu generieren
pdl_selector Wird bei der Erstellung einer Layoutauswahl in einem Formular aufgerufen
perm_is_allowed Wird während perm_is_allowed() aufgerufen, um festzustellen, ob eine Berechtigung für diesen Kanal und Beobachter erlaubt ist
permissions_create Wird aufgerufen, wenn ein Bucheintrag (Verbindung) erstellt wird
permissions_update Wird aufgerufen, wenn eine Berechtigungsaktualisierung übertragen wird
permit_hook Wird aufgerufen, bevor ein registrierter Hook tatsächlich ausgeführt wird, um festzustellen, ob er erlaubt oder blockiert werden soll
personal_xrd Wird bei der Generierung der persönlichen XRD für „old webfinger“ (Diaspora) aufgerufen
photo_post_end Wird nach dem Hochladen eines Fotos aufgerufen
photo_upload_begin Wird aufgerufen, wenn versucht wird, ein Foto hochzuladen
photo_upload_end Wird aufgerufen, wenn ein Foto-Upload verarbeitet wurde
photo_upload_file Wird aufgerufen, um alternative Dateinamen für einen Upload zu generieren
photo_upload_form Wird aufgerufen, wenn ein Foto-Upload-Formular generiert wird
photo_view_filter Wird aufgerufen, bevor die Daten an die photo_view-Vorlage übergeben werden
poke_verbs Wird bei der Erstellung der Liste der Aktionen für das Modul „poke“ aufgerufen
post_local Wird aufgerufen, wenn ein Artikel auf diesem Rechner über mod/item.php eingestellt wurde (auch über API)
post_local_end Wird aufgerufen, wenn ein lokaler Postvorgang abgeschlossen ist
post_local_start Wird aufgerufen, wenn ein lokaler Postvorgang beginnt
post_mail Wird aufgerufen, wenn eine Mail-Nachricht verfasst wurde
post_mail_end Wird aufgerufen, wenn eine Mail-Nachricht zugestellt wurde
post_remote Wird aufgerufen, wenn eine Aktivität von einem anderen Standort eintrifft
post_remote_end Wird nach der Verarbeitung einer Remote-Post aufgerufen
post_remote_update Wird bei der Verarbeitung eines entfernten Beitrags aufgerufen, der eine Bearbeitung oder Aktualisierung beinhaltet
post_remote_update_end Wird nach der Verarbeitung eines entfernten Beitrags aufgerufen, der eine Bearbeitung oder Aktualisierung beinhaltete
prepare_body Wird aufgerufen, wenn der HTML-Code für ein angezeigtes Konversationsobjekt generiert wird.
prepare_body_final Wird nach der Generierung des HTML für ein angezeigtes Konversationselement aufgerufen
prepare_body_init Wird vor der Generierung des HTML für ein angezeigtes Konversationselement aufgerufen
privacygroup_extras Wird vor der Generierung des HTML für die Bearbeitungsoptionen der Privacy Group aufgerufen
privacygroup_extras_delete Wird aufgerufen, nachdem die Privatsphärengruppe gelöscht wurde.
privacygroup_extras_post Wird aufgerufen, wenn das Formular zur Bearbeitung der Privatsphärengruppe abgeschickt wird.
proc_run Wird beim Aufruf von PHP-Unterprozessen aufgerufen
process_channel_sync_delivery Wird aufgerufen, wenn ein 'Sync-Paket' mit Struktur- und Tabellenaktualisierungen von einem Channel-Clone angenommen wird.
profile_advanced Wird bei der Generierung einer erweiterten Profilseite aufgerufen
profil_edit Wird bei der Bearbeitung eines Profils aufgerufen
profil_foto_inhalt_ende Wird bei der Änderung eines Profilfotos aufgerufen
profil_post Wird beim Posten eines bearbeiteten Profils aufgerufen
profile_sidebar Wird aufgerufen, wenn die „Kanal-Seitenleiste“ oder das Miniprofil erstellt wird
profile_sidebar_enter Wird vor der Erstellung der 'Channel Sidebar' oder des Miniprofils aufgerufen
queue_deliver Wird aufgerufen, wenn eine Nachricht in der Warteschlange zugestellt wird
register_account Wird aufgerufen, wenn ein Konto erstellt worden ist
render_location Wird aufgerufen, um eine ineraktive Inline-Map zu erzeugen
replace_macros Wird vor dem Aufrufen des Vorlagenprozessors aufgerufen
reverse_magic_auth Wird vor dem Aufruf von reverse magic auth aufgerufen, um Sie auf Ihre eigene Website zu schicken, damit Sie sich auf dieser Website authentifizieren können
Einstellungen_Konto Wird bei der Erstellung des Formulars für die Kontoeinstellungen aufgerufen
einstellungen_form Wird bei der Erstellung des Formulars für die Channel-Einstellungen aufgerufen
einstellungen_post Wird bei der Buchung aus dem Formular für die Kanaleinstellungen aufgerufen
sexpref_selector Wird aufgerufen, wenn ein Dropdown-Menü für sexuelle Präferenzen erstellt wird (erweitertes Profil)
sexpref_selector_min Wird aufgerufen, wenn eine Auswahlliste der sexuellen Präferenzen erstellt wird (normales Profil)
smilie Wird beim Übersetzen von Emoticons aufgerufen
status_editor Wird bei der Erstellung des status_editor aufgerufen.
stream_item Wird für jedes Element aufgerufen, das über conversation() zur Anzeige gerendert wird
system_app_installed_filter Wird aufgerufen, wenn festgestellt wird, ob eine System-App installiert ist.
tagged Wird aufgerufen, wenn eine Lieferung verarbeitet wird, die dazu führt, dass Sie getaggt werden
thumbnail Wird beim Erzeugen von Miniaturbildern für die Kachelansicht des Cloud-Speichers aufgerufen
update_unseen Wird vor dem automatischen Markieren von im Browser geladenen Sendungen, die gesehen wurden, aufgerufen
validate_channelname Wird verwendet, um die von einem Kanal verwendeten Namen zu validieren
webfinger Wird beim Besuch des Dienstes webfinger (RFC7033) aufgerufen
well_known Wird beim Zugriff auf die speziellen '.well-known'-Site-Adressen aufgerufen
wiki_preprocess Wird aufgerufen, bevor Markdown-/Bbcode-Prozessoren für Wikiseiten ausgeführt werden
zot_best_algorithm Wird bei der Aushandlung von Verschlüsselungsalgorithmen mit entfernten Sites aufgerufen
zid Wird aufgerufen, wenn die zid des Beobachters zu einer URL hinzugefügt wird
zid_init Wird bei der Authentifizierung eines Besuchers aufgerufen, der zid verwendet hat
zot_finger Wird aufgerufen, wenn ein Nomad-Infopaket angefordert wurde (dies ist unser Webfinger-Erkennungsmechanismus)
Noch zu organisierende Informationen
Hier ist, wie Sie sich uns anschließen können. Richten Sie sich zunächst ein funktionierendes Git-Paket auf dem System ein, auf dem Sie entwickeln werden.
Erstellen Sie Ihr eigenes Github-Konto.
Sie können das Red-Repository von https://framagit.org/hubzilla/core.git forken/klonen. Folgen Sie den Anweisungen hier: http://help.github.com/fork-a-repo/, um Ihren eigenen Tracking-Fork auf github zu erstellen und zu verwenden.
Gehen Sie dann auf Ihre Github-Seite und erstellen Sie einen „Pull request“, wenn Sie bereit sind, uns mitzuteilen, dass Ihre Arbeit zusammengeführt werden soll.
Wichtig
Bitte ziehen Sie alle Änderungen aus dem Projekt-Repository ein und fügen Sie sie mit Ihrer Arbeit zusammen **, bevor** Sie einen Pull-Request erstellen. Wir behalten uns das Recht vor, jeden Patch abzulehnen, der zu einer großen Anzahl von Merge-Konflikten führt. Dies gilt insbesondere für Sprachübersetzungen, bei denen wir möglicherweise nicht in der Lage sind, die feinen Unterschiede zwischen den konfligierenden Versionen zu verstehen.
Testen Sie außerdem Ihre Änderungen. Gehen Sie nicht davon aus, dass eine einfache Korrektur nicht etwas anderes kaputt macht. Bitten Sie nach Möglichkeit einen erfahrenen Red-Entwickler, den Code zu überprüfen.
Wie man Hubzilla thematisiert Dies ist eine kurze Dokumentation über das, was ich beim Versuch, das Aussehen von Hubzilla zu ändern, herausgefunden habe.
Zuerst müssen Sie ein neues Thema erstellen. Dieses befindet sich in /view/theme, und ich habe mich für „redbasic“ entschieden, da es im Moment das einzig verfügbare ist. Nehmen wir an, ich nenne es . Oh, und vergessen Sie nicht, die Funktion _init in /php/theme.php in _init() statt redbasic_init() umzubenennen.
Wenn Sie nun Javascript- oder CSS-Dateien hinzufügen müssen, fügen Sie sie zu /js oder /css hinzu und „registrieren“ sie dann in _init()
durch head_add_js('file.js')
und head_add_css('file.css')
.
Jetzt werden Sie wahrscheinlich eine Vorlage ändern wollen. Diese sind in /view/tpl ODER view//tpl zu finden. Alles, was Sie tun müssen, ist, das, was Sie ändern wollen, in das tpl-Verzeichnis Ihres Themes zu kopieren.
Wir sind ziemlich entspannt, wenn es um Entwickler geht. Wir haben nicht viele Regeln. Einige von uns sind überlastet, und wenn Sie helfen wollen, lassen wir Sie gerne helfen. Wenn Sie sich jedoch an ein paar Richtlinien halten, wird der Prozess reibungsloser und die Zusammenarbeit einfacher. Wir haben Entwickler aus der ganzen Welt mit unterschiedlichen Fähigkeiten, unterschiedlichen kulturellen Hintergründen und unterschiedlicher Geduld. Unsere oberste Regel ist es, andere zu respektieren. Manchmal ist das schwierig, und manchmal haben wir sehr unterschiedliche Ansichten darüber, wie die Dinge funktionieren sollten, aber wenn sich jeder bemüht, werden wir gut miteinander auskommen.
Hier ist, wie Sie sich uns anschließen können.
Besorgen Sie sich zunächst ein funktionierendes Git-Paket auf dem System, auf dem Sie die Entwicklung durchführen werden.
Erstellen Sie Ihr eigenes Github-Konto.
Du kannst das Hubzilla-Repository von https://framagit.org/hubzilla/core.git forken/klonen. Folgen Sie den Anweisungen hier: http://help.github.com/fork-a-repo/, um Ihren eigenen Tracking-Fork auf github zu erstellen und zu verwenden.
Gehen Sie dann auf Ihre Github-Seite und erstellen Sie eine „Pull-Anfrage“, wenn Sie bereit sind, uns mitzuteilen, dass Ihre Arbeit zusammengeführt werden soll.
Wichtig
Bitte ziehen Sie alle Änderungen aus dem Projekt-Repository ein und fügen Sie sie mit Ihrer Arbeit zusammen **, bevor** Sie einen Pull-Request erstellen. Wir behalten uns das Recht vor, jeden Patch abzulehnen, der zu einer großen Anzahl von Merge-Konflikten führt. Dies gilt insbesondere für Sprachübersetzungen, bei denen wir möglicherweise nicht in der Lage sind, die feinen Unterschiede zwischen den konfligierenden Versionen zu verstehen.
Testen Sie außerdem Ihre Änderungen. Gehen Sie nicht davon aus, dass eine einfache Korrektur nicht etwas anderes kaputt macht. Bitten Sie nach Möglichkeit einen erfahrenen Red-Entwickler, den Code zu überprüfen.
Weitere Dokumentation finden Sie auf den Github-Wikiseiten unter: https://github.com/friendica/red/wiki
Konsensbildung
Codeänderungen, die einen offensichtlichen Fehler beheben, sind ziemlich einfach. Wenn Sie zum Beispiel auf „Speichern“ klicken und das, was Sie zu speichern versuchen, nicht gespeichert wird, ist es ziemlich offensichtlich, was das beabsichtigte Verhalten sein sollte. Bei der Entwicklung von Funktionsanfragen kann es vorkommen, dass eine große Anzahl von Community-Mitgliedern davon betroffen ist und dass andere Mitglieder der Community nicht mit der Notwendigkeit der Funktion oder der von Ihnen vorgeschlagenen Implementierung einverstanden sind. Es kann sein, dass sie etwas nicht als Fehler oder als wünschenswerte Funktion ansehen.
Wir ermutigen zur Konsensbildung innerhalb der Gemeinschaft, wenn es um eine Funktion geht, die als kontrovers angesehen werden könnte oder wenn es keine einstimmige Entscheidung gibt, dass die vorgeschlagene Funktion der richtige Weg ist, um die Aufgabe zu erfüllen. Die erste Anlaufstelle für Ihre Ideen ist Channel One]. Andere haben vielleicht Anregungen oder können Sie auf Aspekte Ihres Konzepts hinweisen, die in unserem Umfeld problematisch sein könnten. Vielleicht stoßen Sie aber auch auf Widerstand gegen Ihren Plan. Das bedeutet nicht, dass Sie aufhören und/oder die Funktion ignorieren sollten. Hören Sie sich die Bedenken der anderen an und versuchen Sie, alle Probleme bei der Umsetzung zu lösen.
Es gibt Stellen, an denen Widerstände nicht ausgeräumt werden können. In diesen Fällen sollten Sie in Erwägung ziehen, Ihre Funktion optional zu machen oder ein nicht standardmäßiges Verhalten vorzusehen, das ausdrücklich aktiviert werden muss. Diese Technik kann oft verwendet werden, wenn eine Funktion eine bedeutende, aber nicht einstimmige Unterstützung hat. Diejenigen, die die Funktion wünschen, können sie einschalten, und diejenigen, die sie nicht wollen, können sie ausgeschaltet lassen. Wenn eine Funktion andere Netzwerke oder Websites nutzt oder nur von einer kleinen Minderheit der Gemeinschaft als wünschenswert angesehen wird, sollten Sie in Erwägung ziehen, die Funktion über ein Addon oder Plugin verfügbar zu machen. Auch hier gilt, dass diejenigen, die die Funktion nicht wünschen, sie auch nicht installieren müssen. Plugins sind relativ einfach zu erstellen und „Haken“ können leicht hinzugefügt oder geändert werden, wenn die aktuellen Haken nicht das tun, was nötig ist, damit Ihr Plugin funktioniert.