From ca98dcef55c7505822c9a6df56c31436619e5dca Mon Sep 17 00:00:00 2001 From: Daniel Oaks Date: Sat, 11 Sep 2021 11:50:55 +1000 Subject: [PATCH 1/5] Add metadata caps/numerics --- gencapdefs.py | 12 ++++++++++++ irc/caps/defs.go | Bin 5209 -> 11598 bytes irc/numerics.go | 15 +++++++++++++++ 3 files changed, 27 insertions(+) diff --git a/gencapdefs.py b/gencapdefs.py index b1d2ebf2..2c6b28f9 100644 --- a/gencapdefs.py +++ b/gencapdefs.py @@ -87,6 +87,18 @@ CAPDEFS = [ url="https://ircv3.net/specs/extensions/message-tags.html", standard="IRCv3", ), + CapDef( + identifier="Metadata", + name="draft/metadata", + url="https://github.com/DanielOaks/ircv3-specifications/blob/metadata/core/metadata.md", + standard="draft IRCv3", + ), + CapDef( + identifier="MetadataNotify", + name="metadata-notify", + url="https://github.com/DanielOaks/ircv3-specifications/blob/metadata/core/metadata.md", + standard="draft IRCv3", + ), CapDef( identifier="MultiPrefix", name="multi-prefix", diff --git a/irc/caps/defs.go b/irc/caps/defs.go index 7eea88670745e63211da2ed510dd6b27a9244de7..1512e65bb7bc9642aed51d51e8d4d51238e176b3 100644 GIT binary patch literal 11598 zcmc&)+in{-5ap{2^dE#gwLvAtmpX2MKBTtMxUiixc2KlIP|K2~xW35H#fek&*V~@M z5yi_ccg>a7h9K=~cR0g29L@}f{O{iz)lpq_f!~2TQw`jA)QuXeuhm!j+g4BYbw&NA zUaGh1Q0?LSvw8vAiTbF{LEBJ$TrYKd`QK4fyd7$u*LXex*9opY(4MM0{GO;QJiBmY z_Hf?^x09K?9rYS?hxk3lbyw{`GVc!1k3;nizx(+7u3DP@scP#h``v})YjB!?`kNWI zHr_YzbPBnrxo(G}Ro$;|^=~msFQGjVnd;sh;*Q$)bt(r)@fFKLN7|<^z4rVpyHdIn`rT zmVeBWTwT(UkQU3do-Po%Q4e7|d6Hr%<>@KU+}Ks-qqbo&1N91XO`_&vwnO_H;49qf zu^(SX935Y;bYy(*{TA_Mpl8-Z$7;q!Mw)Q8_4M05=3)a`OInPyZL`sfxk{e=GK|@V zv1W=)r3L>mM6`1ws(asr4MAxsQYL23C%n zbCip5Nk@7gw#$|46j#;;n0fno!E&vbcI(T#532NDEgciH@oh(Q`m91(l7e`u$EA4Sm+<=dG zK0`69e>#S{uzaqRXxU?YOdZzuw5fR)YhvWeIOXy!!_3-PN{uZhEw(C)>0AXpKkEGg zojIq&8J&)w&$p@mnsKfR!I(V3Fk7SComV?0Be9yNqqqmeZh;%Cr^~FEa3l=hhp3yx z<;5&9u6a6&%m}!%z>0rQuT!~>mO6Ac#-v&#J)h++Yf_hgJ$6|pHLRSMVUUih?-!4? zf6Qj0sc8CMv8i*T0laTLD8{6P=*4uchMJpS70v2Ja!hLG%1N8$`D^?9tldVYhtD#7 z^s0=8$+q6;S`w>jpBIi%Hm~HWpV^V{t;>du4!*Qld^(tCy}r)r=n;L^Bg2^f8agvu zqK6><+w6xMv-pi+9=Tjj7_vZX_u!hZaUYeKAm{X1smCE$7Gb|Gy?eUD)KwiX&yI zt+v%rn;?(NuaT!)4?Vn@H}&CUWrR`j2;=YSQw5P@%%sIFhbJxSLV&!pnoGaaHGT(f zv?j9$$2`|q#Nyf0G~nLEEV|Y^qhfP)p;Rt6Hn+;~NJsb&;JIB|=NGCfvFQsC?ZP66 zY#Z^2nYi6gD6_&(Xm^2c3+I_!KH*Ut7$PCvbeRGzJ~`j6EI_zByuzh_mm75Gr@ zirEup;i}=g0!pqnc+$zI$vbP~)7bMS{&Uf-s0Xa1xu+Ri$#(6OvR5DDAUmXHr#swt zE^Za>U;0|Q{Vd)sj7cfq0gJVy=L+|AVzl9UGOmSP{g^6#oHkoIcIC&F&{A`LO i7q*wI%cU>R1AHES49vz-m$y$Fk1eLnKiXG`KmQ+wMr@P- literal 5209 zcmbuDZExE)5XWCjpF+s1t(dI%VNM#LFR~=qGB{3Wrx>=PSSXp6xX6?sQf}R0-+jji zNt6u6QuijY$@}wuKJku6*qGuI8?xX$m_tL6Rj=PQpVgn3(%Vh{eKl4mid zxIi3lyzt;X@6d~sZSa;oyUy*Sw|so^?r!g&yoc-MhwH`SkCFQ(aNQ`QjC1j3?MD3FY&dhl&Cn zU;uGgEH5y_lrw1%63#G(rPPN7rm)o5{l3j|9YtA5`7+~Vdl0`-tbM<_*-smygGbR0 z5YLb@_NlZ!gSFw;B%J5$DhNms?WZG(dBAcUu>gPJm@)#tJ80|t>1aGk_%3ywws-l1 zMFR2q$e(|CkWDv8=V=q8DO$sqksZ0{(E6EN!^7cDSR zv?mLQ-pVT+6UL#6Kz3A6n*wdQHS^?bokxYC@6g7CCuKN_vYkpu_170ENwy@CE?JP5 zX&TI?Kh_!8BC^2WB#2U+uCS;EL$D(y^b4u%0KZZ;+B(;11K24=&E{EAm$SUc@{BT$P+Lj68PhY-%5DwsV%vC#Ut7XJ^{`NVbFAeNxs ziCVtFn}>`Nh-}5%XV1!G0Hpp-X}=wJHlG7-hr|NBKr}AlNM{vl&(Nlo?g*3dk+BVK z5hXZ%L@zA398c!s$z*#m3n%mQ@dQmbczUr3FVFD|pGUylz*uM>%9O*oN9(NWNxQ3b zN3^|*!1OIN7ma@l;0nWL+p+op?#WkZ*|+1(#uu(rd$-WtMM?I6851qsi4u>&)ZZ!F z4%I7#$W$4{-t=oj)7$mejMSChR)y+J`5TM}z-br0kO5uQTUD7NU0d+(>7H=h@355!Sz(q#8+r2Krpg@78D-x;hFzs@0=xb#n0oI)uUMBG+cVZ% z&xdA{^~W<+8qM@+!xGiueSx>+%c-=Gg~W&J1K1A05)QP=*m$yA>b3 z7kgYhk*0aF?Gh#}eGaArNE(p|)HtF<~d-e2lgE ht$IM!HT4B*jQntvuxhxQRMJ)tw)Qtn{0pzz{sW~S(e?lU diff --git a/irc/numerics.go b/irc/numerics.go index 79afff9f..5322ac52 100644 --- a/irc/numerics.go +++ b/irc/numerics.go @@ -183,6 +183,21 @@ const ( RPL_MONLIST = "732" RPL_ENDOFMONLIST = "733" ERR_MONLISTFULL = "734" + RPL_WHOISKEYVALUE = "760" + RPL_KEYVALUE = "761" + RPL_METADATAEND = "762" + ERR_METADATALIMIT = "764" + ERR_TARGETINVALID = "765" + ERR_NOMATCHINGKEY = "766" + ERR_KEYINVALID = "767" + ERR_KEYNOTSET = "768" + ERR_KEYNOPERMISSION = "769" + RPL_METADATASUBOK = "770" + RPL_METADATAUNSUBOK = "771" + RPL_METADATASUBS = "772" + ERR_METADATATOOMANYSUBS = "773" + ERR_METADATASYNCLATER = "774" + ERR_METADATARATELIMIT = "775" RPL_LOGGEDIN = "900" RPL_LOGGEDOUT = "901" ERR_NICKLOCKED = "902" From 512d89ba185f66f4da98b014de73299d5fa695ee Mon Sep 17 00:00:00 2001 From: Daniel Oaks Date: Sat, 11 Sep 2021 12:05:12 +1000 Subject: [PATCH 2/5] Fucking Windows saving with some dodgy encoding --- irc/caps/defs.go | Bin 11598 -> 5627 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/irc/caps/defs.go b/irc/caps/defs.go index 1512e65bb7bc9642aed51d51e8d4d51238e176b3..d2b5e1a20c9591020060f69076cdfaed9e66a31d 100644 GIT binary patch literal 5627 zcmbuD-*4MC5XYaTze32#LiG;Pzti{$f7=bL78@d_O5Dw_>?R|MdBjSbun2$Vm@)#-9kq4gWOOph_$K$gws-l! zA_RLNB?U*mbfAqMP}-M|qjWeNh=6R|CKFCwSf9|oXV}1Uc+47+9k9l!1M3&Wlk8BS zVqw%jMAF;}j`HCEfZ={&Nl-aBDvid%X*|L&l|=0?=rT)xDk&X3iZ1j?PFMbOfY+bVxbL7E&dMH+1U5mAdaA3 zi(0O5SlFkfj&(P*Z_Y9Nqk@Xo| zAxdz5hn`q;b~2uwjK}NKX*`}CpN!FDg(s)0`0N-@@o@so4UB{K7IU;h92wX?aouRm zGtfH!Ek>DS-69a@MI4!FqNJ#BeKp#we6OZ*QEzh&t2M1_LC+X(jLwZNd0!}9lh7NlOET(z^#?|;B}0GxIa3K`Iuj?m<{bnU>qp*zBHzb1o7+rfQCOJ)VH z<=TNaM={RvYKd71&F{gNn=5lz9hH6m7ZIok72CaH><9{P8Ta)o?faq^%xo MB?8>|4-P~B2Z%3W=l}o! literal 11598 zcmc&)+in{-5ap{2^dE#gwLvAtmpX2MKBTtMxUiixc2KlIP|K2~xW35H#fek&*V~@M z5yi_ccg>a7h9K=~cR0g29L@}f{O{iz)lpq_f!~2TQw`jA)QuXeuhm!j+g4BYbw&NA zUaGh1Q0?LSvw8vAiTbF{LEBJ$TrYKd`QK4fyd7$u*LXex*9opY(4MM0{GO;QJiBmY z_Hf?^x09K?9rYS?hxk3lbyw{`GVc!1k3;nizx(+7u3DP@scP#h``v})YjB!?`kNWI zHr_YzbPBnrxo(G}Ro$;|^=~msFQGjVnd;sh;*Q$)bt(r)@fFKLN7|<^z4rVpyHdIn`rT zmVeBWTwT(UkQU3do-Po%Q4e7|d6Hr%<>@KU+}Ks-qqbo&1N91XO`_&vwnO_H;49qf zu^(SX935Y;bYy(*{TA_Mpl8-Z$7;q!Mw)Q8_4M05=3)a`OInPyZL`sfxk{e=GK|@V zv1W=)r3L>mM6`1ws(asr4MAxsQYL23C%n zbCip5Nk@7gw#$|46j#;;n0fno!E&vbcI(T#532NDEgciH@oh(Q`m91(l7e`u$EA4Sm+<=dG zK0`69e>#S{uzaqRXxU?YOdZzuw5fR)YhvWeIOXy!!_3-PN{uZhEw(C)>0AXpKkEGg zojIq&8J&)w&$p@mnsKfR!I(V3Fk7SComV?0Be9yNqqqmeZh;%Cr^~FEa3l=hhp3yx z<;5&9u6a6&%m}!%z>0rQuT!~>mO6Ac#-v&#J)h++Yf_hgJ$6|pHLRSMVUUih?-!4? zf6Qj0sc8CMv8i*T0laTLD8{6P=*4uchMJpS70v2Ja!hLG%1N8$`D^?9tldVYhtD#7 z^s0=8$+q6;S`w>jpBIi%Hm~HWpV^V{t;>du4!*Qld^(tCy}r)r=n;L^Bg2^f8agvu zqK6><+w6xMv-pi+9=Tjj7_vZX_u!hZaUYeKAm{X1smCE$7Gb|Gy?eUD)KwiX&yI zt+v%rn;?(NuaT!)4?Vn@H}&CUWrR`j2;=YSQw5P@%%sIFhbJxSLV&!pnoGaaHGT(f zv?j9$$2`|q#Nyf0G~nLEEV|Y^qhfP)p;Rt6Hn+;~NJsb&;JIB|=NGCfvFQsC?ZP66 zY#Z^2nYi6gD6_&(Xm^2c3+I_!KH*Ut7$PCvbeRGzJ~`j6EI_zByuzh_mm75Gr@ zirEup;i}=g0!pqnc+$zI$vbP~)7bMS{&Uf-s0Xa1xu+Ri$#(6OvR5DDAUmXHr#swt zE^Za>U;0|Q{Vd)sj7cfq0gJVy=L+|AVzl9UGOmSP{g^6#oHkoIcIC&F&{A`LO i7q*wI%cU>R1AHES49vz-m$y$Fk1eLnKiXG`KmQ+wMr@P- From 060d06ba6aaf429a95020fbe51828c7bdc257725 Mon Sep 17 00:00:00 2001 From: Daniel Oaks Date: Sun, 12 Sep 2021 21:05:48 +1000 Subject: [PATCH 3/5] Only stage some metadata changes for now, not the vendor update --- default.yaml | 44 +++++++++++++++++++++++ irc/client.go | 25 ++++++++------ irc/commands.go | 4 +++ irc/config.go | 54 +++++++++++++++++++++++++++++ irc/handlers.go | 90 ++++++++++++++++++++++++++++++++++++++++++++++++ irc/help.go | 8 +++++ irc/metadata.go | 4 +++ traditional.yaml | 44 +++++++++++++++++++++++ 8 files changed, 263 insertions(+), 10 deletions(-) create mode 100644 irc/metadata.go diff --git a/default.yaml b/default.yaml index 3fd72ea1..774b0b4e 100644 --- a/default.yaml +++ b/default.yaml @@ -364,6 +364,50 @@ server: # the default value of 512. DO NOT change this on a public server: # max-line-len: 512 +# metadata options +metadata: + # maximum number of keys users can have set. + # this excludes admin-set keys which users cannot set or view + max-keys: 16 + + # maximum number of keys users can subscribe to at one time. + # opers can subscribe to more than this though + max-subs: 16 + + users: + # uncomment this if you ONLY want these keys to be settable + # allowed-keys: + # - avatar + # - color + # - display-name + # - homepage + # - status + + # uncomment this if you want all BUT these keys to be settable + # blocked-keys: + # - example-bad-key + # - another-bad-example + + # these keys are restricted to opers + restricted-keys: + - admin:* + - server:* + + channels: + # uncomment this if you ONLY want these keys to be settable + # allowed-keys: + # - url + + # uncomment this if you want all BUT these keys to be settable + # blocked-keys: + # - example-bad-key + # - another-bad-example + + # these keys are restricted to opers + restricted-keys: + - admin:* + - server:* + # account options accounts: # is account authentication enabled, i.e., can users log into existing accounts? diff --git a/irc/client.go b/irc/client.go index a344c671..44d25ea8 100644 --- a/irc/client.go +++ b/irc/client.go @@ -20,6 +20,7 @@ import ( "github.com/ergochat/irc-go/ircfmt" "github.com/ergochat/irc-go/ircmsg" "github.com/ergochat/irc-go/ircreader" + "github.com/soroushj/menge" "github.com/xdg-go/scram" "github.com/ergochat/ergo/irc/caps" @@ -174,6 +175,9 @@ type Session struct { capState caps.State capVersion caps.Version + stateMutex sync.RWMutex // tier 1 + subscribedMetadataKeys menge.StringSet + registrationMessages int zncPlaybackTimes *zncPlaybackTimes @@ -349,16 +353,17 @@ func (server *Server) RunClient(conn IRCConn) { } client.history.Initialize(config.History.ClientLength, time.Duration(config.History.AutoresizeWindow)) session := &Session{ - client: client, - socket: socket, - capVersion: caps.Cap301, - capState: caps.NoneState, - ctime: now, - lastActive: now, - realIP: realIP, - proxiedIP: proxiedIP, - isTor: wConn.Config.Tor, - hideSTS: wConn.Config.Tor || wConn.Config.HideSTS, + client: client, + socket: socket, + capVersion: caps.Cap301, + capState: caps.NoneState, + ctime: now, + lastActive: now, + realIP: realIP, + proxiedIP: proxiedIP, + isTor: wConn.Config.Tor, + hideSTS: wConn.Config.Tor || wConn.Config.HideSTS, + subscribedMetadataKeys: menge.NewStringSet(), } client.sessions = []*Session{session} diff --git a/irc/commands.go b/irc/commands.go index 19ea99f5..123523e1 100644 --- a/irc/commands.go +++ b/irc/commands.go @@ -178,6 +178,10 @@ func init() { handler: lusersHandler, minParams: 0, }, + "METADATA": { + handler: metadataHandler, + minParams: 2, + }, "MODE": { handler: modeHandler, minParams: 1, diff --git a/irc/config.go b/irc/config.go index ec0ee96e..dbed4c63 100644 --- a/irc/config.go +++ b/irc/config.go @@ -300,6 +300,38 @@ func (t *ThrottleConfig) UnmarshalYAML(unmarshal func(interface{}) error) (err e return } +type MetadataKeyConfig struct { + AllowedKeys []string `yaml:"allowed-keys"` + AllowedKeysMatcher *regexp.Regexp + BlockedKeys []string `yaml:"blocked-keys"` + BlockedKeysMatcher *regexp.Regexp + RestrictedKeys []string `yaml:"restricted-keys"` + RestrictedKeysMatcher *regexp.Regexp +} + +func (mkc *MetadataKeyConfig) compileMatchers() (err error) { + mkc.AllowedKeysMatcher, err = utils.CompileMasks(mkc.AllowedKeys) + if err != nil { + err = errors.New("allowed-keys") + } + mkc.BlockedKeysMatcher, err = utils.CompileMasks(mkc.BlockedKeys) + if err != nil { + err = errors.New("blocked-keys") + } + mkc.RestrictedKeysMatcher, err = utils.CompileMasks(mkc.RestrictedKeys) + if err != nil { + err = errors.New("restricted-keys") + } + return err +} + +type MetadataConfig struct { + MaxKeys int `yaml:"max-keys"` + MaxSubs int `yaml:"max-subs"` + Users MetadataKeyConfig + Channels MetadataKeyConfig +} + type AccountConfig struct { Registration AccountRegistrationConfig AuthenticationEnabled bool `yaml:"authentication-enabled"` @@ -621,6 +653,8 @@ type Config struct { MySQL mysql.Config } + Metadata MetadataConfig + Accounts AccountConfig Channels struct { @@ -1228,6 +1262,26 @@ func LoadConfig(filename string) (config *Config, err error) { config.Server.capValues[caps.Multiline] = multilineCapValue } + // confirm that we don't have both allowed and blocked metadata keys set + config.Server.capValues[caps.Metadata] = fmt.Sprintf("maxsub=%d,maxkey=%d", config.Metadata.MaxSubs, config.Metadata.MaxKeys) + + if len(config.Metadata.Users.AllowedKeys) > 0 && len(config.Metadata.Users.BlockedKeys) > 0 { + return nil, errors.New("You can only set either allowed-keys or blocked-keys in metadata.users, not both") + } + if len(config.Metadata.Channels.AllowedKeys) > 0 && len(config.Metadata.Channels.BlockedKeys) > 0 { + return nil, errors.New("You can only set either allowed-keys or blocked-keys in metadata.channels, not both") + } + + err = config.Metadata.Users.compileMatchers() + if err != nil { + return nil, fmt.Errorf("Could not compile metadata.users.%s", err.Error()) + } + + err = config.Metadata.Channels.compileMatchers() + if err != nil { + return nil, fmt.Errorf("Could not compile metadata.channels.%s", err.Error()) + } + // handle legacy name 'bouncer' for 'multiclient' section: if config.Accounts.Bouncer != nil { config.Accounts.Multiclient = *config.Accounts.Bouncer diff --git a/irc/handlers.go b/irc/handlers.go index cbacabd9..afb5956a 100644 --- a/irc/handlers.go +++ b/irc/handlers.go @@ -12,6 +12,7 @@ import ( "fmt" "net" "os" + "regexp" "runtime" "runtime/debug" "runtime/pprof" @@ -1709,6 +1710,95 @@ func lusersHandler(server *Server, client *Client, msg ircmsg.Message, rb *Respo return false } +// METADATA [ ... []] +func metadataHandler(server *Server, client *Client, msg ircmsg.Message, rb *ResponseBuffer) bool { + // target := msg.Params[0] + subCommand := strings.ToUpper(msg.Params[1]) + + config := server.Config().Metadata + + //TODO: do this once when the server boots? + keyNameMatcher, _ := regexp.Compile(`^[a-z0-9_.-][a-z0-9_.\-:]*$`) + + switch subCommand { + // these subcommands affect the client itself, or other targets + // + + // these subcommands affect the current session + // + case "SUB": + var addedKeys []string + + rb.session.stateMutex.Lock() + defer rb.session.stateMutex.Unlock() + for i, key := range msg.Params { + if i < 2 { + // skip target and subcommand + continue + } + + if len(rb.session.subscribedMetadataKeys)+len(addedKeys) > config.MaxSubs { + rb.Add(nil, server.name, ERR_METADATATOOMANYSUBS, client.nick, key) + break + } + + if !keyNameMatcher.MatchString(key) { + rb.Add(nil, server.name, ERR_KEYINVALID, client.nick, key) + continue + } + + // see if key is restricted + if client.Oper() == nil && (config.Users.RestrictedKeysMatcher.MatchString(key) || config.Channels.RestrictedKeysMatcher.MatchString(key)) { + rb.Add(nil, server.name, ERR_KEYNOPERMISSION, client.nick, "*", key, "permission denied") + // still let the user subscribe to the key, don't continue on to the next one + } + + addedKeys = append(addedKeys, key) + } + rb.session.subscribedMetadataKeys.Add(addedKeys...) + + if len(addedKeys) > 0 { + rb.Add(nil, server.name, RPL_METADATASUBOK, client.nick, strings.Join(addedKeys, " ")) + } + rb.Add(nil, server.name, RPL_METADATAEND, client.nick, "end of metadata") + + case "UNSUB": + var removedKeys []string + + rb.session.stateMutex.Lock() + defer rb.session.stateMutex.Unlock() + for i, key := range msg.Params { + if i < 2 { + // skip target and subcommand + continue + } + + if !keyNameMatcher.MatchString(key) { + rb.Add(nil, server.name, ERR_KEYINVALID, client.nick, key) + continue + } + + removedKeys = append(removedKeys, key) + } + rb.session.subscribedMetadataKeys.Remove(removedKeys...) + + if len(removedKeys) > 0 { + rb.Add(nil, server.name, RPL_METADATAUNSUBOK, client.nick, strings.Join(removedKeys, " ")) + } + rb.Add(nil, server.name, RPL_METADATAEND, client.nick, "end of metadata") + + case "SUBS": + rb.session.stateMutex.RLock() + defer rb.session.stateMutex.RUnlock() + if rb.session.subscribedMetadataKeys.Size() > 0 { + //TODO: loop and return subscriptions with multiple numerics if we need to + rb.Add(nil, server.name, RPL_METADATASUBS, client.nick, strings.Join(rb.session.subscribedMetadataKeys.AsSlice(), " ")) + } + rb.Add(nil, server.name, RPL_METADATAEND, client.nick, "end of metadata") + } + return false +} + // MODE [ [...]] func modeHandler(server *Server, client *Client, msg ircmsg.Message, rb *ResponseBuffer) bool { if 0 < len(msg.Params[0]) && msg.Params[0][0] == '#' { diff --git a/irc/help.go b/irc/help.go index 1b526788..975b1c16 100644 --- a/irc/help.go +++ b/irc/help.go @@ -347,6 +347,14 @@ Lists all the nicknames you are currently monitoring. MONITOR S Lists whether each nick in your MONITOR list is online or offline.`, + }, + "metadata": { + text: `METADATA + +Lets you add metadata to yourself and channels, as well as subscribe +to metadata changes. The subcommands are: + +//TODO`, }, "motd": { text: `MOTD [server] diff --git a/irc/metadata.go b/irc/metadata.go new file mode 100644 index 00000000..7cfee472 --- /dev/null +++ b/irc/metadata.go @@ -0,0 +1,4 @@ +// Copyright (c) 2021 Daniel Oaks +// released under the MIT license + +package irc diff --git a/traditional.yaml b/traditional.yaml index f86a79de..8f907094 100644 --- a/traditional.yaml +++ b/traditional.yaml @@ -337,6 +337,50 @@ server: # the default value of 512. DO NOT change this on a public server: # max-line-len: 512 +# metadata options +metadata: + # maximum number of keys users can have set. + # this excludes admin-set keys which users cannot set or view + max-keys: 16 + + # maximum number of keys users can subscribe to at one time. + # opers can subscribe to more than this though + max-subs: 16 + + users: + # uncomment this if you ONLY want these keys to be settable + # allowed-keys: + # - avatar + # - color + # - display-name + # - homepage + # - status + + # uncomment this if you want all BUT these keys to be settable + # blocked-keys: + # - example-bad-key + # - another-bad-example + + # these keys are restricted to opers + restricted-keys: + - admin:* + - server:* + + channels: + # uncomment this if you ONLY want these keys to be settable + # allowed-keys: + # - url + + # uncomment this if you want all BUT these keys to be settable + # blocked-keys: + # - example-bad-key + # - another-bad-example + + # these keys are restricted to opers + restricted-keys: + - admin:* + - server:* + # account options accounts: # is account authentication enabled, i.e., can users log into existing accounts? From e6ee9e50e0bc576cea33e25a78024079a98534f9 Mon Sep 17 00:00:00 2001 From: Daniel Oaks Date: Mon, 13 Sep 2021 06:51:43 +1000 Subject: [PATCH 4/5] Use our own stringset instead of menge's --- irc/client.go | 5 ++--- irc/handlers.go | 8 ++++---- irc/utils/types.go | 19 +++++++++++++++++++ 3 files changed, 25 insertions(+), 7 deletions(-) diff --git a/irc/client.go b/irc/client.go index 44d25ea8..087d5608 100644 --- a/irc/client.go +++ b/irc/client.go @@ -20,7 +20,6 @@ import ( "github.com/ergochat/irc-go/ircfmt" "github.com/ergochat/irc-go/ircmsg" "github.com/ergochat/irc-go/ircreader" - "github.com/soroushj/menge" "github.com/xdg-go/scram" "github.com/ergochat/ergo/irc/caps" @@ -176,7 +175,7 @@ type Session struct { capVersion caps.Version stateMutex sync.RWMutex // tier 1 - subscribedMetadataKeys menge.StringSet + subscribedMetadataKeys utils.StringSet registrationMessages int @@ -363,7 +362,7 @@ func (server *Server) RunClient(conn IRCConn) { proxiedIP: proxiedIP, isTor: wConn.Config.Tor, hideSTS: wConn.Config.Tor || wConn.Config.HideSTS, - subscribedMetadataKeys: menge.NewStringSet(), + subscribedMetadataKeys: make(utils.StringSet), } client.sessions = []*Session{session} diff --git a/irc/handlers.go b/irc/handlers.go index afb5956a..38bf3eb5 100644 --- a/irc/handlers.go +++ b/irc/handlers.go @@ -1737,7 +1737,7 @@ func metadataHandler(server *Server, client *Client, msg ircmsg.Message, rb *Res continue } - if len(rb.session.subscribedMetadataKeys)+len(addedKeys) > config.MaxSubs { + if rb.session.subscribedMetadataKeys.Size() > config.MaxSubs { rb.Add(nil, server.name, ERR_METADATATOOMANYSUBS, client.nick, key) break } @@ -1754,8 +1754,8 @@ func metadataHandler(server *Server, client *Client, msg ircmsg.Message, rb *Res } addedKeys = append(addedKeys, key) + rb.session.subscribedMetadataKeys.Add(key) } - rb.session.subscribedMetadataKeys.Add(addedKeys...) if len(addedKeys) > 0 { rb.Add(nil, server.name, RPL_METADATASUBOK, client.nick, strings.Join(addedKeys, " ")) @@ -1779,8 +1779,8 @@ func metadataHandler(server *Server, client *Client, msg ircmsg.Message, rb *Res } removedKeys = append(removedKeys, key) + rb.session.subscribedMetadataKeys.Remove(key) } - rb.session.subscribedMetadataKeys.Remove(removedKeys...) if len(removedKeys) > 0 { rb.Add(nil, server.name, RPL_METADATAUNSUBOK, client.nick, strings.Join(removedKeys, " ")) @@ -1792,7 +1792,7 @@ func metadataHandler(server *Server, client *Client, msg ircmsg.Message, rb *Res defer rb.session.stateMutex.RUnlock() if rb.session.subscribedMetadataKeys.Size() > 0 { //TODO: loop and return subscriptions with multiple numerics if we need to - rb.Add(nil, server.name, RPL_METADATASUBS, client.nick, strings.Join(rb.session.subscribedMetadataKeys.AsSlice(), " ")) + rb.Add(nil, server.name, RPL_METADATASUBS, client.nick, strings.Join(rb.session.subscribedMetadataKeys.Keys(), " ")) } rb.Add(nil, server.name, RPL_METADATAEND, client.nick, "end of metadata") } diff --git a/irc/utils/types.go b/irc/utils/types.go index 249b486e..bcb20153 100644 --- a/irc/utils/types.go +++ b/irc/utils/types.go @@ -15,3 +15,22 @@ func (s StringSet) Has(str string) bool { func (s StringSet) Add(str string) { s[str] = empty{} } + +func (s StringSet) Remove(str string) { + _, ok := s[str] + if ok { + delete(s, str) + } +} + +func (s StringSet) Size() int { + return len(s) +} + +func (s StringSet) Keys() (keys []string) { + for key := range s { + keys = append(keys, key) + } + + return keys +} From b4cb12a2036cc43f1c8438414f61d584f31102f7 Mon Sep 17 00:00:00 2001 From: Daniel Oaks Date: Mon, 13 Sep 2021 06:53:58 +1000 Subject: [PATCH 5/5] Rename types.go -> stringset.go for consistency --- irc/utils/{types.go => stringset.go} | 1 + 1 file changed, 1 insertion(+) rename irc/utils/{types.go => stringset.go} (93%) diff --git a/irc/utils/types.go b/irc/utils/stringset.go similarity index 93% rename from irc/utils/types.go rename to irc/utils/stringset.go index bcb20153..74fb8ce3 100644 --- a/irc/utils/types.go +++ b/irc/utils/stringset.go @@ -1,4 +1,5 @@ // Copyright (c) 2020 Shivaram Lingamneni +// Copyright (c) 2021 Daniel Oaks // released under the MIT license package utils