the aspect manouvre

master
bqv 2 years ago
parent afedd306ea
commit 5c3305976c
No known key found for this signature in database
GPG Key ID: 9E2FF3BDEBDFC910

@ -1,19 +1,23 @@
.plugin.o: plugin.cpp plugin.hh config.hh account.hh omemo.hh \ .plugin.o: plugin.cpp plugin.hh config.hh \
/usr/include/signal/signal_protocol.h /usr/include/signal/ratchet.h \ deps/optional/include/tl/optional.hpp deps/fmt/include/fmt/core.h \
account.hh pgp.hh omemo.hh /usr/include/signal/signal_protocol.h \
/usr/include/signal/ratchet.h \
/usr/include/signal/signal_protocol_types.h /usr/include/signal/curve.h \ /usr/include/signal/signal_protocol_types.h /usr/include/signal/curve.h \
/usr/include/signal/session_record.h \ /usr/include/signal/session_record.h \
/usr/include/signal/session_pre_key.h \ /usr/include/signal/session_pre_key.h \
/usr/include/signal/sender_key_record.h signal.hh \ /usr/include/signal/sender_key_record.h signal.hh \
deps/fmt/include/fmt/core.h /usr/include/signal/key_helper.h \ /usr/include/signal/key_helper.h /usr/include/signal/session_builder.h \
/usr/include/signal/session_builder.h \
/usr/include/signal/session_cipher.h \ /usr/include/signal/session_cipher.h \
/usr/include/signal/session_pre_key.h /usr/include/signal/protocol.h \ /usr/include/signal/session_pre_key.h /usr/include/signal/protocol.h \
/usr/include/signal/curve.h connection.hh command.hh input.hh buffer.hh \ /usr/include/signal/curve.h channel.hh connection.hh xmpp/ns.hh \
completion.hh strophe.hh user.hh command.hh input.hh buffer.hh completion.hh
plugin.hh: plugin.hh:
config.hh: config.hh:
deps/optional/include/tl/optional.hpp:
deps/fmt/include/fmt/core.h:
account.hh: account.hh:
pgp.hh:
omemo.hh: omemo.hh:
/usr/include/signal/signal_protocol.h: /usr/include/signal/signal_protocol.h:
/usr/include/signal/ratchet.h: /usr/include/signal/ratchet.h:
@ -23,19 +27,23 @@ omemo.hh:
/usr/include/signal/session_pre_key.h: /usr/include/signal/session_pre_key.h:
/usr/include/signal/sender_key_record.h: /usr/include/signal/sender_key_record.h:
signal.hh: signal.hh:
deps/fmt/include/fmt/core.h:
/usr/include/signal/key_helper.h: /usr/include/signal/key_helper.h:
/usr/include/signal/session_builder.h: /usr/include/signal/session_builder.h:
/usr/include/signal/session_cipher.h: /usr/include/signal/session_cipher.h:
/usr/include/signal/session_pre_key.h: /usr/include/signal/session_pre_key.h:
/usr/include/signal/protocol.h: /usr/include/signal/protocol.h:
/usr/include/signal/curve.h: /usr/include/signal/curve.h:
channel.hh:
connection.hh: connection.hh:
xmpp/ns.hh:
strophe.hh:
user.hh:
command.hh: command.hh:
input.hh: input.hh:
buffer.hh: buffer.hh:
completion.hh: completion.hh:
.account.o: account.cpp /usr/include/libxml2/libxml/xmlwriter.h \ .account.o: account.cpp deps/fmt/include/fmt/core.h \
/usr/include/libxml2/libxml/xmlwriter.h \
/usr/include/libxml2/libxml/xmlversion.h \ /usr/include/libxml2/libxml/xmlversion.h \
/usr/include/libxml2/libxml/xmlexports.h \ /usr/include/libxml2/libxml/xmlexports.h \
/usr/include/libxml2/libxml/xmlIO.h \ /usr/include/libxml2/libxml/xmlIO.h \
@ -53,18 +61,18 @@ completion.hh:
/usr/include/libxml2/libxml/SAX2.h /usr/include/libxml2/libxml/xlink.h \ /usr/include/libxml2/libxml/SAX2.h /usr/include/libxml2/libxml/xlink.h \
/usr/include/libxml2/libxml/xmlmemory.h \ /usr/include/libxml2/libxml/xmlmemory.h \
/usr/include/libxml2/libxml/threads.h plugin.hh xmpp/stanza.hh config.hh \ /usr/include/libxml2/libxml/threads.h plugin.hh xmpp/stanza.hh config.hh \
input.hh omemo.hh /usr/include/signal/signal_protocol.h \ deps/optional/include/tl/optional.hpp input.hh omemo.hh \
/usr/include/signal/ratchet.h \ /usr/include/signal/signal_protocol.h /usr/include/signal/ratchet.h \
/usr/include/signal/signal_protocol_types.h /usr/include/signal/curve.h \ /usr/include/signal/signal_protocol_types.h /usr/include/signal/curve.h \
/usr/include/signal/session_record.h \ /usr/include/signal/session_record.h \
/usr/include/signal/session_pre_key.h \ /usr/include/signal/session_pre_key.h \
/usr/include/signal/sender_key_record.h signal.hh \ /usr/include/signal/sender_key_record.h signal.hh \
deps/fmt/include/fmt/core.h /usr/include/signal/key_helper.h \ /usr/include/signal/key_helper.h /usr/include/signal/session_builder.h \
/usr/include/signal/session_builder.h \
/usr/include/signal/session_cipher.h \ /usr/include/signal/session_cipher.h \
/usr/include/signal/session_pre_key.h /usr/include/signal/protocol.h \ /usr/include/signal/session_pre_key.h /usr/include/signal/protocol.h \
/usr/include/signal/curve.h account.hh connection.hh user.hh \ /usr/include/signal/curve.h account.hh pgp.hh channel.hh connection.hh \
deps/optional/include/tl/optional.hpp channel.hh buffer.hh xmpp/ns.hh strophe.hh user.hh buffer.hh
deps/fmt/include/fmt/core.h:
/usr/include/libxml2/libxml/xmlwriter.h: /usr/include/libxml2/libxml/xmlwriter.h:
/usr/include/libxml2/libxml/xmlversion.h: /usr/include/libxml2/libxml/xmlversion.h:
/usr/include/libxml2/libxml/xmlexports.h: /usr/include/libxml2/libxml/xmlexports.h:
@ -89,6 +97,7 @@ completion.hh:
plugin.hh: plugin.hh:
xmpp/stanza.hh: xmpp/stanza.hh:
config.hh: config.hh:
deps/optional/include/tl/optional.hpp:
input.hh: input.hh:
omemo.hh: omemo.hh:
/usr/include/signal/signal_protocol.h: /usr/include/signal/signal_protocol.h:
@ -99,7 +108,6 @@ omemo.hh:
/usr/include/signal/session_pre_key.h: /usr/include/signal/session_pre_key.h:
/usr/include/signal/sender_key_record.h: /usr/include/signal/sender_key_record.h:
signal.hh: signal.hh:
deps/fmt/include/fmt/core.h:
/usr/include/signal/key_helper.h: /usr/include/signal/key_helper.h:
/usr/include/signal/session_builder.h: /usr/include/signal/session_builder.h:
/usr/include/signal/session_cipher.h: /usr/include/signal/session_cipher.h:
@ -107,24 +115,31 @@ deps/fmt/include/fmt/core.h:
/usr/include/signal/protocol.h: /usr/include/signal/protocol.h:
/usr/include/signal/curve.h: /usr/include/signal/curve.h:
account.hh: account.hh:
pgp.hh:
channel.hh:
connection.hh: connection.hh:
xmpp/ns.hh:
strophe.hh:
user.hh: user.hh:
deps/optional/include/tl/optional.hpp:
channel.hh:
buffer.hh: buffer.hh:
.buffer.o: buffer.cpp plugin.hh account.hh omemo.hh \ .buffer.o: buffer.cpp plugin.hh account.hh \
/usr/include/signal/signal_protocol.h /usr/include/signal/ratchet.h \ deps/optional/include/tl/optional.hpp deps/fmt/include/fmt/core.h pgp.hh \
omemo.hh /usr/include/signal/signal_protocol.h \
/usr/include/signal/ratchet.h \
/usr/include/signal/signal_protocol_types.h /usr/include/signal/curve.h \ /usr/include/signal/signal_protocol_types.h /usr/include/signal/curve.h \
/usr/include/signal/session_record.h \ /usr/include/signal/session_record.h \
/usr/include/signal/session_pre_key.h \ /usr/include/signal/session_pre_key.h \
/usr/include/signal/sender_key_record.h signal.hh \ /usr/include/signal/sender_key_record.h signal.hh \
deps/fmt/include/fmt/core.h /usr/include/signal/key_helper.h \ /usr/include/signal/key_helper.h /usr/include/signal/session_builder.h \
/usr/include/signal/session_builder.h \
/usr/include/signal/session_cipher.h \ /usr/include/signal/session_cipher.h \
/usr/include/signal/session_pre_key.h /usr/include/signal/protocol.h \ /usr/include/signal/session_pre_key.h /usr/include/signal/protocol.h \
/usr/include/signal/curve.h channel.hh buffer.hh /usr/include/signal/curve.h config.hh channel.hh connection.hh \
xmpp/ns.hh strophe.hh user.hh buffer.hh
plugin.hh: plugin.hh:
account.hh: account.hh:
deps/optional/include/tl/optional.hpp:
deps/fmt/include/fmt/core.h:
pgp.hh:
omemo.hh: omemo.hh:
/usr/include/signal/signal_protocol.h: /usr/include/signal/signal_protocol.h:
/usr/include/signal/ratchet.h: /usr/include/signal/ratchet.h:
@ -134,18 +149,23 @@ omemo.hh:
/usr/include/signal/session_pre_key.h: /usr/include/signal/session_pre_key.h:
/usr/include/signal/sender_key_record.h: /usr/include/signal/sender_key_record.h:
signal.hh: signal.hh:
deps/fmt/include/fmt/core.h:
/usr/include/signal/key_helper.h: /usr/include/signal/key_helper.h:
/usr/include/signal/session_builder.h: /usr/include/signal/session_builder.h:
/usr/include/signal/session_cipher.h: /usr/include/signal/session_cipher.h:
/usr/include/signal/session_pre_key.h: /usr/include/signal/session_pre_key.h:
/usr/include/signal/protocol.h: /usr/include/signal/protocol.h:
/usr/include/signal/curve.h: /usr/include/signal/curve.h:
config.hh:
channel.hh: channel.hh:
connection.hh:
xmpp/ns.hh:
strophe.hh:
user.hh:
buffer.hh: buffer.hh:
.channel.o: channel.cpp deps/fmt/include/fmt/core.h \ .channel.o: channel.cpp deps/fmt/include/fmt/core.h \
deps/optional/include/tl/optional.hpp plugin.hh account.hh omemo.hh \ deps/optional/include/tl/optional.hpp plugin.hh account.hh pgp.hh \
/usr/include/signal/signal_protocol.h /usr/include/signal/ratchet.h \ omemo.hh /usr/include/signal/signal_protocol.h \
/usr/include/signal/ratchet.h \
/usr/include/signal/signal_protocol_types.h /usr/include/signal/curve.h \ /usr/include/signal/signal_protocol_types.h /usr/include/signal/curve.h \
/usr/include/signal/session_record.h \ /usr/include/signal/session_record.h \
/usr/include/signal/session_pre_key.h \ /usr/include/signal/session_pre_key.h \
@ -153,14 +173,15 @@ buffer.hh:
/usr/include/signal/key_helper.h /usr/include/signal/session_builder.h \ /usr/include/signal/key_helper.h /usr/include/signal/session_builder.h \
/usr/include/signal/session_cipher.h \ /usr/include/signal/session_cipher.h \
/usr/include/signal/session_pre_key.h /usr/include/signal/protocol.h \ /usr/include/signal/session_pre_key.h /usr/include/signal/protocol.h \
/usr/include/signal/curve.h user.hh channel.hh input.hh buffer.hh pgp.hh \ /usr/include/signal/curve.h config.hh channel.hh connection.hh \
util.hh xmpp/node.hh xmpp/xep-0027.inl xmpp/ns.hh xmpp/xep-0030.inl \ xmpp/ns.hh strophe.hh user.hh input.hh buffer.hh util.hh xmpp/node.hh \
xmpp/xep-0045.inl xmpp/xep-0049.inl xmpp/xep-0115.inl xmpp/xep-0280.inl \ xmpp/xep-0027.inl xmpp/xep-0030.inl xmpp/xep-0045.inl xmpp/xep-0049.inl \
xmpp/xep-0319.inl xmpp/rfc-6121.inl xmpp/xep-0115.inl xmpp/xep-0280.inl xmpp/xep-0319.inl xmpp/rfc-6121.inl
deps/fmt/include/fmt/core.h: deps/fmt/include/fmt/core.h:
deps/optional/include/tl/optional.hpp: deps/optional/include/tl/optional.hpp:
plugin.hh: plugin.hh:
account.hh: account.hh:
pgp.hh:
omemo.hh: omemo.hh:
/usr/include/signal/signal_protocol.h: /usr/include/signal/signal_protocol.h:
/usr/include/signal/ratchet.h: /usr/include/signal/ratchet.h:
@ -176,15 +197,17 @@ signal.hh:
/usr/include/signal/session_pre_key.h: /usr/include/signal/session_pre_key.h:
/usr/include/signal/protocol.h: /usr/include/signal/protocol.h:
/usr/include/signal/curve.h: /usr/include/signal/curve.h:
user.hh: config.hh:
channel.hh: channel.hh:
connection.hh:
xmpp/ns.hh:
strophe.hh:
user.hh:
input.hh: input.hh:
buffer.hh: buffer.hh:
pgp.hh:
util.hh: util.hh:
xmpp/node.hh: xmpp/node.hh:
xmpp/xep-0027.inl: xmpp/xep-0027.inl:
xmpp/ns.hh:
xmpp/xep-0030.inl: xmpp/xep-0030.inl:
xmpp/xep-0045.inl: xmpp/xep-0045.inl:
xmpp/xep-0049.inl: xmpp/xep-0049.inl:
@ -192,22 +215,25 @@ xmpp/xep-0115.inl:
xmpp/xep-0280.inl: xmpp/xep-0280.inl:
xmpp/xep-0319.inl: xmpp/xep-0319.inl:
xmpp/rfc-6121.inl: xmpp/rfc-6121.inl:
.command.o: command.cpp plugin.hh account.hh omemo.hh \ .command.o: command.cpp plugin.hh account.hh \
/usr/include/signal/signal_protocol.h /usr/include/signal/ratchet.h \ deps/optional/include/tl/optional.hpp deps/fmt/include/fmt/core.h pgp.hh \
omemo.hh /usr/include/signal/signal_protocol.h \
/usr/include/signal/ratchet.h \
/usr/include/signal/signal_protocol_types.h /usr/include/signal/curve.h \ /usr/include/signal/signal_protocol_types.h /usr/include/signal/curve.h \
/usr/include/signal/session_record.h \ /usr/include/signal/session_record.h \
/usr/include/signal/session_pre_key.h \ /usr/include/signal/session_pre_key.h \
/usr/include/signal/sender_key_record.h signal.hh \ /usr/include/signal/sender_key_record.h signal.hh \
deps/fmt/include/fmt/core.h /usr/include/signal/key_helper.h \ /usr/include/signal/key_helper.h /usr/include/signal/session_builder.h \
/usr/include/signal/session_builder.h \
/usr/include/signal/session_cipher.h \ /usr/include/signal/session_cipher.h \
/usr/include/signal/session_pre_key.h /usr/include/signal/protocol.h \ /usr/include/signal/session_pre_key.h /usr/include/signal/protocol.h \
/usr/include/signal/curve.h user.hh \ /usr/include/signal/curve.h config.hh channel.hh connection.hh \
deps/optional/include/tl/optional.hpp channel.hh buffer.hh message.hh \ xmpp/ns.hh strophe.hh user.hh buffer.hh message.hh command.hh \
command.hh sexp/driver.hh sexp/scanner.hh sexp/parser.tab.hh \ sexp/driver.hh sexp/scanner.hh sexp/parser.tab.hh sexp/location.hh
sexp/location.hh
plugin.hh: plugin.hh:
account.hh: account.hh:
deps/optional/include/tl/optional.hpp:
deps/fmt/include/fmt/core.h:
pgp.hh:
omemo.hh: omemo.hh:
/usr/include/signal/signal_protocol.h: /usr/include/signal/signal_protocol.h:
/usr/include/signal/ratchet.h: /usr/include/signal/ratchet.h:
@ -217,16 +243,18 @@ omemo.hh:
/usr/include/signal/session_pre_key.h: /usr/include/signal/session_pre_key.h:
/usr/include/signal/sender_key_record.h: /usr/include/signal/sender_key_record.h:
signal.hh: signal.hh:
deps/fmt/include/fmt/core.h:
/usr/include/signal/key_helper.h: /usr/include/signal/key_helper.h:
/usr/include/signal/session_builder.h: /usr/include/signal/session_builder.h:
/usr/include/signal/session_cipher.h: /usr/include/signal/session_cipher.h:
/usr/include/signal/session_pre_key.h: /usr/include/signal/session_pre_key.h:
/usr/include/signal/protocol.h: /usr/include/signal/protocol.h:
/usr/include/signal/curve.h: /usr/include/signal/curve.h:
user.hh: config.hh:
deps/optional/include/tl/optional.hpp:
channel.hh: channel.hh:
connection.hh:
xmpp/ns.hh:
strophe.hh:
user.hh:
buffer.hh: buffer.hh:
message.hh: message.hh:
command.hh: command.hh:
@ -234,21 +262,25 @@ sexp/driver.hh:
sexp/scanner.hh: sexp/scanner.hh:
sexp/parser.tab.hh: sexp/parser.tab.hh:
sexp/location.hh: sexp/location.hh:
.completion.o: completion.cpp plugin.hh config.hh account.hh omemo.hh \ .completion.o: completion.cpp plugin.hh config.hh \
/usr/include/signal/signal_protocol.h /usr/include/signal/ratchet.h \ deps/optional/include/tl/optional.hpp deps/fmt/include/fmt/core.h \
account.hh pgp.hh omemo.hh /usr/include/signal/signal_protocol.h \
/usr/include/signal/ratchet.h \
/usr/include/signal/signal_protocol_types.h /usr/include/signal/curve.h \ /usr/include/signal/signal_protocol_types.h /usr/include/signal/curve.h \
/usr/include/signal/session_record.h \ /usr/include/signal/session_record.h \
/usr/include/signal/session_pre_key.h \ /usr/include/signal/session_pre_key.h \
/usr/include/signal/sender_key_record.h signal.hh \ /usr/include/signal/sender_key_record.h signal.hh \
deps/fmt/include/fmt/core.h /usr/include/signal/key_helper.h \ /usr/include/signal/key_helper.h /usr/include/signal/session_builder.h \
/usr/include/signal/session_builder.h \
/usr/include/signal/session_cipher.h \ /usr/include/signal/session_cipher.h \
/usr/include/signal/session_pre_key.h /usr/include/signal/protocol.h \ /usr/include/signal/session_pre_key.h /usr/include/signal/protocol.h \
/usr/include/signal/curve.h channel.hh user.hh \ /usr/include/signal/curve.h channel.hh connection.hh xmpp/ns.hh \
deps/optional/include/tl/optional.hpp buffer.hh completion.hh strophe.hh user.hh buffer.hh completion.hh
plugin.hh: plugin.hh:
config.hh: config.hh:
deps/optional/include/tl/optional.hpp:
deps/fmt/include/fmt/core.h:
account.hh: account.hh:
pgp.hh:
omemo.hh: omemo.hh:
/usr/include/signal/signal_protocol.h: /usr/include/signal/signal_protocol.h:
/usr/include/signal/ratchet.h: /usr/include/signal/ratchet.h:
@ -258,7 +290,6 @@ omemo.hh:
/usr/include/signal/session_pre_key.h: /usr/include/signal/session_pre_key.h:
/usr/include/signal/sender_key_record.h: /usr/include/signal/sender_key_record.h:
signal.hh: signal.hh:
deps/fmt/include/fmt/core.h:
/usr/include/signal/key_helper.h: /usr/include/signal/key_helper.h:
/usr/include/signal/session_builder.h: /usr/include/signal/session_builder.h:
/usr/include/signal/session_cipher.h: /usr/include/signal/session_cipher.h:
@ -266,23 +297,30 @@ deps/fmt/include/fmt/core.h:
/usr/include/signal/protocol.h: /usr/include/signal/protocol.h:
/usr/include/signal/curve.h: /usr/include/signal/curve.h:
channel.hh: channel.hh:
connection.hh:
xmpp/ns.hh:
strophe.hh:
user.hh: user.hh:
deps/optional/include/tl/optional.hpp:
buffer.hh: buffer.hh:
completion.hh: completion.hh:
.config.o: config.cpp plugin.hh account.hh omemo.hh \ .config.o: config.cpp plugin.hh account.hh \
/usr/include/signal/signal_protocol.h /usr/include/signal/ratchet.h \ deps/optional/include/tl/optional.hpp deps/fmt/include/fmt/core.h pgp.hh \
omemo.hh /usr/include/signal/signal_protocol.h \
/usr/include/signal/ratchet.h \
/usr/include/signal/signal_protocol_types.h /usr/include/signal/curve.h \ /usr/include/signal/signal_protocol_types.h /usr/include/signal/curve.h \
/usr/include/signal/session_record.h \ /usr/include/signal/session_record.h \
/usr/include/signal/session_pre_key.h \ /usr/include/signal/session_pre_key.h \
/usr/include/signal/sender_key_record.h signal.hh \ /usr/include/signal/sender_key_record.h signal.hh \
deps/fmt/include/fmt/core.h /usr/include/signal/key_helper.h \ /usr/include/signal/key_helper.h /usr/include/signal/session_builder.h \
/usr/include/signal/session_builder.h \
/usr/include/signal/session_cipher.h \ /usr/include/signal/session_cipher.h \
/usr/include/signal/session_pre_key.h /usr/include/signal/protocol.h \ /usr/include/signal/session_pre_key.h /usr/include/signal/protocol.h \
/usr/include/signal/curve.h config.hh /usr/include/signal/curve.h config.hh channel.hh connection.hh \
xmpp/ns.hh strophe.hh user.hh
plugin.hh: plugin.hh:
account.hh: account.hh:
deps/optional/include/tl/optional.hpp:
deps/fmt/include/fmt/core.h:
pgp.hh:
omemo.hh: omemo.hh:
/usr/include/signal/signal_protocol.h: /usr/include/signal/signal_protocol.h:
/usr/include/signal/ratchet.h: /usr/include/signal/ratchet.h:
@ -292,7 +330,6 @@ omemo.hh:
/usr/include/signal/session_pre_key.h: /usr/include/signal/session_pre_key.h:
/usr/include/signal/sender_key_record.h: /usr/include/signal/sender_key_record.h:
signal.hh: signal.hh:
deps/fmt/include/fmt/core.h:
/usr/include/signal/key_helper.h: /usr/include/signal/key_helper.h:
/usr/include/signal/session_builder.h: /usr/include/signal/session_builder.h:
/usr/include/signal/session_cipher.h: /usr/include/signal/session_cipher.h:
@ -300,6 +337,11 @@ deps/fmt/include/fmt/core.h:
/usr/include/signal/protocol.h: /usr/include/signal/protocol.h:
/usr/include/signal/curve.h: /usr/include/signal/curve.h:
config.hh: config.hh:
channel.hh:
connection.hh:
xmpp/ns.hh:
strophe.hh:
user.hh:
.connection.o: connection.cpp deps/fmt/include/fmt/core.h \ .connection.o: connection.cpp deps/fmt/include/fmt/core.h \
deps/fmt/include/fmt/chrono.h deps/fmt/include/fmt/format.h \ deps/fmt/include/fmt/chrono.h deps/fmt/include/fmt/format.h \
deps/fmt/include/fmt/core.h /usr/include/libxml2/libxml/uri.h \ deps/fmt/include/fmt/core.h /usr/include/libxml2/libxml/uri.h \
@ -324,8 +366,8 @@ config.hh:
deps/optional/include/tl/optional.hpp xmpp/xep-0027.inl xmpp/ns.hh \ deps/optional/include/tl/optional.hpp xmpp/xep-0027.inl xmpp/ns.hh \
xmpp/xep-0030.inl xmpp/xep-0045.inl xmpp/xep-0049.inl xmpp/xep-0115.inl \ xmpp/xep-0030.inl xmpp/xep-0045.inl xmpp/xep-0049.inl xmpp/xep-0115.inl \
xmpp/xep-0280.inl xmpp/xep-0319.inl xmpp/rfc-6121.inl xmpp/stanza.hh \ xmpp/xep-0280.inl xmpp/xep-0319.inl xmpp/rfc-6121.inl xmpp/stanza.hh \
config.hh account.hh omemo.hh /usr/include/signal/signal_protocol.h \ config.hh account.hh pgp.hh omemo.hh \
/usr/include/signal/ratchet.h \ /usr/include/signal/signal_protocol.h /usr/include/signal/ratchet.h \
/usr/include/signal/signal_protocol_types.h /usr/include/signal/curve.h \ /usr/include/signal/signal_protocol_types.h /usr/include/signal/curve.h \
/usr/include/signal/session_record.h \ /usr/include/signal/session_record.h \
/usr/include/signal/session_pre_key.h \ /usr/include/signal/session_pre_key.h \
@ -333,7 +375,7 @@ config.hh:
/usr/include/signal/key_helper.h /usr/include/signal/session_builder.h \ /usr/include/signal/key_helper.h /usr/include/signal/session_builder.h \
/usr/include/signal/session_cipher.h \ /usr/include/signal/session_cipher.h \
/usr/include/signal/session_pre_key.h /usr/include/signal/protocol.h \ /usr/include/signal/session_pre_key.h /usr/include/signal/protocol.h \
/usr/include/signal/curve.h user.hh channel.hh connection.hh pgp.hh \ /usr/include/signal/curve.h channel.hh connection.hh strophe.hh user.hh \
util.hh deps/diff/diff.h util.hh deps/diff/diff.h
deps/fmt/include/fmt/core.h: deps/fmt/include/fmt/core.h:
deps/fmt/include/fmt/chrono.h: deps/fmt/include/fmt/chrono.h:
@ -375,6 +417,7 @@ xmpp/rfc-6121.inl:
xmpp/stanza.hh: xmpp/stanza.hh:
config.hh: config.hh:
account.hh: account.hh:
pgp.hh:
omemo.hh: omemo.hh:
/usr/include/signal/signal_protocol.h: /usr/include/signal/signal_protocol.h:
/usr/include/signal/ratchet.h: /usr/include/signal/ratchet.h:
@ -390,25 +433,30 @@ signal.hh:
/usr/include/signal/session_pre_key.h: /usr/include/signal/session_pre_key.h:
/usr/include/signal/protocol.h: /usr/include/signal/protocol.h:
/usr/include/signal/curve.h: /usr/include/signal/curve.h:
user.hh:
channel.hh: channel.hh:
connection.hh: connection.hh:
pgp.hh: strophe.hh:
user.hh:
util.hh: util.hh:
deps/diff/diff.h: deps/diff/diff.h:
.input.o: input.cpp plugin.hh account.hh omemo.hh \ .input.o: input.cpp plugin.hh account.hh \
/usr/include/signal/signal_protocol.h /usr/include/signal/ratchet.h \ deps/optional/include/tl/optional.hpp deps/fmt/include/fmt/core.h pgp.hh \
omemo.hh /usr/include/signal/signal_protocol.h \
/usr/include/signal/ratchet.h \
/usr/include/signal/signal_protocol_types.h /usr/include/signal/curve.h \ /usr/include/signal/signal_protocol_types.h /usr/include/signal/curve.h \
/usr/include/signal/session_record.h \ /usr/include/signal/session_record.h \
/usr/include/signal/session_pre_key.h \ /usr/include/signal/session_pre_key.h \
/usr/include/signal/sender_key_record.h signal.hh \ /usr/include/signal/sender_key_record.h signal.hh \
deps/fmt/include/fmt/core.h /usr/include/signal/key_helper.h \ /usr/include/signal/key_helper.h /usr/include/signal/session_builder.h \
/usr/include/signal/session_builder.h \
/usr/include/signal/session_cipher.h \ /usr/include/signal/session_cipher.h \
/usr/include/signal/session_pre_key.h /usr/include/signal/protocol.h \ /usr/include/signal/session_pre_key.h /usr/include/signal/protocol.h \
/usr/include/signal/curve.h channel.hh buffer.hh message.hh input.hh /usr/include/signal/curve.h config.hh channel.hh connection.hh \
xmpp/ns.hh strophe.hh user.hh buffer.hh message.hh input.hh
plugin.hh: plugin.hh:
account.hh: account.hh:
deps/optional/include/tl/optional.hpp:
deps/fmt/include/fmt/core.h:
pgp.hh:
omemo.hh: omemo.hh:
/usr/include/signal/signal_protocol.h: /usr/include/signal/signal_protocol.h:
/usr/include/signal/ratchet.h: /usr/include/signal/ratchet.h:
@ -418,31 +466,39 @@ omemo.hh:
/usr/include/signal/session_pre_key.h: /usr/include/signal/session_pre_key.h:
/usr/include/signal/sender_key_record.h: /usr/include/signal/sender_key_record.h:
signal.hh: signal.hh:
deps/fmt/include/fmt/core.h:
/usr/include/signal/key_helper.h: /usr/include/signal/key_helper.h:
/usr/include/signal/session_builder.h: /usr/include/signal/session_builder.h:
/usr/include/signal/session_cipher.h: /usr/include/signal/session_cipher.h:
/usr/include/signal/session_pre_key.h: /usr/include/signal/session_pre_key.h:
/usr/include/signal/protocol.h: /usr/include/signal/protocol.h:
/usr/include/signal/curve.h: /usr/include/signal/curve.h:
config.hh:
channel.hh: channel.hh:
connection.hh:
xmpp/ns.hh:
strophe.hh:
user.hh:
buffer.hh: buffer.hh:
message.hh: message.hh:
input.hh: input.hh:
.message.o: message.cpp plugin.hh account.hh omemo.hh \ .message.o: message.cpp plugin.hh account.hh \
/usr/include/signal/signal_protocol.h /usr/include/signal/ratchet.h \ deps/optional/include/tl/optional.hpp deps/fmt/include/fmt/core.h pgp.hh \
omemo.hh /usr/include/signal/signal_protocol.h \
/usr/include/signal/ratchet.h \
/usr/include/signal/signal_protocol_types.h /usr/include/signal/curve.h \ /usr/include/signal/signal_protocol_types.h /usr/include/signal/curve.h \
/usr/include/signal/session_record.h \ /usr/include/signal/session_record.h \
/usr/include/signal/session_pre_key.h \ /usr/include/signal/session_pre_key.h \
/usr/include/signal/sender_key_record.h signal.hh \ /usr/include/signal/sender_key_record.h signal.hh \
deps/fmt/include/fmt/core.h /usr/include/signal/key_helper.h \ /usr/include/signal/key_helper.h /usr/include/signal/session_builder.h \
/usr/include/signal/session_builder.h \
/usr/include/signal/session_cipher.h \ /usr/include/signal/session_cipher.h \
/usr/include/signal/session_pre_key.h /usr/include/signal/protocol.h \ /usr/include/signal/session_pre_key.h /usr/include/signal/protocol.h \
/usr/include/signal/curve.h channel.hh user.hh \ /usr/include/signal/curve.h config.hh channel.hh connection.hh \
deps/optional/include/tl/optional.hpp message.hh xmpp/ns.hh strophe.hh user.hh message.hh
plugin.hh: plugin.hh:
account.hh: account.hh:
deps/optional/include/tl/optional.hpp:
deps/fmt/include/fmt/core.h:
pgp.hh:
omemo.hh: omemo.hh:
/usr/include/signal/signal_protocol.h: /usr/include/signal/signal_protocol.h:
/usr/include/signal/ratchet.h: /usr/include/signal/ratchet.h:
@ -452,16 +508,18 @@ omemo.hh:
/usr/include/signal/session_pre_key.h: /usr/include/signal/session_pre_key.h:
/usr/include/signal/sender_key_record.h: /usr/include/signal/sender_key_record.h:
signal.hh: signal.hh:
deps/fmt/include/fmt/core.h:
/usr/include/signal/key_helper.h: /usr/include/signal/key_helper.h:
/usr/include/signal/session_builder.h: /usr/include/signal/session_builder.h:
/usr/include/signal/session_cipher.h: /usr/include/signal/session_cipher.h:
/usr/include/signal/session_pre_key.h: /usr/include/signal/session_pre_key.h:
/usr/include/signal/protocol.h: /usr/include/signal/protocol.h:
/usr/include/signal/curve.h: /usr/include/signal/curve.h:
config.hh:
channel.hh: channel.hh:
connection.hh:
xmpp/ns.hh:
strophe.hh:
user.hh: user.hh:
deps/optional/include/tl/optional.hpp:
message.hh: message.hh:
.omemo.o: omemo.cpp deps/fmt/include/fmt/core.h \ .omemo.o: omemo.cpp deps/fmt/include/fmt/core.h \
deps/optional/include/tl/optional.hpp \ deps/optional/include/tl/optional.hpp \
@ -738,7 +796,7 @@ message.hh:
deps/range-v3/include/range/v3/view/trim.hpp \ deps/range-v3/include/range/v3/view/trim.hpp \
deps/range-v3/include/range/v3/view/unbounded.hpp \ deps/range-v3/include/range/v3/view/unbounded.hpp \
deps/range-v3/include/range/v3/view/unique.hpp plugin.hh xmpp/stanza.hh \ deps/range-v3/include/range/v3/view/unique.hpp plugin.hh xmpp/stanza.hh \
account.hh omemo.hh /usr/include/signal/signal_protocol.h \ account.hh pgp.hh omemo.hh /usr/include/signal/signal_protocol.h \
/usr/include/signal/ratchet.h \ /usr/include/signal/ratchet.h \
/usr/include/signal/signal_protocol_types.h /usr/include/signal/curve.h \ /usr/include/signal/signal_protocol_types.h /usr/include/signal/curve.h \
/usr/include/signal/session_record.h \ /usr/include/signal/session_record.h \
@ -747,7 +805,8 @@ message.hh:
/usr/include/signal/key_helper.h /usr/include/signal/session_builder.h \ /usr/include/signal/key_helper.h /usr/include/signal/session_builder.h \
/usr/include/signal/session_cipher.h \ /usr/include/signal/session_cipher.h \
/usr/include/signal/session_pre_key.h /usr/include/signal/protocol.h \ /usr/include/signal/session_pre_key.h /usr/include/signal/protocol.h \
/usr/include/signal/curve.h gcrypt.hh util.hh /usr/include/signal/curve.h config.hh channel.hh connection.hh \
xmpp/ns.hh strophe.hh user.hh gcrypt.hh util.hh
deps/fmt/include/fmt/core.h: deps/fmt/include/fmt/core.h:
deps/optional/include/tl/optional.hpp: deps/optional/include/tl/optional.hpp:
deps/range-v3/include/range/v3/all.hpp: deps/range-v3/include/range/v3/all.hpp:
@ -1026,6 +1085,7 @@ deps/range-v3/include/range/v3/view/unique.hpp:
plugin.hh: plugin.hh:
xmpp/stanza.hh: xmpp/stanza.hh:
account.hh: account.hh:
pgp.hh:
omemo.hh: omemo.hh:
/usr/include/signal/signal_protocol.h: /usr/include/signal/signal_protocol.h:
/usr/include/signal/ratchet.h: /usr/include/signal/ratchet.h:
@ -1041,26 +1101,36 @@ signal.hh:
/usr/include/signal/session_pre_key.h: /usr/include/signal/session_pre_key.h:
/usr/include/signal/protocol.h: /usr/include/signal/protocol.h:
/usr/include/signal/curve.h: /usr/include/signal/curve.h:
config.hh:
channel.hh:
connection.hh:
xmpp/ns.hh:
strophe.hh:
user.hh:
gcrypt.hh: gcrypt.hh:
util.hh: util.hh:
.pgp.o: pgp.cpp deps/fmt/include/fmt/core.h plugin.hh pgp.hh .pgp.o: pgp.cpp deps/fmt/include/fmt/core.h plugin.hh pgp.hh
deps/fmt/include/fmt/core.h: deps/fmt/include/fmt/core.h:
plugin.hh: plugin.hh:
pgp.hh: pgp.hh:
.user.o: user.cpp plugin.hh account.hh omemo.hh \ .user.o: user.cpp plugin.hh account.hh \
/usr/include/signal/signal_protocol.h /usr/include/signal/ratchet.h \ deps/optional/include/tl/optional.hpp deps/fmt/include/fmt/core.h pgp.hh \
omemo.hh /usr/include/signal/signal_protocol.h \
/usr/include/signal/ratchet.h \
/usr/include/signal/signal_protocol_types.h /usr/include/signal/curve.h \ /usr/include/signal/signal_protocol_types.h /usr/include/signal/curve.h \
/usr/include/signal/session_record.h \ /usr/include/signal/session_record.h \
/usr/include/signal/session_pre_key.h \ /usr/include/signal/session_pre_key.h \
/usr/include/signal/sender_key_record.h signal.hh \ /usr/include/signal/sender_key_record.h signal.hh \
deps/fmt/include/fmt/core.h /usr/include/signal/key_helper.h \ /usr/include/signal/key_helper.h /usr/include/signal/session_builder.h \
/usr/include/signal/session_builder.h \
/usr/include/signal/session_cipher.h \ /usr/include/signal/session_cipher.h \
/usr/include/signal/session_pre_key.h /usr/include/signal/protocol.h \ /usr/include/signal/session_pre_key.h /usr/include/signal/protocol.h \
/usr/include/signal/curve.h user.hh \ /usr/include/signal/curve.h config.hh channel.hh connection.hh \
deps/optional/include/tl/optional.hpp channel.hh xmpp/ns.hh strophe.hh user.hh
plugin.hh: plugin.hh:
account.hh: account.hh:
deps/optional/include/tl/optional.hpp:
deps/fmt/include/fmt/core.h:
pgp.hh:
omemo.hh: omemo.hh:
/usr/include/signal/signal_protocol.h: /usr/include/signal/signal_protocol.h:
/usr/include/signal/ratchet.h: /usr/include/signal/ratchet.h:
@ -1070,16 +1140,18 @@ omemo.hh:
/usr/include/signal/session_pre_key.h: /usr/include/signal/session_pre_key.h:
/usr/include/signal/sender_key_record.h: /usr/include/signal/sender_key_record.h:
signal.hh: signal.hh:
deps/fmt/include/fmt/core.h:
/usr/include/signal/key_helper.h: /usr/include/signal/key_helper.h:
/usr/include/signal/session_builder.h: /usr/include/signal/session_builder.h:
/usr/include/signal/session_cipher.h: /usr/include/signal/session_cipher.h:
/usr/include/signal/session_pre_key.h: /usr/include/signal/session_pre_key.h:
/usr/include/signal/protocol.h: /usr/include/signal/protocol.h:
/usr/include/signal/curve.h: /usr/include/signal/curve.h:
user.hh: config.hh:
deps/optional/include/tl/optional.hpp:
channel.hh: channel.hh:
connection.hh:
xmpp/ns.hh:
strophe.hh:
user.hh:
.util.o: util.cpp plugin.hh util.hh .util.o: util.cpp plugin.hh util.hh
plugin.hh: plugin.hh:
util.hh: util.hh:

@ -4,7 +4,17 @@
((c-mode ((c-mode
(eval . (setq-local flycheck-clang-include-path (eval . (setq-local flycheck-clang-include-path
(list (expand-file-name "libstrophe" (projectile-project-root)) (list (expand-file-name "libstrophe" (projectile-project-root))
(expand-file-name "json-c" (projectile-project-root))))) (expand-file-name "json-c" (projectile-project-root))
(string-trim-right
(substring
(shell-command-to-string "xml2-config --cflags") 2))
(string-trim-right
(substring
(shell-command-to-string "pkg-config --cflags libsignal-protocol-c") 2))
"/usr/include/libxml2/" "/usr/include/signal"
(expand-file-name "deps/fmt/include" (projectile-project-root))
(expand-file-name "deps/optional/include" (projectile-project-root))
(expand-file-name "deps/range-v3/include" (projectile-project-root)))))
(eval . (setq-local company-clang-arguments (eval . (setq-local company-clang-arguments
(list (concat "-I" (expand-file-name "libstrophe" (projectile-project-root))) (list (concat "-I" (expand-file-name "libstrophe" (projectile-project-root)))
(concat "-I" (expand-file-name "json-c" (projectile-project-root)))))) (concat "-I" (expand-file-name "json-c" (projectile-project-root))))))
@ -17,6 +27,6 @@
"'; /debug tags")) "'; /debug tags"))
" "))) " ")))
(flycheck-clang-warnings . ("all" "extra" "error-implicit-function-declaration" "no-missing-field-initializers")) (flycheck-clang-warnings . ("all" "extra" "error-implicit-function-declaration" "no-missing-field-initializers"))
(flycheck-clang-language-standard . "gnu99") (flycheck-clang-language-standard . "c++20")
(flycheck-checker . c/c++-clang) (flycheck-checker . c/c++-clang)
(projectile-project-compilation-cmd . "bear -- make -j8"))) (projectile-project-compilation-cmd . "bear -- make -j8")))

1
.gitignore vendored

@ -1,6 +1,7 @@
.direnv .direnv
*~ *~
compile_commands.json compile_commands.json
launch.json
.cache .cache
cscope* cscope*
*.d *.d

@ -8,6 +8,7 @@
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#include <assert.h> #include <assert.h>
#include <fmt/core.h>
#include <libxml/xmlwriter.h> #include <libxml/xmlwriter.h>
#include <weechat/weechat-plugin.h> #include <weechat/weechat-plugin.h>
@ -22,291 +23,12 @@
#include "channel.hh" #include "channel.hh"
#include "buffer.hh" #include "buffer.hh"
std::unordered_map<std::string, struct t_account *> accounts; std::unordered_map<std::string, weechat::account> weechat::accounts;
char *account_options[ACCOUNT_NUM_OPTIONS][2] =
{ { (char*)"jid", (char*)"" },
{ (char*)"password", (char*)"" },
{ (char*)"tls", (char*)"normal" },
{ (char*)"nickname", (char*)"" },
{ (char*)"autoconnect", (char*)"" },
{ (char*)"resource", (char*)"" },
{ (char*)"status", (char*)"probably about to segfault" },
{ (char*)"pgp_path", (char*)"" },
{ (char*)"pgp_keyid", (char*)"" },
};
struct t_account *account__search(const char *name)
{
if (!name)
return NULL;
auto ptr_account = accounts.find(name);
if (ptr_account != accounts.end())
{
return ptr_account->second;
}
/* account not found */
return NULL;
}
struct t_account *account__casesearch(const char *name)
{
if (!name)
return NULL;
for (auto ptr_account : accounts)
{
if (weechat_strcasecmp(ptr_account.second->name, name) == 0)
return ptr_account.second;
}
/* account not found */
return NULL;
}
int account__search_option(const char *option_name)
{
int i;
if (!option_name)
return -1;
for (i = 0; i < ACCOUNT_NUM_OPTIONS; i++)
{
if (weechat_strcasecmp(account_options[i][0], option_name) == 0)
return i;
}
/* account option not found */
return -1;
}
struct t_account_device *account__search_device(struct t_account *account, uint32_t id)
{
struct t_account_device *ptr_device;
if (!account)
return NULL;
for (ptr_device = account->devices; ptr_device;
ptr_device = ptr_device->next_device)
{
if (ptr_device->id == id)
return ptr_device;
}
return NULL;
}
void account__add_device(struct t_account *account,
struct t_account_device *device)
{
struct t_account_device *new_device;
new_device = account__search_device(account, device->id);
if (!new_device)
{
new_device = new struct t_account_device;
new_device->id = device->id;
new_device->name = strdup(device->name);
new_device->label = device->label ? strdup(device->label) : NULL;
new_device->prev_device = account->last_device;
new_device->next_device = NULL;
if (account->last_device)
(account->last_device)->next_device = new_device;
else
account->devices = new_device;
account->last_device = new_device;
}
}
void account__free_device(struct t_account *account, struct t_account_device *device)
{
struct t_account_device *new_devices;
if (!account || !device)
return;
/* remove device from devices list */
if (account->last_device == device)
account->last_device = device->prev_device;
if (device->prev_device)
{
(device->prev_device)->next_device = device->next_device;
new_devices = account->devices;
}
else
new_devices = device->next_device;
if (device->next_device)
(device->next_device)->prev_device = device->prev_device;
/* free device data */
if (device->label)
free(device->label);
if (device->name)
free(device->name);
delete device;
account->devices = new_devices;
}
void account__free_device_all(struct t_account *account)
{
while (account->devices)
account__free_device(account, account->devices);
}
xmpp_stanza_t *account__get_devicelist(struct t_account *account)
{
xmpp_stanza_t *parent, **children;
struct t_account_device *device;
const char *ns, *node;
char id[64] = {0};
int i = 0;
device = new struct t_account_device;
device->id = account->omemo.device_id;
snprintf(id, sizeof(id), "%u", device->id);
device->name = strdup(id);
device->label = strdup("weechat");
children = (xmpp_stanza_t **)malloc(sizeof(xmpp_stanza_t *) * 128);
children[i++] = stanza__iq_pubsub_publish_item_list_device(
account->context, NULL, with_noop(device->name), NULL);
free(device->label);
free(device->name);
delete device;
for (device = account->devices; device;
device = device->next_device)
{
if (device->id != account->omemo.device_id)
children[i++] = stanza__iq_pubsub_publish_item_list_device(
account->context, NULL, with_noop(device->name), NULL);
}
children[i] = NULL;
node = "eu.siacs.conversations.axolotl";
children[0] = stanza__iq_pubsub_publish_item_list(
account->context, NULL, children, with_noop(node));
children[1] = NULL;
children[0] = stanza__iq_pubsub_publish_item(
account->context, NULL, children, with_noop("current"));
node = "eu.siacs.conversations.axolotl.devicelist";
children[0] = stanza__iq_pubsub_publish(account->context,
NULL, children,
with_noop(node));
ns = "http://jabber.org/protocol/pubsub";
children[0] = stanza__iq_pubsub(account->context, NULL,
children, with_noop(ns));
parent = stanza__iq(account->context, NULL,
children, NULL, strdup("announce1"),
NULL, NULL, strdup("set"));
free(children);
return parent;
}
struct t_account_mam_query *account__add_mam_query(struct t_account *account,
struct t_channel *channel,
const char *id,
time_t *start, time_t *end)
{
struct t_account_mam_query *mam_query;
if (!(mam_query = account__mam_query_search(account, id)))
{
mam_query = (struct t_account_mam_query*)malloc(sizeof(struct t_account_mam_query));
mam_query->id = strdup(id);
mam_query->with = strdup(channel->id);
mam_query->has_start = start != NULL;
if (mam_query->has_start)
mam_query->start = *start;
mam_query->has_end = end != NULL;
if (mam_query->has_end)
mam_query->end = *end;
mam_query->prev_mam_query = account->last_mam_query;
mam_query->next_mam_query = NULL;
if (account->last_mam_query)
(account->last_mam_query)->next_mam_query = mam_query;
else
account->mam_queries = mam_query;
account->last_mam_query = mam_query;
}
return mam_query;
}
struct t_account_mam_query *account__mam_query_search(struct t_account *account,
const char *id)
{
struct t_account_mam_query *ptr_mam_query;
if (!account || !id)
return NULL;
for (ptr_mam_query = account->mam_queries; ptr_mam_query;
ptr_mam_query = ptr_mam_query->next_mam_query)
{
if (weechat_strcasecmp(ptr_mam_query->id, id) == 0)
return ptr_mam_query;
}
return NULL;
}
void account__mam_query_free(struct t_account *account, void weechat::log_emit(void *const userdata, const xmpp_log_level_t level,
struct t_account_mam_query *mam_query)
{
struct t_account_mam_query *new_mam_queries;
if (!account || !mam_query)
return;
/* remove mam_query from mam_queries list */
if (account->last_mam_query == mam_query)
account->last_mam_query = mam_query->prev_mam_query;
if (mam_query->prev_mam_query)
{
(mam_query->prev_mam_query)->next_mam_query = mam_query->next_mam_query;
new_mam_queries = account->mam_queries;
}
else
new_mam_queries = mam_query->next_mam_query;
if (mam_query->next_mam_query)
(mam_query->next_mam_query)->prev_mam_query = mam_query->prev_mam_query;
/* free mam_query data */
if (mam_query->id)
free(mam_query->id);
if (mam_query->with)
free(mam_query->with);
free(mam_query);
account->mam_queries = new_mam_queries;
}
void account__mam_query_free_all(struct t_account *account)
{
while (account->mam_queries)
account__mam_query_free(account, account->mam_queries);
}
void account__log_emit_weechat(void *const userdata, const xmpp_log_level_t level,
const char *const area, const char *const msg) const char *const area, const char *const msg)
{ {
struct t_account *account = (struct t_account*)userdata; auto account = static_cast<weechat::account*>(userdata);
static const char *log_level_name[4] = {"debug", "info", "warn", "error"}; static const char *log_level_name[4] = {"debug", "info", "warn", "error"};
@ -389,331 +111,338 @@ void account__log_emit_weechat(void *const userdata, const xmpp_log_level_t leve
} }
} }
struct t_account *account__alloc(const char *name) bool weechat::account::search(weechat::account* &out,
const std::string name, bool casesensitive)
{ {
struct t_account *new_account; if (name.empty())
int i, length; return false;
char *option_name;
if (account__casesearch(name)) if (casesensitive)
return NULL; {
for (auto& account : weechat::accounts)
{
if (weechat_strcasecmp(account.second.name.data(), name.data()) == 0)
{
out = &account.second;
return true;
}
}
}
else if (auto account = accounts.find(name); account != accounts.end())
{
out = &account->second;
return true;
}
/* alloc memory for new account */ (void) out;
new_account = new struct t_account; return false;
std::memset(&new_account->omemo, 0, sizeof(new_account->omemo)); }
if (!new_account)
bool weechat::account::search_device(weechat::account::device* out, std::uint32_t id)
{
if (id == 0)
return false;
if (auto device = devices.find(id); device != devices.end())
{ {
weechat_printf(NULL, out = &device->second;
_("%s%s: error when allocating new account"), return true;
weechat_prefix("error"), WEECHAT_XMPP_PLUGIN_NAME); }
(void) out;
return NULL; return NULL;
}
void weechat::account::add_device(weechat::account::device *device)
{
if (!devices.contains(device->id))
{
devices[device->id].id = device->id;
devices[device->id].name = device->name;
devices[device->id].label = device->label;
} }
}
accounts[name] = new_account; void weechat::account::device_free_all()
{
devices.clear();
}
/* set name */ xmpp_stanza_t *weechat::account::get_devicelist()
new_account->name = strdup(name); {
int i = 0;
/* internal vars */ account::device device;
new_account->reloading_from_config = 0;
new_account->is_connected = 0; device.id = omemo.device_id;
new_account->disconnected = 0; device.name = fmt::format("%u", device.id);
device.label = "weechat";
new_account->current_retry = 0; auto children = (xmpp_stanza_t **)malloc(sizeof(xmpp_stanza_t *) * 128);
new_account->reconnect_delay = 0; children[i++] = stanza__iq_pubsub_publish_item_list_device(
new_account->reconnect_start = 0; context, NULL, with_noop(device.name.data()), NULL);
new_account->logger.handler = &account__log_emit_weechat; for (auto& device : devices)
new_account->logger.userdata = new_account;
new_account->memory.alloc = [](const size_t size, void *const) {
return calloc(1, size);
};
new_account->memory.free = [](void *ptr, void *const) {
free(ptr);
};
new_account->memory.realloc = [](void *ptr, const size_t size, void *const) {
return realloc(ptr, size);
};
new_account->memory.userdata = new_account;
new_account->context = xmpp_ctx_new(&new_account->memory, &new_account->logger);
new_account->connection = NULL;
new_account->buffer = NULL;
new_account->buffer_as_string = NULL;
new_account->devices = NULL;
new_account->last_device = NULL;
new_account->mam_queries = NULL;
new_account->last_mam_query = NULL;
new_account->users = NULL;
new_account->last_user = NULL;
new_account->channels = NULL;
new_account->last_channel = NULL;
/* create options with null value */
for (i = 0; i < ACCOUNT_NUM_OPTIONS; i++)
{ {
new_account->options[i] = NULL; if (device.first != omemo.device_id)
children[i++] = stanza__iq_pubsub_publish_item_list_device(
length = strlen(new_account->name) + 1 + context, NULL, with_noop(device.second.name.data()), NULL);
strlen(account_options[i][0]) +
512 + /* inherited option name(xmpp.account_default.xxx) */
1;
option_name = (char*)malloc(length);
if (option_name)
{
snprintf(option_name, length, "%s.%s << xmpp.account_default.%s",
new_account->name,
account_options[i][0],
account_options[i][0]);
new_account->options[i] = config__account_new_option(
config_file,
config_section_account,
i,
option_name,
account_options[i][1],
account_options[i][1],
0,
&config__account_check_value_cb,
account_options[i][0],
NULL,
&config__account_change_cb,
account_options[i][0],
NULL);
config__account_change_cb(account_options[i][0], NULL,
new_account->options[i]);
free(option_name);
}
} }
return new_account; children[i] = NULL;
const char *node = "eu.siacs.conversations.axolotl";
children[0] = stanza__iq_pubsub_publish_item_list(
context, NULL, children, with_noop(node));
children[1] = NULL;
children[0] = stanza__iq_pubsub_publish_item(
context, NULL, children, with_noop("current"));
node = "eu.siacs.conversations.axolotl.devicelist";
children[0] = stanza__iq_pubsub_publish(context, NULL, children, with_noop(node));
const char *ns = "http://jabber.org/protocol/pubsub";
children[0] = stanza__iq_pubsub(context, NULL, children, with_noop(ns));
xmpp_stanza_t * parent = stanza__iq(context, NULL,
children, NULL, strdup("announce1"),
NULL, NULL, strdup("set"));
free(children);
return parent;
} }
void account__free_data(struct t_account *account) void weechat::account::add_mam_query(const std::string id, const std::string with,
tl::optional<time_t> start, tl::optional<time_t> end)
{ {
//int i; if (!mam_queries.contains(id))
{
mam_queries[id].id = id;
mam_queries[id].with = with;
if (!account) mam_queries[id].start = start;
return; mam_queries[id].end = end;
}
}
/* free linked lists */ bool weechat::account::mam_query_search(weechat::account::mam_query* out,
/* const std::string id)
for (i = 0; i < IRC_SERVER_NUM_OUTQUEUES_PRIO; i++) {
if (id.empty())
return false;
if (auto mam_query = mam_queries.find(id); mam_query != mam_queries.end())
{ {
account__outqueue_free_all(account, i); out = &mam_query->second;
return true;
} }
xmpp_redirect_free_all(account);
xmpp_notify_free_all(account);
*/
account__free_device_all(account);
account__mam_query_free_all(account);
channel__free_all(account);
user__free_all(account);
/* free hashtables */
/*
weechat_hashtable_free(account->join_manual);
weechat_hashtable_free(account->join_channel_key);
weechat_hashtable_free(account->join_noswitch);
*/
/* close xmpp context */ (void) out;
if (account->connection) return false;
xmpp_conn_release(account->connection); }
if (account->context)
xmpp_ctx_free(account->context);
/* free account data */ void weechat::account::mam_query_remove(const std::string id)
//for (i = 0; i < ACCOUNT_NUM_OPTIONS; i++) {
//{ mam_queries.erase(id);
// if (account->options[i]) }
// weechat_config_option_free(account->options[i]);
//}
if (account->name) void weechat::account::mam_query_free_all()
free(account->name); {
mam_queries.clear();
}
if (account->buffer_as_string) xmpp_log_t make_logger(void *userdata)
free(account->buffer_as_string); {
xmpp_log_t logger = { nullptr };
logger.handler = &weechat::log_emit;
logger.userdata = userdata;
return logger;
}
//channel__free_all(account); xmpp_mem_t make_memory(void *userdata)
//user__free_all(account); {
xmpp_mem_t memory = { nullptr };
memory.alloc = [](const size_t size, void *const) {
return calloc(1, size);
};
memory.free = [](void *ptr, void *const) {
free(ptr);
};
memory.realloc = [](void *ptr, const size_t size, void *const) {
return realloc(ptr, size);
};
memory.userdata = userdata;
return memory;
} }
void account__free(struct t_account *account) weechat::account::account(config_file& config_file, const std::string name)
: name(name), memory(make_memory(this)), logger(make_logger(this))
, context(&memory, &logger), connection(*this, context)
, config_account(config_file, config_file.configuration.section_account, name.data())
{ {
if (!account) if (account* result = nullptr; account::search(result, name))
return; throw std::invalid_argument("account already exists");
this->jid(config_file.configuration.account_default.option_jid.string().data());
this->password(config_file.configuration.account_default.option_password.string().data());
this->tls(config_file.configuration.account_default.option_tls.string().data());
this->nickname(config_file.configuration.account_default.option_nickname.string().data());
this->autoconnect(config_file.configuration.account_default.option_autoconnect.string().data());
this->resource(config_file.configuration.account_default.option_resource.string().data());
this->status(config_file.configuration.account_default.option_status.string().data());
this->pgp_path(config_file.configuration.account_default.option_pgp_path.string().data());
this->pgp_keyid(config_file.configuration.account_default.option_pgp_keyid.string().data());
}
weechat::account::~account()
{
/* /*
* close account buffer (and all channels/privates) * close account buffer (and all channels/privates)
* (only if we are not in a /upgrade, because during upgrade we want to * (only if we are not in a /upgrade, because during upgrade we want to
* keep connections and closing account buffer would disconnect from account) * keep connections and closing account buffer would disconnect from account)
*/ */
if (account->buffer) if (buffer)
weechat_buffer_close(account->buffer); weechat_buffer_close(buffer);
accounts.erase(account->name); accounts.erase(name);
account__free_data(account); /* close xmpp context */
delete account; if (connection)
} xmpp_conn_release(connection);
if (context)
xmpp_ctx_free(context);
void account__free_all() delete this;
{
for (auto account : accounts)
{
account__free(account.second);
}
} }
void account__disconnect(struct t_account *account, int reconnect) void weechat::account::disconnect(int reconnect)
{ {
(void) reconnect; if (is_connected)
struct t_channel *ptr_channel;
if (account->is_connected)
{ {
/* /*
* remove all nicks and write disconnection message on each * remove all nicks and write disconnection message on each
* channel/private buffer * channel/private buffer
*/ */
user__free_all(account); //user::free_all(this); // TOFIX
weechat_nicklist_remove_all(account->buffer); weechat_nicklist_remove_all(buffer);
for (ptr_channel = account->channels; ptr_channel; for (auto& ptr_channel : channels)
ptr_channel = ptr_channel->next_channel)
{ {
weechat_nicklist_remove_all(ptr_channel->buffer); weechat_nicklist_remove_all(ptr_channel.second.buffer);
weechat_printf( weechat_printf(
ptr_channel->buffer, ptr_channel.second.buffer,
_("%s%s: disconnected from account"), _("%s%s: disconnected from account"),
weechat_prefix("network"), WEECHAT_XMPP_PLUGIN_NAME); weechat_prefix("network"), WEECHAT_XMPP_PLUGIN_NAME);
} }
/* remove away status on account buffer */ /* remove away status on account buffer */
//weechat_buffer_set(account->buffer, "localvar_del_away", ""); //weechat_buffer_set(buffer, "localvar_del_away", "");
} }
account__close_connection(account); reset();
if (account->buffer) if (buffer)
{ {
weechat_printf( weechat_printf(
account->buffer, buffer,
_("%s%s: disconnected from account"), _("%s%s: disconnected from account"),
weechat_prefix ("network"), WEECHAT_XMPP_PLUGIN_NAME); weechat_prefix ("network"), WEECHAT_XMPP_PLUGIN_NAME);
} }
if (reconnect) if (reconnect)
{ {
if (account->current_retry++ == 0) if (current_retry++ == 0)
{ {
account->reconnect_delay = 5; reconnect_delay = 5;
account->reconnect_start = time(NULL) + account->reconnect_delay; reconnect_start = time(NULL) + reconnect_delay;
} }
account->current_retry %= 5; current_retry %= 5;
} }
else else
{ {
account->current_retry = 0; current_retry = 0;
account->reconnect_delay = 0; reconnect_delay = 0;
account->reconnect_start = 0; reconnect_start = 0;
} }
/* /*
account->lag = 0; lag = 0;
account->lag_displayed = -1; lag_displayed = -1;
account->lag_check_time.tv_sec = 0; lag_check_time.tv_sec = 0;
account->lag_check_time.tv_usec = 0; lag_check_time.tv_usec = 0;
account->lag_next_check = time(NULL) + lag_next_check = time(NULL) +
weechat_config_integer(xmpp_config_network_lag_check); weechat_config_integer(xmpp_config_network_lag_check);
account->lag_last_refresh = 0; lag_last_refresh = 0;
account__set_lag(account); account__set_lag(account);
*/ // lag based on xmpp ping */ // lag based on xmpp ping
account->disconnected = !reconnect; disconnected = !reconnect;
/* send signal "account_disconnected" with account name */ /* send signal "account_disconnected" with account name */
(void) weechat_hook_signal_send("xmpp_account_disconnected", (void) weechat_hook_signal_send("xmpp_account_disconnected",
WEECHAT_HOOK_SIGNAL_STRING, account->name); WEECHAT_HOOK_SIGNAL_STRING, name.data());
} }
void account__disconnect_all() void weechat::account::disconnect_all()
{ {
for (auto ptr_account : accounts) for (auto& account : accounts)
{ {
account__disconnect(ptr_account.second, 0); account.second.disconnect(0);
} }
} }
struct t_gui_buffer *account__create_buffer(struct t_account *account) struct t_gui_buffer *weechat::account::create_buffer()
{ {
char buffer_name[256], charset_modifier[256]; buffer = weechat_buffer_new(fmt::format("account.{}", name).data(),
snprintf(buffer_name, sizeof(buffer_name),
"account.%s", account->name);
account->buffer = weechat_buffer_new(buffer_name,
&input__data_cb, NULL, NULL, &input__data_cb, NULL, NULL,
&buffer__close_cb, NULL, NULL); &buffer__close_cb, NULL, NULL);
if (!account->buffer) if (!buffer)
return NULL; return NULL;
weechat_printf(account->buffer, "xmpp: %s", account->name); weechat_printf(buffer, "xmpp: %s", name.data());
if (!weechat_buffer_get_integer(account->buffer, "short_name_is_set")) if (!weechat_buffer_get_integer(buffer, "short_name_is_set"))
weechat_buffer_set(account->buffer, "short_name", account->name); weechat_buffer_set(buffer, "short_name", name.data());
weechat_buffer_set(account->buffer, "localvar_set_type", "server"); weechat_buffer_set(buffer, "localvar_set_type", "server");
weechat_buffer_set(account->buffer, "localvar_set_account", account->name); weechat_buffer_set(buffer, "localvar_set_account", name.data());
snprintf(charset_modifier, sizeof (charset_modifier), weechat_buffer_set(buffer, "localvar_set_charset_modifier",
"account.%s", account->name); fmt::format("account.{}", name).data());
weechat_buffer_set(account->buffer, "localvar_set_charset_modifier", weechat_buffer_set(buffer, "title", name.data());
charset_modifier);
weechat_buffer_set(account->buffer, "title", weechat_buffer_set(buffer, "nicklist", "1");
(account->name) ? account->name : ""); weechat_buffer_set(buffer, "nicklist_display_groups", "0");
weechat_buffer_set_pointer(buffer, "nicklist_callback",
weechat_buffer_set(account->buffer, "nicklist", "1");
weechat_buffer_set(account->buffer, "nicklist_display_groups", "0");
weechat_buffer_set_pointer(account->buffer, "nicklist_callback",
(void*)&buffer__nickcmp_cb); (void*)&buffer__nickcmp_cb);
weechat_buffer_set_pointer(account->buffer, "nicklist_callback_pointer", weechat_buffer_set_pointer(buffer, "nicklist_callback_pointer",
account); this);
return account->buffer; return buffer;
} }
void account__close_connection(struct t_account *account) void weechat::account::reset()
{ {
if (account->connection) if (connection)
{ {
if (xmpp_conn_is_connected(account->connection)) if (xmpp_conn_is_connected(connection))
xmpp_disconnect(account->connection); xmpp_disconnect(connection);
} }
account->is_connected = 0; is_connected = 0;
} }
int account__connect(struct t_account *account) int weechat::account::connect()
{ {
if (!account->buffer) if (!buffer)
{ {
if (!account__create_buffer(account)) if (!create_buffer())
return 0; return 0;
weechat_buffer_set(account->buffer, "display", "auto"); weechat_buffer_set(buffer, "display", "auto");
} }
account__close_connection(account); reset();
account->is_connected = is_connected = connection.connect(std::string(jid()), std::string(password()), tls());
connection__connect(account, &account->connection, account_jid(account),
account_password(account), account_tls(account));
(void) weechat_hook_signal_send("xmpp_account_connecting", (void) weechat_hook_signal_send("xmpp_account_connecting",
WEECHAT_HOOK_SIGNAL_STRING, account->name); WEECHAT_HOOK_SIGNAL_STRING, name.data());
return account->is_connected; return is_connected;
} }
int account__timer_cb(const void *pointer, void *data, int remaining_calls) int weechat::account::timer_cb(const void *pointer, void *data, int remaining_calls)
{ {
(void) pointer; (void) pointer;
(void) data; (void) data;
@ -723,17 +452,17 @@ int account__timer_cb(const void *pointer, void *data, int remaining_calls)
{ {
if (accounts.empty()) return WEECHAT_RC_ERROR; if (accounts.empty()) return WEECHAT_RC_ERROR;
for (auto ptr_account : accounts) for (auto& ptr_account : accounts)
{ {
if (ptr_account.second->is_connected if (ptr_account.second.is_connected
&& (xmpp_conn_is_connecting(ptr_account.second->connection) && (xmpp_conn_is_connecting(ptr_account.second.connection)
|| xmpp_conn_is_connected(ptr_account.second->connection))) || xmpp_conn_is_connected(ptr_account.second.connection)))
connection__process(ptr_account.second->context, ptr_account.second->connection, 10); ptr_account.second.connection.process(ptr_account.second.context, 10);
else if (ptr_account.second->disconnected); else if (ptr_account.second.disconnected);
else if (ptr_account.second->reconnect_start > 0 else if (ptr_account.second.reconnect_start > 0
&& ptr_account.second->reconnect_start < time(NULL)) && ptr_account.second.reconnect_start < time(NULL))
{ {
account__connect(ptr_account.second); ptr_account.second.connect();
} }
} }

@ -7,155 +7,144 @@
#include <ctime> #include <ctime>
#include <cstdint> #include <cstdint>
#include <memory> #include <memory>
#include <string>
#include <string_view>
#include <unordered_map> #include <unordered_map>
#include <strophe.h> #include <tl/optional.hpp>
#include "fmt/core.h"
#include "strophe.h"
#include "pgp.hh"
#include "omemo.hh" #include "omemo.hh"
#include "config.hh"
#include "channel.hh"
#include "connection.hh"
#include "user.hh"
extern std::unordered_map<std::string, struct t_account *> accounts; namespace weechat
enum t_account_option
{
ACCOUNT_OPTION_JID,
ACCOUNT_OPTION_PASSWORD,
ACCOUNT_OPTION_TLS,
ACCOUNT_OPTION_NICKNAME,
ACCOUNT_OPTION_AUTOCONNECT,
ACCOUNT_OPTION_RESOURCE,
ACCOUNT_OPTION_STATUS,
ACCOUNT_OPTION_PGP_PATH,
ACCOUNT_OPTION_PGP_KEYID,
ACCOUNT_NUM_OPTIONS,
};
#define account__option_string(account, option) \
weechat_config_string(account->options[ACCOUNT_OPTION_ ## option])
#define account__option_integer(account, option) \
weechat_config_integer(account->options[ACCOUNT_OPTION_ ## option])
#define account__option_boolean(account, option) \
weechat_config_boolean(account->options[ACCOUNT_OPTION_ ## option])
#define account_option_set(account, option, value) \
weechat_config_option_set(account->options[option], value, 1)
#define account_jid(account) \
account->connection && xmpp_conn_is_connected(account->connection) ? \
xmpp_jid_bare(account->context, xmpp_conn_get_bound_jid(account->connection)) : \
weechat_config_string(account->options[ACCOUNT_OPTION_JID])
#define account_jid_device(account) \
account->connection && xmpp_conn_is_connected(account->connection) ? \
xmpp_conn_get_bound_jid(account->connection) : \
xmpp_jid_new(account->context, \
xmpp_jid_node(account->context, \
weechat_config_string(account->options[ACCOUNT_OPTION_JID])), \
xmpp_jid_domain(account->context, \
weechat_config_string(account->options[ACCOUNT_OPTION_JID])), \
"weechat")
#define account_password(account) \
weechat_config_string(account->options[ACCOUNT_OPTION_PASSWORD])
#define account_tls(account) \
weechat_config_integer(account->options[ACCOUNT_OPTION_TLS])
#define account_nickname(account) \
weechat_config_string(account->options[ACCOUNT_OPTION_NICKNAME])
#define account_autoconnect(account) \
weechat_config_boolean(account->options[ACCOUNT_OPTION_AUTOCONNECT])
#define account_resource(account) \
weechat_config_string(account->options[ACCOUNT_OPTION_RESOURCE])
#define account_status(account) \
weechat_config_string(account->options[ACCOUNT_OPTION_STATUS])
#define account_pgp_path(account) \
weechat_config_string(account->options[ACCOUNT_OPTION_PGP_PATH])
#define account_pgp_keyid(account) \
weechat_config_string(account->options[ACCOUNT_OPTION_PGP_KEYID])
struct t_account_device
{
uint32_t id;
char *name;
char *label;
struct t_account_device *prev_device;
struct t_account_device *next_device;
};
struct t_account_mam_query
{
char *id;
char *with;
int has_start;
time_t start;
int has_end;
time_t end;
struct t_account_mam_query *prev_mam_query;
struct t_account_mam_query *next_mam_query;
};
struct t_account
{ {
char *name; class channel;
struct t_config_option *options[ACCOUNT_NUM_OPTIONS]; class user;
int reloading_from_config; void log_emit(void *const userdata, const xmpp_log_level_t level,
const char *const area, const char *const msg);
int is_connected;
int disconnected; class account : public config_account
{
int current_retry; public:
int reconnect_delay; struct device
int reconnect_start; {
std::uint32_t id;
xmpp_mem_t memory; std::string name;
xmpp_log_t logger; std::string label;
xmpp_ctx_t *context; };
xmpp_conn_t *connection;
struct mam_query
struct t_gui_buffer *buffer; {
char *buffer_as_string; std::string id;
std::string with;
tl::optional<time_t> start;
tl::optional<time_t> end;
};
public:
bool disconnected = false;
std::unordered_map<std::uint32_t, device> devices;
std::unordered_map<std::string, mam_query> mam_queries;
private:
bool is_connected = false;
int current_retry = 0;
int reconnect_delay = 0;
int reconnect_start = 0;
xmpp_mem_t memory = { nullptr };
xmpp_log_t logger = { nullptr };
std::string buffer_as_string;
friend void log_emit(void *const userdata, const xmpp_log_level_t level,
const char *const area, const char *const msg);
public:
std::string name;
weechat::xmpp::pgp pgp;
weechat::xmpp::omemo omemo; weechat::xmpp::omemo omemo;
struct t_pgp *pgp; libstrophe::context context;
weechat::connection connection;
struct t_account_device *devices; struct t_gui_buffer *buffer = nullptr;
struct t_account_device *last_device; std::unordered_map<std::string, weechat::channel> channels;
struct t_account_mam_query *mam_queries; std::unordered_map<std::string, weechat::user> users;
struct t_account_mam_query *last_mam_query;
struct t_user *users; std::unordered_map<std::string, struct t_config_option *> options;
struct t_user *last_user;
struct t_channel *channels; int reloading_from_config = 0;
struct t_channel *last_channel;
public:
struct t_account *prev_account; account(config_file& config_file, const std::string name);
struct t_account *next_account; ~account();
};
static bool search(account* &out,
extern char *account_options[][2]; const std::string name, bool casesensitive = false);
static int timer_cb(const void *pointer, void *data, int remaining_calls);
struct t_account *account__search(const char *account_name); static void disconnect_all();
struct t_account *account__casesearch (const char *account_name);
int account__search_option(const char *option_name); bool connected() { return is_connected; }
struct t_account_device *account__search_device(struct t_account *account,
uint32_t id); bool search_device(device* out, std::uint32_t id);
void account__add_device(struct t_account *account, void add_device(device *device);
struct t_account_device *device); void device_free_all();
void account__free_device(struct t_account *account, xmpp_stanza_t *get_devicelist();
struct t_account_device *device);
void account__free_device_all(struct t_account *account); void add_mam_query(const std::string id, const std::string with,
xmpp_stanza_t *account__get_devicelist(struct t_account *account); tl::optional<time_t> start, tl::optional<time_t> end);
struct t_account_mam_query *account__add_mam_query(struct t_account *account, bool mam_query_search(mam_query* out, const std::string id);
struct t_channel *channel, void mam_query_remove(const std::string id);
const char *id, void mam_query_free_all();
time_t *start, time_t *end);
struct t_account_mam_query *account__mam_query_search(struct t_account *account, struct t_gui_buffer* create_buffer();
const char *id);
void account__mam_query_free(struct t_account *account, void disconnect(int reconnect);
struct t_account_mam_query *mam_query); void reset();
void account__mam_query_free_all(struct t_account *account); int connect();
struct t_account *account__alloc(const char *name);
void account__free_data(struct t_account *account); std::string_view jid() {
void account__free(struct t_account *account); if (connection && xmpp_conn_is_connected(connection))
void account__free_all(); return xmpp_jid_bare(context, xmpp_conn_get_bound_jid(connection));
void account__disconnect(struct t_account *account, int reconnect); else
void account__disconnect_all(); return this->option_jid.string();
void account__close_connection(struct t_account *account); }
int account__connect(struct t_account *account); void jid(std::string jid) { this->option_jid = jid; }
int account__timer_cb(const void *pointer, void *data, int remaining_calls); std::string_view jid_device() {
if (connection && xmpp_conn_is_connected(connection))
return xmpp_conn_get_bound_jid(connection);
else
return xmpp_jid_new(context,
xmpp_jid_node(context, this->option_jid.string().data()),
xmpp_jid_domain(context, this->option_jid.string().data()),
"weechat");
}
std::string_view password() { return this->option_password.string(); }
void password(std::string password) { this->option_password = password; }
tls_policy tls() { return static_cast<tls_policy>(this->option_tls.integer()); }
void tls(tls_policy tls) { this->option_tls = fmt::format("%d", static_cast<int>(tls)); }
void tls(std::string tls) { this->option_tls = tls; }
std::string_view nickname() { return this->option_nickname.string(); }
void nickname(std::string nickname) { this->option_nickname = nickname; }
bool autoconnect() { return this->option_autoconnect.boolean(); }
void autoconnect(bool autoconnect) { this->option_autoconnect = autoconnect ? "on" : "off"; }
void autoconnect(std::string autoconnect) { this->option_autoconnect = autoconnect; }
std::string_view resource() { return this->option_resource.string(); }
void resource(std::string resource) { this->option_resource = resource; }
std::string_view status() { return this->option_status.string(); }
void status(std::string status) { this->option_status = status; }
std::string_view pgp_path() { return this->option_pgp_path.string(); }
void pgp_path(std::string pgp_path) { this->option_pgp_path = pgp_path; }
std::string_view pgp_keyid() { return this->option_pgp_keyid.string(); }
void pgp_keyid(std::string pgp_keyid) { this->option_pgp_keyid = pgp_keyid; }
};
extern std::unordered_map<std::string, account> accounts;
}

@ -13,37 +13,33 @@
#include "buffer.hh" #include "buffer.hh"
void buffer__get_account_and_channel(struct t_gui_buffer *buffer, void buffer__get_account_and_channel(struct t_gui_buffer *buffer,
struct t_account **account, weechat::account **account,
struct t_channel **channel) weechat::channel **channel)
{ {
struct t_account *ptr_account;
struct t_channel *ptr_channel;
if (!buffer) if (!buffer)
return; return;
*account = NULL; *account = nullptr;
*channel = NULL; *channel = nullptr;
/* look for a account or channel using this buffer */ /* look for a account or channel using this buffer */
for (auto ptr_account : accounts) for (auto& ptr_account : weechat::accounts)
{ {
if (ptr_account.second->buffer == buffer) if (ptr_account.second.buffer == buffer)
{ {
if (account) if (account)
*account = ptr_account.second; *account = &ptr_account.second;
return; return;
} }
for (ptr_channel = ptr_account.second->channels; ptr_channel; for (auto& ptr_channel : ptr_account.second.channels)
ptr_channel = ptr_channel->next_channel)
{ {
if (ptr_channel->buffer == buffer) if (ptr_channel.second.buffer == buffer)
{ {
if (account) if (account)
*account = ptr_account.second; *account = &ptr_account.second;
if (channel) if (channel)
*channel = ptr_channel; *channel = &ptr_channel.second;
return; return;
} }
} }
@ -56,9 +52,8 @@ char *buffer__typing_bar_cb(const void *pointer, void *data,
struct t_gui_buffer *buffer, struct t_gui_buffer *buffer,
struct t_hashtable *extra_info) struct t_hashtable *extra_info)
{ {
struct t_channel_typing *ptr_typing; weechat::account *account;
struct t_account *account; weechat::channel *channel;
struct t_channel *channel;
char notification[256]; char notification[256];
unsigned typecount; unsigned typecount;
@ -78,17 +73,16 @@ char *buffer__typing_bar_cb(const void *pointer, void *data,
typecount = 0; typecount = 0;
for (ptr_typing = channel->typings; ptr_typing; for (auto& ptr_typing : channel->typings)
ptr_typing = ptr_typing->next_typing)
{ {
switch (++typecount) switch (++typecount)
{ {
case 1: case 1:
strcpy(notification, ptr_typing->name); strcpy(notification, ptr_typing.name);
break; break;
case 2: case 2:
strcat(notification, ", "); strcat(notification, ", ");
strcat(notification, ptr_typing->name); strcat(notification, ptr_typing.name);
break; break;
case 3: case 3:
default: default:
@ -115,12 +109,12 @@ int buffer__nickcmp_cb(const void *pointer, void *data,
const char *nick1, const char *nick1,
const char *nick2) const char *nick2)
{ {
struct t_account *account; weechat::account *account;
(void) data; (void) data;
if (pointer) if (pointer)
account = (struct t_account *)pointer; account = (weechat::account *)pointer;
else else
buffer__get_account_and_channel(buffer, &account, NULL); buffer__get_account_and_channel(buffer, &account, NULL);
@ -138,8 +132,8 @@ int buffer__close_cb(const void *pointer, void *data,
struct t_gui_buffer *buffer) struct t_gui_buffer *buffer)
{ {
struct t_weechat_plugin *buffer_plugin = NULL; struct t_weechat_plugin *buffer_plugin = NULL;
struct t_account *ptr_account = NULL; weechat::account *ptr_account = NULL;
struct t_channel *ptr_channel = NULL; weechat::channel *ptr_channel = NULL;
(void) pointer; (void) pointer;
(void) data; (void) data;
@ -155,9 +149,9 @@ int buffer__close_cb(const void *pointer, void *data,
{ {
if (ptr_account) if (ptr_account)
{ {
if (ptr_account->is_connected) if (ptr_account->connected())
{ {
account__disconnect(ptr_account, 0); ptr_account->disconnect(0);
} }
ptr_account->buffer = NULL; ptr_account->buffer = NULL;
@ -167,9 +161,9 @@ int buffer__close_cb(const void *pointer, void *data,
{ {
if (ptr_account && ptr_channel) if (ptr_account && ptr_channel)
{ {
if (ptr_account->is_connected) if (ptr_account->connected())
{ {
channel__free(ptr_account, ptr_channel); ptr_account->channels.erase(ptr_channel->name);
} }
} }
} }
@ -177,9 +171,9 @@ int buffer__close_cb(const void *pointer, void *data,
{ {
if (ptr_account && ptr_channel) if (ptr_account && ptr_channel)
{ {
if (ptr_account->is_connected) if (ptr_account->connected())
{ {
channel__free(ptr_account, ptr_channel); ptr_account->channels.erase(ptr_channel->name);
} }
} }
} }

@ -5,8 +5,8 @@
#pragma once #pragma once
void buffer__get_account_and_channel(struct t_gui_buffer *buffer, void buffer__get_account_and_channel(struct t_gui_buffer *buffer,
struct t_account **account, weechat::account **account,
struct t_channel **channel); weechat::channel **channel);
char *buffer__typing_bar_cb(const void *pointer, void *data, char *buffer__typing_bar_cb(const void *pointer, void *data,
struct t_gui_bar_item *item, struct t_gui_bar_item *item,

File diff suppressed because it is too large Load Diff

@ -5,212 +5,165 @@
#pragma once #pragma once
#include <ctime> #include <ctime>
#include <unordered_set>
#include <string> #include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include <tl/optional.hpp>
#define CHANNEL_MEMBERS_SPEAKING_LIMIT 128 #define CHANNEL_MEMBERS_SPEAKING_LIMIT 128
enum t_channel_type namespace weechat
{
CHANNEL_TYPE_MUC,
CHANNEL_TYPE_PM,
};
enum t_channel_transport
{
CHANNEL_TRANSPORT_PLAIN,
CHANNEL_TRANSPORT_OMEMO,
CHANNEL_TRANSPORT_PGP,
CHANNEL_TRANSPORT_OTR,
CHANNEL_TRANSPORT_OX,
};
struct t_channel_typing
{ {
class account;
class user;
class channel
{
public:
enum class chat_type { MUC, PM };
enum class transport { PLAIN, OMEMO, PGP, OTR, OX };
static const char *transport_name(enum transport transport)
{
switch (transport)
{
case transport::PLAIN:
return "PLAINTEXT";
case transport::OMEMO:
return "OMEMO";
case transport::PGP:
return "PGP";
case transport::OTR:
return "OTR";
default:
return NULL;
}
}
struct typing
{
union { union {
char *id; char *id;
struct t_user *user; weechat::user *user;
}; };
char *name; char *name;
time_t ts; time_t ts;
};
struct t_channel_typing *prev_typing; struct member
struct t_channel_typing *next_typing; {
};
struct t_channel_member
{
char *id; char *id;
char *role; char *role;
char *affiliation; char *affiliation;
};
struct t_channel_member *prev_member; struct topic
struct t_channel_member *next_member; {
}; char *value = nullptr;
char *creator = nullptr;
struct t_channel_topic time_t last_set = 0;
{ };
char *value;
char *creator;
time_t last_set;
};
struct t_channel_unread struct unread
{ {
char *id; char *id;
char *thread; char *thread;
}; };
struct t_channel private:
{ topic topic;
enum t_channel_type type;
char *id; /* mpim */
char *name; char *creator = nullptr;
enum t_channel_transport transport; double last_read = 0.0;
int unread_count = 0;
int unread_count_display = 0;
struct t_hook *typing_hook_timer = nullptr;
struct t_hook *self_typing_hook_timer = nullptr;
public:
std::vector<weechat::channel::unread> unreads;
public:
std::string id;
std::string name;
enum chat_type type;
enum transport transport = weechat::channel::transport::PLAIN;
struct { struct {
int enabled; int enabled;
struct t_hashtable *devicelist_requests; struct t_hashtable *devicelist_requests;
struct t_hashtable *bundle_requests; struct t_hashtable *bundle_requests;
} omemo; } omemo;
struct { struct {
int enabled; int enabled = 1;
std::unordered_set<std::string> *ids; std::unordered_set<std::string> ids;
} pgp; } pgp;
struct { struct {
int enabled; int enabled = 0;
} otr; } otr;
struct t_weelist *members_speaking[2] = { nullptr };
std::vector<typing> self_typings;
std::vector<typing> typings;
std::unordered_map<std::string, member> members;
struct t_channel_topic topic; public:
/* mpim */
char *creator;
double last_read;
int unread_count;
int unread_count_display;
struct t_hook *typing_hook_timer;
struct t_hook *self_typing_hook_timer;
struct t_weelist *members_speaking[2];
struct t_weelist *unreads;
struct t_channel_typing *self_typings;
struct t_channel_typing *last_self_typing;
struct t_channel_typing *typings;
struct t_channel_typing *last_typing;
struct t_channel_member *members;
struct t_channel_member *last_member;
struct t_gui_buffer *buffer; struct t_gui_buffer *buffer;
char *buffer_as_string;
struct t_channel *prev_channel; public:
struct t_channel *next_channel; channel(weechat::account& account, enum chat_type type, const char *id, const char *name);
}; ~channel();
const char *channel__transport_name(enum t_channel_transport transport); void set_transport(enum weechat::channel::transport transport, int force);
void channel__set_transport(struct t_channel *channel, struct t_gui_buffer *search_buffer(weechat::channel::chat_type type,
enum t_channel_transport transport, int force); const char *name);
struct t_gui_buffer *create_buffer(weechat::channel::chat_type type,
const char *name);
struct t_account *channel__account(struct t_channel *channel); void add_nicklist_groups();
struct t_channel *channel__search(struct t_account *account, void member_speaking_add_to_list(const char *nick, int highlight);
const char *id); void member_speaking_add(const char *nick, int highlight);
void member_speaking_rename(const char *old_nick, const char *new_nick);
void member_speaking_rename_if_present(const char *nick);
void channel__add_nicklist_groups(struct t_account *account, static int typing_cb(const void *pointer, void *data, int remaining_calls);
struct t_channel *channel); typing *typing_search(const char *id);
int add_typing(weechat::user *user);
struct t_channel *channel__new(struct t_account *account, static int self_typing_cb(const void *pointer, void *data, int remaining_calls);
enum t_channel_type type, typing *self_typing_search(weechat::user *user);
const char *id, const char *name); int add_self_typing(weechat::user *user);
void channel__member_speaking_add(struct t_channel *channel, static int hotlist_update_cb(const void *pointer, void *data,
const char *nick, int highlight);
void channel__member_speaking_rename(struct t_channel *channel,
const char *old_nick,
const char *new_nick);
void channel__member_speaking_rename_if_present(struct t_account *account,
struct t_channel *channel,
const char *nick);
void channel__typing_free(struct t_channel *channel,
struct t_channel_typing *typing);
void channel__typing_free_all(struct t_channel *channel);
int channel__typing_cb(const void *pointer,
void *data,
int remaining_calls);
struct t_channel_typing *channel__typing_search(struct t_channel *channel,
const char *id);
int channel__add_typing(struct t_channel *channel,
struct t_user *user);
void channel__self_typing_free(struct t_channel *channel,
struct t_channel_typing *typing);
void channel__self_typing_free_all(struct t_channel *channel);
int channel__self_typing_cb(const void *pointer,
void *data,
int remaining_calls);
struct t_channel_typing *channel__self_typing_search(struct t_channel *channel,
struct t_user *user);
int channel__add_self_typing(struct t_channel *channel,
struct t_user *user);
int channel__hotlist_update_cb(const void *pointer, void *data,
const char *signal, const char *type_data, const char *signal, const char *type_data,
void *signal_data); void *signal_data);
void channel__unread_free(struct t_channel_unread *unread); void free(channel *channel);
void free_all();
void channel__unread_free_all(struct t_channel *channel);
void channel__free(struct t_account *account,
struct t_channel *channel);
void channel__free_all(struct t_account *account);
void channel__update_topic(struct t_channel *channel,
const char* title,
const char* creator,
int last_set);
void channel__update_name(struct t_channel *channel, void update_topic(const char* title, const char* creator, int last_set);
const char* name); void update_name(const char* name);
void update_purpose(const char* purpose, const char* creator, int last_set);
void channel__update_purpose(struct t_channel *channel, member *add_member(const char *id, const char *client);
const char* purpose, member *member_search(const char *id);
const char* creator, member *remove_member(const char *id, const char *reason);
int last_set);
struct t_channel_member *channel__add_member(struct t_account *account, int send_message(std::string to, std::string body,
struct t_channel *channel, tl::optional<std::string> oob = {});
const char *id, const char *client); int send_message(const char *to, const char *body);
struct t_channel_member *channel__member_search(struct t_channel *channel, void send_reads();
const char *id); void send_typing(weechat::user *user);
void send_paused(weechat::user *user);
struct t_channel_member *channel__remove_member(struct t_account *account, void fetch_mam(const char *id, time_t *start, time_t *end, const char *after);
struct t_channel *channel,
const char *id, const char *reason);
int channel__send_message(struct t_account *account, struct t_channel *channel, weechat::account& account;
const char *to, const char *body); };
}
void channel__send_reads(struct t_account *account, struct t_channel *channel);
void channel__send_typing(struct t_account *account, struct t_channel *channel,
struct t_user *user);
void channel__send_paused(struct t_account *account, struct t_channel *channel,
struct t_user *user);
void channel__fetch_mam(struct t_account *account, struct t_channel *channel,
const char *id, time_t *start, time_t *end, const char *after);

@ -10,6 +10,7 @@
#include <errno.h> #include <errno.h>
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
#include <utility>
#include <weechat/weechat-plugin.h> #include <weechat/weechat-plugin.h>
#include "plugin.hh" #include "plugin.hh"
@ -24,27 +25,27 @@
#define MAM_DEFAULT_DAYS 2 #define MAM_DEFAULT_DAYS 2
#define STR(X) #X #define STR(X) #X
void command__display_account(struct t_account *account) void command__display_account(weechat::account *account)
{ {
int num_channels, num_pv; int num_channels, num_pv;
if (account->is_connected) if (account->connected())
{ {
num_channels = 0;//xmpp_account_get_channel_count(account); num_channels = 0;//xmpp_account_get_channel_count(account);
num_pv = 0;//xmpp_account_get_pv_count(account); num_pv = 0;//xmpp_account_get_pv_count(account);
weechat_printf( weechat_printf(
NULL, NULL,
" %s %s%s%s %s(%s%s%s) [%s%s%s]%s, %d %s, %d pv", " %s %s%s%s %s(%s%s%s) [%s%s%s]%s, %d %s, %d pv",
(account->is_connected) ? "*" : " ", (account->connected()) ? "*" : " ",
weechat_color("chat_server"), weechat_color("chat_server"),
account->name, account->name.data(),
weechat_color("reset"), weechat_color("reset"),
weechat_color("chat_delimiters"), weechat_color("chat_delimiters"),
weechat_color("chat_server"), weechat_color("chat_server"),
account_jid(account), account->jid().data(),
weechat_color("chat_delimiters"), weechat_color("chat_delimiters"),
weechat_color("reset"), weechat_color("reset"),
(account->is_connected) ? _("connected") : _("not connected"), (account->connected()) ? _("connected") : _("not connected"),
weechat_color("chat_delimiters"), weechat_color("chat_delimiters"),
weechat_color("reset"), weechat_color("reset"),
num_channels, num_channels,
@ -57,11 +58,11 @@ void command__display_account(struct t_account *account)
NULL, NULL,
" %s%s%s %s(%s%s%s)%s", " %s%s%s %s(%s%s%s)%s",
weechat_color("chat_server"), weechat_color("chat_server"),
account->name, account->name.data(),
weechat_color("reset"), weechat_color("reset"),
weechat_color("chat_delimiters"), weechat_color("chat_delimiters"),
weechat_color("chat_server"), weechat_color("chat_server"),
account_jid(account), account->jid().data(),
weechat_color("chat_delimiters"), weechat_color("chat_delimiters"),
weechat_color("reset")); weechat_color("reset"));
} }
@ -70,7 +71,6 @@ void command__display_account(struct t_account *account)
void command__account_list(int argc, char **argv) void command__account_list(int argc, char **argv)
{ {
int i, one_account_found; int i, one_account_found;
struct t_account *ptr_account2;
char *account_name = NULL; char *account_name = NULL;
for (i = 2; i < argc; i++) for (i = 2; i < argc; i++)
@ -80,13 +80,13 @@ void command__account_list(int argc, char **argv)
} }
if (!account_name) if (!account_name)
{ {
if (!accounts.empty()) if (!weechat::accounts.empty())
{ {
weechat_printf(NULL, ""); weechat_printf(NULL, "");
weechat_printf(NULL, _("All accounts:")); weechat_printf(NULL, _("All accounts:"));
for (auto ptr_account2 : accounts) for (auto& ptr_account2 : weechat::accounts)
{ {
command__display_account(ptr_account2.second); command__display_account(&ptr_account2.second);
} }
} }
else else
@ -95,9 +95,9 @@ void command__account_list(int argc, char **argv)
else else
{ {
one_account_found = 0; one_account_found = 0;
for (auto ptr_account2 : accounts) for (auto& ptr_account2 : weechat::accounts)
{ {
if (weechat_strcasestr(ptr_account2.second->name, account_name)) if (weechat_strcasestr(ptr_account2.second.name.data(), account_name))
{ {
if (!one_account_found) if (!one_account_found)
{ {
@ -107,7 +107,7 @@ void command__account_list(int argc, char **argv)
account_name); account_name);
} }
one_account_found = 1; one_account_found = 1;
command__display_account(ptr_account2.second); command__display_account(&ptr_account2.second);
} }
} }
if (!one_account_found) if (!one_account_found)
@ -119,10 +119,8 @@ void command__account_list(int argc, char **argv)
void command__add_account(const char *name, const char *jid, const char *password) void command__add_account(const char *name, const char *jid, const char *password)
{ {
struct t_account *account; weechat::account *account = nullptr;
if (weechat::account::search(account, name, true))
account = account__casesearch(name);
if (account)
{ {
weechat_printf( weechat_printf(
NULL, NULL,
@ -132,7 +130,10 @@ void command__add_account(const char *name, const char *jid, const char *passwor
return; return;
} }
account = account__alloc(name); ;
account = &weechat::accounts.emplace(
std::piecewise_construct, std::forward_as_tuple(name),
std::forward_as_tuple(weechat::config::instance->file, name)).first->second;
if (!account) if (!account)
{ {
weechat_printf( weechat_printf(
@ -144,19 +145,18 @@ void command__add_account(const char *name, const char *jid, const char *passwor
account->name = strdup(name); account->name = strdup(name);
if (jid) if (jid)
account_option_set(account, ACCOUNT_OPTION_JID, strdup(jid)); account->jid(jid);
if (password) if (password)
account_option_set(account, ACCOUNT_OPTION_PASSWORD, strdup(password)); account->password(password);
if (jid) if (jid)
account_option_set(account, ACCOUNT_OPTION_NICKNAME, account->nickname(xmpp_jid_node(account->context, jid));
strdup(xmpp_jid_node(account->context, jid)));
weechat_printf( weechat_printf(
NULL, NULL,
_("%s: account %s%s%s %s(%s%s%s)%s added"), _("%s: account %s%s%s %s(%s%s%s)%s added"),
WEECHAT_XMPP_PLUGIN_NAME, WEECHAT_XMPP_PLUGIN_NAME,
weechat_color("chat_server"), weechat_color("chat_server"),
account->name, account->name.data(),
weechat_color("reset"), weechat_color("reset"),
weechat_color("chat_delimiters"), weechat_color("chat_delimiters"),
weechat_color("chat_server"), weechat_color("chat_server"),
@ -189,21 +189,21 @@ void command__account_add(struct t_gui_buffer *buffer, int argc, char **argv)
} }
} }
int command__connect_account(struct t_account *account) int command__connect_account(weechat::account *account)
{ {
if (!account) if (!account)
return 0; return 0;
if (account->is_connected) if (account->connected())
{ {
weechat_printf( weechat_printf(
NULL, NULL,
_("%s%s: already connected to account \"%s\"!"), _("%s%s: already connected to account \"%s\"!"),
weechat_prefix("error"), WEECHAT_XMPP_PLUGIN_NAME, weechat_prefix("error"), WEECHAT_XMPP_PLUGIN_NAME,
account->name); account->name.data());
} }
account__connect(account); account->connect();
return 1; return 1;
} }
@ -211,7 +211,7 @@ int command__connect_account(struct t_account *account)
int command__account_connect(struct t_gui_buffer *buffer, int argc, char **argv) int command__account_connect(struct t_gui_buffer *buffer, int argc, char **argv)
{ {
int i, nb_connect, connect_ok; int i, nb_connect, connect_ok;
struct t_account *ptr_account; weechat::account *ptr_account = nullptr;
(void) buffer; (void) buffer;
(void) argc; (void) argc;
@ -223,8 +223,7 @@ int command__account_connect(struct t_gui_buffer *buffer, int argc, char **argv)
for (i = 2; i < argc; i++) for (i = 2; i < argc; i++)
{ {
nb_connect++; nb_connect++;
ptr_account = account__search(argv[i]); if (weechat::account::search(ptr_account, argv[i]))
if (ptr_account)
{ {
if (!command__connect_account(ptr_account)) if (!command__connect_account(ptr_account))
{ {
@ -245,21 +244,21 @@ int command__account_connect(struct t_gui_buffer *buffer, int argc, char **argv)
return (connect_ok) ? WEECHAT_RC_OK : WEECHAT_RC_ERROR; return (connect_ok) ? WEECHAT_RC_OK : WEECHAT_RC_ERROR;
} }
int command__disconnect_account(struct t_account *account) int command__disconnect_account(weechat::account *account)
{ {
if (!account) if (!account)
return 0; return 0;
if (!account->is_connected) if (!account->connected())
{ {
weechat_printf( weechat_printf(
NULL, NULL,
_("%s%s: not connected to account \"%s\"!"), _("%s%s: not connected to account \"%s\"!"),
weechat_prefix("error"), WEECHAT_XMPP_PLUGIN_NAME, weechat_prefix("error"), WEECHAT_XMPP_PLUGIN_NAME,
account->name); account->name.data());
} }
account__disconnect(account, 0); account->disconnect(0);
return 1; return 1;
} }
@ -267,7 +266,7 @@ int command__disconnect_account(struct t_account *account)
int command__account_disconnect(struct t_gui_buffer *buffer, int argc, char **argv) int command__account_disconnect(struct t_gui_buffer *buffer, int argc, char **argv)
{ {
int i, nb_disconnect, disconnect_ok; int i, nb_disconnect, disconnect_ok;
struct t_account *ptr_account; weechat::account *ptr_account;
(void) argc; (void) argc;
(void) argv; (void) argv;
@ -277,7 +276,7 @@ int command__account_disconnect(struct t_gui_buffer *buffer, int argc, char **ar
nb_disconnect = 0; nb_disconnect = 0;
if (argc < 2) if (argc < 2)
{ {
struct t_channel *ptr_channel; weechat::channel *ptr_channel;
buffer__get_account_and_channel(buffer, &ptr_account, &ptr_channel); buffer__get_account_and_channel(buffer, &ptr_account, &ptr_channel);
@ -292,8 +291,7 @@ int command__account_disconnect(struct t_gui_buffer *buffer, int argc, char **ar
for (i = 2; i < argc; i++) for (i = 2; i < argc; i++)
{ {
nb_disconnect++; nb_disconnect++;
ptr_account = account__search(argv[i]); if (weechat::account::search(ptr_account, argv[i]))
if (ptr_account)
{ {
if (!command__disconnect_account(ptr_account)) if (!command__disconnect_account(ptr_account))
{ {
@ -323,9 +321,6 @@ void command__account_delete(struct t_gui_buffer *buffer, int argc, char **argv)
{ {
(void) buffer; (void) buffer;
struct t_account *account;
char *account_name;
if (argc < 3) if (argc < 3)
{ {
weechat_printf( weechat_printf(
@ -337,8 +332,9 @@ void command__account_delete(struct t_gui_buffer *buffer, int argc, char **argv)
return; return;
} }
account = account__search(argv[2]); weechat::account *account = nullptr;
if (!account)
if (!weechat::account::search(account, argv[2]))
{ {
weechat_printf( weechat_printf(
NULL, NULL,
@ -347,7 +343,7 @@ void command__account_delete(struct t_gui_buffer *buffer, int argc, char **argv)
argv[2], "xmpp delete"); argv[2], "xmpp delete");
return; return;
} }
if (account->is_connected) if (account->connected())
{ {
weechat_printf( weechat_printf(
NULL, NULL,
@ -358,17 +354,15 @@ void command__account_delete(struct t_gui_buffer *buffer, int argc, char **argv)
return; return;
} }
account_name = strdup(account->name); std::string account_name = account->name;
account__free(account); weechat::accounts.erase(account->name);
weechat_printf( weechat_printf(
NULL, NULL,
_("%s: account %s%s%s has been deleted"), _("%s: account %s%s%s has been deleted"),
WEECHAT_XMPP_PLUGIN_NAME, WEECHAT_XMPP_PLUGIN_NAME,
weechat_color("chat_server"), weechat_color("chat_server"),
(account_name) ? account_name : "???", !account_name.empty() ? account_name.data() : "???",
weechat_color("reset")); weechat_color("reset"));
if (account_name)
free(account_name);
} }
int command__account(const void *pointer, void *data, int command__account(const void *pointer, void *data,
@ -428,8 +422,8 @@ int command__enter(const void *pointer, void *data,
struct t_gui_buffer *buffer, int argc, struct t_gui_buffer *buffer, int argc,
char **argv, char **argv_eol) char **argv, char **argv_eol)
{ {
struct t_account *ptr_account = NULL; weechat::account *ptr_account = NULL;
struct t_channel *ptr_channel = NULL; weechat::channel *ptr_channel = NULL;
xmpp_stanza_t *pres; xmpp_stanza_t *pres;
char *jid, *pres_jid, *text; char *jid, *pres_jid, *text;
@ -442,7 +436,7 @@ int command__enter(const void *pointer, void *data,
if (!ptr_account) if (!ptr_account)
return WEECHAT_RC_ERROR; return WEECHAT_RC_ERROR;
if (!ptr_account->is_connected) if (!ptr_account->connected())
{ {
weechat_printf(buffer, weechat_printf(buffer,
_("%s%s: you are not connected to server"), _("%s%s: you are not connected to server"),
@ -464,19 +458,21 @@ int command__enter(const void *pointer, void *data,
ptr_account->context, ptr_account->context,
xmpp_jid_node(ptr_account->context, jid), xmpp_jid_node(ptr_account->context, jid),
xmpp_jid_domain(ptr_account->context, jid), xmpp_jid_domain(ptr_account->context, jid),
account_nickname(ptr_account) ptr_account->nickname().data()
&& strlen(account_nickname(ptr_account)) && strlen(ptr_account->nickname().data())
? account_nickname(ptr_account) ? ptr_account->nickname().data()
: xmpp_jid_node(ptr_account->context, : xmpp_jid_node(ptr_account->context,
account_jid(ptr_account))); ptr_account->jid().data()));
ptr_channel = channel__search(ptr_account, jid); if (!ptr_account->channels.contains(jid))
if (!ptr_channel) ptr_channel = &ptr_account->channels.emplace(
ptr_channel = channel__new(ptr_account, CHANNEL_TYPE_MUC, jid, jid); std::make_pair(jid, weechat::channel {
*ptr_account, weechat::channel::chat_type::MUC, jid, jid
})).first->second;
pres = xmpp_presence_new(ptr_account->context); pres = xmpp_presence_new(ptr_account->context);
xmpp_stanza_set_to(pres, pres_jid); xmpp_stanza_set_to(pres, pres_jid);
xmpp_stanza_set_from(pres, account_jid(ptr_account)); xmpp_stanza_set_from(pres, ptr_account->jid().data());
xmpp_stanza_t *pres__x = xmpp_stanza_new(ptr_account->context); xmpp_stanza_t *pres__x = xmpp_stanza_new(ptr_account->context);
xmpp_stanza_set_name(pres__x, "x"); xmpp_stanza_set_name(pres__x, "x");
@ -491,7 +487,7 @@ int command__enter(const void *pointer, void *data,
{ {
text = argv_eol[2]; text = argv_eol[2];
channel__send_message(ptr_account, ptr_channel, jid, text); ptr_channel->send_message(jid, text);
} }
char buf[16]; char buf[16];
@ -511,13 +507,15 @@ int command__enter(const void *pointer, void *data,
xmpp_jid_domain(ptr_account->context, buffer_jid), xmpp_jid_domain(ptr_account->context, buffer_jid),
weechat_buffer_get_string(buffer, "localvar_nick")); weechat_buffer_get_string(buffer, "localvar_nick"));
ptr_channel = channel__search(ptr_account, buffer_jid); if (!ptr_account->channels.contains(buffer_jid))
if (!ptr_channel) ptr_channel = &ptr_account->channels.emplace(
ptr_channel = channel__new(ptr_account, CHANNEL_TYPE_MUC, buffer_jid, buffer_jid); std::make_pair(jid, weechat::channel {
*ptr_account, weechat::channel::chat_type::MUC, buffer_jid, buffer_jid
})).first->second;
pres = xmpp_presence_new(ptr_account->context); pres = xmpp_presence_new(ptr_account->context);
xmpp_stanza_set_to(pres, pres_jid); xmpp_stanza_set_to(pres, pres_jid);
xmpp_stanza_set_from(pres, account_jid(ptr_account)); xmpp_stanza_set_from(pres, ptr_account->jid().data());
xmpp_stanza_t *pres__x = xmpp_stanza_new(ptr_account->context); xmpp_stanza_t *pres__x = xmpp_stanza_new(ptr_account->context);
xmpp_stanza_set_name(pres__x, "x"); xmpp_stanza_set_name(pres__x, "x");
@ -536,8 +534,8 @@ int command__open(const void *pointer, void *data,
struct t_gui_buffer *buffer, int argc, struct t_gui_buffer *buffer, int argc,
char **argv, char **argv_eol) char **argv, char **argv_eol)
{ {
struct t_account *ptr_account = NULL; weechat::account *ptr_account = NULL;
struct t_channel *ptr_channel = NULL; weechat::channel *ptr_channel = NULL;
xmpp_stanza_t *pres; xmpp_stanza_t *pres;
char *jid, *text; char *jid, *text;
@ -550,7 +548,7 @@ int command__open(const void *pointer, void *data,
if (!ptr_account) if (!ptr_account)
return WEECHAT_RC_ERROR; return WEECHAT_RC_ERROR;
if (!ptr_account->is_connected) if (!ptr_account->connected())
{ {
weechat_printf(buffer, weechat_printf(buffer,
_("%s%s: you are not connected to server"), _("%s%s: you are not connected to server"),
@ -569,30 +567,33 @@ int command__open(const void *pointer, void *data,
{ {
jid = xmpp_jid_new( jid = xmpp_jid_new(
ptr_account->context, ptr_account->context,
xmpp_jid_node(ptr_account->context, ptr_channel->name), xmpp_jid_node(ptr_account->context, ptr_channel->name.data()),
xmpp_jid_domain(ptr_account->context, ptr_channel->name), xmpp_jid_domain(ptr_account->context, ptr_channel->name.data()),
jid); jid);
} }
pres = xmpp_presence_new(ptr_account->context); pres = xmpp_presence_new(ptr_account->context);
xmpp_stanza_set_to(pres, jid); xmpp_stanza_set_to(pres, jid);
xmpp_stanza_set_from(pres, account_jid(ptr_account)); xmpp_stanza_set_from(pres, ptr_account->jid().data());
xmpp_send(ptr_account->connection, pres); xmpp_send(ptr_account->connection, pres);
xmpp_stanza_release(pres); xmpp_stanza_release(pres);
struct t_channel *channel = channel__search(ptr_account, jid); auto channel = ptr_account->channels.find(jid);
if (!channel) if (channel == ptr_account->channels.end())
channel = channel__new(ptr_account, CHANNEL_TYPE_PM, jid, jid); channel = ptr_account->channels.emplace(
std::make_pair(jid, weechat::channel {
*ptr_account, weechat::channel::chat_type::PM, jid, jid
})).first;
if (argc > 2) if (argc > 2)
{ {
text = argv_eol[2]; text = argv_eol[2];
channel__send_message(ptr_account, channel, jid, text); channel->second.send_message(jid, text);
} }
char buf[16]; char buf[16];
int num = weechat_buffer_get_integer(channel->buffer, "number"); int num = weechat_buffer_get_integer(channel->second.buffer, "number");
snprintf(buf, sizeof(buf), "/buffer %d", num); snprintf(buf, sizeof(buf), "/buffer %d", num);
weechat_command(ptr_account->buffer, buf); weechat_command(ptr_account->buffer, buf);
} }
@ -606,8 +607,8 @@ int command__msg(const void *pointer, void *data,
struct t_gui_buffer *buffer, int argc, struct t_gui_buffer *buffer, int argc,
char **argv, char **argv_eol) char **argv, char **argv_eol)
{ {
struct t_account *ptr_account = NULL; weechat::account *ptr_account = NULL;
struct t_channel *ptr_channel = NULL; weechat::channel *ptr_channel = NULL;
xmpp_stanza_t *message; xmpp_stanza_t *message;
char *text; char *text;
@ -629,7 +630,7 @@ int command__msg(const void *pointer, void *data,
return WEECHAT_RC_OK; return WEECHAT_RC_OK;
} }
if (!ptr_account->is_connected) if (!ptr_account->connected())
{ {
weechat_printf(buffer, weechat_printf(buffer,
_("%s%s: you are not connected to server"), _("%s%s: you are not connected to server"),
@ -642,16 +643,17 @@ int command__msg(const void *pointer, void *data,
text = argv_eol[1]; text = argv_eol[1];
message = xmpp_message_new(ptr_account->context, message = xmpp_message_new(ptr_account->context,
ptr_channel->type == CHANNEL_TYPE_MUC ? "groupchat" : "chat", ptr_channel->type == weechat::channel::chat_type::MUC ? "groupchat" : "chat",
ptr_channel->name, NULL); ptr_channel->name.data(), NULL);
xmpp_message_set_body(message, text); xmpp_message_set_body(message, text);
xmpp_send(ptr_account->connection, message); xmpp_send(ptr_account->connection, message);
xmpp_stanza_release(message); xmpp_stanza_release(message);
if (ptr_channel->type != CHANNEL_TYPE_MUC) if (ptr_channel->type != weechat::channel::chat_type::MUC)
weechat_printf_date_tags(ptr_channel->buffer, 0, weechat_printf_date_tags(ptr_channel->buffer, 0,
"xmpp_message,message,private,notify_none,self_msg,log1", "xmpp_message,message,private,notify_none,self_msg,log1",
"%s\t%s", "%s\t%s",
user__as_prefix_raw(ptr_account, account_jid(ptr_account)), text); weechat::user::search(ptr_account, ptr_account->jid().data())->as_prefix_raw().data(),
text);
} }
return WEECHAT_RC_OK; return WEECHAT_RC_OK;
@ -661,8 +663,8 @@ int command__me(const void *pointer, void *data,
struct t_gui_buffer *buffer, int argc, struct t_gui_buffer *buffer, int argc,
char **argv, char **argv_eol) char **argv, char **argv_eol)
{ {
struct t_account *ptr_account = NULL; weechat::account *ptr_account = NULL;
struct t_channel *ptr_channel = NULL; weechat::channel *ptr_channel = NULL;
xmpp_stanza_t *message; xmpp_stanza_t *message;
char *text; char *text;
@ -684,7 +686,7 @@ int command__me(const void *pointer, void *data,
return WEECHAT_RC_OK; return WEECHAT_RC_OK;
} }
if (!ptr_account->is_connected) if (!ptr_account->connected())
{ {
weechat_printf(buffer, weechat_printf(buffer,
_("%s%s: you are not connected to server"), _("%s%s: you are not connected to server"),
@ -697,17 +699,17 @@ int command__me(const void *pointer, void *data,
text = argv_eol[0]; text = argv_eol[0];
message = xmpp_message_new(ptr_account->context, message = xmpp_message_new(ptr_account->context,
ptr_channel->type == CHANNEL_TYPE_MUC ? "groupchat" : "chat", ptr_channel->type == weechat::channel::chat_type::MUC ? "groupchat" : "chat",
ptr_channel->name, NULL); ptr_channel->name.data(), NULL);
xmpp_message_set_body(message, text); xmpp_message_set_body(message, text);
xmpp_send(ptr_account->connection, message); xmpp_send(ptr_account->connection, message);
xmpp_stanza_release(message); xmpp_stanza_release(message);
if (ptr_channel->type != CHANNEL_TYPE_MUC) if (ptr_channel->type != weechat::channel::chat_type::MUC)
weechat_printf_date_tags(ptr_channel->buffer, 0, weechat_printf_date_tags(ptr_channel->buffer, 0,
"xmpp_message,message,action,private,notify_none,self_msg,log1", "xmpp_message,message,action,private,notify_none,self_msg,log1",
"%s%s %s", "%s%s %s",
weechat_prefix("action"), weechat_prefix("action"),
user__as_prefix_raw(ptr_account, account_jid(ptr_account)), weechat::user::search(ptr_account, ptr_account->jid().data())->as_prefix_raw().data(),
strlen(text) > strlen("/me ") ? text+4 : ""); strlen(text) > strlen("/me ") ? text+4 : "");
} }
@ -718,8 +720,8 @@ int command__mam(const void *pointer, void *data,
struct t_gui_buffer *buffer, int argc, struct t_gui_buffer *buffer, int argc,
char **argv, char **argv_eol) char **argv, char **argv_eol)
{ {
struct t_account *ptr_account = NULL; weechat::account *ptr_account = NULL;
struct t_channel *ptr_channel = NULL; weechat::channel *ptr_channel = NULL;
int days; int days;
(void) pointer; (void) pointer;
@ -761,7 +763,7 @@ int command__mam(const void *pointer, void *data,
else else
ago->tm_mday -= MAM_DEFAULT_DAYS; ago->tm_mday -= MAM_DEFAULT_DAYS;
start = mktime(ago); start = mktime(ago);
channel__fetch_mam(ptr_account, ptr_channel, NULL, &start, NULL, NULL); ptr_channel->fetch_mam(NULL, &start, NULL, NULL);
return WEECHAT_RC_OK; return WEECHAT_RC_OK;
} }
@ -770,8 +772,8 @@ int command__omemo(const void *pointer, void *data,
struct t_gui_buffer *buffer, int argc, struct t_gui_buffer *buffer, int argc,
char **argv, char **argv_eol) char **argv, char **argv_eol)
{ {
struct t_account *ptr_account = NULL; weechat::account *ptr_account = NULL;
struct t_channel *ptr_channel = NULL; weechat::channel *ptr_channel = NULL;
(void) pointer; (void) pointer;
(void) data; (void) data;
@ -796,7 +798,7 @@ int command__omemo(const void *pointer, void *data,
ptr_channel->omemo.enabled = 1; ptr_channel->omemo.enabled = 1;
ptr_channel->pgp.enabled = 0; ptr_channel->pgp.enabled = 0;
channel__set_transport(ptr_channel, CHANNEL_TRANSPORT_OMEMO, 0); ptr_channel->set_transport(weechat::channel::transport::OMEMO, 0);
return WEECHAT_RC_OK; return WEECHAT_RC_OK;
} }
@ -805,8 +807,8 @@ int command__pgp(const void *pointer, void *data,
struct t_gui_buffer *buffer, int argc, struct t_gui_buffer *buffer, int argc,
char **argv, char **argv_eol) char **argv, char **argv_eol)
{ {
struct t_account *ptr_account = NULL; weechat::account *ptr_account = NULL;
struct t_channel *ptr_channel = NULL; weechat::channel *ptr_channel = NULL;
char *keyid; char *keyid;
(void) pointer; (void) pointer;
@ -831,12 +833,12 @@ int command__pgp(const void *pointer, void *data,
{ {
keyid = argv_eol[1]; keyid = argv_eol[1];
ptr_channel->pgp.ids->emplace(keyid); ptr_channel->pgp.ids.emplace(keyid);
} }
ptr_channel->omemo.enabled = 0; ptr_channel->omemo.enabled = 0;
ptr_channel->pgp.enabled = 1; ptr_channel->pgp.enabled = 1;
channel__set_transport(ptr_channel, CHANNEL_TRANSPORT_PGP, 0); ptr_channel->set_transport(weechat::channel::transport::PGP, 0);
return WEECHAT_RC_OK; return WEECHAT_RC_OK;
} }
@ -845,8 +847,8 @@ int command__plain(const void *pointer, void *data,
struct t_gui_buffer *buffer, int argc, struct t_gui_buffer *buffer, int argc,
char **argv, char **argv_eol) char **argv, char **argv_eol)
{ {
struct t_account *ptr_account = NULL; weechat::account *ptr_account = NULL;
struct t_channel *ptr_channel = NULL; weechat::channel *ptr_channel = NULL;
(void) pointer; (void) pointer;
(void) data; (void) data;
@ -871,7 +873,7 @@ int command__plain(const void *pointer, void *data,
ptr_channel->omemo.enabled = 0; ptr_channel->omemo.enabled = 0;
ptr_channel->pgp.enabled = 0; ptr_channel->pgp.enabled = 0;
channel__set_transport(ptr_channel, CHANNEL_TRANSPORT_PLAIN, 0); ptr_channel->set_transport(weechat::channel::transport::PLAIN, 0);
return WEECHAT_RC_OK; return WEECHAT_RC_OK;
} }
@ -880,8 +882,8 @@ int command__xml(const void *pointer, void *data,
struct t_gui_buffer *buffer, int argc, struct t_gui_buffer *buffer, int argc,
char **argv, char **argv_eol) char **argv, char **argv_eol)
{ {
struct t_account *ptr_account = NULL; weechat::account *ptr_account = NULL;
struct t_channel *ptr_channel = NULL; weechat::channel *ptr_channel = NULL;
xmpp_stanza_t *stanza; xmpp_stanza_t *stanza;
(void) pointer; (void) pointer;
@ -893,7 +895,7 @@ int command__xml(const void *pointer, void *data,
if (!ptr_account) if (!ptr_account)
return WEECHAT_RC_ERROR; return WEECHAT_RC_ERROR;
if (!ptr_account->is_connected) if (!ptr_account->connected())
{ {
weechat_printf(buffer, weechat_printf(buffer,
_("%s%s: you are not connected to server"), _("%s%s: you are not connected to server"),
@ -947,13 +949,12 @@ int command__xmpp(const void *pointer, void *data,
struct t_gui_buffer *buffer, int argc, struct t_gui_buffer *buffer, int argc,
char **argv, char **argv_eol) char **argv, char **argv_eol)
{ {
struct t_account *ptr_account = NULL;
struct t_channel *ptr_channel = NULL;
xmpp_stanza_t *stanza;
(void) pointer; (void) pointer;
(void) data; (void) data;
(void) buffer;
(void) argc;
(void) argv; (void) argv;
(void) argv_eol;
weechat_printf(nullptr, weechat_printf(nullptr,
_("%s%s %s [%s]"), _("%s%s %s [%s]"),

@ -18,11 +18,11 @@
#include "completion.hh" #include "completion.hh"
void completion__channel_nicks_add_speakers(struct t_gui_completion *completion, void completion__channel_nicks_add_speakers(struct t_gui_completion *completion,
struct t_account *account, weechat::account *account,
struct t_channel *channel, weechat::channel *channel,
int highlight) int highlight)
{ {
struct t_user *user; weechat::user *user;
const char *member; const char *member;
int list_size, i; int list_size, i;
@ -35,7 +35,7 @@ void completion__channel_nicks_add_speakers(struct t_gui_completion *completion,
weechat_list_get(channel->members_speaking[highlight], i)); weechat_list_get(channel->members_speaking[highlight], i));
if (member) if (member)
{ {
user = user__search(account, member); user = weechat::user::search(account, member);
if (user) if (user)
weechat_hook_completion_list_add(completion, weechat_hook_completion_list_add(completion,
user->profile.display_name, user->profile.display_name,
@ -50,10 +50,9 @@ int completion__channel_nicks_cb(const void *pointer, void *data,
struct t_gui_buffer *buffer, struct t_gui_buffer *buffer,
struct t_gui_completion *completion) struct t_gui_completion *completion)
{ {
struct t_account *ptr_account; weechat::account *ptr_account;
struct t_channel *ptr_channel; weechat::channel *ptr_channel;
struct t_channel_member *ptr_member; weechat::user *ptr_user;
struct t_user *ptr_user;
/* make C compiler happy */ /* make C compiler happy */
(void) pointer; (void) pointer;
@ -68,30 +67,29 @@ int completion__channel_nicks_cb(const void *pointer, void *data,
{ {
switch (ptr_channel->type) switch (ptr_channel->type)
{ {
case CHANNEL_TYPE_MUC: case weechat::channel::chat_type::MUC:
case CHANNEL_TYPE_PM: case weechat::channel::chat_type::PM:
for (ptr_member = ptr_channel->members; ptr_member; for (auto& ptr_member : ptr_channel->members)
ptr_member = ptr_member->next_member)
{ {
ptr_user = user__search(ptr_account, ptr_member->id); ptr_user = weechat::user::search(ptr_account, ptr_member.second.id);
if (ptr_user) if (ptr_user)
weechat_hook_completion_list_add(completion, weechat_hook_completion_list_add(completion,
ptr_user->profile.display_name, ptr_user->profile.display_name,
1, WEECHAT_LIST_POS_SORT); 1, WEECHAT_LIST_POS_SORT);
} }
/* add recent speakers on channel */ /* add recent speakers on channel */
if (weechat_config_integer(config_look_nick_completion_smart) == CONFIG_NICK_COMPLETION_SMART_SPEAKERS) if (weechat_config_integer(weechat::config::instance->look.nick_completion_smart) == static_cast<int>(weechat::config::nick_completion::SMART_SPEAKERS))
{ {
completion__channel_nicks_add_speakers(completion, ptr_account, ptr_channel, 0); completion__channel_nicks_add_speakers(completion, ptr_account, ptr_channel, 0);
} }
/* add members whose make highlights on me recently on this channel */ /* add members whose make highlights on me recently on this channel */
if (weechat_config_integer(config_look_nick_completion_smart) == CONFIG_NICK_COMPLETION_SMART_SPEAKERS_HIGHLIGHTS) if (weechat_config_integer(weechat::config::instance->look.nick_completion_smart) == static_cast<int>(weechat::config::nick_completion::SMART_SPEAKERS_HIGHLIGHTS))
{ {
completion__channel_nicks_add_speakers(completion, ptr_account, ptr_channel, 1); completion__channel_nicks_add_speakers(completion, ptr_account, ptr_channel, 1);
} }
/* add self member at the end */ /* add self member at the end */
weechat_hook_completion_list_add(completion, weechat_hook_completion_list_add(completion,
ptr_account->name, ptr_account->name.data(),
1, WEECHAT_LIST_POS_END); 1, WEECHAT_LIST_POS_END);
break; break;
} }
@ -105,17 +103,15 @@ int completion__accounts_cb(const void *pointer, void *data,
struct t_gui_buffer *buffer, struct t_gui_buffer *buffer,
struct t_gui_completion *completion) struct t_gui_completion *completion)
{ {
struct t_account *ptr_account;
/* make C compiler happy */ /* make C compiler happy */
(void) pointer; (void) pointer;
(void) data; (void) data;
(void) completion_item; (void) completion_item;
(void) buffer; (void) buffer;
for (auto ptr_account : accounts) for (auto& ptr_account : weechat::accounts)
{ {
weechat_hook_completion_list_add(completion, account_jid(ptr_account.second), weechat_hook_completion_list_add(completion, ptr_account.second.jid().data(),
0, WEECHAT_LIST_POS_SORT); 0, WEECHAT_LIST_POS_SORT);
} }

@ -5,322 +5,71 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
#include <strophe.h> #include <sstream>
#include <weechat/weechat-plugin.h> #include <weechat/weechat-plugin.h>
#include "strophe.h"
#include "plugin.hh" #include "plugin.hh"
#include "account.hh" #include "account.hh"
#include "config.hh" #include "config.hh"
struct t_config_file *config_file; int account_read_cb(weechat::config_section& section,
struct t_config_section *config_section_account_default;
struct t_config_section *config_section_account;
struct t_config_option *config_look_nick_completion_smart;
struct t_config_option *config_account_default[ACCOUNT_NUM_OPTIONS];
int config__account_check_value_cb(const void *pointer, void *data,
struct t_config_option *option,
const char *value)
{
(void) pointer;
(void) data;
(void) option;
(void) value;
return 1;
}
void config__account_change_cb(const void *pointer, void *data,
struct t_config_option *option)
{
(void) pointer;
(void) data;
const char *name =
weechat_config_option_get_string(option, "name");
const char *value =
weechat_config_option_get_string(option, "value");
int split_num;
char **split = weechat_string_split(name, ".", NULL, 0, 2, &split_num);
struct t_account *account = account__search(split[0]);
if (split_num >= 2 && account)
{
const char *key = split[1];
(void) key;
(void) value;
}
weechat_string_free_split(split);
}
void config__account_default_change_cb(const void *pointer, void *data,
struct t_config_option *option)
{
(void) pointer;
(void) data;
(void) option;
}
struct t_config_option *
config__account_new_option (struct t_config_file *config_file,
struct t_config_section *section,
int index_option,
const char *option_name,
const char *default_value,
const char *value,
int null_value_allowed,
int (*callback_check_value)(const void *pointer,
void *data,
struct t_config_option *option,
const char *value),
const void *callback_check_value_pointer,
void *callback_check_value_data,
void (*callback_change)(const void *pointer,
void *data,
struct t_config_option *option),
const void *callback_change_pointer,
void *callback_change_data)
{
struct t_config_option *new_option;
new_option = NULL;
switch (index_option)
{
case ACCOUNT_OPTION_JID:
new_option = weechat_config_new_option (
config_file, section,
option_name, "string",
N_("XMPP Account JID"),
NULL, 0, 0,
default_value, value,
null_value_allowed,
callback_check_value,
callback_check_value_pointer,
callback_check_value_data,
callback_change,
callback_change_pointer,
callback_change_data,
NULL, NULL, NULL);
break;
case ACCOUNT_OPTION_PASSWORD:
new_option = weechat_config_new_option (
config_file, section,
option_name, "string",
N_("XMPP Account Password"),
NULL, 0, 0,
default_value, value,
null_value_allowed,
callback_check_value,
callback_check_value_pointer,
callback_check_value_data,
callback_change,
callback_change_pointer,
callback_change_data,
NULL, NULL, NULL);
break;
case ACCOUNT_OPTION_TLS:
new_option = weechat_config_new_option (
config_file, section,
option_name, "integer",
N_("XMPP Server TLS Policy"),
"disable|normal|trust", 0, 0,
default_value, value,
null_value_allowed,
callback_check_value,
callback_check_value_pointer,
callback_check_value_data,
callback_change,
callback_change_pointer,
callback_change_data,
NULL, NULL, NULL);
break;
case ACCOUNT_OPTION_NICKNAME:
new_option = weechat_config_new_option (
config_file, section,
option_name, "string",
N_("XMPP Account Nickname"),
NULL, 0, 0,
default_value, value,
null_value_allowed,
callback_check_value,
callback_check_value_pointer,
callback_check_value_data,
callback_change,
callback_change_pointer,
callback_change_data,
NULL, NULL, NULL);
break;
case ACCOUNT_OPTION_AUTOCONNECT:
new_option = weechat_config_new_option (
config_file, section,
option_name, "boolean",
N_("Autoconnect XMPP Account"),
NULL, 0, 0,
default_value, value,
null_value_allowed,
callback_check_value,
callback_check_value_pointer,
callback_check_value_data,
callback_change,
callback_change_pointer,
callback_change_data,
NULL, NULL, NULL);
break;
case ACCOUNT_OPTION_RESOURCE:
new_option = weechat_config_new_option (
config_file, section,
option_name, "string",
N_("XMPP Account Resource"),
NULL, 0, 0,
default_value, value,
null_value_allowed,
callback_check_value,
callback_check_value_pointer,
callback_check_value_data,
callback_change,
callback_change_pointer,
callback_change_data,
NULL, NULL, NULL);
break;
case ACCOUNT_OPTION_STATUS:
new_option = weechat_config_new_option (
config_file, section,
option_name, "string",
N_("XMPP Account Login Status"),
NULL, 0, 0,
default_value, value,
null_value_allowed,
callback_check_value,
callback_check_value_pointer,
callback_check_value_data,
callback_change,
callback_change_pointer,
callback_change_data,
NULL, NULL, NULL);
break;
case ACCOUNT_OPTION_PGP_PATH:
new_option = weechat_config_new_option (
config_file, section,
option_name, "string",
N_("XMPP Account PGP Keyring Dir"),
NULL, 0, 0,
default_value, value,
null_value_allowed,
callback_check_value,
callback_check_value_pointer,
callback_check_value_data,
callback_change,
callback_change_pointer,
callback_change_data,
NULL, NULL, NULL);
break;
case ACCOUNT_OPTION_PGP_KEYID:
new_option = weechat_config_new_option (
config_file, section,
option_name, "string",
N_("XMPP Account PGP Key ID"),
NULL, 0, 0,
default_value, value,
null_value_allowed,
callback_check_value,
callback_check_value_pointer,
callback_check_value_data,
callback_change,
callback_change_pointer,
callback_change_data,
NULL, NULL, NULL);
break;
case ACCOUNT_NUM_OPTIONS:
break;
}
return new_option;
}
void config__account_create_default_options(struct t_config_section *section)
{
int i;
for (i = 0; i < ACCOUNT_NUM_OPTIONS; i++)
{
config_account_default[i] = config__account_new_option(
config_file,
section,
i,
account_options[i][0],
account_options[i][1],
account_options[i][1],
0,
&config__account_check_value_cb,
account_options[i][0],
NULL,
&config__account_default_change_cb,
account_options[i][0],
NULL);
}
}
int config__account_read_cb (const void *pointer, void *data,
struct t_config_file *config_file,
struct t_config_section *section,
const char *option_name, const char *value) const char *option_name, const char *value)
{ {
struct t_account *ptr_account; if (!option_name)
int index_option, rc, i; return WEECHAT_CONFIG_READ_MEMORY_ERROR;
char *pos_option, *account_name; std::istringstream breadcrumbs(option_name);
std::string account_name, option_id;
(void) pointer; std::getline(breadcrumbs, account_name, '.');
(void) data; std::getline(breadcrumbs, option_id, '.');
(void) config_file; if (account_name.empty())
(void) section; return WEECHAT_CONFIG_READ_MEMORY_ERROR;
rc = WEECHAT_CONFIG_OPTION_SET_ERROR; int rc = WEECHAT_CONFIG_READ_OK;
weechat::account* account = nullptr;
if (option_name) if (!weechat::account::search(account, account_name))
{ account = &weechat::accounts.emplace(
pos_option = const_cast<char*>(strrchr(option_name, '.')); std::piecewise_construct, std::forward_as_tuple(account_name),
if (pos_option) std::forward_as_tuple(weechat::config::instance->file, account_name)).first->second;
{ if (account)
account_name = weechat_strndup(option_name, {
pos_option - option_name); auto options = {
pos_option++; std::ref(account->option_jid),
if (account_name) std::ref(account->option_password),
{ std::ref(account->option_tls),
index_option = account__search_option(pos_option); std::ref(account->option_nickname),
if (index_option >= 0) std::ref(account->option_autoconnect),
{ std::ref(account->option_resource),
ptr_account = account__search(account_name); std::ref(account->option_status),
if (!ptr_account) std::ref(account->option_pgp_path),
ptr_account = account__alloc(account_name); std::ref(account->option_pgp_keyid),
if (ptr_account) };
{
if (!ptr_account->reloading_from_config++) if (!account->reloading_from_config++)
{ {
for (i = 0; i < ACCOUNT_NUM_OPTIONS; i++) for (auto option : options)
{ option.get().clear();
weechat_config_option_set( }
ptr_account->options[i], NULL, 1);
} account->reloading_from_config %= options.size();
}
ptr_account->reloading_from_config %= if (option_id == "jid") rc |= (account->option_jid = value) == WEECHAT_CONFIG_OPTION_SET_ERROR;
ACCOUNT_NUM_OPTIONS; if (option_id == "password") rc |= (account->option_password = value) == WEECHAT_CONFIG_OPTION_SET_ERROR;
rc = weechat_config_option_set( if (option_id == "tls") rc |= (account->option_tls = value) == WEECHAT_CONFIG_OPTION_SET_ERROR;
ptr_account->options[index_option], value, 1); if (option_id == "nickname") rc |= (account->option_nickname = value) == WEECHAT_CONFIG_OPTION_SET_ERROR;
if (!ptr_account->reloading_from_config) if (option_id == "autoconnect") rc |= (account->option_autoconnect = value) == WEECHAT_CONFIG_OPTION_SET_ERROR;
{ if (option_id == "resource") rc |= (account->option_resource = value) == WEECHAT_CONFIG_OPTION_SET_ERROR;
const char *ac_global = weechat_info_get("auto_connect", NULL); if (option_id == "status") rc |= (account->option_status = value) == WEECHAT_CONFIG_OPTION_SET_ERROR;
int ac_local = weechat_config_boolean( if (option_id == "pgp_path") rc |= (account->option_pgp_path = value) == WEECHAT_CONFIG_OPTION_SET_ERROR;
ptr_account->options[ACCOUNT_OPTION_AUTOCONNECT]); if (option_id == "pgp_keyid") rc |= (account->option_pgp_keyid = value) == WEECHAT_CONFIG_OPTION_SET_ERROR;
if (ac_local && (strcmp(ac_global, "1") == 0))
account__connect(ptr_account); if (!account->reloading_from_config)
{
bool ac_global = std::stoul(std::unique_ptr<char>(
weechat_info_get("auto_connect", NULL)).get());
bool ac_local = account->autoconnect();
if (ac_local && ac_global)
account->connect();
} }
} }
else else
@ -329,154 +78,77 @@ int config__account_read_cb (const void *pointer, void *data,
NULL, NULL,
_("%s%s: error adding account \"%s\""), _("%s%s: error adding account \"%s\""),
weechat_prefix("error"), WEECHAT_XMPP_PLUGIN_NAME, weechat_prefix("error"), WEECHAT_XMPP_PLUGIN_NAME,
account_name); account_name.data());
}
}
free(account_name);
}
}
} }
if (rc == WEECHAT_CONFIG_OPTION_SET_ERROR) if (rc != WEECHAT_CONFIG_READ_OK)
{ {
weechat_printf( weechat_printf(
NULL, NULL,
_("%s%s: error creating account option \"%s\""), _("%s%s: error creating account option \"%s\""),
weechat_prefix("error"), WEECHAT_XMPP_PLUGIN_NAME, option_name); weechat_prefix("error"), WEECHAT_XMPP_PLUGIN_NAME, option_name);
} }
return rc; return rc;
} }
int config__account_write_cb(const void *pointer, void *data, int account_write_cb(weechat::config_section& section, const char *section_name)
struct t_config_file *config_file,
const char *section_name)
{ {
struct t_account *ptr_account; if (!weechat_config_write_line(section.file, section_name, NULL))
int i;
(void) pointer;
(void) data;
if (!weechat_config_write_line(config_file, section_name, NULL))
return WEECHAT_CONFIG_WRITE_ERROR; return WEECHAT_CONFIG_WRITE_ERROR;
for (auto ptr_account : accounts) for (auto& account : weechat::accounts)
{
for (i = 0; i < ACCOUNT_NUM_OPTIONS; i++)
{ {
if (!weechat_config_write_option(config_file, if (!account.second.write())
ptr_account.second->options[i]))
return WEECHAT_CONFIG_WRITE_ERROR; return WEECHAT_CONFIG_WRITE_ERROR;
} }
}
return WEECHAT_CONFIG_WRITE_OK; return WEECHAT_CONFIG_WRITE_OK;
} }
int config__reload (const void *pointer, void *data, int config_reload(weechat::config_file &file)
struct t_config_file *config_file)
{ {
(void) pointer; //weechat_config_section_free_options(file.configuration.section_account_default);
(void) data; //weechat_config_section_free_options(file.configuration.section_account);
weechat::accounts.clear();
weechat_config_section_free_options(config_section_account_default); return weechat_config_reload(file);
weechat_config_section_free_options(config_section_account);
account__free_all();
return weechat_config_reload(config_file);
} }
int config__init() bool weechat::config_account::write()
{ {
struct t_config_section *ptr_section; if (!option_jid.write()) return false;
if (!option_password.write()) return false;
config_file = weechat_config_new(WEECHAT_XMPP_CONFIG_NAME, if (!option_tls.write()) return false;
&config__reload, NULL, NULL); if (!option_nickname.write()) return false;
if (!option_autoconnect.write()) return false;
if(!config_file) if (!option_resource.write()) return false;
return 0; if (!option_status.write()) return false;
if (!option_pgp_path.write()) return false;
ptr_section = weechat_config_new_section( if (!option_pgp_keyid.write()) return false;
config_file, "look", return true;
0, 0, }
NULL, NULL, NULL,
NULL, NULL, NULL,
NULL, NULL, NULL,
NULL, NULL, NULL,
NULL, NULL, NULL);
if (!ptr_section)
{
weechat_config_free(config_file);
config_file = NULL;
return 0;
}
config_look_nick_completion_smart = weechat_config_new_option ( weechat::config::config()
config_file, ptr_section, : file{*this, "xmpp", &config_reload}
"nick_completion_smart", "integer", , section_account_default{file, "account_default", 0, 0, {}, {}, {}, {}, {}}
N_("smart completion for nicks (completes first with last speakers): " , section_account{file, "account", 0, 0, &account_read_cb, &account_write_cb, {}, {}, {}}
, section_look{file, "look", 0, 0, {}, {}, {}, {}, {}}
, account_default{file, section_account_default}
, look{
.nick_completion_smart{file, section_look, "nick_completion_smart", "integer",
("smart completion for nicks (completes first with last speakers): "
"speakers = all speakers (including highlights), " "speakers = all speakers (including highlights), "
"speakers_highlights = only speakers with highlight"), "speakers_highlights = only speakers with highlight"),
"off|speakers|speakers_highlights", 0, 0, "speakers", NULL, 0, "off|speakers|speakers_highlights", 0, 0,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); "speakers", nullptr, false,
{}, {}, {}}}
ptr_section = weechat_config_new_section(
config_file, "account_default",
0, 0,
NULL, NULL, NULL,
NULL, NULL, NULL,
NULL, NULL, NULL,
NULL, NULL, NULL,
NULL, NULL, NULL);
if (!ptr_section)
{
weechat_config_free(config_file);
config_file = NULL;
return 0;
}
config_section_account_default = ptr_section;
config__account_create_default_options(ptr_section);
ptr_section = weechat_config_new_section(
config_file, "account",
0, 0,
&config__account_read_cb, NULL, NULL,
&config__account_write_cb, NULL, NULL,
NULL, NULL, NULL,
NULL, NULL, NULL,
NULL, NULL, NULL);
if (!ptr_section)
{
weechat_config_free(config_file);
config_file = NULL;
return 0;
}
config_section_account = ptr_section;
return 1;
}
int config__read()
{ {
int rc;
rc = weechat_config_read(config_file);
return rc;
} }
int config__write() weechat::config::~config() {}
{
return weechat_config_write(config_file);
}
void config__free() tl::optional<weechat::config> weechat::config::instance;
{
} bool weechat::config::init() { instance.emplace(); return true; }
bool weechat::config::read() { return instance->file.read(); }
bool weechat::config::write() { return instance->file.read(); }

@ -4,52 +4,362 @@
#pragma once #pragma once
#define WEECHAT_XMPP_CONFIG_NAME "xmpp" #include <memory>
#include <stdexcept>
#include <string>
#include <functional>
#include <unordered_map>
#include <tl/optional.hpp>
#include <weechat/weechat-plugin.h>
#include "fmt/core.h"
#include "plugin.hh"
enum t_config_nick_completion using namespace std::placeholders;
namespace weechat
{ {
CONFIG_NICK_COMPLETION_SMART_OFF = 0, enum class tls_policy
CONFIG_NICK_COMPLETION_SMART_SPEAKERS, {
CONFIG_NICK_COMPLETION_SMART_SPEAKERS_HIGHLIGHTS, disable = 0,
}; normal,
trust,
extern struct t_config_file *config_file; };
extern struct t_config_section *config_section_account_default; class config;
extern struct t_config_section *config_section_account; struct config_file;
struct config_section;
extern struct t_config_option *config_look_nick_completion_smart; struct config_option;
extern struct t_config_option *config_account_default[]; struct config_breadcrumb {
config_breadcrumb(std::string name)
int config__account_check_value_cb(const void *pointer, void *data, : name(name), parent(tl::nullopt) {}
struct t_config_option *option,
const char *value); config_breadcrumb(std::string name, config_breadcrumb& parent)
: name(name), parent(parent) {}
void config__account_change_cb(const void *pointer, void *data,
struct t_config_option *option); std::string name;
tl::optional<config_breadcrumb&> parent;
struct t_config_option *config__account_new_option ( };
struct t_config_file *config_file,
struct t_config_section *section, struct config_free { void operator() (struct t_config_file *ptr) { weechat_config_free(ptr); } };
int index_option, struct config_file : public std::unique_ptr<struct t_config_file, config_free>, public config_breadcrumb {
const char *option_name, config_file(struct t_config_file *ptr, config& config, std::string name)
const char *default_value, : std::unique_ptr<struct t_config_file, config_free>(ptr)
const char *value, , config_breadcrumb(name)
int null_value_allowed, , configuration(config) {
int (*callback_check_value)(const void *pointer, if (ptr == nullptr) throw std::runtime_error("weechat_config_new");
void *data, }
struct t_config_option *option, config_file(config& config, std::string name, std::function<int(config_file&)> cb_reload)
const char *value), : config_file(weechat_config_new(
const void *callback_check_value_pointer, name.data(),
void *callback_check_value_data, [](const void *, void *data, struct t_config_file *config_file) {
void (*callback_change)(const void *pointer, auto& file = *reinterpret_cast<struct config_file*>(data);
void *data, if (file != config_file) throw std::invalid_argument("file != config_file");
struct t_config_option *option), if (!file.reload) return 1;
const void *callback_change_pointer, return file.reload() ? 1 : 0;
void *callback_change_data); }, nullptr, this), config, name) {
this->reload = std::bind(cb_reload, std::ref(*this));
extern int config__init(); }
extern int config__read(); operator struct t_config_file *() { return get(); }
extern int config__write(); std::function<int()> reload;
extern void config__free(); config& configuration;
std::unordered_map<struct t_config_section *, config_section&> sections;
bool read() { return weechat_config_read(*this); }
bool write() { return weechat_config_write(*this); }
};
struct config_section_free { void operator() (struct t_config_section *ptr) { weechat_config_section_free(ptr); } };
struct config_section : public std::unique_ptr<struct t_config_section, config_section_free>, public config_breadcrumb {
config_section(struct t_config_section *ptr, config_file& file, std::string name)
: std::unique_ptr<struct t_config_section, config_section_free>(ptr)
, config_breadcrumb(name)
, file(file) {
if (ptr == nullptr) throw std::runtime_error("weechat_config_new_section");
}
config_section(config_file& config_file, std::string name,
bool user_can_add_options, bool user_can_delete_options,
std::function<bool(config_section&, const char *, const char *)> cb_read,
std::function<bool(config_section&, const char *)> cb_write,
std::function<bool(config_section&, const char *)> cb_write_default,
std::function<bool(config_section&, const char *, const char *)> cb_create_option,
std::function<bool(config_section&, config_option &)> cb_delete_option)
: config_section(weechat_config_new_section(
config_file, name.data(), user_can_add_options, user_can_delete_options,
[](const void *, void *data, struct t_config_file *config_file,
struct t_config_section *sect, const char *option_name, const char *value) {
auto& section = *reinterpret_cast<config_section*>(data);
if (section != sect) throw std::invalid_argument("section != sect");
if (section.file != config_file) throw std::invalid_argument("section.file != config_file");
if (!section.read) return 0;
return section.read(option_name, value) ? 0 : -1;
}, nullptr, this,
[](const void *, void *data, struct t_config_file *config_file,
const char *section_name) {
auto& section = *reinterpret_cast<config_section*>(data);
if (section.file != config_file) throw std::invalid_argument("section.file != config_file");
if (!section.write) return 0;
return section.write(section_name) ? 0 : -1;
}, nullptr, this,
[](const void *, void *data, struct t_config_file *config_file,
const char *section_name) {
auto& section = *reinterpret_cast<config_section*>(data);
if (section.file != config_file) throw std::invalid_argument("section.file != config_file");
if (!section.write_default) return 0;
return section.write_default(section_name) ? 0 : -1;
}, nullptr, this,
[](const void *, void *data, struct t_config_file *config_file,
struct t_config_section *sect, const char *option_name, const char *value) {
auto& section = *reinterpret_cast<config_section*>(data);
if (section != sect) throw std::invalid_argument("section != sect");
if (section.file != config_file) throw std::invalid_argument("section.file != config_file");
if (!section.create_option) return 0;
return section.create_option(option_name, value) ? 0 : -1;
}, nullptr, this,
[](const void *, void *data, struct t_config_file *config_file,
struct t_config_section *sect, struct t_config_option *opt) {
auto& section = *reinterpret_cast<config_section*>(data);
if (section != sect) throw std::invalid_argument("section != sect");
if (section.file != config_file) throw std::invalid_argument("section.file != config_file");
if (!section.delete_option) return 0;
auto option = section.options.find(opt);
if (option == section.options.end()) throw std::invalid_argument("unknown option");
return section.delete_option(option->second) ? 0 : -1;
}, nullptr, this), config_file, name) {
if (cb_read)
this->read = std::bind(cb_read, std::ref(*this), _1, _2);
if (cb_write)
this->write = std::bind(cb_write, std::ref(*this), _1);
if (cb_write_default)
this->write_default = std::bind(cb_write_default, std::ref(*this), _1);
if (cb_create_option)
this->create_option = std::bind(cb_create_option, std::ref(*this), _1, _2);
if (cb_delete_option)
this->delete_option = std::bind(cb_delete_option, std::ref(*this), _1);
}
operator struct t_config_section *() { return get(); }
std::function<bool(const char *, const char *)> read;
std::function<bool(const char *)> write;
std::function<bool(const char *)> write_default;
std::function<bool(const char *, const char *)> create_option;
std::function<bool(config_option&)> delete_option;
config_file& file;
std::unordered_map<struct t_config_option *, config_option&> options;
};
struct config_option_free { void operator() (struct t_config_option *ptr) { weechat_config_option_free(ptr); } };
struct config_option : public std::unique_ptr<struct t_config_option, config_option_free>, public config_breadcrumb {
config_option(struct t_config_option *ptr, config_section& section, std::string name)
: std::unique_ptr<struct t_config_option, config_option_free>(ptr)
, config_breadcrumb(name, section)
, section(section) {
if (ptr == nullptr) throw std::runtime_error("weechat_config_new_option");
}
config_option(config_file& config_file, config_section& section,
std::string name, const char *type, const char *description, const char *string_values,
int min, int max, const char *default_value, const char *value, bool null_value_allowed,
std::function<bool(config_option&, const char *)> cb_check_value,
std::function<void(config_option&)> cb_change,
std::function<void(config_option&)> cb_delete)
: config_option(weechat_config_new_option(
config_file, section,
name.data(), type, description, string_values,
min, max, default_value, value, null_value_allowed,
[](const void *, void *data, struct t_config_option *opt, const char *value) {
auto& option = *reinterpret_cast<config_option*>(data);
if (option != opt) throw std::invalid_argument("option != opt");
if (!option.check_value) return 1;
return option.check_value(value) ? 1 : 0;
}, nullptr, this,
[](const void *, void *data, struct t_config_option *opt) {
auto& option = *reinterpret_cast<config_option*>(data);
if (option != opt) throw std::invalid_argument("option != opt");
if (option.on_changed) option.on_changed();
}, nullptr, this,
[](const void *, void *data, struct t_config_option *opt) {
auto& option = *reinterpret_cast<config_option*>(data);
if (option != opt) throw std::invalid_argument("option != opt");
if (option.on_deleted) option.on_deleted();
}, nullptr, this), section, name) {
if (cb_check_value)
this->check_value = std::bind(cb_check_value, std::ref(*this), _1);
if (cb_change)
this->on_changed = std::bind(cb_change, std::ref(*this));
if (cb_delete)
this->on_deleted = std::bind(cb_delete, std::ref(*this));
}
operator struct t_config_option *() { return get(); }
std::function<bool(const char *)> check_value;
std::function<void()> on_changed;
std::function<void()> on_deleted;
config_section& section;
int operator =(std::string value) { return weechat_config_option_set(*this, value.data(), 1); }
int clear() { return weechat_config_option_set(*this, nullptr, 1); }
std::string_view string() { return weechat_config_string(*this); }
int integer() { return weechat_config_integer(*this); }
bool boolean() { return weechat_config_boolean(*this); }
bool write() { return weechat_config_write_option(section.file, *this); }
};
class config_account {
public:
config_account(config_file& config_file, config_section& section_account, const char *name)
: section(section_account)
, option_jid(config_file, section_account,
fmt::format("{0}.{1} << xmpp.account_default.{1}", name, "jid"),
"string", "XMPP Account JID", nullptr, 0, 0, "", "", false,
[&](config_option&, const char *) { return true; },
[&](config_option&) {},
[&](config_option&) {})
, option_password(config_file, section_account,
fmt::format("{0}.{1} << xmpp.account_default.{1}", name, "password"),
"string", "XMPP Account Password", nullptr, 0, 0, "", "", false,
[&](config_option&, const char *) { return true; },
[&](config_option&) {},
[&](config_option&) {})
, option_tls(config_file, section_account,
fmt::format("{0}.{1} << xmpp.account_default.{1}", name, "tls"),
"integer", "XMPP Server TLS Policy", "disable|normal|trust", 0, 0,
"normal", "normal", false,
[&](config_option&, const char *) { return true; },
[&](config_option&) {},
[&](config_option&) {})
, option_nickname(config_file, section_account,
fmt::format("{0}.{1} << xmpp.account_default.{1}", name, "nickname"),
"string", "XMPP Account Nickname", nullptr, 0, 0, "", "", false,
[&](config_option&, const char *) { return true; },
[&](config_option&) {},
[&](config_option&) {})
, option_autoconnect(config_file, section_account,
fmt::format("{0}.{1} << xmpp.account_default.{1}", name, "autoconnect"),
"boolean", "Autoconnect XMPP Account", nullptr, 0, 0, "", "", false,
[&](config_option&, const char *) { return true; },
[&](config_option&) {},
[&](config_option&) {})
, option_resource(config_file, section_account,
fmt::format("{0}.{1} << xmpp.account_default.{1}", name, "resource"),
"string", "XMPP Account Resource", nullptr, 0, 0, "", "", false,
[&](config_option&, const char *) { return true; },
[&](config_option&) {},
[&](config_option&) {})
, option_status(config_file, section_account,
fmt::format("{0}.{1} << xmpp.account_default.{1}", name, "status"),
"string", "XMPP Account Login Status", nullptr, 0, 0,
"probably about to segfault", "probably about to segfault", false,
[&](config_option&, const char *) { return true; },
[&](config_option&) {},
[&](config_option&) {})
, option_pgp_path(config_file, section_account,
fmt::format("{0}.{1} << xmpp.account_default.{1}", name, "pgp_path"),
"string", "XMPP Account PGP Keyring Dir", nullptr, 0, 0, "", "", false,
[&](config_option&, const char *) { return true; },
[&](config_option&) {},
[&](config_option&) {})
, option_pgp_keyid(config_file, section_account,
fmt::format("{0}.{1} << xmpp.account_default.{1}", name, "pgp_keyid"),
"string", "XMPP Account PGP Key ID", nullptr, 0, 0, "", "", false,
[&](config_option&, const char *) { return true; },
[&](config_option&) {},
[&](config_option&) {})
{
}
config_account(config_file& config_file, config_section& section_account_default)
: section(section_account_default)
, option_jid(config_file, section_account_default,
"jid", "string", "XMPP Account JID", nullptr, 0, 0, "", "", false,
[&](config_option&, const char *) { return true; },
[&](config_option&) {},
[&](config_option&) {})
, option_password(config_file, section_account_default,
"password", "string", "XMPP Account Password", nullptr, 0, 0, "", "", false,
[&](config_option&, const char *) { return true; },
[&](config_option&) {},
[&](config_option&) {})
, option_tls(config_file, section_account_default,
"tls", "integer", "XMPP Server TLS Policy", "disable|normal|trust", 0, 0,
"normal", "normal", false,
[&](config_option&, const char *) { return true; },
[&](config_option&) {},
[&](config_option&) {})
, option_nickname(config_file, section_account_default,
"nickname", "string", "XMPP Account Nickname", nullptr, 0, 0, "", "", false,
[&](config_option&, const char *) { return true; },
[&](config_option&) {},
[&](config_option&) {})
, option_autoconnect(config_file, section_account_default,
"autoconnect", "boolean", "Autoconnect XMPP Account", nullptr, 0, 0, "", "", false,
[&](config_option&, const char *) { return true; },
[&](config_option&) {},
[&](config_option&) {})
, option_resource(config_file, section_account_default,
"resource", "string", "XMPP Account Resource", nullptr, 0, 0, "", "", false,
[&](config_option&, const char *) { return true; },
[&](config_option&) {},
[&](config_option&) {})
, option_status(config_file, section_account_default,
"status", "string", "XMPP Account Login Status", nullptr, 0, 0,
"probably about to segfault", "probably about to segfault", false,
[&](config_option&, const char *) { return true; },
[&](config_option&) {},
[&](config_option&) {})
, option_pgp_path(config_file, section_account_default,
"pgp_path", "string", "XMPP Account PGP Keyring Dir", nullptr, 0, 0, "", "", false,
[&](config_option&, const char *) { return true; },
[&](config_option&) {},
[&](config_option&) {})
, option_pgp_keyid(config_file, section_account_default,
"pgp_keyid", "string", "XMPP Account PGP Key ID", nullptr, 0, 0, "", "", false,
[&](config_option&, const char *) { return true; },
[&](config_option&) {},
[&](config_option&) {})
{
}
config_section& section;
config_option option_jid;
config_option option_password;
config_option option_tls;
config_option option_nickname;
config_option option_autoconnect;
config_option option_resource;
config_option option_status;
config_option option_pgp_path;
config_option option_pgp_keyid;
bool read(const char *, const char *);
bool write();
};
class config {
public:
enum class nick_completion
{
SMART_OFF = 0,
SMART_SPEAKERS,
SMART_SPEAKERS_HIGHLIGHTS,
};
config_file file;
config_section section_account_default;
config_section section_account;
config_section section_look;
config_account account_default;
struct {
config_option nick_completion_smart;
} look;
public:
config();
~config();
static tl::optional<config> instance;
public:
static bool init();
static bool read();
static bool write();
};
}

File diff suppressed because it is too large Load Diff

@ -4,12 +4,74 @@
#pragma once #pragma once
#include <cstdint>
#include <memory>
#include <string>
#include <strophe.h> #include <strophe.h>
#include "xmpp/ns.hh"
#include "strophe.hh"
#include "config.hh"
void connection__init(); namespace weechat {
class account;
int connection__connect(struct t_account *account, xmpp_conn_t **connection, class connection
const char* jid, const char* password, int tls); {
private:
libstrophe::connection m_conn;
void connection__process(xmpp_ctx_t *context, xmpp_conn_t *connection, enum class event {
const unsigned long timeout); connect = XMPP_CONN_CONNECT,
raw_connect = XMPP_CONN_RAW_CONNECT,
disconnect = XMPP_CONN_DISCONNECT,
fail = XMPP_CONN_FAIL,
};
public:
weechat::account &account;
connection(weechat::account &acc, libstrophe::context &ctx)
: m_conn(ctx), account(acc) {
}
inline operator xmpp_conn_t*() {
return m_conn;
}
inline auto send(xmpp_stanza_t *stanza) {
m_conn.send(stanza);
}
inline auto context() {
return m_conn.get_context();
}
inline bool connect_client(const char* altdomain, unsigned short altport, xmpp_conn_handler callback) {
return m_conn.connect_client(altdomain, altport, callback, this) == XMPP_EOK;
}
inline auto handler_add(const char *name, const char *type, xmpp_handler callback) {
return m_conn.handler_add(callback, nullptr, name, type, this);
}
template <typename X, std::enable_if_t<std::is_base_of<xmlns,X>::value, int> = 0>
inline auto handler_add(const char *name, const char *type, xmpp_handler callback) {
return m_conn.handler_add(callback, X(), name, type, this);
}
static void init();
int connect(std::string jid, std::string password, weechat::tls_policy tls);
void process(xmpp_ctx_t *context, const unsigned long timeout);
bool version_handler(xmpp_stanza_t *stanza);
bool presence_handler(xmpp_stanza_t *stanza);
bool message_handler(xmpp_stanza_t *stanza);
bool iq_handler(xmpp_stanza_t *stanza);
bool conn_handler(event status, int error, xmpp_stream_error_t *stream_error);
xmpp_stanza_t *get_caps(xmpp_stanza_t *reply, char **hash);
};
}

@ -16,8 +16,8 @@
int input__data(struct t_gui_buffer *buffer, const char *text) int input__data(struct t_gui_buffer *buffer, const char *text)
{ {
struct t_account *account = NULL; weechat::account *account = NULL;
struct t_channel *channel = NULL; weechat::channel *channel = NULL;
buffer__get_account_and_channel(buffer, &account, &channel); buffer__get_account_and_channel(buffer, &account, &channel);
@ -26,7 +26,7 @@ int input__data(struct t_gui_buffer *buffer, const char *text)
if (channel) if (channel)
{ {
if (!account->is_connected) if (!account->connected())
{ {
weechat_printf(buffer, weechat_printf(buffer,
_("%s%s: you are not connected to server"), _("%s%s: you are not connected to server"),
@ -34,7 +34,7 @@ int input__data(struct t_gui_buffer *buffer, const char *text)
return WEECHAT_RC_OK; return WEECHAT_RC_OK;
} }
if (channel__send_message(account, channel, channel->id, text) == WEECHAT_RC_OK) if (channel->send_message(channel->id, text) == WEECHAT_RC_OK)
return WEECHAT_RC_OK; return WEECHAT_RC_OK;
else else
{ {
@ -62,15 +62,15 @@ int input__data_cb(const void *pointer, void *data,
int input__typing(struct t_gui_buffer *buffer) int input__typing(struct t_gui_buffer *buffer)
{ {
struct t_account *account = NULL; weechat::account *account = NULL;
struct t_channel *channel = NULL; weechat::channel *channel = NULL;
buffer__get_account_and_channel(buffer, &account, &channel); buffer__get_account_and_channel(buffer, &account, &channel);
if (account && account->is_connected && channel) if (account && account->connected() && channel)
{ {
channel__send_reads(account, channel); channel->send_reads();
channel__send_typing(account, channel, NULL); channel->send_typing(NULL);
} }
return WEECHAT_RC_OK; return WEECHAT_RC_OK;

@ -108,7 +108,7 @@ release: xmpp.so
cp xmpp.so .xmpp.so.$(SUFFIX) cp xmpp.so .xmpp.so.$(SUFFIX)
ln -sf .xmpp.so.$(SUFFIX) .xmpp.so ln -sf .xmpp.so.$(SUFFIX) .xmpp.so
xmpp.so: $(OBJS) $(DEPS) $(HDRS) xmpp.so: $(DEPS) $(OBJS) $(HDRS)
$(CXX) $(LDFLAGS) -o $@ $(OBJS) $(DEPS) $(LDLIBS) $(CXX) $(LDFLAGS) -o $@ $(OBJS) $(DEPS) $(LDLIBS)
git ls-files | xargs ls -d | xargs tar cz | objcopy --add-section .source=/dev/stdin xmpp.so git ls-files | xargs ls -d | xargs tar cz | objcopy --add-section .source=/dev/stdin xmpp.so
#objcopy --dump-section .source=/dev/stdout xmpp.so | tar tz #objcopy --dump-section .source=/dev/stdout xmpp.so | tar tz

@ -19,11 +19,11 @@
static const char format_regex[] = "<([^>]*?)>"; static const char format_regex[] = "<([^>]*?)>";
static const size_t max_groups = 2; static const size_t max_groups = 2;
char *message__translate_code(struct t_account *account, char *message__translate_code(weechat::account *account,
const char *code) const char *code)
{ {
struct t_channel *channel; decltype(account->channels)::iterator channel;
struct t_user *user; weechat::user *user;
size_t resultlen; size_t resultlen;
char *identifier, *alttext, *result, *symbol, *prefix; char *identifier, *alttext, *result, *symbol, *prefix;
@ -42,11 +42,11 @@ char *message__translate_code(struct t_account *account,
} }
else else
{ {
channel = channel__search(account, identifier+1); channel = account->channels.find(identifier+1);
if (channel) if (channel != account->channels.end())
{ {
prefix = (char*)"#"; prefix = (char*)"#";
symbol = strdup(channel->name); symbol = strdup(channel->second.name.data());
} }
else else
{ {
@ -63,7 +63,7 @@ char *message__translate_code(struct t_account *account,
} }
else else
{ {
user = user__search(account, identifier+1); user = weechat::user::search(account, identifier+1);
if (user) if (user)
{ {
prefix = (char*)"@"; prefix = (char*)"@";
@ -148,7 +148,7 @@ void message__htmldecode(char *dest, const char *src, size_t n)
return; return;
} }
char *message__decode(struct t_account *account, char *message__decode(weechat::account *account,
const char *text) const char *text)
{ {
int rc; int rc;

@ -6,5 +6,5 @@
#define MESSAGE_MAX_LENGTH 40000 #define MESSAGE_MAX_LENGTH 40000
char *message__decode(struct t_account *account, char *message__decode(weechat::account *account,
const char *text); const char *text);

@ -2125,7 +2125,7 @@ void omemo::handle_bundle(const char *jid, uint32_t device_id,
key_signature, identity_key, omemo); key_signature, identity_key, omemo);
} }
char *omemo::decode(struct t_account *account, const char *jid, char *omemo::decode(weechat::account *account, const char *jid,
xmpp_stanza_t *encrypted) xmpp_stanza_t *encrypted)
{ {
auto omemo = &account->omemo; auto omemo = &account->omemo;
@ -2267,7 +2267,7 @@ char *omemo::decode(struct t_account *account, const char *jid,
return NULL; return NULL;
} }
xmpp_stanza_t *omemo::encode(struct t_account *account, const char *jid, xmpp_stanza_t *omemo::encode(weechat::account *account, const char *jid,
const char *unencrypted) const char *unencrypted)
{ {
auto omemo = &account->omemo; auto omemo = &account->omemo;
@ -2362,7 +2362,7 @@ xmpp_stanza_t *omemo::encode(struct t_account *account, const char *jid,
session_cipher_free(cipher); session_cipher_free(cipher);
} }
signal_int_list_free(devicelist); signal_int_list_free(devicelist);
target = account_jid(account); target = account->jid().data();
} }
free(key_and_tag); free(key_and_tag);

@ -13,19 +13,20 @@
#include <signal_protocol.h> #include <signal_protocol.h>
#include "signal.hh" #include "signal.hh"
struct t_account;
extern const char *OMEMO_ADVICE; extern const char *OMEMO_ADVICE;
namespace weechat::xmpp { namespace weechat {
class account;
struct t_pre_key { namespace xmpp {
struct t_pre_key {
const char *id; const char *id;
const char *public_key; const char *public_key;
}; };
struct omemo struct omemo
{ {
libsignal::context context; libsignal::context context;
libsignal::store_context store_context; libsignal::store_context store_context;
@ -69,11 +70,11 @@ struct omemo
void handle_bundle(const char *jid, std::uint32_t device_id, void handle_bundle(const char *jid, std::uint32_t device_id,
xmpp_stanza_t *items); xmpp_stanza_t *items);
char *decode(struct t_account *account, const char *jid, char *decode(weechat::account *account, const char *jid,
xmpp_stanza_t *encrypted); xmpp_stanza_t *encrypted);
xmpp_stanza_t *encode(struct t_account *account, const char *jid, xmpp_stanza_t *encode(weechat::account *account, const char *jid,
const char *unencrypted); const char *unencrypted);
}; };
}
} }

@ -15,10 +15,10 @@
#include "plugin.hh" #include "plugin.hh"
#include "pgp.hh" #include "pgp.hh"
std::string format_key(struct t_pgp *pgp, std::string_view keyid) std::string format_key(weechat::xmpp::pgp &pgp, std::string_view keyid)
{ {
gpgme_key_t key = nullptr; gpgme_key_t key = nullptr;
gpgme_error_t err = gpgme_get_key(pgp->gpgme, keyid.data(), &key, false); gpgme_error_t err = gpgme_get_key(pgp.gpgme, keyid.data(), &key, false);
if (err) { if (err) {
return fmt::format("{} (none)", keyid); return fmt::format("{} (none)", keyid);
} }
@ -54,37 +54,34 @@ std::string format_key(struct t_pgp *pgp, std::string_view keyid)
#define PGP_SIGNATURE_HEADER "-----BEGIN PGP SIGNATURE-----\r\n" #define PGP_SIGNATURE_HEADER "-----BEGIN PGP SIGNATURE-----\r\n"
#define PGP_SIGNATURE_FOOTER "\r\n-----END PGP SIGNATURE-----" #define PGP_SIGNATURE_FOOTER "\r\n-----END PGP SIGNATURE-----"
const char *PGP_ADVICE = "[PGP encrypted message (XEP-0027)]"; const char *weechat::xmpp::PGP_ADVICE = "[PGP encrypted message (XEP-0027)]";
void pgp__init(struct t_pgp **pgp) weechat::xmpp::pgp::pgp()
{ {
struct t_pgp *new_pgp;
gpgme_error_t err; gpgme_error_t err;
//gpgme_data_t keydata; //gpgme_data_t keydata;
gpgme_check_version(NULL); gpgme_check_version(NULL);
new_pgp = (struct t_pgp*)calloc(1, sizeof(**pgp)); err = gpgme_new(&this->gpgme);
err = gpgme_new(&new_pgp->gpgme);
if (err) { if (err) {
weechat_printf(nullptr, "gpg (error): %s - %s", weechat_printf(nullptr, "gpg (error): %s - %s",
gpgme_strsource(err), gpgme_strerror(err)); gpgme_strsource(err), gpgme_strerror(err));
return; throw nullptr;
} }
gpgme_set_armor(new_pgp->gpgme, true); gpgme_set_armor(this->gpgme, true);
//err = gpgme_data_new_from_file(&keydata, pub, true); //err = gpgme_data_new_from_file(&keydata, pub, true);
//if (err) { //if (err) {
// return; // return;
//} //}
//err = gpgme_op_import(new_pgp->gpgme, keydata); //err = gpgme_op_import(this->gpgme, keydata);
//if (err) { //if (err) {
// return; // return;
//} //}
//gpgme_import_result_t impRes = gpgme_op_import_result(new_pgp->gpgme); //gpgme_import_result_t impRes = gpgme_op_import_result(this->gpgme);
//weechat_printf(nullptr, "(gpg) imported %d keys", impRes->imported); //weechat_printf(nullptr, "(gpg) imported %d keys", impRes->imported);
//err = gpgme_data_new_from_file(&keydata, sec, true); //err = gpgme_data_new_from_file(&keydata, sec, true);
@ -92,28 +89,21 @@ void pgp__init(struct t_pgp **pgp)
// return; // return;
//} //}
//err = gpgme_op_import(new_pgp->gpgme, keydata); //err = gpgme_op_import(this->gpgme, keydata);
//if (err) { //if (err) {
// return; // return;
//} //}
//impRes = gpgme_op_import_result(new_pgp->gpgme); //impRes = gpgme_op_import_result(this->gpgme);
//weechat_printf(nullptr, "(gpg) imported %d secret keys", impRes->imported); //weechat_printf(nullptr, "(gpg) imported %d secret keys", impRes->imported);
*pgp = new_pgp;
} }
void pgp__free(struct t_pgp *pgp) weechat::xmpp::pgp::~pgp()
{ {
if (pgp) gpgme_release(this->gpgme);
{
if (pgp->gpgme)
gpgme_release(pgp->gpgme);
free(pgp);
}
} }
char *pgp__encrypt(struct t_gui_buffer *buffer, struct t_pgp *pgp, const char *source, std::vector<std::string>&& targets, const char *message) char *weechat::xmpp::pgp::encrypt(struct t_gui_buffer *buffer, const char *source, std::vector<std::string>&& targets, const char *message)
{ {
std::string encrypted; std::string encrypted;
gpgme_key_t keys[3] = {NULL,NULL,NULL}; gpgme_key_t keys[3] = {NULL,NULL,NULL};
@ -138,20 +128,20 @@ char *pgp__encrypt(struct t_gui_buffer *buffer, struct t_pgp *pgp, const char *s
/* Encrypt data. */ /* Encrypt data. */
for (const std::string& target : targets) for (const std::string& target : targets)
{ {
err = gpgme_get_key(pgp->gpgme, target.data(), &keys[0], false); err = gpgme_get_key(this->gpgme, target.data(), &keys[0], false);
if (err) { if (err) {
goto encrypt_finish; goto encrypt_finish;
} }
} }
err = gpgme_get_key(pgp->gpgme, source, &keys[1], false); err = gpgme_get_key(this->gpgme, source, &keys[1], false);
if (err) { if (err) {
goto encrypt_finish; goto encrypt_finish;
} }
err = gpgme_op_encrypt(pgp->gpgme, keys, GPGME_ENCRYPT_ALWAYS_TRUST, in, out); err = gpgme_op_encrypt(this->gpgme, keys, GPGME_ENCRYPT_ALWAYS_TRUST, in, out);
if (err) { if (err) {
goto encrypt_finish; goto encrypt_finish;
} }
if (gpgme_encrypt_result_t enc_result = gpgme_op_encrypt_result(pgp->gpgme); if (gpgme_encrypt_result_t enc_result = gpgme_op_encrypt_result(this->gpgme);
enc_result->invalid_recipients) enc_result->invalid_recipients)
{ {
goto encrypt_finish; goto encrypt_finish;
@ -177,7 +167,7 @@ encrypt_finish:
} }
//"hQIMAzlgcSFDGLKEAQ//cGG3DFughC5xBF7xeXz1RdayOfhBAPfoZIq62MVuSnfS\nMfig65Zxz1LtAnnFq90TZY7hiHPBtVlYqg47AbSoYweMdpXsKgbUrd3NNf6k2nsZ\nUkChCtyGuHi8pTzclfle7gT0nNXJ1WcLCZ4ORZCrg3D5A+YTO9tdmE8GQsTT6TdV\nbbxF5yR4JF5SzFhuFL3ZoXPXrWylcwKXarYfoOTa6M2vSsCwApVIXQgJ/FI46sLT\nb0B/EVCjFvcvjkNr7+K7mQtth+x0a0pC4BtEhRvnIRAe/sdGp8NY+DP76clx4U+k\nIDG4H92F632pR6eEIoZttnBoaj0O4sTVAJCao5AoecR4w2FDqBWWtIyQp5vbo17/\nMtzungkk5vQP6Jhu36wa+JKpbHoxomVpHPZfAtIoyaY6pzQ0bUomIlSVpbZDvF68\nZKTlFd89Pm5x0JO5gsVYvf+N9Ed33d34n/0CFz5K5Tgu4Bk0v4LWEy3wtNsuQB4p\nkBSZJk7I2BakcRwP0zwld6rRHFIX1pb7zqThBPZGB9RkWPltiktUTibOII12tWhi\nksFpQJ8l1A8h9vM5kUXIeD6H2yP0CBUEIZF3Sf+jiSRZ/1/n3KoUrKEzkf/y4xgv\n1LA4pMjNLEr6J2fqGyYRFv4Bxv3PIvF17V5CwOtguxGRJHJXdIzm1BSHSqXxHezS\nYAFXMUb9fw3QX7Ed23KiyZjzd/LRsQBqMs9RsYyZB2PqF9x84lQYYbE8lErrryvK\nUEtmJKPw3Hvb7kgGox5vl5+KCg9q64EU9TgQpufYNShKtDz7Fsvc+ncgZoshDUeo\npw==\n=euIB" //"hQIMAzlgcSFDGLKEAQ//cGG3DFughC5xBF7xeXz1RdayOfhBAPfoZIq62MVuSnfS\nMfig65Zxz1LtAnnFq90TZY7hiHPBtVlYqg47AbSoYweMdpXsKgbUrd3NNf6k2nsZ\nUkChCtyGuHi8pTzclfle7gT0nNXJ1WcLCZ4ORZCrg3D5A+YTO9tdmE8GQsTT6TdV\nbbxF5yR4JF5SzFhuFL3ZoXPXrWylcwKXarYfoOTa6M2vSsCwApVIXQgJ/FI46sLT\nb0B/EVCjFvcvjkNr7+K7mQtth+x0a0pC4BtEhRvnIRAe/sdGp8NY+DP76clx4U+k\nIDG4H92F632pR6eEIoZttnBoaj0O4sTVAJCao5AoecR4w2FDqBWWtIyQp5vbo17/\nMtzungkk5vQP6Jhu36wa+JKpbHoxomVpHPZfAtIoyaY6pzQ0bUomIlSVpbZDvF68\nZKTlFd89Pm5x0JO5gsVYvf+N9Ed33d34n/0CFz5K5Tgu4Bk0v4LWEy3wtNsuQB4p\nkBSZJk7I2BakcRwP0zwld6rRHFIX1pb7zqThBPZGB9RkWPltiktUTibOII12tWhi\nksFpQJ8l1A8h9vM5kUXIeD6H2yP0CBUEIZF3Sf+jiSRZ/1/n3KoUrKEzkf/y4xgv\n1LA4pMjNLEr6J2fqGyYRFv4Bxv3PIvF17V5CwOtguxGRJHJXdIzm1BSHSqXxHezS\nYAFXMUb9fw3QX7Ed23KiyZjzd/LRsQBqMs9RsYyZB2PqF9x84lQYYbE8lErrryvK\nUEtmJKPw3Hvb7kgGox5vl5+KCg9q64EU9TgQpufYNShKtDz7Fsvc+ncgZoshDUeo\npw==\n=euIB"
char *pgp__decrypt(struct t_gui_buffer *buffer, struct t_pgp *pgp, const char *ciphertext) char *weechat::xmpp::pgp::decrypt(struct t_gui_buffer *buffer, const char *ciphertext)
{ {
std::string decrypted; std::string decrypted;
uint8_t * buf = NULL; uint8_t * buf = NULL;
@ -207,14 +197,14 @@ char *pgp__decrypt(struct t_gui_buffer *buffer, struct t_pgp *pgp, const char *c
} }
/* Decrypt data. */ /* Decrypt data. */
err = gpgme_op_decrypt(pgp->gpgme, in, out); err = gpgme_op_decrypt(this->gpgme, in, out);
if (gpgme_decrypt_result_t dec_result = gpgme_op_decrypt_result(pgp->gpgme); if (gpgme_decrypt_result_t dec_result = gpgme_op_decrypt_result(this->gpgme);
dec_result) dec_result)
{ {
for (auto recip = dec_result->recipients; recip; recip = recip->next) for (auto recip = dec_result->recipients; recip; recip = recip->next)
{ {
if (!keyids.empty()) keyids += ", "; if (!keyids.empty()) keyids += ", ";
keyids += format_key(pgp, recip->keyid); keyids += format_key(*this, recip->keyid);
} }
if (dec_result->unsupported_algorithm) if (dec_result->unsupported_algorithm)
{ {
@ -243,7 +233,7 @@ decrypt_finish:
return result; return result;
} }
char *pgp__verify(struct t_gui_buffer *buffer, struct t_pgp *pgp, const char *certificate) char *weechat::xmpp::pgp::verify(struct t_gui_buffer *buffer, const char *certificate)
{ {
uint8_t * buf = NULL; uint8_t * buf = NULL;
size_t buf_len = 0; size_t buf_len = 0;
@ -271,11 +261,11 @@ char *pgp__verify(struct t_gui_buffer *buffer, struct t_pgp *pgp, const char *ce
} }
/* Verify data. */ /* Verify data. */
err = gpgme_op_verify(pgp->gpgme, in, out, nullptr); err = gpgme_op_verify(this->gpgme, in, out, nullptr);
if (err) { if (err) {
goto verify_finish; goto verify_finish;
} }
if (vrf_result = gpgme_op_verify_result(pgp->gpgme); if (vrf_result = gpgme_op_verify_result(this->gpgme);
!(vrf_result->signatures->summary & GPGME_SIGSUM_VALID)) !(vrf_result->signatures->summary & GPGME_SIGSUM_VALID))
{ {
//goto verify_finish; //goto verify_finish;
@ -283,10 +273,10 @@ char *pgp__verify(struct t_gui_buffer *buffer, struct t_pgp *pgp, const char *ce
result = strdup(vrf_result->signatures->fpr); result = strdup(vrf_result->signatures->fpr);
err = gpgme_get_key(pgp->gpgme, result, &key, false); err = gpgme_get_key(this->gpgme, result, &key, false);
if (err) { if (err) {
const char *keyids[2] = { result, nullptr }; const char *keyids[2] = { result, nullptr };
err = gpgme_op_receive_keys(pgp->gpgme, keyids); err = gpgme_op_receive_keys(this->gpgme, keyids);
} }
verify_finish: verify_finish:
@ -297,7 +287,7 @@ verify_finish:
return result; return result;
} }
char *pgp__sign(struct t_gui_buffer *buffer, struct t_pgp *pgp, const char *source, const char *message) char *weechat::xmpp::pgp::sign(struct t_gui_buffer *buffer, const char *source, const char *message)
{ {
std::string signature; std::string signature;
char * result = NULL; char * result = NULL;
@ -321,33 +311,33 @@ char *pgp__sign(struct t_gui_buffer *buffer, struct t_pgp *pgp, const char *sour
/* Include signature within key. */ /* Include signature within key. */
{ {
gpgme_keylist_mode_t kmode = gpgme_get_keylist_mode(pgp->gpgme); gpgme_keylist_mode_t kmode = gpgme_get_keylist_mode(this->gpgme);
kmode |= GPGME_KEYLIST_MODE_LOCATE; kmode |= GPGME_KEYLIST_MODE_LOCATE;
kmode |= GPGME_KEYLIST_MODE_SIGS; kmode |= GPGME_KEYLIST_MODE_SIGS;
err = gpgme_set_keylist_mode(pgp->gpgme, kmode); err = gpgme_set_keylist_mode(this->gpgme, kmode);
} }
if (err) { if (err) {
goto sign_finish; goto sign_finish;
} }
err = gpgme_get_key(pgp->gpgme, source, &key, false); err = gpgme_get_key(this->gpgme, source, &key, false);
if (err) { if (err) {
weechat_printf(nullptr, "(gpg) get key fail for %s", source); weechat_printf(nullptr, "(gpg) get key fail for %s", source);
goto sign_finish; goto sign_finish;
} }
err = gpgme_signers_add(pgp->gpgme, key); err = gpgme_signers_add(this->gpgme, key);
if (err) { if (err) {
weechat_printf(nullptr, "(gpg) add key fail for %s", source); weechat_printf(nullptr, "(gpg) add key fail for %s", source);
goto sign_finish; goto sign_finish;
} }
/* Sign data. */ /* Sign data. */
err = gpgme_op_sign(pgp->gpgme, in, out, GPGME_SIG_MODE_DETACH); err = gpgme_op_sign(this->gpgme, in, out, GPGME_SIG_MODE_DETACH);
if (err) { if (err) {
weechat_printf(nullptr, "(gpg) sign fail for %s", source); weechat_printf(nullptr, "(gpg) sign fail for %s", source);
goto sign_finish; goto sign_finish;
} }
if (gpgme_sign_result_t sgn_result = gpgme_op_sign_result(pgp->gpgme); if (gpgme_sign_result_t sgn_result = gpgme_op_sign_result(this->gpgme);
!sgn_result->signatures) !sgn_result->signatures)
{ {
weechat_printf(nullptr, "(gpg) signature fail for %s", source); weechat_printf(nullptr, "(gpg) signature fail for %s", source);

@ -7,22 +7,27 @@
#include <string> #include <string>
#include <vector> #include <vector>
extern const char *PGP_ADVICE; namespace weechat::xmpp
struct t_pgp
{ {
extern const char *PGP_ADVICE;
class pgp
{
public:
struct gpgme_context *gpgme; struct gpgme_context *gpgme;
const char *keyid; const char *keyid;
};
void pgp__init(struct t_pgp **pgp); public:
pgp();
void pgp__free(struct t_pgp *pgp); ~pgp();
char *pgp__decrypt(struct t_gui_buffer *buffer, struct t_pgp *pgp, const char *ciphertext); char *decrypt(struct t_gui_buffer *buffer, const char *ciphertext);
char *pgp__encrypt(struct t_gui_buffer *buffer, struct t_pgp *pgp, const char *source, std::vector<std::string>&& target, const char *message); char *encrypt(struct t_gui_buffer *buffer, const char *source, std::vector<std::string>&& target, const char *message);
char *pgp__verify(struct t_gui_buffer *buffer, struct t_pgp *pgp, const char *certificate); char *verify(struct t_gui_buffer *buffer, const char *certificate);
char *pgp__sign(struct t_gui_buffer *buffer, struct t_pgp *pgp, const char *source, const char *message); char *sign(struct t_gui_buffer *buffer, const char *source, const char *message);
};
}

@ -51,19 +51,19 @@ int weechat_plugin_init(struct t_weechat_plugin *plugin, int argc, char *argv[])
weechat_xmpp_plugin = plugin; weechat_xmpp_plugin = plugin;
if (!config__init()) if (!weechat::config::init())
return WEECHAT_RC_ERROR; return WEECHAT_RC_ERROR;
config__read(); weechat::config::read();
connection__init(); weechat::connection::init();
command__init(); command__init();
completion__init(); completion__init();
weechat_xmpp_process_timer = weechat_hook_timer(TIMER_INTERVAL_SEC * 1000, 0, 0, weechat_xmpp_process_timer = weechat_hook_timer(TIMER_INTERVAL_SEC * 1000, 0, 0,
&account__timer_cb, &weechat::account::timer_cb,
NULL, NULL); NULL, NULL);
if (!weechat_bar_search("typing")) if (!weechat_bar_search("typing"))
@ -95,11 +95,11 @@ int weechat_plugin_end(struct t_weechat_plugin *plugin)
if (weechat_xmpp_process_timer) if (weechat_xmpp_process_timer)
weechat_unhook(weechat_xmpp_process_timer); weechat_unhook(weechat_xmpp_process_timer);
config__write(); weechat::config::write();
account__disconnect_all(); weechat::account::disconnect_all();
account__free_all(); weechat::accounts.clear();
xmpp_shutdown(); xmpp_shutdown();

@ -0,0 +1,207 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, version 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#pragma once
#include <fmt/core.h>
#include <memory>
#include <functional>
#include <type_traits>
#include <strophe.h>
namespace libstrophe {
template<typename T, typename CFun, typename DFun,
CFun &f_create, DFun &f_destroy, typename Base = T>
class type {
private:
T *_ptr;
protected:
typedef T* pointer_type;
inline type(T *ptr) : _ptr(ptr) {
}
template<typename Fun, Fun &func, int success = 0, typename... Args,
typename = std::enable_if_t<std::is_same_v<int, std::invoke_result_t<Fun, pointer_type, std::decay_t<Args>...>>>>
inline void call_checked(Args&&... args) {
int ret = func(*this, std::forward<Args>(args)...);
if (ret != success) throw std::runtime_error(
fmt::format("Strophe Error: expected {}, was {}", success, ret));
}
template<typename Fun, Fun &func, int success = 0, typename... Args,
typename = std::enable_if_t<std::is_same_v<void, std::invoke_result_t<Fun, pointer_type, std::decay_t<Args>...>>>>
inline void call(Args&&... args) {
func(*this, std::forward<Args>(args)...);
}
template<typename Fun, Fun &func, typename... Args,
typename = std::enable_if_t<!std::is_same_v<void, std::invoke_result_t<Fun, pointer_type, std::decay_t<std::decay_t<Args>>...>>>>
inline typename std::invoke_result_t<Fun, pointer_type, std::decay_t<std::decay_t<Args>>...>
call(Args&&... args) {
return func(*this, std::forward<Args>(args)...);
}
public:
inline explicit type() : _ptr(nullptr) {
}
template<typename... Args>
inline explicit type(Args&&... args) : type() {
_ptr = f_create(std::forward<Args>(args)...);
}
inline ~type() {
if (_ptr)
f_destroy(reinterpret_cast<Base*>(_ptr));
_ptr = nullptr;
}
type(const type &other) = delete; /* no copy construction */
type(type &&other) = default;
template<typename... Args>
inline void create(Args&&... args) {
if (_ptr)
f_destroy(reinterpret_cast<Base*>(_ptr));
_ptr = f_create(std::forward<Args>(args)...);
}
type& operator =(const type &other) = delete; /* no copy assignment */
type& operator =(type &&other) = default;
inline operator bool() const { return _ptr; }
inline T* operator *() { return _ptr; }
inline operator T*() { return _ptr; }
inline operator const T*() const { return _ptr; }
};
inline auto initialize = xmpp_initialize;
typedef type<xmpp_ctx_t,
decltype(xmpp_ctx_new), decltype(xmpp_ctx_free),
xmpp_ctx_new, xmpp_ctx_free> context_type;
class context : public context_type {
public:
using context_type::context_type;
inline auto set_verbosity(auto &&...args) {
return call<decltype(xmpp_ctx_set_verbosity),
xmpp_ctx_set_verbosity>(args...);
}
};
typedef type<xmpp_conn_t,
decltype(xmpp_conn_new), decltype(xmpp_conn_release),
xmpp_conn_new, xmpp_conn_release> connection_type;
class connection : public connection_type {
public:
using connection_type::connection_type;
inline connection(context& ctx) {
create(*ctx);
}
inline auto get_context(auto &&...args) {
return call<decltype(xmpp_conn_get_context),
xmpp_conn_get_context>(args...);
}
inline auto get_flags(auto &&...args) {
return call<decltype(xmpp_conn_get_flags),
xmpp_conn_get_flags>(args...);
}
inline auto set_keepalive(auto &&...args) {
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
return call<decltype(xmpp_conn_set_keepalive),
xmpp_conn_set_keepalive>(args...);
#pragma GCC diagnostic pop
}
inline auto set_jid(auto &&...args) {
return call<decltype(xmpp_conn_set_jid),
xmpp_conn_set_jid>(args...);
}
inline auto set_pass(auto &&...args) {
return call<decltype(xmpp_conn_set_pass),
xmpp_conn_set_pass>(args...);
}
inline auto set_flags(auto &&...args) {
return call<decltype(xmpp_conn_set_flags),
xmpp_conn_set_flags>(args...);
}
inline auto send(auto &&...args) {
return call<decltype(xmpp_send), xmpp_send>(args...);
}
inline auto connect_client(auto &&...args) {
return call<decltype(xmpp_connect_client), xmpp_connect_client>(args...);
}
inline auto handler_add(auto &&...args) {
return call<decltype(xmpp_handler_add), xmpp_handler_add>(args...);
}
};
typedef type<xmpp_stanza_t,
decltype(xmpp_stanza_new), decltype(xmpp_stanza_release),
xmpp_stanza_new, xmpp_stanza_release> stanza_type;
class stanza : public stanza_type {
public:
using stanza_type::stanza_type;
inline static stanza reply(auto &&...args) {
return stanza(xmpp_stanza_reply(args...));
}
inline stanza get_name(auto &&...args) {
return call<decltype(xmpp_stanza_get_name),
xmpp_stanza_get_name>(args...);
}
inline stanza get_ns(auto &&...args) {
return call<decltype(xmpp_stanza_get_ns),
xmpp_stanza_get_ns>(args...);
}
inline stanza add_child(auto &&...args) {
call<decltype(xmpp_stanza_add_child),
xmpp_stanza_add_child>(args...);
return std::move(*this);
}
inline stanza set_name(auto &&...args) {
call<decltype(xmpp_stanza_set_name),
xmpp_stanza_set_name>(args...);
return std::move(*this);
}
inline stanza set_ns(auto &&...args) {
call<decltype(xmpp_stanza_set_ns),
xmpp_stanza_set_ns>(args...);
return std::move(*this);
}
inline stanza set_text(auto &&...args) {
call<decltype(xmpp_stanza_set_text),
xmpp_stanza_set_text>(args...);
return std::move(*this);
}
inline stanza set_type(auto &&...args) {
call<decltype(xmpp_stanza_set_type),
xmpp_stanza_set_type>(args...);
return std::move(*this);
}
};
}

@ -5,7 +5,7 @@
TEST_CASE("weechat") TEST_CASE("weechat")
{ {
std::string current("20211106-01"); std::string current("20220312-01");
SUBCASE("plugin api match") SUBCASE("plugin api match")
{ {

@ -14,22 +14,34 @@
#include "user.hh" #include "user.hh"
#include "channel.hh" #include "channel.hh"
const char *user__get_colour(struct t_user *user) std::string weechat::user::get_colour()
{ {
return weechat_info_get("nick_color", user->profile.display_name); return weechat::user::get_colour(this->profile.display_name);
} }
const char *user__get_colour_for_nicklist(struct t_user *user) std::string weechat::user::get_colour(const char *name)
{ {
return weechat_info_get("nick_color_name", user->profile.display_name); return weechat_info_get("nick_color", name);
} }
const char *user__as_prefix_raw(struct t_account *account, std::string weechat::user::get_colour_for_nicklist()
const char *name)
{ {
static char result[2048]; return weechat::user::get_colour_for_nicklist(this->profile.display_name);
}
std::string weechat::user::get_colour_for_nicklist(const char *name)
{
return weechat_info_get("nick_color_name", name);
}
std::string weechat::user::as_prefix_raw()
{
return weechat::user::as_prefix_raw(this->profile.display_name);
}
(void) account; std::string weechat::user::as_prefix_raw(const char *name)
{
static char result[2048];
snprintf(result, sizeof(result), "%s%s%s", snprintf(result, sizeof(result), "%s%s%s",
weechat_info_get("nick_color", name), weechat_info_get("nick_color", name),
@ -38,214 +50,126 @@ const char *user__as_prefix_raw(struct t_account *account,
return result; return result;
} }
const char *user__as_prefix(struct t_account *account, std::string weechat::user::as_prefix()
struct t_user *user,
const char *name)
{ {
static char result[2048]; return weechat::user::as_prefix(this->profile.display_name);
}
(void) account; std::string weechat::user::as_prefix(const char *name)
{
static char result[2048];
snprintf(result, sizeof(result), "%s%s\t", snprintf(result, sizeof(result), "%s%s\t",
user__get_colour(user), weechat::user::get_colour(name).data(), name);
name ? name : user->profile.display_name);
return result; return result;
} }
struct t_user *user__bot_search(struct t_account *account, weechat::user *weechat::user::bot_search(weechat::account *account,
const char *pgp_id) const char *pgp_id)
{ {
struct t_user *ptr_user;
if (!account || !pgp_id) if (!account || !pgp_id)
return NULL; return nullptr;
for (ptr_user = account->users; ptr_user; for (auto& ptr_user : account->users)
ptr_user = ptr_user->next_user)
{ {
if (ptr_user->profile.pgp_id && if (ptr_user.second.profile.pgp_id &&
weechat_strcasecmp(ptr_user->profile.pgp_id, pgp_id) == 0) ptr_user.second.profile.pgp_id == pgp_id)
return ptr_user; return &ptr_user.second;
} }
return NULL; return nullptr;
} }
struct t_user *user__search(struct t_account *account, weechat::user *weechat::user::search(weechat::account *account,
const char *id) const char *id)
{ {
struct t_user *ptr_user;
if (!account || !id) if (!account || !id)
return NULL; return nullptr;
for (ptr_user = account->users; ptr_user; if (auto user = account->users.find(id); user != account->users.end())
ptr_user = ptr_user->next_user) return &user->second;
{
if (weechat_strcasecmp(ptr_user->id, id) == 0)
return ptr_user;
}
return NULL; return nullptr;
} }
void user__nicklist_add(struct t_account *account, void weechat::user::nicklist_add(weechat::account *account,
struct t_channel *channel, weechat::channel *channel)
struct t_user *user)
{ {
struct t_gui_nick_group *ptr_group; struct t_gui_nick_group *ptr_group;
struct t_gui_buffer *ptr_buffer; struct t_gui_buffer *ptr_buffer;
char *name = channel ? user->profile.display_name : user->id; char *name = channel ? this->profile.display_name : this->id;
if (channel && weechat_strcasecmp(xmpp_jid_bare(account->context, name), if (channel && weechat_strcasecmp(xmpp_jid_bare(account->context, name),
channel->id) == 0) channel->id.data()) == 0)
name = xmpp_jid_resource(account->context, name); name = xmpp_jid_resource(account->context, name);
ptr_buffer = channel ? channel->buffer : account->buffer; ptr_buffer = channel ? channel->buffer : account->buffer;
char *group = (char*)"..."; char *group = (char*)"...";
if (weechat_strcasecmp(user->profile.affiliation, (char*)"outcast") == 0) if (this->profile.affiliation ? this->profile.affiliation == std::string("outcast") : false)
group = (char*)"!"; group = (char*)"!";
if (weechat_strcasecmp(user->profile.role, (char*)"visitor") == 0) if (this->profile.role ? this->profile.role == std::string("visitor") : false)
group = (char*)"?"; group = (char*)"?";
if (weechat_strcasecmp(user->profile.role, (char*)"participant") == 0) if (this->profile.role ? this->profile.role == std::string("participant") : false)
group = (char*)"+"; group = (char*)"+";
if (weechat_strcasecmp(user->profile.affiliation, (char*)"member") == 0) if (this->profile.affiliation ? this->profile.affiliation == std::string("member") : false)
group = (char*)"%"; group = (char*)"%";
if (weechat_strcasecmp(user->profile.role, (char*)"moderator") == 0) if (this->profile.role ? this->profile.role == std::string("moderator") : false)
group = (char*)"@"; group = (char*)"@";
if (weechat_strcasecmp(user->profile.affiliation, (char*)"admin") == 0) if (this->profile.affiliation ? this->profile.affiliation == std::string("admin") : false)
group = (char*)"&"; group = (char*)"&";
if (weechat_strcasecmp(user->profile.affiliation, (char*)"owner") == 0) if (this->profile.affiliation ? this->profile.affiliation == std::string("owner") : false)
group = (char*)"~"; group = (char*)"~";
ptr_group = weechat_nicklist_search_group(ptr_buffer, NULL, group); ptr_group = weechat_nicklist_search_group(ptr_buffer, nullptr, group);
weechat_nicklist_add_nick(ptr_buffer, ptr_group, weechat_nicklist_add_nick(ptr_buffer, ptr_group,
name, name,
user->is_away ? this->is_away ?
"weechat.color.nicklist_away" : "weechat.color.nicklist_away" :
user__get_colour_for_nicklist(user), get_colour_for_nicklist().data(),
group, group,
"bar_fg", "bar_fg",
1); 1);
} }
void user__nicklist_remove(struct t_account *account, void weechat::user::nicklist_remove(weechat::account *account,
struct t_channel *channel, weechat::channel *channel)
struct t_user *user)
{ {
struct t_gui_nick *ptr_nick; struct t_gui_nick *ptr_nick;
struct t_gui_buffer *ptr_buffer; struct t_gui_buffer *ptr_buffer;
char *name = user->profile.display_name; char *name = this->profile.display_name;
if (channel && weechat_strcasecmp(xmpp_jid_bare(account->context, name), if (channel && weechat_strcasecmp(xmpp_jid_bare(account->context, name),
channel->id) == 0) channel->id.data()) == 0)
name = xmpp_jid_resource(account->context, name); name = xmpp_jid_resource(account->context, name);
ptr_buffer = channel ? channel->buffer : account->buffer; ptr_buffer = channel ? channel->buffer : account->buffer;
if (name && (ptr_nick = weechat_nicklist_search_nick(ptr_buffer, NULL, name))) if (name && (ptr_nick = weechat_nicklist_search_nick(ptr_buffer, nullptr, name)))
weechat_nicklist_remove_nick(ptr_buffer, ptr_nick); weechat_nicklist_remove_nick(ptr_buffer, ptr_nick);
} }
struct t_user *user__new(struct t_account *account, weechat::user::user(weechat::account *account,
const char *id, const char *display_name) const char *id, const char *display_name)
{ {
struct t_user *new_user, *ptr_user;
if (!account || !id) if (!account || !id)
{ {
return NULL; throw nullptr;
} }
if (!account->users) //if (account->users.empty())
channel__add_nicklist_groups(account, NULL); // channel::add_nicklist_groups(account, nullptr);
ptr_user = user__search(account, id); weechat::user *ptr_user = user::search(account, id);
if (ptr_user) if (ptr_user)
{ {
user__nicklist_add(account, NULL, ptr_user); throw nullptr;
return ptr_user;
} }
new_user = new struct t_user; //account->users += this;
new_user->prev_user = account->last_user;
new_user->next_user = NULL;
if (account->last_user)
(account->last_user)->next_user = new_user;
else
account->users = new_user;
account->last_user = new_user;
new_user->id = strdup(id); this->id = strdup(id);
new_user->name = NULL;
new_user->profile.avatar_hash = NULL; this->profile.display_name = display_name ?
new_user->profile.status_text = NULL;
new_user->profile.status = NULL;
new_user->profile.display_name = display_name ?
strdup(display_name) : strdup(""); strdup(display_name) : strdup("");
new_user->profile.affiliation = NULL;
new_user->profile.email = NULL;
new_user->profile.role = NULL;
new_user->profile.pgp_id = NULL;
new_user->profile.omemo = 0;
new_user->updated = 0;
new_user->is_away = 0;
user__nicklist_add(account, NULL, new_user); nicklist_add(account, nullptr);
return new_user;
}
void user__free(struct t_account *account,
struct t_user *user)
{
struct t_user *new_users;
if (!account || !user)
return;
/* remove user from users list */
if (account->last_user == user)
account->last_user = user->prev_user;
if (user->prev_user)
{
(user->prev_user)->next_user = user->next_user;
new_users = account->users;
}
else
new_users = user->next_user;
if (user->next_user)
(user->next_user)->prev_user = user->prev_user;
/* free user data */
if (user->id)
free(user->id);
if (user->name)
free(user->name);
if (user->profile.avatar_hash)
free(user->profile.avatar_hash);
if (user->profile.status_text)
free(user->profile.status_text);
if (user->profile.status)
free(user->profile.status);
if (user->profile.display_name)
free(user->profile.display_name);
if (user->profile.affiliation)
free(user->profile.affiliation);
if (user->profile.email)
free(user->profile.email);
if (user->profile.role)
free(user->profile.role);
delete user;
account->users = new_users;
}
void user__free_all(struct t_account *account)
{
while (account->users)
user__free(account, account->users);
} }

@ -4,60 +4,67 @@
#pragma once #pragma once
#include <optional> #include <memory>
#include <string> #include <string>
#include <tl/optional.hpp> #include <tl/optional.hpp>
struct t_user_profile namespace weechat
{ {
char *avatar_hash; class account;
char *status_text; class channel;
char *status;
tl::optional<std::string> idle;
char *display_name;
char *email;
char *role;
char *affiliation;
char *pgp_id;
int omemo;
};
struct t_user
{
char *id;
char *name;
struct t_user_profile profile;
int updated;
int is_away;
struct t_user *prev_user; class user
struct t_user *next_user; {
}; private:
struct profile
struct t_channel; {
char *avatar_hash = nullptr;
char *status_text = nullptr;
char *status = nullptr;
tl::optional<std::string> idle;
char *display_name = nullptr;
char *email = nullptr;
char *role = nullptr;
char *affiliation = nullptr;
char *pgp_id = nullptr;
int omemo = 0;
};
const char *user__get_colour(struct t_user *user); private:
char *name = nullptr;
const char *user__as_prefix_raw(struct t_account *account, bool updated = false;
const char *name);
const char *user__as_prefix(struct t_account *account, public:
struct t_user *user, char *id = nullptr;
const char *name); bool is_away = false;
struct profile profile;
struct t_user *user__search(struct t_account *account, public:
const char *id); user(weechat::account *account, const char *id, const char *display_name);
struct t_user *user__new(struct t_account *account, static std::string get_colour(const char *name);
const char *id, const char *display_name); static std::string get_colour_for_nicklist(const char *name);
std::string get_colour();
std::string get_colour_for_nicklist();
static std::string as_prefix_raw(const char *name);
static std::string as_prefix(const char *name);
std::string as_prefix_raw();
std::string as_prefix();
void user__free_all(struct t_account *account); static std::string as_prefix_raw(weechat::account *account, const char *id) {
auto found = std::unique_ptr<user>(search(account, id));
return found ? found->as_prefix_raw() : "";
}
static std::string as_prefix(weechat::account *account, const char *id) {
auto found = std::unique_ptr<user>(search(account, id));
return found ? found->as_prefix() : "";
}
void user__nicklist_add(struct t_account *account, static weechat::user *bot_search(weechat::account *account, const char *pgp_id);
struct t_channel *channel, static weechat::user *search(weechat::account *account, const char *id);
struct t_user *user);
void user__nicklist_remove(struct t_account *account, void nicklist_add(weechat::account *account, weechat::channel *channel);
struct t_channel *channel, void nicklist_remove(weechat::account *account, weechat::channel *channel);
struct t_user *user); };
}

@ -15,8 +15,8 @@
#include <chrono> #include <chrono>
#include <variant> #include <variant>
#include <fmt/core.h> #include <fmt/core.h>
#include <strophe.h>
#include <tl/optional.hpp> #include <tl/optional.hpp>
#include <strophe.h>
std::string get_name(xmpp_stanza_t *stanza); std::string get_name(xmpp_stanza_t *stanza);

Loading…
Cancel
Save