Definitionen und Algorithmen in TeamSpeak 3
Dieses Dokument enthält einige allgemeine Funktionen aus TeamSpeak. Das meiste bezieht sich aufs Query-Interface.
Inhaltsverzeichnis
Codecs
Zunächst einmal ein paar Formeln. Diese setzen MathML-Unterstützung in deinem Browser voraus und enthalten folgende Größen (unter der Annahme, der Codec sei eine feste aber beliebige Kombination aus Codecname und Qualität):
- bOffiziell(Codec, Latenz) = Bitrate laut TeamSpeak-Client (beachte, dass die Latenz seit 3.0.10 nicht mehr einberechnet wird)
- bRoh(Codec) = Roh-Bitrate (ziehe von der im Client seit 3.0.10 angezeigten Bitrate 2250 Byte/s ab)
- d(Codec, Latenz) = Größe eines Pakets
- dMax = Maximum Transmission Unit
- t = Latenz
- tMax(Codec) = Maximale Latenz
Da die Darstellung von MathML bei Verwendung von Klammern im Firefox nicht richtig funktioniert, habe ich einfach mal drauf verzichtet, Parameter zu verwenden. Man denke sie sich bitte entsprechend der obigen Liste dazu.
Bitraten-Dreisatz | Anwendungspaketgröße | Paketgrößengrenzwert (MTU) | Opus-Maximallatenz | Speex/CELT-Maximallatenz |
---|---|---|---|---|
Zur MTU von etwa 527 Byte: Im TeamSpeak-Client vor 3.0.10 ergibt sich für die dort vorhandenen Codec-Latenz-Kombinationen stets d≤526. Dies wird nur ein einziges Mal erreicht, und zwar bei Speex Ultra-Breitband, Qualität 4, Latenz 260 ms. Das nächsthöhere denkbare d bei bRoh aus der Tabelle unten wäre 529. Auch diese Kombination wäre einzigartig (Speex Ultra-Breitband, minimale Qualität, Latenz 880 ms), aber im Client nicht vorhanden. Also muss die MTU zwischen 526 und 528 liegen.
Warum diese Zahl? Erst einmal gibt es eine andere seltsame Zahl, die immer wieder auftaucht: 45. Nennen wir es die Overhead-Konstante. Der Overhead eines Voice-Pakets beträgt 16 Byte auf Anwendungsebene (dazu kommen noch 12 Byte IPv4, 8 Byte UDP), ist also viel geringer. Die 45 werden in obiger Formel allerdings pro Voice-Paket gerechnet, weshalb ich das nicht wirklich verstehe.
Aber warum jetzt 527±1? Zu Zeiten von Modem und ISDN gab es eine MTU von 576 Byte (Ethernet hat 1500, PPPoE 1492). Nehmen wir jetzt eine TS-MTU von 528 an und dass Transportschicht-Header nicht Teil davon sind. Nehmen wir außerdem an, dass TeamSpeak IPv6 verwendet. Dessen Headergröße ist 40 Byte, die von UDP 8. 528 und 48 macht zusammen 576 Byte.
Werte für bRoh in Byte/s:
Codecname \ Qualität | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
---|---|---|---|---|---|---|---|---|---|---|---|
Speex Schmalband (8 kHz) | 300 | 500 | 750 | 1000 | 1400 | 1900 | 2300 | 3100 | |||
Speex Breitband (16 kHz) | 500 | 750 | 1000 | 1250 | 1600 | 2100 | 2600 | 3000 | 3500 | 4300 | 5300 |
Speex Ultra-Breitband (32 kHz) | 550 | 950 | 1200 | 1450 | 1850 | 2350 | 2800 | 3200 | 3700 | 4500 | 5500 |
CELT Mono (48 kHz) | 4000 | 5000 | 6000 | 8000 | 12000 | ||||||
Opus Voice | 550 | 1050 | 1550 | 2050 | 2600 | 3100 | 3600 | 4100 | 4650 | 5150 | 5650 |
Opus Music | 900 | 1800 | 2700 | 3600 | 4500 | 5400 | 6300 | 7200 | 8100 | 9000 | 9900 |
Die Bitrate von Opus ist nicht konstant sondern variabel. Sein Hintergrundrauschen zu übertragen benötigt etwas weniger Bandbreite als beispielsweise zu sprechen oder zu summen. Beim Standard-Opus-Voice-Preset (Qualität 6) wichen die Bitrate beispielsweise um jeweils etwa 250 Byte/s von bOffiziell ab. Vermutlich hat man deshalb die Maximallatenz auf 20 ms festgesetzt, da man keinen exakten Grenzwert angeben kann. Die maximal denkbare nominale Paketgröße d beträgt 243 Byte, bis zur Grenze von 528 Byte ist somit noch genug Platz – sehr viel mehr als an Abweichung realistisch wäre: Im erwähnten Fall waren die Codecdaten je Paket laut obiger Tabelle 72 Byte groß und die genannten Abweichungen betrugen 5 Byte pro Paket. Das entspricht etwa ca. ±7 %, während man selbst bei Opus Music Qualität 10 eine Abweichung bei den Codecdaten um ca. +144 % benötigen würde, um dMax zu erreichen.
Rechteberechnung
Wer die offizielle Dokumentation des Rechtesystems nicht mag (z.B. weil sie zu lang ist) oder gerne ein paar Spezialfälle erklärt bekommen möchte, findet hier meine technisierte Erklärung des Rechtesystems.
Wert
Es gibt fünf Gründe, warum ein Client Rechte haben kann, die der folgenden Liste entsprechend von oben nach unten abgearbeitet werden (sprich der unterste ist der wichtigste).
- Servergruppen: siehe dazu den übernächsten Abschnitt zum Negiertflag
- Client (Serverebene)
- Channel: gilt nicht, wenn ein Skipflag gesetzt wurde
- Channelgruppe: gilt nicht, wenn ein Skipflag gesetzt wurde
- Client (Channelebene)
Alle folgenden Erklärungen gelten immer nur für ein einzelnes Recht. Für jedes Recht wird einzeln bestimmt, was wirkt.
permoverview
und permfind
benennen die Tiers nullterminiert.
Skip
Mit Skip werden Channel- und Channelgruppenrechte übersprungen. Um zu bestimmen, ob ein Client nach der Auswertung von Servergruppen- und Server-Clientrechten ein Skipflag bei einem Recht hat, geht man für jedes einzelne Recht wie folgt vor:
- Ist ein Clientrecht gesetzt, gilt dessen Skipflag.
- Ist kein Clientrecht gesetzt, zählt das Skipflag der wirkenden Servergruppe.
- Gibt es Gruppen mit Negiertflag, fallen alle anderen Gruppen weg.
- Wirken immer noch mehrere Servergruppen, zählt die Gruppe mit der niedrigsten ID.
Skip überspringt keine Channel-Clientrechte.
Negiert
Normalerweise gilt bei Servergruppen der jeweils höchste Wert.
Ist bei irgendeiner Servergruppe eines Clients das Negiertflag gesetzt, zählen für das Recht nur die Servergruppen mit Negiertflag bei diesem Recht. Von diesen Gruppen wirkt die niedrigste. Dies gilt insbesondere auch dann, wenn Servergruppen ohne Negiertflag niedriger sind als das die niedrigste mit Negiertflag. Damit gilt auch folgender Spezialfall: Hat ein Client nur bei einer seiner Gruppen ein Negiertflag, wirkt diese immer.
Vergabe (Grant)
Gibt an, wie viel i_client_permission_modify_power
man braucht, um ein Recht zu ändern. Dafür muss der Client dieses Vergabe-Recht für das entsprechende Recht ungleich 0 besitzen.
Das Vergaberecht erhält man, indem man den ersten Buchstaben des Originalrechts durch i_needed_permission_modify_power
ersetzt. Da sich das Vergaberecht immer auf sein Originalrecht der dazugehörigen Quelle bezieht, sind Skip und Negiert sinn- und wirkungslos. permget
führt die Berechnungen aber trotzdem durch.
b_client_skip_channelgroup_permissions
Wird dieses Recht in den ersten beiden Tiers gesetzt (die Berechnung erfolgt wie zuvor genannt), werden alle Channelgruppen- sowie – entgegen des Namens – alle Channel-Rechte ignoriert. Es funktioniert also genau wie wenn jedes Skip gesetzt wäre.
Widersprechen sich für ein Recht Skip und b_client_skip_channelgroup_permissions
, wird stets geskippt.
Query-Verbindung
Verbindungsauf- und abbau
Query benutzt eine einfache TCP-Verbindung. Man kann zwar einen Telnet-Client verwenden, die über das bloße Austauschen von Zeichen herausgehenden Funktionen von Telnet werden jedoch vom TeamSpeak-Server nicht unterstützt.
Die folgende Tabelle zeigt, in welchen Versionen man mit welchen Mitteln den Timeout verhindern kann:
Versionen | Timeout | Absatz | Leerzeichen+Absatz | Befehl+Absatz |
---|---|---|---|---|
– 3.2.0 | 10 Minuten | ja | ja | ja |
3.3.0-beta1 – 3.3.0-beta2 | 5 Minuten | nein | nein | nein |
3.3.0-beta3 – 3.3.1-steadyclock | 5 Minuten | nein | nein1 | ja |
3.3.1 – | 5 Minuten | nein | ja | ja |
Anmerkung: Ich bin mir nicht sicher, zu welcher Gruppe 3.3.0-beta2 gehört. Ich hatte sie ursprünglich zur Gruppe mit 3.3.0-beta3 gezählt, basierend auf dieser Ankündigung müsste die obige Tabelle richtig sein.
- Fußnoten:
- 1 = Dies ist die offiziell von TeamSpeak empfohlene Art und Weise, den Timeout zu verhindern. Der Server nimmt anschließend allerdings keine Befehle mehr entgegen und der Client bleibt für immer auf dem Server (bis der Server neugestartet wird), was zum Exploiten verwendet werden kann. TeamSpeak schien nicht so sicher zu sein (vgl. andere Posts im verlinkten Thread), ob das ein Bug oder ein Feature sein soll, hat es aber dann wie in der Tabelle angegeben geändert.
Trennt man die Verbindung regulär mittels TCP und hat einen Server ausgewählt, bekommen die anderen Clients sofort ein Timeout mitgeteilt, auch wenn das nicht stimmt, da man die Verbindung ja normal getrennt hat. Daher sollte man quit
verwenden.
Zeichensatz
TeamSpeak unterstützt Unicode nicht richtig. Es wird lediglich UCS-2 (Universal Coded Character Set in 2 bytes, entspricht der Basic Multilingual Plane, kurz BMP) unterstützt. Viele Piktogramme, beispielsweise fast alle Smileys, auf denen auch Messenger-Apps wie WhatsApp aufbauen, sind in UCS-2 nicht enthalten.
Offiziellen Angaben zufolge verwendet TeamSpeak UTF-8. Das ist gelogen. TeamSpeaks Handy-Apps verwenden ausdrücklich kein UTF-8 sondern CESU-8. Bis Serverversion 3.0.11.3 akzeptiert TeamSpeak auf diese Weise auch Zeichen, die von UCS-2 nicht abgedeckt werden, kann damit jedoch nicht umgehen und zerstört sich somit die Datenbank, sodass ihr Snapshots von solchen Servern nicht mehr einspielen könnt.
CESU-8 ist ein nachträglich standardisiertes Fehlverhalten von Software, die nur UCS-2 unterstützt und versucht, mithilfe von UTF-16-Surrogates kodierte Zeichen in UTF-8 umzuwandeln. Da UTF-16 und UCS-2 inzwischen nicht mehr dasselbe sind, entsteht statt UTF-8 ein Text in CESU-8. Gibt sich Query-Client einen Namen, der CESU-8-kodierte Zeichen außerhalb von UCS-2 enthält, fliegen alle Clients mit „convert error“ vom Server, auch wenn sie den Query-Client nicht sehen können.
Als Absatzzeichen wird die Folge 0x0A
0x0D
benutzt, also die Windows-Folge falschrum. Warum das so ist, ist mir schleierhaft.
Die maximale Länge einer Zeile beträgt (ohne Absatz) 9203 Bytes. Dieses Limit gilt nicht für die 12 Befehle zum Hinzufügen und Entfernen von Rechten sowie serversnapshotdeploy
. Es gibt ein paar Befehle, wo das stört.
Zeichensatz-Kompatibilität
Software | Zeichenvorrat | akzeptierte Kodierungen | verwendete Kodierung | Datenbank-Format |
---|---|---|---|---|
YaTQA (1.3.3.5b) | Unicode | UTF-8 | UTF-8 | UTF-16LE als Hex |
YaTQA (bis 1.3.3.5, 1.3.3.5c bis 3.1) | Unicode | CESU-8 | UTF-8 | UTF-16LE als Hex |
YaTQA (ab 3.1b) | Unicode | UTF-8, CESU-8 | UTF-8 | UTF-16LE als Hex |
TeamSpeak-Desktop-Client (bis unbekannt) | nur BMP | unbekannt | kleinster gemeinsamer Nenner | unbekannt |
TeamSpeak-Desktop-Client (ab unbekannt) | Unicode | UTF-8 | UTF-8 | UTF-8 |
TeamSpeak-Mobile-Client (Generation 1) | Unicode | CESU-8 | CESU-8 | unbekannt |
TeamSpeak-Mobile-Client (Generation 2) | Unicode | UTF-8, CESU-8 | UTF-8 | unbekannt |
TeamSpeak-Server (bis 3.0.11.3) | Unicode | CESU-8 | CESU-8 | CESU-8 |
TeamSpeak-Server (3.0.11.4 bis 3.1.3) | nur BMP | kleinster gemeinsamer Nenner | CESU-8 (falls schon in DB) | unverändert |
TeamSpeak-Server (ab 3.2.0) | BMP+Emojis | UTF-8 | UTF-8 | |
TeaSpeak-Server | Unicode | UTF-8, CESU-8 | UTF-8 | UTF-8 |
TeamSpeak-Server filtern UTF-8-Zeichen heraus, die nicht durch die BMP abgedeckt sind (falls der String zu kurz wird, gibt es invalid parameter size
). CESU-8 führt seit 3.0.11.4 zu einem invalid parameter
(Code 1538) beim Sender, zuvor zu convert error
beim Empfänger. Neuere TeamSpeak-Clients (ca. ab 2016) wandeln Zeichen aus ungültigen UTF-8-Sequenzen (dazu gehört auch CESU-8) in ein Ersetzungszeichen (�) je enthaltenem Byte um.
Wie man sieht, können die aktuellen Mobile-Clients, YaTQA ab 3.1b und der TeaSpeak-Server Nachrichten unabhängig vom Zeichensatz empfangen. Außerdem halten sich diese Programme daran, dass das TeamSpeak3-Protokoll die Verwendung von UTF-8 vorsieht. Die Verwendung von Unicode auf TeamSpeak-Servern ist seit 3.0.11.4 für keine Client-Art mehr möglich.
TeamSpeak 3.2.0 – BMP + Emojis
TeamSpeak unterstützt in 3.2.0 neben der BMP noch folgende Blöcke der SIP (von den anderen 15 Ebenen wird nichts unterstützt):
- 🇦
U+1F1E6
–🇿U+1F1FF
Dies sind die Zeichen, von denen Zweierkombinationen (bzw. mehr für die Landesteile des Vereinigten Königreichs) eine Flagge ergeben, z.B. 🇩🇪. TeamSpeak unterstützt damit nur einen Teilbereich von etwa 10% des BlocksU+1F100
–U+1F1FF
Enclosed Alphanumeric Supplement, obwohl beispielsweise Firefox 🆎U+1F18E
(Blutgruppe AB) und 🆑U+1F191
–🆚U+1F19A
als Emoji darstellt. Weitere bedeutende Zeichen in dem von TeamSpeak nicht unterstützten Block sind die anderen Blutgruppen 🅰U+1F170
, 🅱U+1F171
und 🅾U+1F17E
(im Amerikanischen wird die Blutgruppe 0 stattdessen Blutgruppe O genannt) sowie das Parkplatz-Symbol 🅿U+1F17F
, für die in Windows 7 eine Schriftart mitgeliefert werden. - 🌀
U+1F300
–🙏U+1F64F
Hierin befinden sich die Blöcke 🌀U+1F300
–🗿U+1F5FF
Miscellaneous Symbols and Pictographs und 😀U+1F600
–🙏U+1F64F
Emoticons. - 🚀
U+1F680
–U+1F6FF
Entspricht dem Unicode-Block Transport and Map Symbols. Zwischen diesem und dem letzten unterstützten liegt übrigens der relativ neue Block Ornamental Dingbats. U+1F900
–U+1F9FF
Entspricht dem Unicode-Block Supplemental Symbols and Pictographs. Zwischen diesem und dem letzten unterstützten liegen einige Blöcke, die als Emojis zählen.
Folgende Bereiche aus der BMP fehlen:
U+0
–U+8
U+B
–U+C
U+E
–U+1F
U+7F
–U+9F
SteuerzeichenU+200E
–U+200F
Schreibrichtungszeichen, vermutlich um zu verhindern, dass der Chat gestört wird. Es gibt allerdings noch ein ähnliches beiU+061C
, das erlaubt ist.U+2028
–U+2029
U+202A
–U+202E
Schreibrichtungszeichen, vermutlich um zu verhindern, dass der Chat gestört wird. Es gibt allerdings noch ein paar ähnliche beiU+2066
–U+2069
, die erlaubt sind.U+FFF9
–U+FFFB
AnmerkungenU+FFFC
–U+FFFD
ErsetzungszeichenU+FFFE
–U+FFFF
not a character
Bilder
TeamSpeak unterstützt folgende Formate:
bmp
- Windows Bitmap
gif
- Graphics Interchange Format
jpg
,jpeg
- Joint Photographic Experts Group
png
- Portable Network Graphics (APNG wird nicht unterstützt)
pbm
- Portable Bitmap (ASCII und binär)
pgm
- Portable Graymap (ASCII und binär)
ppm
- Portable Pixmap (ASCII und binär)
xbm
- X BitMap
xpm
- X PixMap (nur XPM Version 1)
svg
(seit v3.1.5)- Scalable Vector Graphics (Tiny 1.2)
Die Liste gilt für alle Orte, an denen TeamSpeak Bilder unterstützt.
Icons
Icons können nicht animiert sein. Die maximalen Abmessungen betragen 16×16.
Der Dateiname eines Icons ist sein CRC32. Der Algorithmus ist mit dem aus PNG und ZIP identisch. YaTQA ruft deshalb auch einfach die CRC-Funktion in pngdelphi
auf. Das Unix-Programm cksum
verwendet ein anderes Polynom.
Der Name kann vom Client allerdings frei bestimmt werden. Es gibt Software, die für Icon-Dateinamen Zufallszahlen nimmt. Das ist aber nicht empfehlenswert.
Datentypen
Die Datentypen, die für Icon-IDs verwendet werden, sind nicht einheitlich, sondern je nach Kontext unterschiedlich.
Kontext | Parameter | Lesen | Schreiben |
---|---|---|---|
*permlist *addperm | permsid=i_icon_id value= | Vorzeichen | Vorzeichen |
clientlist -icon clientinfo | client_icon_id= | Vorzeichen | nur über clientaddperm |
clientdbinfo | client_icon_id= | 0 (defekt) | nur über clientaddperm |
serverinfo serveredit | virtualserver_icon_id= | Vorzeichen | vorzeichenlos |
channellist -icon channelinfo channeledit* | channel_icon_id | Vorzeichen | vorzeichenlos* |
* = channeledit
bewirkt eine semipermanente Änderung, die bei einem Neustart des Servers verloren geht. Benutze lieber die Rechtefunktion.
channelcreate
kann keine Icons schreiben (1538 invalid parameter
).
Avatare
Die maximalen Abmessungen betragen 300×300.
Der Client lädt den Avatar eines Nutzers immer dann herunter, wenn dessen client_flag_avatar
einen neuen Wert erhält. Dies ist der MD5-Hash und kein Flag. Query-Clients, die eine normale UID haben, können ihren eigenen Avatar hochladen und diesen String für sich mit clientupdate
setzen.
Die Avatare liegen platt im Channel mit der ID 0 rum. Der Dateiname leitet sich von der Globalen ID des Besitzers ab (nicht von client_flag_avatar
). Man dekodiert den Base64-String (also die Globale ID) und stellt diese 20 Bytes ähnlich der Hex-Darstellung dar. Allerdings wird nicht das normale [0-9a-f] sondern [a-p] zum Anzeigen genommen. clientinfo
und clientdbinfo
geben diese Darstellung als client_base64HashClientUID
zurück, eine Bezeichnung die völliger Schwachsinn ist.
Die fremden Avatare können nicht per ftinitupload
überschrieben werden, der eigene aber schon, wenn man sich in TS mit „Server Query Login“ einen Account erstellt hat und diesen nutzt. Man kann auch den Avatar auf Servern ändern, die nicht der eigene Heimatserver sind, wenn man mit der UID des Query-Accounts schon mal dort war. Ist der Parameter size
als serveradmin
größer 0, wird eine Fehlermeldung zurückgegeben. War er 0, stürzte bis Version 3.0.1-pre1 die gesamte Instanz ab.
War ein Benutzer lange Zeit inaktiv und wurde sein Datenbankeintrag gelöscht, ist der Besitzer übrigens auch nicht mehr auffindbar (man kann ja einfach die oben genannte – bijektive – Abbildung rückgängig machen und über die dann erhaltene globale ID die Datenbank-ID und danach widerum die Datenbank-Infos abrufen). Die Avatare bleiben in dem Fall allerdings erhalten und nehmen Platz auf dem Server weg. Seit 3.0.3 kann man Avatare aktiver(!) Benutzer löschen und ab 3.0.5 werden bei der Datenbanksäuberung auch die Avatare inaktiver Benutzer gelöscht. Eine Lösung für Avatare von Benutzern, die vor dieser Aktualisierung (auf Version 3.0.5) wegen Inaktivität gelöscht wurden, bleibt uns TeamSpeak allerdings schuldig.
Beispiel für die Berechnung einer client_base64HashClientUID
Hier ein Beispiel für die Berechnung anhand meiner eigenen UID yGRWD2BOWPC6xSROXoi7U8NAljI=
.
UID | y | G | R | W | ... | l | j | I | = | |||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Binär | 1 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 1 | 1 | 0 | ... | 1 | 0 | 0 | 1 | 0 | 1 | 1 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | – |
Dezimal | 12 | 8 | 6 | 4 | 5 | 6 | ... | 9 | 6 | 3 | 2 | – | ||||||||||||||||||||||||||||||||
Hex | C | 8 | 6 | 4 | 5 | 6 | ... | 9 | 6 | 3 | 2 | – | ||||||||||||||||||||||||||||||||
Datei | m | i | g | e | f | g | ... | j | g | d | c | – |
Der Algorithmus ist somit auch problemlos umkehrbar.
Schnappschüsse
Schnappschüsse enthalten am Anfang der Datei einen Hash. Hierbei handelt es sich um einen SHA1-Hash der restlichen UTF-8-kodierten Daten (ohne Absatz am Ende).
Beim Einspielen von Schnappschüssen laufen intern offenbar normale Query-Befehle ab. Werden diese geändert, kommt es zu Fehlern. Packt man beispielsweise serveradmin
in eine Servergruppe, kann ein solcher Schnappschuss auf neueren Servern nicht mehr eingespielt werden, die es serveradmin
mehr erlauben, einer Servergruppe beizutreten. Da er bestehende Mitgliedschaften nicht kontrolliert werden, produzieren Server, die nach dem Hinzufügen von serveradmin
zu einer Servergruppe aktualisiert wurden, ungültige Schnappschüsse.
Client-Cache
Die Benennung der Unterordner von cache
und chats
ist die in Base64 kodierte Server-UID, welche an sich bereits Base64-kodiert ist. Durch die erneute Kodierung können die nicht alphanumerischen Zeichen 62 und 63 nicht mehr auftreten. Damit wird verhindert, dass Zeichen 63 (Schrägstrich) zu ungültigen Dateinamen führt. Für Zeichen 63 müssten nämlich in der Binärkodierung des ursprünglichen Base64 in ASCII sechs Einsen aufeinanderfolgen können, es gibt aber nicht einmal die Möglichkeit für fünf Einsen hintereinander, sodass auch das Plus nicht auftreten kann.
In den Unterordnern befinden sich bei cache
Avatare (clients
) und Icons (icons
). Bei den Chats befinden sich private Chats im Unterordner clients
. Die dortigen Dateinamen sind die ebenfalls (ein weiteres Mal) in Base64-kodierten UIDs der Gesprächspartner. Bei reinen Query-Accounts wird entsprechend einfach serveradmin
oder ServerQuery
in Base64 kodiert, da es sich dabei um die UIDs handelt.
TXT
-Chatlogs enthalten nur Chats und dazugehörigen Informationen, HTML
-Dateien hingegen alle möglichen Benachrichtigungen aus dem Log. Da den HTML-Dateien ein Header (und auch sonst alles außer dem Inhalt) fehlt, musst du deinen Browser ggf. manuell auf UTF-8 stellen, um sie zu lesen. Bilder zu Beginn der Zeilen werden fehlen.
BBcode
Ein vor die öffnende eckige Klammer gestelllter Backslash verhindert das Parsen des darauffolgenden Tags.
Die maximale Stack-Größe beträgt 20. Es gibt glücklicherweise nur 10 Tags, die gleichzeitig aktiv sein können, sodass das Limit prinzipiell nichts verhindert, was sonst nicht möglich wäre. Wer aber seine Tags konsequent nicht schließt, kommt ziemlich schnell an das Limit. Das selbstschließende Tag ([hr]
) wird zwar nicht zum Limit addiert, kann nicht genutzt werden, wenn 20 Elemente auf dem Stack sind. Auch Absätze werden dann nur als Leerzeichen dargestellt. Listeneinträge zählen auch als Element; ihr End-Tag wird automatisch vor weiteren Listeneinträgen und am Ende er Liste ergänzt. Das alles lässt darauf schließen, dass maximal 20 daraus generierte HTML-Tags aktiv sein können.
Inline-Elemente
[b]Text[/b]
- fett
[i]Text[/i]
- kursiv
[u]Text[/u]
- unterstrichen
[color=X]Text[/color]
- Farbe (siehe unten)
[url=URL]Text[/url]
[url]URL[/url]
- Link
Block-Elemente
Block-Elemente können nur in Channelbeschreibungen verwendet werden.
[hr]
- Horizontale Trennleiste
[size=X]Text[/size]
- Ändert die Größe zu einer bestimmten Höhe in Punkten (siehe unten).
[img]URL{/img]
- Bild
[left]Text[/left]
- linksbündig
[center]Text[/center]
- zentriert
[right]Text[/right]
- rechtsbündig
[list][*]Text[/list]
- Liste (Schachtelung möglich)
Rein interne Links
(Wird noch ergänzt.)
Namen sind in UTF-8 zu kodieren und anschließend URL-Encoding zu verwenden. Яedeemer + Kiwi wäre also %D0%AFedeemer%20%2B%20Kiwi
. Client-UIDs (nicht jedoch Server-UIDs!) werden unverändert übernommen, selbst wenn sie URL-Encoding haben müssten.
client://{Client-ID}/{Client-UID}~{Name}
- Client-ID: Client-ID im Serverbaum, 0 beim Einfügen in Channelbeschreibungen.
- Client-UID: Globale ID des Clients
- Name: Name. Keine Ahnung, was das soll.
- Diese Links können durch Drag und Drop von Clients in Eingabefelder erstellt werden.
channelid://{Channel-ID}
- Channel-ID: Channel-ID, 0 für Server
ts3file://{Serveraddresse}?port={Serverport}&serverUID={ServerUID}&channel={ChannelID}&path={Pfad mit Schrägstrich am Ende und Anfang}&filename={Dateiname}&isDir={0=Datei, 1=Ordner}&size={Größe in Bytes}&fileDateTime={Änderungsdatum, Unix-Timestamp}
- Keine Ahnung, wofür man das alles braucht. Man kann diesen Link extern verwenden, es öffnet sich aber lediglich der TeamSpeak-Client. Mehr passiert nicht. Die Serveradresse wird als einziger String nicht escapet. Das führt seit 3.1.6 zu Problemen, da &-Zeichen gültige Zeichen in Server-Nicknames sind.
ts3image://{Dateiname}?channel={ChannelID}&path={Pfad mit Schrägstrich am Ende und Anfang}
- Es wird überhaupt kein Escaping verwendet. Weder für Zeichen noch für Nicht-ASCII-Buchstaben.
Extern funktionsfähige Links
Diese werden bei Installation von TeamSpeak in der Registry angelegt.
ts3server://{Serveradresse}?port={Serverport}&nickname={Nickname}&password={Serverpasswort}&channel={Channel-Name}&cid={Channel-ID}&channelpassword{Channel-Passwort}&token={Token}&addbookmark={Favoriten-Name}
- Nickname: Namen des Benutzers setzen, den dieser auf dem Server haben soll, wenn er sich mit dem Link verbindet
- ...
- Channel-ID: Laut TeamSpeak-FAQ geht die Channel-ID vor, wenn sowohl sie als auch der Channel-Name angegeben ist.
- ...
(Quelle)
Der notwendige Grad des Escapings unterscheidet sich zwischen intern und extern: Und-Zeichen werden mit vorangestelltem Backslash escapet. Zwingend zu escapen sind für externe Programme (oder beim Einfügen in Windows+R) nur in UTF-8 zu kodierende Zeichen (UTF-8 allein ohne Escaping funktioniert nicht), Prozentzeichen und Und-Zeichen. Auch die Escape-Sequenz des Und-Zeichens muss selbst nicht noch in URL-Encoding escaped werden. Innerhalb des TeamSpeak-Clients muss aber zumindest das Und-Zeichen escapet werden, eventuell auch noch weitere. Zudem erkennt der Client keine intern verwendeten Links mit nicht escapeten Leerzeichen (auch nicht mit URL-Tag), die man bei einem externen Aufruf weglassen kann, wenn man Anführungszeichen als umschließende Quantifizierer verwendet. Wird der TeamSpeak-Client neu gestartet, verschwinden allerdings die Quantifizierer und solche Links funktionieren nicht mehr, obwohl der Client sich neu verbindet. Die Nutzung als Quantifizierer, die man beim Aufruf eines Links nicht so einfach verhindern kann, dürfte auch der einzige Grund sein, warum Anführungszeichen überhaupt zu escapen sind. Links, die nicht zu quantifizieren sind, dürften als direkte Parameter des Prozesses nicht erfordern, dass Anführungszeichen escapet werden.
Zeichen | extern/minimal | intern minimal | Freund einladen |
---|---|---|---|
Leerzeichen | Leerzeichen | %20 | %20 |
! | ! | ! | %21 |
" | %22 | " oder %22 | %22 |
# | %23 | # | %23 |
$ | $ | $ | %24 |
% | %25 | %25 | %25 |
& | \& oder %26 | %26 oder \%26 | %5C%26 |
' | ' | ' | %27 |
( | ( | ( | %28 |
) | ) | ) | %29 |
* | * | * | %2A |
+ | + | + | %2B |
, | , | , | %2C |
/ (Name) | \/ oder \\/ | \/ oder \\/ | %5C%5C%2F |
/ (Trenner) | / | / | %2F |
: | : | : | %3A |
; | ; | ; | %3B |
= | = | = | %3D |
? | ? | ? | %3F |
@ | @ | @ | %40 |
[ | [ | [ | %5B |
\ | \ | \ | %5C%5C |
] | ] | ] | %5D |
{ | { | { | %7B |
| | | | | | %7C |
} | } | } | %7D |
UCS-2 | ist verpflichtend in UTF-8 zu kodieren und mit % zu escapen |
Zum Schrägstrich: Der mit „Name“ bezeichnete Schrägstrich ist Teil eines Channelnamens. Der als „Trenner“ bezeichnete Schrägstrich trennt Channel und Subchannel. Channelnamen sind nur pro Ebene eindeutig.
Das Anführungszeichen nicht zu escapen bricht automatisch erkannte Links an dieser Stelle ab. Manuell erzeugter BBCode funktioniert. Er scheint Zeichen zu geben, bei denen das umgekehrt ist. Die obige Tabelle bezieht sich zunächst einmal auf die automatische Erkennung.
YaTQA verwendet das extern-minimale-System aus der ersten Spalte.
Farben
Als Schreibweise eignen sich #123456
und #123
sowie folgende Namen:
Farbname | Farbrepäsentation |
---|---|
aliceblue | |
antiquewhite | |
aqua | |
aquamarine | |
azure | |
beige | |
bisque | |
black | |
blanchedalmond | |
blue | |
blueviolet | |
brown | |
burlywood | |
cadetblue | |
chartreuse | |
chocolate | |
coral | |
cornflowerblue | |
cornsilk | |
crimson | |
cyan | |
darkblue | |
darkcyan | |
darkgoldenrod | |
darkgray | |
darkgreen | |
darkgrey | |
darkkhaki | |
darkmagenta | |
darkolivegreen | |
darkorange | |
darkorchid | |
darkred | |
darksalmon | |
darkseagreen | |
darkslateblue | |
darkslategray | |
darkslategrey | |
darkturquoise | |
darkviolet | |
deeppink | |
deepskyblue | |
dimgray | |
dimgrey | |
dodgerblue | |
firebrick | |
floralwhite | |
forestgreen | |
fuchsia | |
gainsboro | |
ghostwhite | |
gold | |
goldenrod | |
gray | |
green | |
greenyellow | |
grey | |
honeydew | |
hotpink | |
indianred | |
indigo | |
ivory | |
khaki | |
lavender | |
lavenderblush | |
lawngreen | |
lemonchiffon | |
lightblue | |
lightcoral | |
lightcyan | |
lightgoldenrodyellow | |
lightgray | |
lightgreen | |
lightgrey | |
lightpink | |
lightsalmon | |
lightseagreen | |
lightskyblue | |
lightslategray | |
lightslategrey | |
lightsteelblue | |
lightyellow | |
lime | |
limegreen | |
linen | |
magenta | |
maroon | |
mediumaquamarine | |
mediumblue | |
mediumorchid | |
mediumpurple | |
mediumseagreen | |
mediumslateblue | |
mediumspringgreen | |
mediumturquoise | |
mediumvioletred | |
midnightblue | |
mintcream | |
mistyrose | |
moccasin | |
navajowhite | |
navy | |
oldlace | |
olive | |
olivedrab | |
orange | |
orangered | |
orchid | |
palegoldenrod | |
palegreen | |
paleturquoise | |
palevioletred | |
papayawhip | |
peachpuff | |
peru | |
pink | |
plum | |
powderblue | |
purple | |
red | |
rosybrown | |
royalblue | |
saddlebrown | |
salmon | |
sandybrown | |
seagreen | |
seashell | |
sienna | |
silver | |
skyblue | |
slateblue | |
slategray | |
slategrey | |
snow | |
springgreen | |
steelblue | |
tan | |
teal | |
thistle | |
tomato | |
turquoise | |
violet | |
wheat | |
white | |
whitesmoke | |
yellow | |
yellowgreen |
Außerdem gibt es noch transparent
, das in YaTQA nicht unterstützt werden kann, da die Bearbeitungskomponente von Windows nur RGB-Werte speichert, jedoch außer Standardfarbe (clWindowText
in Delphi) keine Rollen wie „Hintergrundfarbe des Eingabefeldes“ (clWindow
in Delphi), die dann in die RGB-Farbe umgewandelt wird, die der Nutzer vorgesehen hat (also meist weiß).
Die Farbe rebeccapurple wird derzeit nicht unterstützt, ebenso currentColor und inherit.
Wie alle Farbnamen, die nur aus Groß- und Kleinbuchstaben (Groß- und Kleinschreibung wird ignoriert) bestehen (auch Zahlen sind nicht erlaubt) und deren Bedeutung der Client nicht kennt, wird auch RebeccaPurple vom TS-Client als schwarz oder Standard (da bin ich mir nicht sicher) interpretiert. YaTQA interpretiert ihm unbekannte Farbnamen nicht, um im Falle von nicht implementierten Farbnamen keinen Datenverlust zu verursachen. Dadurch verschiebt sich im WYSIWYG-Editor von YaTQA das Ende von Farben, weil das End-Tag des ungültigen Namens als End-Tag des letzten gültigen Namens interpretiert wird.
Der TS3Client verhält sich auf diese Weise bei allen Angaben, die keine gültigen Hex-Codes sind und nicht nur aus Groß- und Kleinbuchstaben bestehen, YaTQA wie gesagt auch bei nicht bekannten Namen aus Groß- und Kleinbuchstaben.
Vor (nicht eingeschlossen) Clientversion 3.0.0 gab es wesentlich mehr Farben, basierend auf den X11-Farbnamen. Die meisten dieser wurden mit genanntem Update entfernt, sodass nur noch die W3C-Farbnamen blieben.
- Folgende Farben wurden hinzugefügt:
lime
silver - W3C-Farbnamen (rechts), die unter X11 (links) anders aussahen:
gray > gray
green > green
grey > grey
maroon > maroon
purple > purple
(Dadurch ist jetzt dunkelgrau wesentlich heller als grau.) - Alle Farbnamen mit Zahlen (dazu gehörten unter anderem 101 Graustufen und vier weitere Abstufungen für die meisten Farben) wurden entfernt. Zudem wurden folgende Farben entfernt:
lightgoldenrod
lightslateblue
navyblue
violetred
Schriftgrößen
Mit Clientversion 3.0.3 wurde die BBcode-Interpretation geändert, nämlich von HTML-Größeneinheiten wie in <font size="X">
zu Punkten (<span style="font-size:Xpt;">
).
Die angekündigte Legacy-Interpretation [size=+X]
, X ∈ {1, ..., 7}, funktioniert nicht. Fängt der Parameter mit + an, wird die Schriftgröße zurückgesetzt, egal was danach kommt (ob gar nichts, eine Zahl, ein kleiner Roman, ...).
Größen von Clients vor (nicht eingeschlossen) Clientversion 3.0.3 (erste Spalte):
alt (HTML) | entspricht Pixel | entspricht Punkt |
---|---|---|
-1 | 9px | 7pt |
andere negative Werte | 8px | 6pt |
0 | 8px | 6pt |
1 | 8px | 6pt |
2 | 9px | 7pt |
3 | 11px (Standard) | 8pt |
4 | 13px | 10pt |
5 | 17px | 13pt |
6 | 22px | 17pt |
andere positive Werte | 26px | 19~20pt |
+ gefolgt von irgendwas | 11px (Standard) | 8pt |
Da die Größen einer Pixelgröße entsprechen, die etwas genauer als die dann eingeführten Punktgrößen sind, ist im Falle von HTML-Größe 7 keine verlustfreie Umrechnung in das Punkt-System möglich!