Zesstra | 10341b8 | 2020-09-12 13:02:54 +0200 | [diff] [blame] | 1 | /* /std/channel_supervisor.c |
Zesstra | 0caa8e4 | 2020-08-11 22:51:59 +0200 | [diff] [blame] | 2 | // |
Zesstra | 10341b8 | 2020-09-12 13:02:54 +0200 | [diff] [blame] | 3 | // Der Standard-Supervisor fuer Ebenen. Sollte von allen Objekten geerbt |
| 4 | // werden, die Zugriffsrechte fuer Ebenen verwalten ("das Sagen" auf der Ebene |
| 5 | // haben). |
| 6 | // Das Objekt braucht ggf. eine eUID zum Dateizugriff. Zum Setzen dieser ist |
| 7 | // der Erbende verantwortlich. |
| 8 | // Standardmaessig wird /p/daemon/channeld.init[.testmud] eingelesen. |
| 9 | // Erbende koennen ihre Daten auch voellig anderweitig einlesen/ermitteln und |
| 10 | // Rechte voellig anders pruefen statt gegen ein Level zu pruefen. |
| 11 | // Das einzig wichtige fuer die Rechtepruefung ist die Funktion |
| 12 | // ch_check_access(), die vom CHANNELD gerufen wird. Sie muss 1 zurueckgeben, |
| 13 | // falls die Aktion erlaubt wird und 0 anderenfalls. |
| 14 | // |
| 15 | // Benutzung fuer Standardebenen: |
| 16 | // Dieses Objekt erben, ggf. eine eUID setzen und ch_read_init_file() |
| 17 | // rufen. |
| 18 | // Zusaetzlich sollte dieses Objekt aber auch ein Namen haben, weil es |
| 19 | // damit auf den Ebenen angezeigt wird. (D.h. minimal name() und Name() |
| 20 | // sollten implementiert/geerbt sein.) |
| 21 | */ |
Zesstra | 0caa8e4 | 2020-08-11 22:51:59 +0200 | [diff] [blame] | 22 | |
Zesstra | 10341b8 | 2020-09-12 13:02:54 +0200 | [diff] [blame] | 23 | #pragma strict_types, rtt_checks |
Zesstra | 0caa8e4 | 2020-08-11 22:51:59 +0200 | [diff] [blame] | 24 | #pragma no_shadow, no_clone |
| 25 | |
| 26 | #include <wizlevels.h> |
Zesstra | 10341b8 | 2020-09-12 13:02:54 +0200 | [diff] [blame] | 27 | #include <regexp.h> |
Zesstra | 0caa8e4 | 2020-08-11 22:51:59 +0200 | [diff] [blame] | 28 | #include "/p/daemon/channel.h" |
| 29 | #include <living/description.h> |
| 30 | |
Zesstra | 0caa8e4 | 2020-08-11 22:51:59 +0200 | [diff] [blame] | 31 | /* Speichert Sende- und Empfangslevel sowie Flags zu den einzelnen Channeln. |
Zesstra | 10341b8 | 2020-09-12 13:02:54 +0200 | [diff] [blame] | 32 | mapping ch_access_data = ([ string channel_name : (<ch_access>) ]) */ |
| 33 | struct ch_access { |
| 34 | int recv; |
| 35 | int send; |
| 36 | int flags; |
| 37 | }; |
| 38 | // nicht nosave hier, damit man es zwar nosave erben kann, aber ggf. auch |
| 39 | // speichern kann |
| 40 | protected mapping ch_access_data = m_allocate(0, 1); |
Zesstra | 0caa8e4 | 2020-08-11 22:51:59 +0200 | [diff] [blame] | 41 | |
Zesstra | 10341b8 | 2020-09-12 13:02:54 +0200 | [diff] [blame] | 42 | // oeffentlicher Name des Supervisors |
| 43 | protected string ch_sv_name = "Generischer SV"; |
| 44 | |
| 45 | protected void ch_set_sv_name(string newname) |
| 46 | { |
| 47 | ch_sv_name = newname; |
| 48 | } |
| 49 | |
| 50 | public varargs string name(int casus,int demon) |
| 51 | { |
| 52 | return ch_sv_name; |
| 53 | } |
| 54 | |
| 55 | public varargs string Name(int casus, int demon) |
| 56 | { |
| 57 | return capitalize(name( casus, demon )||""); |
| 58 | } |
| 59 | |
| 60 | // ch_check_access() prueft die Zugriffsberechtigungen auf Ebenen. |
Zesstra | 0caa8e4 | 2020-08-11 22:51:59 +0200 | [diff] [blame] | 61 | // |
Zesstra | 10341b8 | 2020-09-12 13:02:54 +0200 | [diff] [blame] | 62 | // Wird vom CHANNELD gerufen. |
Zesstra | 0caa8e4 | 2020-08-11 22:51:59 +0200 | [diff] [blame] | 63 | // Gibt 1 zurueck, wenn Aktion erlaubt, 0 sonst. |
Zesstra | 0caa8e4 | 2020-08-11 22:51:59 +0200 | [diff] [blame] | 64 | // |
| 65 | // Verlassen (C_LEAVE) ist immer erlaubt. Die anderen Aktionen sind in zwei |
| 66 | // Gruppen eingeteilt: |
| 67 | // 1) RECV. Die Aktionen dieser Gruppe sind Suchen (C_FIND), Auflisten |
| 68 | // (C_LIST) und Betreten (C_JOIN). |
| 69 | // 2) SEND. Die Aktion dieser Gruppe ist zur Zeit nur Senden (C_SEND). |
| 70 | // |
| 71 | // Aktionen werden zugelassen, wenn Spieler/MagierLevel groesser ist als die |
| 72 | // fuer die jeweilige Aktionsgruppe RECV oder SEND festgelegte Stufe. |
Zesstra | 10341b8 | 2020-09-12 13:02:54 +0200 | [diff] [blame] | 73 | // Handelt es sich um eine Magierebene (<accessflags> enthaelt das Flag |
| 74 | // CH_ACCESS_WIZARD), muss die Magierstufe des Spielers groesser sein als die |
| 75 | // Mindeststufe der Ebene. Ansonsten wird gegen den Spielerlevel geprueft. |
| 76 | // Enthaelt <accessflags> das Flag CH_ACCESS_NOGUEST, darf die Ebene nicht von |
| 77 | // Gaesten benutzt werden. |
Zesstra | 0caa8e4 | 2020-08-11 22:51:59 +0200 | [diff] [blame] | 78 | // |
| 79 | // Wenn RECV_LVL oder SEND_LVL auf -1 gesetzt ist, sind die Aktionen der |
| 80 | // jeweiligen Gruppen komplett geblockt. |
| 81 | |
Zesstra | 10341b8 | 2020-09-12 13:02:54 +0200 | [diff] [blame] | 82 | public int ch_check_access(string ch, object user, string cmd) |
Zesstra | 0caa8e4 | 2020-08-11 22:51:59 +0200 | [diff] [blame] | 83 | { |
Zesstra | 10341b8 | 2020-09-12 13:02:54 +0200 | [diff] [blame] | 84 | struct ch_access access = ch_access_data[ch]; |
| 85 | // <user> ist Gast, es sind aber keine Gaeste zugelassen? Koennen wir |
Zesstra | 0caa8e4 | 2020-08-11 22:51:59 +0200 | [diff] [blame] | 86 | // direkt ablehnen. |
Zesstra | 10341b8 | 2020-09-12 13:02:54 +0200 | [diff] [blame] | 87 | if ((access.flags & CH_ACCESS_NOGUEST) && ({int})user->QueryGuest()) |
Zesstra | 0caa8e4 | 2020-08-11 22:51:59 +0200 | [diff] [blame] | 88 | return 0; |
| 89 | |
| 90 | // Ebenso auf Magier- oder Seherebenen, wenn ein Spieler anfragt, der |
| 91 | // noch kein Seher ist. |
Zesstra | 10341b8 | 2020-09-12 13:02:54 +0200 | [diff] [blame] | 92 | if ((access.flags & CH_ACCESS_WIZARD) && query_wiz_level(user) < SEER_LVL) |
Zesstra | 0caa8e4 | 2020-08-11 22:51:59 +0200 | [diff] [blame] | 93 | return 0; |
| 94 | |
| 95 | // Ebene ist Magierebene? Dann werden alle Stufenlimits gegen Magierlevel |
| 96 | // geprueft, ansonsten gegen Spielerlevel. |
Zesstra | 10341b8 | 2020-09-12 13:02:54 +0200 | [diff] [blame] | 97 | int level = (access.flags & CH_ACCESS_WIZARD |
| 98 | ? query_wiz_level(user) |
| 99 | : ({int})user->QueryProp(P_LEVEL)); |
Zesstra | 0caa8e4 | 2020-08-11 22:51:59 +0200 | [diff] [blame] | 100 | |
| 101 | switch (cmd) |
| 102 | { |
| 103 | case C_FIND: |
| 104 | case C_LIST: |
| 105 | case C_JOIN: |
Zesstra | 10341b8 | 2020-09-12 13:02:54 +0200 | [diff] [blame] | 106 | if (access.recv == -1) |
Zesstra | 0caa8e4 | 2020-08-11 22:51:59 +0200 | [diff] [blame] | 107 | return 0; |
Zesstra | 10341b8 | 2020-09-12 13:02:54 +0200 | [diff] [blame] | 108 | if (access.recv <= level) |
Zesstra | 0caa8e4 | 2020-08-11 22:51:59 +0200 | [diff] [blame] | 109 | return 1; |
| 110 | break; |
| 111 | |
| 112 | case C_SEND: |
Zesstra | 10341b8 | 2020-09-12 13:02:54 +0200 | [diff] [blame] | 113 | if (access.send == -1) |
Zesstra | 0caa8e4 | 2020-08-11 22:51:59 +0200 | [diff] [blame] | 114 | return 0; |
Zesstra | 10341b8 | 2020-09-12 13:02:54 +0200 | [diff] [blame] | 115 | if (access.send <= level) |
Zesstra | 0caa8e4 | 2020-08-11 22:51:59 +0200 | [diff] [blame] | 116 | return 1; |
| 117 | break; |
| 118 | |
| 119 | // Verlassen ist immer erlaubt |
| 120 | case C_LEAVE: |
| 121 | return 1; |
Zesstra | 0caa8e4 | 2020-08-11 22:51:59 +0200 | [diff] [blame] | 122 | } |
| 123 | return 0; |
| 124 | } |
| 125 | |
Zesstra | 10341b8 | 2020-09-12 13:02:54 +0200 | [diff] [blame] | 126 | // ch_store_access() - Angaben zu Zugriffsrechten fuer eine Ebene merken |
| 127 | // Angaben kommen in folgender Reihenfolge: |
| 128 | // string* chinfo = ({ channel_name, receive_level, send_level, |
| 129 | // adminflags, channelflags, description, |
| 130 | // supervisor }) |
| 131 | // mapping &data ist im Regelfall das <ch_access_data>, was per |
| 132 | // Referenz uebergeben wird (auch wenn das nicht noetig ist, |
| 133 | // macht es klar, was beabsichtigt ist). |
| 134 | protected void ch_store_access(string* chinfo, mapping data) |
Zesstra | 0caa8e4 | 2020-08-11 22:51:59 +0200 | [diff] [blame] | 135 | { |
Zesstra | 10341b8 | 2020-09-12 13:02:54 +0200 | [diff] [blame] | 136 | object supervisor; |
Zesstra | 0caa8e4 | 2020-08-11 22:51:59 +0200 | [diff] [blame] | 137 | |
Zesstra | 10341b8 | 2020-09-12 13:02:54 +0200 | [diff] [blame] | 138 | // Nur die Angabe des SV (Index 6) im initfile ist optional, alle Elemente |
| 139 | // davor muessen da sein. Wenn kein Supervisor angegeben ist, wird der |
| 140 | // Default-SV angenommen. |
| 141 | |
| 142 | if (sizeof(chinfo) >= 7) |
Zesstra | 0caa8e4 | 2020-08-11 22:51:59 +0200 | [diff] [blame] | 143 | { |
Zesstra | 10341b8 | 2020-09-12 13:02:54 +0200 | [diff] [blame] | 144 | if (stringp(chinfo[6]) && sizeof(chinfo[6])) |
| 145 | supervisor = find_object(chinfo[6]); |
Zesstra | 0caa8e4 | 2020-08-11 22:51:59 +0200 | [diff] [blame] | 146 | } |
Zesstra | 10341b8 | 2020-09-12 13:02:54 +0200 | [diff] [blame] | 147 | else if (sizeof(chinfo) == 6) |
| 148 | supervisor = find_object(DEFAULTSV); |
| 149 | else |
| 150 | return; |
| 151 | |
| 152 | // Nur Daten merken, wenn wir auch der Supervisor fuer die Ebene sein |
| 153 | // sollen. |
| 154 | if (supervisor != this_object()) |
| 155 | return; |
| 156 | |
| 157 | struct ch_access access = (<ch_access> |
| 158 | recv: to_int(chinfo[1]), |
| 159 | send: to_int(chinfo[2]), |
| 160 | flags: to_int(chinfo[3]) |
| 161 | ); |
| 162 | |
| 163 | data[lower_case(chinfo[0])] = access; |
| 164 | // Rest der Ebenendaten interessiert uns nicht. |
| 165 | } |
| 166 | |
| 167 | // Liest ein channeld.init file ein. Wenn keines angegeben wird, wird der |
| 168 | // das Standardfile fuers Mud eingelesen. Die Angaben werden in das Mapping |
| 169 | // <ch_access_data> uebernommen, dieses vorher aber nicht geloescht. |
| 170 | // Der Rueckgabewert ist < 0 fuer Fehler, ansonsten die Groesse von |
| 171 | // <ch_access_data> nach Einlesen des Files. |
| 172 | protected varargs int ch_read_init_file(string fname) |
| 173 | { |
| 174 | string ch_list; |
| 175 | if (!fname) |
| 176 | { |
| 177 | #if !defined(__TESTMUD__) && MUDNAME=="MorgenGrauen" |
| 178 | fname = CHMASTER ".init"; |
| 179 | #else |
| 180 | fname = CHMASTER ".init.testmud"; |
| 181 | #endif |
| 182 | } |
| 183 | |
| 184 | ch_list = read_file(fname); |
| 185 | if (!stringp(ch_list)) |
| 186 | return -1; |
| 187 | |
| 188 | // Channeldatensaetze erzeugen, dazu zuerst Datenfile in Zeilen zerlegen |
| 189 | // "Allgemein: 0: 0: 0: 0: Allgemeine Unterhaltungsebene" |
| 190 | // Danach drueberlaufen und in Einzelfelder splitten, dabei gleich die |
| 191 | // Trennzeichen (Doppelpunkt, Tab und Space) rausfiltern. |
| 192 | foreach(string ch : old_explode(ch_list, "\n")) |
| 193 | { |
| 194 | if (ch[0]=='#') |
| 195 | continue; |
| 196 | ch_store_access(regexplode(ch, ":[ \t]*", RE_OMIT_DELIM), |
| 197 | &ch_access_data); |
| 198 | } |
| 199 | return sizeof(ch_access_data); |
| 200 | } |
| 201 | |
| 202 | // Nur falls es mal gebraucht wird und damit es schon jetzt alle rufen |
| 203 | // koennen. |
| 204 | protected void create() |
| 205 | { |
| 206 | } |
| 207 | |
| 208 | public varargs int remove(int silent) |
| 209 | { |
| 210 | destruct(this_object()); |
| 211 | return 1; |
Zesstra | 0caa8e4 | 2020-08-11 22:51:59 +0200 | [diff] [blame] | 212 | } |
| 213 | |