diff --git a/.depend b/.depend index 2fdb74c..a2e7a70 100644 --- a/.depend +++ b/.depend @@ -1,19 +1,23 @@ -.plugin.o: plugin.cpp plugin.hh config.hh account.hh omemo.hh \ - /usr/include/signal/signal_protocol.h /usr/include/signal/ratchet.h \ +.plugin.o: plugin.cpp plugin.hh config.hh \ + 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/session_record.h \ /usr/include/signal/session_pre_key.h \ /usr/include/signal/sender_key_record.h signal.hh \ - deps/fmt/include/fmt/core.h /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_pre_key.h /usr/include/signal/protocol.h \ - /usr/include/signal/curve.h connection.hh command.hh input.hh buffer.hh \ - completion.hh + /usr/include/signal/curve.h channel.hh connection.hh xmpp/ns.hh \ + strophe.hh user.hh command.hh input.hh buffer.hh completion.hh plugin.hh: config.hh: +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: @@ -23,19 +27,23 @@ omemo.hh: /usr/include/signal/session_pre_key.h: /usr/include/signal/sender_key_record.h: signal.hh: -deps/fmt/include/fmt/core.h: /usr/include/signal/key_helper.h: /usr/include/signal/session_builder.h: /usr/include/signal/session_cipher.h: /usr/include/signal/session_pre_key.h: /usr/include/signal/protocol.h: /usr/include/signal/curve.h: +channel.hh: connection.hh: +xmpp/ns.hh: +strophe.hh: +user.hh: command.hh: input.hh: buffer.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/xmlexports.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/xmlmemory.h \ /usr/include/libxml2/libxml/threads.h plugin.hh xmpp/stanza.hh config.hh \ - input.hh omemo.hh /usr/include/signal/signal_protocol.h \ - /usr/include/signal/ratchet.h \ + deps/optional/include/tl/optional.hpp input.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/session_record.h \ /usr/include/signal/session_pre_key.h \ /usr/include/signal/sender_key_record.h signal.hh \ - deps/fmt/include/fmt/core.h /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_pre_key.h /usr/include/signal/protocol.h \ - /usr/include/signal/curve.h account.hh connection.hh user.hh \ - deps/optional/include/tl/optional.hpp channel.hh buffer.hh + /usr/include/signal/curve.h account.hh pgp.hh channel.hh connection.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/xmlversion.h: /usr/include/libxml2/libxml/xmlexports.h: @@ -89,6 +97,7 @@ completion.hh: plugin.hh: xmpp/stanza.hh: config.hh: +deps/optional/include/tl/optional.hpp: input.hh: omemo.hh: /usr/include/signal/signal_protocol.h: @@ -99,7 +108,6 @@ omemo.hh: /usr/include/signal/session_pre_key.h: /usr/include/signal/sender_key_record.h: signal.hh: -deps/fmt/include/fmt/core.h: /usr/include/signal/key_helper.h: /usr/include/signal/session_builder.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/curve.h: account.hh: +pgp.hh: +channel.hh: connection.hh: +xmpp/ns.hh: +strophe.hh: user.hh: -deps/optional/include/tl/optional.hpp: -channel.hh: buffer.hh: -.buffer.o: buffer.cpp plugin.hh account.hh omemo.hh \ - /usr/include/signal/signal_protocol.h /usr/include/signal/ratchet.h \ +.buffer.o: buffer.cpp plugin.hh account.hh \ + 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/session_record.h \ /usr/include/signal/session_pre_key.h \ /usr/include/signal/sender_key_record.h signal.hh \ - deps/fmt/include/fmt/core.h /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_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: account.hh: +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: @@ -134,18 +149,23 @@ omemo.hh: /usr/include/signal/session_pre_key.h: /usr/include/signal/sender_key_record.h: signal.hh: -deps/fmt/include/fmt/core.h: /usr/include/signal/key_helper.h: /usr/include/signal/session_builder.h: /usr/include/signal/session_cipher.h: /usr/include/signal/session_pre_key.h: /usr/include/signal/protocol.h: /usr/include/signal/curve.h: +config.hh: channel.hh: +connection.hh: +xmpp/ns.hh: +strophe.hh: +user.hh: buffer.hh: .channel.o: channel.cpp deps/fmt/include/fmt/core.h \ - deps/optional/include/tl/optional.hpp plugin.hh account.hh omemo.hh \ - /usr/include/signal/signal_protocol.h /usr/include/signal/ratchet.h \ + deps/optional/include/tl/optional.hpp plugin.hh 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/session_record.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/session_cipher.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 \ - util.hh xmpp/node.hh 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-0280.inl \ - xmpp/xep-0319.inl xmpp/rfc-6121.inl + /usr/include/signal/curve.h config.hh channel.hh connection.hh \ + xmpp/ns.hh strophe.hh user.hh input.hh buffer.hh util.hh xmpp/node.hh \ + xmpp/xep-0027.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 deps/fmt/include/fmt/core.h: deps/optional/include/tl/optional.hpp: plugin.hh: account.hh: +pgp.hh: omemo.hh: /usr/include/signal/signal_protocol.h: /usr/include/signal/ratchet.h: @@ -176,15 +197,17 @@ signal.hh: /usr/include/signal/session_pre_key.h: /usr/include/signal/protocol.h: /usr/include/signal/curve.h: -user.hh: +config.hh: channel.hh: +connection.hh: +xmpp/ns.hh: +strophe.hh: +user.hh: input.hh: buffer.hh: -pgp.hh: util.hh: xmpp/node.hh: xmpp/xep-0027.inl: -xmpp/ns.hh: xmpp/xep-0030.inl: xmpp/xep-0045.inl: xmpp/xep-0049.inl: @@ -192,22 +215,25 @@ xmpp/xep-0115.inl: xmpp/xep-0280.inl: xmpp/xep-0319.inl: xmpp/rfc-6121.inl: -.command.o: command.cpp plugin.hh account.hh omemo.hh \ - /usr/include/signal/signal_protocol.h /usr/include/signal/ratchet.h \ +.command.o: command.cpp plugin.hh account.hh \ + 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/session_record.h \ /usr/include/signal/session_pre_key.h \ /usr/include/signal/sender_key_record.h signal.hh \ - deps/fmt/include/fmt/core.h /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_pre_key.h /usr/include/signal/protocol.h \ - /usr/include/signal/curve.h user.hh \ - deps/optional/include/tl/optional.hpp channel.hh buffer.hh message.hh \ - command.hh sexp/driver.hh sexp/scanner.hh sexp/parser.tab.hh \ - sexp/location.hh + /usr/include/signal/curve.h config.hh channel.hh connection.hh \ + xmpp/ns.hh strophe.hh user.hh buffer.hh message.hh command.hh \ + sexp/driver.hh sexp/scanner.hh sexp/parser.tab.hh sexp/location.hh plugin.hh: account.hh: +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: @@ -217,16 +243,18 @@ omemo.hh: /usr/include/signal/session_pre_key.h: /usr/include/signal/sender_key_record.h: signal.hh: -deps/fmt/include/fmt/core.h: /usr/include/signal/key_helper.h: /usr/include/signal/session_builder.h: /usr/include/signal/session_cipher.h: /usr/include/signal/session_pre_key.h: /usr/include/signal/protocol.h: /usr/include/signal/curve.h: -user.hh: -deps/optional/include/tl/optional.hpp: +config.hh: channel.hh: +connection.hh: +xmpp/ns.hh: +strophe.hh: +user.hh: buffer.hh: message.hh: command.hh: @@ -234,21 +262,25 @@ sexp/driver.hh: sexp/scanner.hh: sexp/parser.tab.hh: sexp/location.hh: -.completion.o: completion.cpp plugin.hh config.hh account.hh omemo.hh \ - /usr/include/signal/signal_protocol.h /usr/include/signal/ratchet.h \ +.completion.o: completion.cpp plugin.hh config.hh \ + 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/session_record.h \ /usr/include/signal/session_pre_key.h \ /usr/include/signal/sender_key_record.h signal.hh \ - deps/fmt/include/fmt/core.h /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_pre_key.h /usr/include/signal/protocol.h \ - /usr/include/signal/curve.h channel.hh user.hh \ - deps/optional/include/tl/optional.hpp buffer.hh completion.hh + /usr/include/signal/curve.h channel.hh connection.hh xmpp/ns.hh \ + strophe.hh user.hh buffer.hh completion.hh plugin.hh: config.hh: +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: @@ -258,7 +290,6 @@ omemo.hh: /usr/include/signal/session_pre_key.h: /usr/include/signal/sender_key_record.h: signal.hh: -deps/fmt/include/fmt/core.h: /usr/include/signal/key_helper.h: /usr/include/signal/session_builder.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/curve.h: channel.hh: +connection.hh: +xmpp/ns.hh: +strophe.hh: user.hh: -deps/optional/include/tl/optional.hpp: buffer.hh: completion.hh: -.config.o: config.cpp plugin.hh account.hh omemo.hh \ - /usr/include/signal/signal_protocol.h /usr/include/signal/ratchet.h \ +.config.o: config.cpp plugin.hh account.hh \ + 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/session_record.h \ /usr/include/signal/session_pre_key.h \ /usr/include/signal/sender_key_record.h signal.hh \ - deps/fmt/include/fmt/core.h /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_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: account.hh: +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: @@ -292,7 +330,6 @@ omemo.hh: /usr/include/signal/session_pre_key.h: /usr/include/signal/sender_key_record.h: signal.hh: -deps/fmt/include/fmt/core.h: /usr/include/signal/key_helper.h: /usr/include/signal/session_builder.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/curve.h: config.hh: +channel.hh: +connection.hh: +xmpp/ns.hh: +strophe.hh: +user.hh: .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/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 \ 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 \ - config.hh account.hh omemo.hh /usr/include/signal/signal_protocol.h \ - /usr/include/signal/ratchet.h \ + config.hh 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/session_record.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/session_cipher.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 deps/fmt/include/fmt/core.h: deps/fmt/include/fmt/chrono.h: @@ -375,6 +417,7 @@ xmpp/rfc-6121.inl: xmpp/stanza.hh: config.hh: account.hh: +pgp.hh: omemo.hh: /usr/include/signal/signal_protocol.h: /usr/include/signal/ratchet.h: @@ -390,25 +433,30 @@ signal.hh: /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: +strophe.hh: +user.hh: util.hh: deps/diff/diff.h: -.input.o: input.cpp plugin.hh account.hh omemo.hh \ - /usr/include/signal/signal_protocol.h /usr/include/signal/ratchet.h \ +.input.o: input.cpp plugin.hh account.hh \ + 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/session_record.h \ /usr/include/signal/session_pre_key.h \ /usr/include/signal/sender_key_record.h signal.hh \ - deps/fmt/include/fmt/core.h /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_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: account.hh: +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: @@ -418,31 +466,39 @@ omemo.hh: /usr/include/signal/session_pre_key.h: /usr/include/signal/sender_key_record.h: signal.hh: -deps/fmt/include/fmt/core.h: /usr/include/signal/key_helper.h: /usr/include/signal/session_builder.h: /usr/include/signal/session_cipher.h: /usr/include/signal/session_pre_key.h: /usr/include/signal/protocol.h: /usr/include/signal/curve.h: +config.hh: channel.hh: +connection.hh: +xmpp/ns.hh: +strophe.hh: +user.hh: buffer.hh: message.hh: input.hh: -.message.o: message.cpp plugin.hh account.hh omemo.hh \ - /usr/include/signal/signal_protocol.h /usr/include/signal/ratchet.h \ +.message.o: message.cpp plugin.hh account.hh \ + 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/session_record.h \ /usr/include/signal/session_pre_key.h \ /usr/include/signal/sender_key_record.h signal.hh \ - deps/fmt/include/fmt/core.h /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_pre_key.h /usr/include/signal/protocol.h \ - /usr/include/signal/curve.h channel.hh user.hh \ - deps/optional/include/tl/optional.hpp message.hh + /usr/include/signal/curve.h config.hh channel.hh connection.hh \ + xmpp/ns.hh strophe.hh user.hh message.hh plugin.hh: account.hh: +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: @@ -452,16 +508,18 @@ omemo.hh: /usr/include/signal/session_pre_key.h: /usr/include/signal/sender_key_record.h: signal.hh: -deps/fmt/include/fmt/core.h: /usr/include/signal/key_helper.h: /usr/include/signal/session_builder.h: /usr/include/signal/session_cipher.h: /usr/include/signal/session_pre_key.h: /usr/include/signal/protocol.h: /usr/include/signal/curve.h: +config.hh: channel.hh: +connection.hh: +xmpp/ns.hh: +strophe.hh: user.hh: -deps/optional/include/tl/optional.hpp: message.hh: .omemo.o: omemo.cpp deps/fmt/include/fmt/core.h \ 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/unbounded.hpp \ 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/signal_protocol_types.h /usr/include/signal/curve.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/session_cipher.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/optional/include/tl/optional.hpp: deps/range-v3/include/range/v3/all.hpp: @@ -1026,6 +1085,7 @@ deps/range-v3/include/range/v3/view/unique.hpp: plugin.hh: xmpp/stanza.hh: account.hh: +pgp.hh: omemo.hh: /usr/include/signal/signal_protocol.h: /usr/include/signal/ratchet.h: @@ -1041,26 +1101,36 @@ signal.hh: /usr/include/signal/session_pre_key.h: /usr/include/signal/protocol.h: /usr/include/signal/curve.h: +config.hh: +channel.hh: +connection.hh: +xmpp/ns.hh: +strophe.hh: +user.hh: gcrypt.hh: util.hh: .pgp.o: pgp.cpp deps/fmt/include/fmt/core.h plugin.hh pgp.hh deps/fmt/include/fmt/core.h: plugin.hh: pgp.hh: -.user.o: user.cpp plugin.hh account.hh omemo.hh \ - /usr/include/signal/signal_protocol.h /usr/include/signal/ratchet.h \ +.user.o: user.cpp plugin.hh account.hh \ + 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/session_record.h \ /usr/include/signal/session_pre_key.h \ /usr/include/signal/sender_key_record.h signal.hh \ - deps/fmt/include/fmt/core.h /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_pre_key.h /usr/include/signal/protocol.h \ - /usr/include/signal/curve.h user.hh \ - deps/optional/include/tl/optional.hpp channel.hh + /usr/include/signal/curve.h config.hh channel.hh connection.hh \ + xmpp/ns.hh strophe.hh user.hh plugin.hh: account.hh: +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: @@ -1070,16 +1140,18 @@ omemo.hh: /usr/include/signal/session_pre_key.h: /usr/include/signal/sender_key_record.h: signal.hh: -deps/fmt/include/fmt/core.h: /usr/include/signal/key_helper.h: /usr/include/signal/session_builder.h: /usr/include/signal/session_cipher.h: /usr/include/signal/session_pre_key.h: /usr/include/signal/protocol.h: /usr/include/signal/curve.h: -user.hh: -deps/optional/include/tl/optional.hpp: +config.hh: channel.hh: +connection.hh: +xmpp/ns.hh: +strophe.hh: +user.hh: .util.o: util.cpp plugin.hh util.hh plugin.hh: util.hh: diff --git a/.dir-locals.el b/.dir-locals.el index 211b59a..7d36b01 100644 --- a/.dir-locals.el +++ b/.dir-locals.el @@ -4,7 +4,17 @@ ((c-mode (eval . (setq-local flycheck-clang-include-path (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 (list (concat "-I" (expand-file-name "libstrophe" (projectile-project-root))) (concat "-I" (expand-file-name "json-c" (projectile-project-root)))))) @@ -17,6 +27,6 @@ "'; /debug tags")) " "))) (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) (projectile-project-compilation-cmd . "bear -- make -j8"))) diff --git a/.gitignore b/.gitignore index e46f175..d62f577 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ .direnv *~ compile_commands.json +launch.json .cache cscope* *.d diff --git a/account.cpp b/account.cpp index efe4804..442f435 100644 --- a/account.cpp +++ b/account.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -22,291 +23,12 @@ #include "channel.hh" #include "buffer.hh" -std::unordered_map 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; -} +std::unordered_map weechat::accounts; -void account__free_device_all(struct t_account *account) +void weechat::log_emit(void *const userdata, const xmpp_log_level_t level, + const char *const area, const char *const msg) { - 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, - 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) -{ - struct t_account *account = (struct t_account*)userdata; + auto account = static_cast(userdata); 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; - int i, length; - char *option_name; + if (name.empty()) + return false; - if (account__casesearch(name)) - return NULL; + if (casesensitive) + { + 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; + } + + (void) out; + return false; +} - /* alloc memory for new account */ - new_account = new struct t_account; - 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, - _("%s%s: error when allocating new account"), - weechat_prefix("error"), WEECHAT_XMPP_PLUGIN_NAME); - return NULL; + out = &device->second; + return true; } - accounts[name] = new_account; + (void) out; + return NULL; +} - /* set name */ - new_account->name = strdup(name); +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; + } +} - /* internal vars */ - new_account->reloading_from_config = 0; +void weechat::account::device_free_all() +{ + devices.clear(); +} - new_account->is_connected = 0; - new_account->disconnected = 0; +xmpp_stanza_t *weechat::account::get_devicelist() +{ + int i = 0; - new_account->current_retry = 0; - new_account->reconnect_delay = 0; - new_account->reconnect_start = 0; + account::device device; - new_account->logger.handler = &account__log_emit_weechat; - 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++) + device.id = omemo.device_id; + device.name = fmt::format("%u", device.id); + device.label = "weechat"; + + auto children = (xmpp_stanza_t **)malloc(sizeof(xmpp_stanza_t *) * 128); + children[i++] = stanza__iq_pubsub_publish_item_list_device( + context, NULL, with_noop(device.name.data()), NULL); + + for (auto& device : devices) { - new_account->options[i] = NULL; - - length = strlen(new_account->name) + 1 + - 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); - } + if (device.first != omemo.device_id) + children[i++] = stanza__iq_pubsub_publish_item_list_device( + context, NULL, with_noop(device.second.name.data()), NULL); } - 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 start, tl::optional end) { - //int i; + if (!mam_queries.contains(id)) + { + mam_queries[id].id = id; + mam_queries[id].with = with; - if (!account) - return; + mam_queries[id].start = start; + mam_queries[id].end = end; + } +} - /* free linked lists */ - /* - for (i = 0; i < IRC_SERVER_NUM_OUTQUEUES_PRIO; i++) +bool weechat::account::mam_query_search(weechat::account::mam_query* out, + const std::string id) +{ + 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 */ - if (account->connection) - xmpp_conn_release(account->connection); - if (account->context) - xmpp_ctx_free(account->context); + (void) out; + return false; +} - /* free account data */ - //for (i = 0; i < ACCOUNT_NUM_OPTIONS; i++) - //{ - // if (account->options[i]) - // weechat_config_option_free(account->options[i]); - //} +void weechat::account::mam_query_remove(const std::string id) +{ + mam_queries.erase(id); +} - if (account->name) - free(account->name); +void weechat::account::mam_query_free_all() +{ + mam_queries.clear(); +} - if (account->buffer_as_string) - free(account->buffer_as_string); +xmpp_log_t make_logger(void *userdata) +{ + xmpp_log_t logger = { nullptr }; + logger.handler = &weechat::log_emit; + logger.userdata = userdata; + return logger; +} - //channel__free_all(account); - //user__free_all(account); +xmpp_mem_t make_memory(void *userdata) +{ + 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) - return; + if (account* result = nullptr; account::search(result, name)) + 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) * (only if we are not in a /upgrade, because during upgrade we want to * keep connections and closing account buffer would disconnect from account) */ - if (account->buffer) - weechat_buffer_close(account->buffer); + if (buffer) + weechat_buffer_close(buffer); - accounts.erase(account->name); + accounts.erase(name); - account__free_data(account); - delete account; -} + /* close xmpp context */ + if (connection) + xmpp_conn_release(connection); + if (context) + xmpp_ctx_free(context); -void account__free_all() -{ - for (auto account : accounts) - { - account__free(account.second); - } + delete this; } -void account__disconnect(struct t_account *account, int reconnect) +void weechat::account::disconnect(int reconnect) { - (void) reconnect; - - struct t_channel *ptr_channel; - - if (account->is_connected) + if (is_connected) { /* * remove all nicks and write disconnection message on each * channel/private buffer */ - user__free_all(account); - weechat_nicklist_remove_all(account->buffer); - for (ptr_channel = account->channels; ptr_channel; - ptr_channel = ptr_channel->next_channel) + //user::free_all(this); // TOFIX + weechat_nicklist_remove_all(buffer); + for (auto& ptr_channel : channels) { - weechat_nicklist_remove_all(ptr_channel->buffer); + weechat_nicklist_remove_all(ptr_channel.second.buffer); weechat_printf( - ptr_channel->buffer, + ptr_channel.second.buffer, _("%s%s: disconnected from account"), weechat_prefix("network"), WEECHAT_XMPP_PLUGIN_NAME); } /* 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( - account->buffer, + buffer, _("%s%s: disconnected from account"), weechat_prefix ("network"), WEECHAT_XMPP_PLUGIN_NAME); } if (reconnect) { - if (account->current_retry++ == 0) + if (current_retry++ == 0) { - account->reconnect_delay = 5; - account->reconnect_start = time(NULL) + account->reconnect_delay; + reconnect_delay = 5; + reconnect_start = time(NULL) + reconnect_delay; } - account->current_retry %= 5; + current_retry %= 5; } else { - account->current_retry = 0; - account->reconnect_delay = 0; - account->reconnect_start = 0; + current_retry = 0; + reconnect_delay = 0; + reconnect_start = 0; } /* - account->lag = 0; - account->lag_displayed = -1; - account->lag_check_time.tv_sec = 0; - account->lag_check_time.tv_usec = 0; - account->lag_next_check = time(NULL) + + lag = 0; + lag_displayed = -1; + lag_check_time.tv_sec = 0; + lag_check_time.tv_usec = 0; + lag_next_check = time(NULL) + weechat_config_integer(xmpp_config_network_lag_check); - account->lag_last_refresh = 0; + lag_last_refresh = 0; account__set_lag(account); */ // lag based on xmpp ping - account->disconnected = !reconnect; + disconnected = !reconnect; /* send signal "account_disconnected" with account name */ (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]; - - snprintf(buffer_name, sizeof(buffer_name), - "account.%s", account->name); - account->buffer = weechat_buffer_new(buffer_name, - &input__data_cb, NULL, NULL, - &buffer__close_cb, NULL, NULL); - if (!account->buffer) + buffer = weechat_buffer_new(fmt::format("account.{}", name).data(), + &input__data_cb, NULL, NULL, + &buffer__close_cb, NULL, NULL); + if (!buffer) return NULL; - weechat_printf(account->buffer, "xmpp: %s", account->name); - - if (!weechat_buffer_get_integer(account->buffer, "short_name_is_set")) - weechat_buffer_set(account->buffer, "short_name", account->name); - weechat_buffer_set(account->buffer, "localvar_set_type", "server"); - weechat_buffer_set(account->buffer, "localvar_set_account", account->name); - snprintf(charset_modifier, sizeof (charset_modifier), - "account.%s", account->name); - weechat_buffer_set(account->buffer, "localvar_set_charset_modifier", - charset_modifier); - weechat_buffer_set(account->buffer, "title", - (account->name) ? account->name : ""); - - weechat_buffer_set(account->buffer, "nicklist", "1"); - weechat_buffer_set(account->buffer, "nicklist_display_groups", "0"); - weechat_buffer_set_pointer(account->buffer, "nicklist_callback", + weechat_printf(buffer, "xmpp: %s", name.data()); + + if (!weechat_buffer_get_integer(buffer, "short_name_is_set")) + weechat_buffer_set(buffer, "short_name", name.data()); + weechat_buffer_set(buffer, "localvar_set_type", "server"); + weechat_buffer_set(buffer, "localvar_set_account", name.data()); + weechat_buffer_set(buffer, "localvar_set_charset_modifier", + fmt::format("account.{}", name).data()); + weechat_buffer_set(buffer, "title", name.data()); + + weechat_buffer_set(buffer, "nicklist", "1"); + weechat_buffer_set(buffer, "nicklist_display_groups", "0"); + weechat_buffer_set_pointer(buffer, "nicklist_callback", (void*)&buffer__nickcmp_cb); - weechat_buffer_set_pointer(account->buffer, "nicklist_callback_pointer", - account); + weechat_buffer_set_pointer(buffer, "nicklist_callback_pointer", + 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)) - xmpp_disconnect(account->connection); + if (xmpp_conn_is_connected(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; - weechat_buffer_set(account->buffer, "display", "auto"); + weechat_buffer_set(buffer, "display", "auto"); } - account__close_connection(account); + reset(); - account->is_connected = - connection__connect(account, &account->connection, account_jid(account), - account_password(account), account_tls(account)); + is_connected = connection.connect(std::string(jid()), std::string(password()), tls()); (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) data; @@ -723,17 +452,17 @@ int account__timer_cb(const void *pointer, void *data, int remaining_calls) { if (accounts.empty()) return WEECHAT_RC_ERROR; - for (auto ptr_account : accounts) + for (auto& ptr_account : accounts) { - if (ptr_account.second->is_connected - && (xmpp_conn_is_connecting(ptr_account.second->connection) - || xmpp_conn_is_connected(ptr_account.second->connection))) - connection__process(ptr_account.second->context, ptr_account.second->connection, 10); - else if (ptr_account.second->disconnected); - else if (ptr_account.second->reconnect_start > 0 - && ptr_account.second->reconnect_start < time(NULL)) + if (ptr_account.second.is_connected + && (xmpp_conn_is_connecting(ptr_account.second.connection) + || xmpp_conn_is_connected(ptr_account.second.connection))) + ptr_account.second.connection.process(ptr_account.second.context, 10); + else if (ptr_account.second.disconnected); + else if (ptr_account.second.reconnect_start > 0 + && ptr_account.second.reconnect_start < time(NULL)) { - account__connect(ptr_account.second); + ptr_account.second.connect(); } } diff --git a/account.hh b/account.hh index 5cb84c0..1646255 100644 --- a/account.hh +++ b/account.hh @@ -7,155 +7,144 @@ #include #include #include +#include +#include #include -#include +#include +#include "fmt/core.h" +#include "strophe.h" +#include "pgp.hh" #include "omemo.hh" +#include "config.hh" +#include "channel.hh" +#include "connection.hh" +#include "user.hh" -extern std::unordered_map accounts; - -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 +namespace weechat { - char *name; - struct t_config_option *options[ACCOUNT_NUM_OPTIONS]; - - int reloading_from_config; - - int is_connected; - int disconnected; - - int current_retry; - int reconnect_delay; - int reconnect_start; - - xmpp_mem_t memory; - xmpp_log_t logger; - xmpp_ctx_t *context; - xmpp_conn_t *connection; - - struct t_gui_buffer *buffer; - char *buffer_as_string; - - weechat::xmpp::omemo omemo; - struct t_pgp *pgp; - - struct t_account_device *devices; - struct t_account_device *last_device; - struct t_account_mam_query *mam_queries; - struct t_account_mam_query *last_mam_query; - struct t_user *users; - struct t_user *last_user; - struct t_channel *channels; - struct t_channel *last_channel; - - struct t_account *prev_account; - struct t_account *next_account; -}; - -extern char *account_options[][2]; - -struct t_account *account__search(const char *account_name); -struct t_account *account__casesearch (const char *account_name); -int account__search_option(const char *option_name); -struct t_account_device *account__search_device(struct t_account *account, - uint32_t id); -void account__add_device(struct t_account *account, - struct t_account_device *device); -void account__free_device(struct t_account *account, - struct t_account_device *device); -void account__free_device_all(struct t_account *account); -xmpp_stanza_t *account__get_devicelist(struct t_account *account); -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 *account__mam_query_search(struct t_account *account, - const char *id); -void account__mam_query_free(struct t_account *account, - struct t_account_mam_query *mam_query); -void account__mam_query_free_all(struct t_account *account); -struct t_account *account__alloc(const char *name); -void account__free_data(struct t_account *account); -void account__free(struct t_account *account); -void account__free_all(); -void account__disconnect(struct t_account *account, int reconnect); -void account__disconnect_all(); -void account__close_connection(struct t_account *account); -int account__connect(struct t_account *account); -int account__timer_cb(const void *pointer, void *data, int remaining_calls); + class channel; + class user; + + void log_emit(void *const userdata, const xmpp_log_level_t level, + const char *const area, const char *const msg); + + class account : public config_account + { + public: + struct device + { + std::uint32_t id; + std::string name; + std::string label; + }; + + struct mam_query + { + std::string id; + std::string with; + tl::optional start; + tl::optional end; + }; + + public: + bool disconnected = false; + + std::unordered_map devices; + std::unordered_map 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; + libstrophe::context context; + weechat::connection connection; + struct t_gui_buffer *buffer = nullptr; + std::unordered_map channels; + std::unordered_map users; + + std::unordered_map options; + + int reloading_from_config = 0; + + public: + account(config_file& config_file, const std::string name); + ~account(); + + static bool search(account* &out, + const std::string name, bool casesensitive = false); + static int timer_cb(const void *pointer, void *data, int remaining_calls); + static void disconnect_all(); + + bool connected() { return is_connected; } + + bool search_device(device* out, std::uint32_t id); + void add_device(device *device); + void device_free_all(); + xmpp_stanza_t *get_devicelist(); + + void add_mam_query(const std::string id, const std::string with, + tl::optional start, tl::optional end); + bool mam_query_search(mam_query* out, const std::string id); + void mam_query_remove(const std::string id); + void mam_query_free_all(); + + struct t_gui_buffer* create_buffer(); + + void disconnect(int reconnect); + void reset(); + int connect(); + + std::string_view jid() { + if (connection && xmpp_conn_is_connected(connection)) + return xmpp_jid_bare(context, xmpp_conn_get_bound_jid(connection)); + else + return this->option_jid.string(); + } + void jid(std::string jid) { this->option_jid = jid; } + 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(this->option_tls.integer()); } + void tls(tls_policy tls) { this->option_tls = fmt::format("%d", static_cast(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 accounts; +} diff --git a/buffer.cpp b/buffer.cpp index de64a1b..808f0a6 100644 --- a/buffer.cpp +++ b/buffer.cpp @@ -13,37 +13,33 @@ #include "buffer.hh" void buffer__get_account_and_channel(struct t_gui_buffer *buffer, - struct t_account **account, - struct t_channel **channel) + weechat::account **account, + weechat::channel **channel) { - struct t_account *ptr_account; - struct t_channel *ptr_channel; - if (!buffer) return; - *account = NULL; - *channel = NULL; + *account = nullptr; + *channel = nullptr; /* 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) - *account = ptr_account.second; + *account = &ptr_account.second; return; } - for (ptr_channel = ptr_account.second->channels; ptr_channel; - ptr_channel = ptr_channel->next_channel) + for (auto& ptr_channel : ptr_account.second.channels) { - if (ptr_channel->buffer == buffer) + if (ptr_channel.second.buffer == buffer) { if (account) - *account = ptr_account.second; + *account = &ptr_account.second; if (channel) - *channel = ptr_channel; + *channel = &ptr_channel.second; return; } } @@ -56,9 +52,8 @@ char *buffer__typing_bar_cb(const void *pointer, void *data, struct t_gui_buffer *buffer, struct t_hashtable *extra_info) { - struct t_channel_typing *ptr_typing; - struct t_account *account; - struct t_channel *channel; + weechat::account *account; + weechat::channel *channel; char notification[256]; unsigned typecount; @@ -78,17 +73,16 @@ char *buffer__typing_bar_cb(const void *pointer, void *data, typecount = 0; - for (ptr_typing = channel->typings; ptr_typing; - ptr_typing = ptr_typing->next_typing) + for (auto& ptr_typing : channel->typings) { switch (++typecount) { case 1: - strcpy(notification, ptr_typing->name); + strcpy(notification, ptr_typing.name); break; case 2: strcat(notification, ", "); - strcat(notification, ptr_typing->name); + strcat(notification, ptr_typing.name); break; case 3: default: @@ -115,12 +109,12 @@ int buffer__nickcmp_cb(const void *pointer, void *data, const char *nick1, const char *nick2) { - struct t_account *account; + weechat::account *account; (void) data; if (pointer) - account = (struct t_account *)pointer; + account = (weechat::account *)pointer; else 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_weechat_plugin *buffer_plugin = NULL; - struct t_account *ptr_account = NULL; - struct t_channel *ptr_channel = NULL; + weechat::account *ptr_account = NULL; + weechat::channel *ptr_channel = NULL; (void) pointer; (void) data; @@ -155,9 +149,9 @@ int buffer__close_cb(const void *pointer, void *data, { 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; @@ -167,9 +161,9 @@ int buffer__close_cb(const void *pointer, void *data, { 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->is_connected) + if (ptr_account->connected()) { - channel__free(ptr_account, ptr_channel); + ptr_account->channels.erase(ptr_channel->name); } } } diff --git a/buffer.hh b/buffer.hh index e78a366..f6d0c01 100644 --- a/buffer.hh +++ b/buffer.hh @@ -5,8 +5,8 @@ #pragma once void buffer__get_account_and_channel(struct t_gui_buffer *buffer, - struct t_account **account, - struct t_channel **channel); + weechat::account **account, + weechat::channel **channel); char *buffer__typing_bar_cb(const void *pointer, void *data, struct t_gui_bar_item *item, diff --git a/channel.cpp b/channel.cpp index 91c87ad..91229ce 100644 --- a/channel.cpp +++ b/channel.cpp @@ -24,95 +24,38 @@ #include "util.hh" #include "xmpp/node.hh" -const char *channel__transport_name(enum t_channel_transport transport) -{ - switch (transport) - { - case CHANNEL_TRANSPORT_PLAIN: - return "PLAINTEXT"; - case CHANNEL_TRANSPORT_OMEMO: - return "OMEMO"; - case CHANNEL_TRANSPORT_PGP: - return "PGP"; - case CHANNEL_TRANSPORT_OTR: - return "OTR"; - default: - return NULL; - } -} - -void channel__set_transport(struct t_channel *channel, enum t_channel_transport transport, int force) +void weechat::channel::set_transport(enum weechat::channel::transport transport, int force) { if (force) switch (transport) { - case CHANNEL_TRANSPORT_PLAIN: - channel->omemo.enabled = 0; - channel->pgp.enabled = 0; + case weechat::channel::transport::PLAIN: + omemo.enabled = 0; + pgp.enabled = 0; break; - case CHANNEL_TRANSPORT_OMEMO: - channel->omemo.enabled = 1; - channel->pgp.enabled = 0; + case weechat::channel::transport::OMEMO: + omemo.enabled = 1; + pgp.enabled = 0; break; - case CHANNEL_TRANSPORT_PGP: - channel->omemo.enabled = 0; - channel->pgp.enabled = 1; + case weechat::channel::transport::PGP: + omemo.enabled = 0; + pgp.enabled = 1; break; default: break; } - if (channel->transport != transport) - { - channel->transport = transport; - weechat_printf_date_tags(channel->buffer, 0, NULL, "%s%sTransport: %s", - weechat_prefix("network"), weechat_color("gray"), - channel__transport_name(channel->transport)); - } -} -struct t_account *channel__account(struct t_channel *channel) -{ - struct t_account *ptr_account; - struct t_channel *ptr_channel; - - if (!channel) - return NULL; - - for (auto ptr_account : accounts) + if (this->transport != transport) { - for (ptr_channel = ptr_account.second->channels; ptr_channel; - ptr_channel = ptr_channel->next_channel) - { - if (ptr_channel == channel) - return ptr_account.second; - } - } - - /* account not found */ - return NULL; -} - -struct t_channel *channel__search(struct t_account *account, - const char *id) -{ - struct t_channel *ptr_channel; - - if (!account || !id) - return NULL; - - for (ptr_channel = account->channels; ptr_channel; - ptr_channel = ptr_channel->next_channel) - { - if (weechat_strcasecmp(ptr_channel->id, id) == 0) - return ptr_channel; + this->transport = transport; + weechat_printf_date_tags(buffer, 0, NULL, "%s%sTransport: %s", + weechat_prefix("network"), weechat_color("gray"), + weechat::channel::transport_name(this->transport)); } - - return NULL; } -struct t_gui_buffer *channel__search_buffer(struct t_account *account, - enum t_channel_type type, - const char *name) +struct t_gui_buffer *weechat::channel::search_buffer(weechat::channel::chat_type type, + const char *name) { struct t_hdata *hdata_buffer; struct t_gui_buffer *ptr_buffer; @@ -133,11 +76,11 @@ struct t_gui_buffer *channel__search_buffer(struct t_account *account, if (ptr_type && ptr_type[0] && ptr_account_name && ptr_account_name[0] && ptr_remote_jid && ptr_remote_jid[0] - && ( (( (type == CHANNEL_TYPE_MUC)) + && ( (( (type == weechat::channel::chat_type::MUC)) && (strcmp(ptr_type, "room") == 0)) - || (( (type == CHANNEL_TYPE_PM)) + || (( (type == weechat::channel::chat_type::PM)) && (strcmp(ptr_type, "private") == 0))) - && (strcmp(ptr_account_name, account->name) == 0) + && (ptr_account_name == account.name) && (weechat_strcasecmp(ptr_remote_jid, name) == 0)) { return ptr_buffer; @@ -149,28 +92,25 @@ struct t_gui_buffer *channel__search_buffer(struct t_account *account, return NULL; } -struct t_gui_buffer *channel__create_buffer(struct t_account *account, - enum t_channel_type type, - const char *name) +struct t_gui_buffer *weechat::channel::create_buffer(weechat::channel::chat_type type, + const char *name) { struct t_gui_buffer *ptr_buffer; int buffer_created; const char *short_name = NULL, *localvar_remote_jid = NULL; - char buffer_name[1024] = {0}; buffer_created = 0; - snprintf(buffer_name, sizeof(buffer_name), - "%s.%s", account->name, name); + std::string buffer_name = fmt::format("{}.{}", account.name, name); - ptr_buffer = channel__search_buffer(account, type, name); + ptr_buffer = weechat::channel::search_buffer(type, name); if (ptr_buffer) { weechat_nicklist_remove_all(ptr_buffer); } else { - ptr_buffer = weechat_buffer_new(buffer_name, + ptr_buffer = weechat_buffer_new(buffer_name.data(), &input__data_cb, NULL, NULL, &buffer__close_cb, NULL, NULL); if (!ptr_buffer) @@ -196,24 +136,23 @@ struct t_gui_buffer *channel__create_buffer(struct t_account *account, (localvar_remote_jid && (strcmp(localvar_remote_jid, short_name) == 0))) { weechat_buffer_set(ptr_buffer, "short_name", - xmpp_jid_node(account->context, name)); + xmpp_jid_node(account.context, name)); } } - if(!(account_nickname(account) && strlen(account_nickname(account)))) - account_option_set(account, ACCOUNT_OPTION_NICKNAME, - xmpp_jid_node(account->context, account_jid(account))); + if(!(account.nickname().size())) + account.nickname(xmpp_jid_node(account.context, account.jid().data())); // Set notify level for buffer: "0" = never add to hotlist // "1" = add for highlights only // "2" = add for highlights and messages // "3" = add for all messages. weechat_buffer_set(ptr_buffer, "notify", - (type == CHANNEL_TYPE_PM) ? "3" : "2"); + (type == weechat::channel::chat_type::PM) ? "3" : "2"); weechat_buffer_set(ptr_buffer, "localvar_set_type", - (type == CHANNEL_TYPE_PM) ? "private" : "channel"); + (type == weechat::channel::chat_type::PM) ? "private" : "channel"); weechat_buffer_set(ptr_buffer, "localvar_set_nick", - account_nickname(account)); - weechat_buffer_set(ptr_buffer, "localvar_set_account", account->name); + account.nickname().data()); + weechat_buffer_set(ptr_buffer, "localvar_set_account", account.name.data()); weechat_buffer_set(ptr_buffer, "localvar_set_remote_jid", name); weechat_buffer_set(ptr_buffer, "input_multiline", "1"); @@ -223,18 +162,18 @@ struct t_gui_buffer *channel__create_buffer(struct t_account *account, WEECHAT_HOOK_SIGNAL_POINTER, ptr_buffer); weechat_buffer_set(ptr_buffer, "input_get_unknown_commands", "1"); - if (type != CHANNEL_TYPE_PM) + if (type != weechat::channel::chat_type::PM) { weechat_buffer_set(ptr_buffer, "nicklist", "1"); weechat_buffer_set(ptr_buffer, "nicklist_display_groups", "0"); weechat_buffer_set_pointer(ptr_buffer, "nicklist_callback", (void*)&buffer__nickcmp_cb); weechat_buffer_set_pointer(ptr_buffer, "nicklist_callback_pointer", - account); + &account); } weechat_buffer_set(ptr_buffer, "highlight_words_add", - account_nickname(account)); + account.nickname().data()); weechat_buffer_set(ptr_buffer, "highlight_tags_restrict", "message"); } @@ -242,223 +181,151 @@ struct t_gui_buffer *channel__create_buffer(struct t_account *account, return ptr_buffer; } -void channel__add_nicklist_groups(struct t_account *account, - struct t_channel *channel) +void weechat::channel::add_nicklist_groups() { - struct t_gui_buffer *ptr_buffer; - char str_group[32]; - - if (channel && channel->type == CHANNEL_TYPE_PM) + if (type == weechat::channel::chat_type::PM) return; - ptr_buffer = channel ? channel->buffer : account->buffer; - - snprintf(str_group, sizeof(str_group), "%03d|%s", 000, "~"); - weechat_nicklist_add_group(ptr_buffer, NULL, str_group, + weechat_nicklist_add_group(buffer, NULL, fmt::format("%03d|%s", 000, "~").data(), "weechat.color.nicklist_group", 1); - snprintf(str_group, sizeof(str_group), "%03d|%s", 001, "&"); - weechat_nicklist_add_group(ptr_buffer, NULL, str_group, + weechat_nicklist_add_group(buffer, NULL, fmt::format("%03d|%s", 001, "&").data(), "weechat.color.nicklist_group", 1); - snprintf(str_group, sizeof(str_group), "%03d|%s", 002, "@"); - weechat_nicklist_add_group(ptr_buffer, NULL, str_group, + weechat_nicklist_add_group(buffer, NULL, fmt::format("%03d|%s", 002, "@").data(), "weechat.color.nicklist_group", 1); - snprintf(str_group, sizeof(str_group), "%03d|%s", 003, "%"); - weechat_nicklist_add_group(ptr_buffer, NULL, str_group, + weechat_nicklist_add_group(buffer, NULL, fmt::format("%03d|%s", 003, "%").data(), "weechat.color.nicklist_group", 1); - snprintf(str_group, sizeof(str_group), "%03d|%s", 004, "+"); - weechat_nicklist_add_group(ptr_buffer, NULL, str_group, + weechat_nicklist_add_group(buffer, NULL, fmt::format("%03d|%s", 004, "+").data(), "weechat.color.nicklist_group", 1); - snprintf(str_group, sizeof(str_group), "%03d|%s", 005, "?"); - weechat_nicklist_add_group(ptr_buffer, NULL, str_group, + weechat_nicklist_add_group(buffer, NULL, fmt::format("%03d|%s", 005, "?").data(), "weechat.color.nicklist_group", 1); - snprintf(str_group, sizeof(str_group), "%03d|%s", 006, "!"); - weechat_nicklist_add_group(ptr_buffer, NULL, str_group, + weechat_nicklist_add_group(buffer, NULL, fmt::format("%03d|%s", 006, "!").data(), "weechat.color.nicklist_group", 1); - snprintf(str_group, sizeof(str_group), "%03d|%s", 999, "..."); - weechat_nicklist_add_group(ptr_buffer, NULL, str_group, + weechat_nicklist_add_group(buffer, NULL, fmt::format("%03d|%s", 999, "...").data(), "weechat.color.nicklist_group", 1); } -struct t_channel *channel__new(struct t_account *account, - enum t_channel_type type, - const char *id, const char *name) +weechat::channel::channel(weechat::account& account, + weechat::channel::chat_type type, + const char *id, const char *name) : id(id), name(name), type(type), account(account) { - struct t_channel *new_channel, *ptr_channel, *muc_channel; - struct t_gui_buffer *ptr_buffer; - struct t_hook *typing_timer, *self_typing_timer; + if (!id || !name || !name[0]) + throw std::invalid_argument("channel()"); - if (!account || !id || !name || !name[0]) - return NULL; + //if (weechat::channel::search(&account, id)) + // throw std::invalid_argument("duplicate"); - ptr_channel = channel__search(account, id); - if (ptr_channel) + buffer = weechat::channel::create_buffer(type, name); + if (!buffer) + throw std::invalid_argument("buffer fail"); + else if (type == weechat::channel::chat_type::PM) { - return ptr_channel; - } - - ptr_buffer = channel__create_buffer(account, type, name); - if (!ptr_buffer) - return NULL; - else if (type == CHANNEL_TYPE_PM) - { - muc_channel = channel__search(account, jid(account->context, id).bare.data()); - if (muc_channel) + auto muc_channel = account.channels.find(jid(account.context, + id).bare.data()); + if (muc_channel != account.channels.end()) { - weechat_buffer_merge(ptr_buffer, muc_channel->buffer); + weechat_buffer_merge(buffer, muc_channel->second.buffer); } } - if ((new_channel = (struct t_channel*)malloc(sizeof(*new_channel))) == NULL) - return NULL; - - typing_timer = weechat_hook_timer(1 * 1000, 0, 0, - &channel__typing_cb, - new_channel, NULL); - - self_typing_timer = weechat_hook_timer(1 * 1000, 0, 0, - &channel__self_typing_cb, - new_channel, NULL); - - new_channel->type = type; - new_channel->id = strdup(id); - new_channel->name = strdup(name); - new_channel->transport = CHANNEL_TRANSPORT_PLAIN; - new_channel->omemo.enabled = type == CHANNEL_TYPE_PM ? 1 : 0; - new_channel->omemo.devicelist_requests = weechat_hashtable_new(64, - WEECHAT_HASHTABLE_STRING, WEECHAT_HASHTABLE_POINTER, NULL, NULL); - new_channel->omemo.bundle_requests = weechat_hashtable_new(64, - WEECHAT_HASHTABLE_STRING, WEECHAT_HASHTABLE_POINTER, NULL, NULL); - new_channel->pgp.enabled = 1; - new_channel->pgp.ids = new std::remove_pointerpgp.ids)>::type; - new_channel->otr.enabled = 0; - - new_channel->topic.value = NULL; - new_channel->topic.creator = NULL; - new_channel->topic.last_set = 0; - - new_channel->creator = NULL; - new_channel->last_read = 0.0; - new_channel->unread_count = 0; - new_channel->unread_count_display = 0; - - new_channel->typing_hook_timer = typing_timer; - new_channel->self_typing_hook_timer = self_typing_timer; - new_channel->members_speaking[0] = NULL; - new_channel->members_speaking[1] = NULL; - new_channel->unreads = NULL; - new_channel->self_typings = NULL; - new_channel->last_self_typing = NULL; - new_channel->typings = NULL; - new_channel->last_typing = NULL; - new_channel->members = NULL; - new_channel->last_member = NULL; - new_channel->buffer = ptr_buffer; - new_channel->buffer_as_string = NULL; - - new_channel->prev_channel = account->last_channel; - new_channel->next_channel = NULL; - if (account->last_channel) - (account->last_channel)->next_channel = new_channel; - else - account->channels = new_channel; - account->last_channel = new_channel; + typing_hook_timer = weechat_hook_timer(1 * 1000, 0, 0, + &weechat::channel::typing_cb, + this, nullptr); + + self_typing_hook_timer = weechat_hook_timer(1 * 1000, 0, 0, + &weechat::channel::self_typing_cb, + this, nullptr); + + omemo.enabled = type == weechat::channel::chat_type::PM ? 1 : 0; + omemo.devicelist_requests = weechat_hashtable_new(64, + WEECHAT_HASHTABLE_STRING, WEECHAT_HASHTABLE_POINTER, nullptr, nullptr); + omemo.bundle_requests = weechat_hashtable_new(64, + WEECHAT_HASHTABLE_STRING, WEECHAT_HASHTABLE_POINTER, nullptr, nullptr); - channel__add_nicklist_groups(account, new_channel); + add_nicklist_groups(); - if (type != CHANNEL_TYPE_MUC) + if (type != weechat::channel::chat_type::MUC) { time_t start = time(NULL); struct tm *ago = gmtime(&start); ago->tm_mday -= 7; start = mktime(ago); - channel__fetch_mam(account, new_channel, NULL, &start, NULL, NULL); + fetch_mam(nullptr, &start, nullptr, nullptr); } - - return new_channel; } -void channel__member_speaking_add_to_list(struct t_channel *channel, - const char *nick, - int highlight) +void weechat::channel::member_speaking_add_to_list(const char *nick, int highlight) { int size, to_remove, i; struct t_weelist_item *ptr_item; /* create list if it does not exist */ - if (!channel->members_speaking[highlight]) - channel->members_speaking[highlight] = weechat_list_new(); + if (!members_speaking[highlight]) + members_speaking[highlight] = weechat_list_new(); /* remove item if it was already in list */ - ptr_item = weechat_list_casesearch(channel->members_speaking[highlight], nick); + ptr_item = weechat_list_casesearch(members_speaking[highlight], nick); if (ptr_item) - weechat_list_remove(channel->members_speaking[highlight], ptr_item); + weechat_list_remove(members_speaking[highlight], ptr_item); /* add nick in list */ - weechat_list_add(channel->members_speaking[highlight], nick, + weechat_list_add(members_speaking[highlight], nick, WEECHAT_LIST_POS_END, NULL); /* reduce list size if it's too big */ - size = weechat_list_size(channel->members_speaking[highlight]); + size = weechat_list_size(members_speaking[highlight]); if (size > CHANNEL_MEMBERS_SPEAKING_LIMIT) { to_remove = size - CHANNEL_MEMBERS_SPEAKING_LIMIT; for (i = 0; i < to_remove; i++) { weechat_list_remove( - channel->members_speaking[highlight], - weechat_list_get(channel->members_speaking[highlight], 0)); + members_speaking[highlight], + weechat_list_get(members_speaking[highlight], 0)); } } } -void channel__member_speaking_add(struct t_channel *channel, - const char *nick, int highlight) +void weechat::channel::member_speaking_add(const char *nick, int highlight) { if (highlight < 0) highlight = 0; if (highlight > 1) highlight = 1; if (highlight) - channel__member_speaking_add_to_list(channel, nick, 1); + weechat::channel::member_speaking_add_to_list(nick, 1); - channel__member_speaking_add_to_list(channel, nick, 0); + weechat::channel::member_speaking_add_to_list(nick, 0); } -void channel__member_speaking_rename(struct t_channel *channel, - const char *old_nick, - const char *new_nick) +void weechat::channel::member_speaking_rename(const char *old_nick, const char *new_nick) { struct t_weelist_item *ptr_item; int i; for (i = 0; i < 2; i++) { - if (channel->members_speaking[i]) + if (members_speaking[i]) { - ptr_item = weechat_list_search(channel->members_speaking[i], old_nick); + ptr_item = weechat_list_search(members_speaking[i], old_nick); if (ptr_item) weechat_list_set(ptr_item, new_nick); } } } -void channel__member_speaking_rename_if_present(struct t_account *account, - struct t_channel *channel, - const char *nick) +void weechat::channel::member_speaking_rename_if_present(const char *nick) { struct t_weelist_item *ptr_item; int i, j, list_size; - (void) account; - for (i = 0; i < 2; i++) { - if (channel->members_speaking[i]) + if (members_speaking[i]) { - list_size = weechat_list_size(channel->members_speaking[i]); + list_size = weechat_list_size(members_speaking[i]); for (j = 0; j < list_size; j++) { - ptr_item = weechat_list_get(channel->members_speaking[i], j); + ptr_item = weechat_list_get(members_speaking[i], j); if (ptr_item && (weechat_strcasecmp(weechat_list_string(ptr_item), nick) == 0)) weechat_list_set(ptr_item, nick); @@ -467,51 +334,9 @@ void channel__member_speaking_rename_if_present(struct t_account *account, } } -void channel__typing_free(struct t_channel *channel, - struct t_channel_typing *typing) +int weechat::channel::typing_cb(const void *pointer, void *data, int remaining_calls) { - struct t_channel_typing *new_typings; - - if (!channel || !typing) - return; - - /* remove typing from typings list */ - if (channel->last_typing == typing) - channel->last_typing = typing->prev_typing; - if (typing->prev_typing) - { - (typing->prev_typing)->next_typing = typing->next_typing; - new_typings = channel->typings; - } - else - new_typings = typing->next_typing; - - if (typing->next_typing) - (typing->next_typing)->prev_typing = typing->prev_typing; - - /* free typing data */ - if (typing->id) - free(typing->id); - if (typing->name) - free(typing->name); - - free(typing); - - channel->typings = new_typings; -} - -void channel__typing_free_all(struct t_channel *channel) -{ - while (channel->typings) - channel__typing_free(channel, channel->typings); -} - -int channel__typing_cb(const void *pointer, - void *data, - int remaining_calls) -{ - struct t_channel_typing *ptr_typing, *next_typing; - struct t_channel *channel; + weechat::channel *channel; const char *localvar; unsigned typecount; time_t now; @@ -522,133 +347,69 @@ int channel__typing_cb(const void *pointer, if (!pointer) return WEECHAT_RC_ERROR; - channel = (struct t_channel *)pointer; + channel = (weechat::channel *)pointer; now = time(NULL); typecount = 0; - for (ptr_typing = channel->typings; ptr_typing; - ptr_typing = ptr_typing->next_typing) + for (auto ptr_typing = channel->typings.begin(); + ptr_typing != channel->typings.end(); ptr_typing++) { - next_typing = ptr_typing->next_typing; - - while (ptr_typing && now - ptr_typing->ts > 5) + if (now - ptr_typing->ts > 5) { - channel__typing_free(channel, ptr_typing); - ptr_typing = next_typing; - if (ptr_typing) - next_typing = ptr_typing->next_typing; + channel->typings.erase(ptr_typing); } - if (!ptr_typing) - break; - typecount++; } localvar = weechat_buffer_get_string(channel->buffer, "localvar_typing"); if (!localvar || strncmp(localvar, typecount > 0 ? "1" : "0", 1) != 0) - weechat_buffer_set(channel->buffer, - "localvar_set_typing", + weechat_buffer_set(channel->buffer, "localvar_set_typing", typecount > 0 ? "1" : "0"); weechat_bar_item_update("typing"); return WEECHAT_RC_OK; } -struct t_channel_typing *channel__typing_search(struct t_channel *channel, - const char *id) +weechat::channel::typing *weechat::channel::typing_search(const char *id) { - struct t_channel_typing *ptr_typing; - - if (!channel || !id) - return NULL; + if (!id) + return nullptr; - for (ptr_typing = channel->typings; ptr_typing; - ptr_typing = ptr_typing->next_typing) + for (auto& ptr_typing : typings) { - if (weechat_strcasecmp(ptr_typing->id, id) == 0) - return ptr_typing; + if (weechat_strcasecmp(ptr_typing.id, id) == 0) + return &ptr_typing; } - return NULL; + return nullptr; } -int channel__add_typing(struct t_channel *channel, - struct t_user *user) +int weechat::channel::add_typing(weechat::user *user) { - struct t_channel_typing *new_typing; + weechat::channel::typing *new_typing; int ret = 0; - new_typing = channel__typing_search(channel, user->id); + new_typing = weechat::channel::typing_search(user->id); if (!new_typing) { - new_typing = (struct t_channel_typing*)malloc(sizeof(*new_typing)); + new_typing = (weechat::channel::typing*)malloc(sizeof(*new_typing)); new_typing->id = strdup(user->id); new_typing->name = strdup(user->profile.display_name); - new_typing->prev_typing = channel->last_typing; - new_typing->next_typing = NULL; - if (channel->last_typing) - (channel->last_typing)->next_typing = new_typing; - else - channel->typings = new_typing; - channel->last_typing = new_typing; - ret = 1; } - new_typing->ts = time(NULL); + new_typing->ts = time(nullptr); - channel__typing_cb(channel, NULL, 0); + weechat::channel::typing_cb(this, nullptr, 0); return ret; } -void channel__self_typing_free(struct t_channel *channel, - struct t_channel_typing *typing) -{ - struct t_channel_typing *new_typings; - - if (!channel || !typing) - return; - - /* remove typing from typings list */ - if (channel->last_self_typing == typing) - channel->last_self_typing = typing->prev_typing; - if (typing->prev_typing) - { - (typing->prev_typing)->next_typing = typing->next_typing; - new_typings = channel->self_typings; - } - else - new_typings = typing->next_typing; - - if (typing->next_typing) - (typing->next_typing)->prev_typing = typing->prev_typing; - - /* free typing data */ - if (typing->name) - free(typing->name); - - free(typing); - - channel->self_typings = new_typings; -} - -void channel__self_typing_free_all(struct t_channel *channel) +int weechat::channel::self_typing_cb(const void *pointer, void *data, int remaining_calls) { - while (channel->self_typings) - channel__self_typing_free(channel, channel->self_typings); -} - -int channel__self_typing_cb(const void *pointer, - void *data, - int remaining_calls) -{ - struct t_channel_typing *ptr_typing, *next_typing; - struct t_account *account; - struct t_channel *channel; time_t now; (void) data; @@ -657,299 +418,128 @@ int channel__self_typing_cb(const void *pointer, if (!pointer) return WEECHAT_RC_ERROR; - channel = (struct t_channel *)pointer; - account = channel__account(channel); + weechat::channel *channel = (weechat::channel *)pointer; now = time(NULL); - for (ptr_typing = channel->self_typings; ptr_typing; - ptr_typing = ptr_typing->next_typing) + for (auto ptr_typing = channel->self_typings.begin(); + ptr_typing != channel->self_typings.end(); ptr_typing++) { - next_typing = ptr_typing->next_typing; - - while (ptr_typing && now - ptr_typing->ts > 10) + if (now - ptr_typing->ts > 10) { - channel__send_paused(account, channel, ptr_typing->user); - channel__self_typing_free(channel, ptr_typing); - ptr_typing = next_typing; - if (ptr_typing) - next_typing = ptr_typing->next_typing; + channel->send_paused(ptr_typing->user); + channel->self_typings.erase(ptr_typing); } - - if (!ptr_typing) - break; } return WEECHAT_RC_OK; } -struct t_channel_typing *channel__self_typing_search(struct t_channel *channel, - struct t_user *user) +weechat::channel::typing *weechat::channel::self_typing_search(weechat::user *user) { - struct t_channel_typing *ptr_typing; - - if (!channel) - return NULL; - - for (ptr_typing = channel->self_typings; ptr_typing; - ptr_typing = ptr_typing->next_typing) + for (auto& ptr_typing : typings) { - if (user == ptr_typing->user) - return ptr_typing; + if (user == ptr_typing.user) + return &ptr_typing; } - return NULL; + return nullptr; } -int channel__add_self_typing(struct t_channel *channel, - struct t_user *user) +int weechat::channel::add_self_typing(weechat::user *user) { - struct t_channel_typing *new_typing; + weechat::channel::typing *new_typing; int ret = 0; - new_typing = channel__self_typing_search(channel, user); + new_typing = self_typing_search(user); if (!new_typing) { - new_typing = (struct t_channel_typing*)malloc(sizeof(*new_typing)); + new_typing = (weechat::channel::typing*)malloc(sizeof(*new_typing)); new_typing->user = user; new_typing->name = user ? strdup(user->profile.display_name) : NULL; - new_typing->prev_typing = channel->last_self_typing; - new_typing->next_typing = NULL; - new_typing->ts = time(NULL); - if (channel->last_self_typing) - (channel->last_self_typing)->next_typing = new_typing; - else - channel->self_typings = new_typing; - channel->last_self_typing = new_typing; - ret = 1; } - channel__self_typing_cb(channel, NULL, 0); + self_typing_cb(this, nullptr, 0); return ret; } -void channel__unread_free(struct t_channel_unread *unread) -{ - if (!unread) - return; - - if (unread->id) - free(unread->id); - if (unread->thread) - free(unread->thread); - free(unread); -} - -void channel__unread_free_all(struct t_channel *channel) -{ - if (channel->unreads) - { - int list_size = weechat_list_size(channel->unreads); - - for (int i = 0; i < list_size; i++) - { - struct t_weelist_item *ptr_item = weechat_list_get(channel->unreads, i); - if (ptr_item) - { - struct t_channel_unread *unread = (struct t_channel_unread *)weechat_list_user_data(ptr_item); - - channel__unread_free(unread); - - weechat_list_remove(channel->unreads, ptr_item); - } - } - - weechat_list_free(channel->unreads); - } -} - -void channel__member_free(struct t_channel *channel, - struct t_channel_member *member) -{ - struct t_channel_member *new_members; - - if (!channel || !member) - return; - - /* remove member from members list */ - if (channel->last_member == member) - channel->last_member = member->prev_member; - if (member->prev_member) - { - (member->prev_member)->next_member = member->next_member; - new_members = channel->members; - } - else - new_members = member->next_member; - - if (member->next_member) - (member->next_member)->prev_member = member->prev_member; - - /* free member data */ - if (member->id) - free(member->id); - if (member->role) - free(member->role); - if (member->affiliation) - free(member->affiliation); - - free(member); - - channel->members = new_members; -} - -void channel__member_free_all(struct t_channel *channel) -{ - while (channel->members) - channel__member_free(channel, channel->members); -} - -void channel__free(struct t_account *account, - struct t_channel *channel) -{ - struct t_channel *new_channels; - - if (!account || !channel) - return; - - /* remove channel from channels list */ - if (account->last_channel == channel) - account->last_channel = channel->prev_channel; - if (channel->prev_channel) - { - (channel->prev_channel)->next_channel = channel->next_channel; - new_channels = account->channels; - } - else - new_channels = channel->next_channel; - - if (channel->next_channel) - (channel->next_channel)->prev_channel = channel->prev_channel; - - /* free hooks */ - if (channel->typing_hook_timer) - weechat_unhook(channel->typing_hook_timer); - if (channel->self_typing_hook_timer) - weechat_unhook(channel->self_typing_hook_timer); - - /* free linked lists */ - channel__self_typing_free_all(channel); - channel__typing_free_all(channel); - channel__member_free_all(channel); - channel__unread_free_all(channel); - - /* free channel data */ - if (channel->id) - free(channel->id); - if (channel->name) - free(channel->name); - if (channel->pgp.ids) - { - delete channel->pgp.ids; - channel->pgp.ids = nullptr; - } - if (channel->topic.value) - free(channel->topic.value); - if (channel->topic.creator) - free(channel->topic.creator); - if (channel->creator) - free(channel->creator); - if (channel->members_speaking[0]) - weechat_list_free(channel->members_speaking[0]); - if (channel->members_speaking[1]) - weechat_list_free(channel->members_speaking[1]); - if (channel->buffer_as_string) - free(channel->buffer_as_string); - - free(channel); - - account->channels = new_channels; -} - -void channel__free_all(struct t_account *account) +weechat::channel::~channel() { - while (account->channels) - channel__free(account, account->channels); + if (typing_hook_timer) + weechat_unhook(typing_hook_timer); + if (self_typing_hook_timer) + weechat_unhook(self_typing_hook_timer); + + if (members_speaking[0]) + weechat_list_free(members_speaking[0]); + if (members_speaking[1]) + weechat_list_free(members_speaking[1]); } -void channel__update_topic(struct t_channel *channel, - const char* topic, - const char* creator, - int last_set) +void weechat::channel::update_topic(const char* topic, const char* creator, int last_set) { - if (channel->topic.value) - free(channel->topic.value); - if (channel->topic.creator) - free(channel->topic.creator); - channel->topic.value = (topic) ? strdup(topic) : NULL; - channel->topic.creator = (creator) ? strdup(creator) : NULL; - channel->topic.last_set = last_set; - - if (channel->topic.value) - weechat_buffer_set(channel->buffer, "title", topic); + if (this->topic.value) + ::free(this->topic.value); + if (this->topic.creator) + ::free(this->topic.creator); + this->topic.value = (topic) ? strdup(topic) : NULL; + this->topic.creator = (creator) ? strdup(creator) : NULL; + this->topic.last_set = last_set; + + if (this->topic.value) + weechat_buffer_set(buffer, "title", topic); else - weechat_buffer_set(channel->buffer, "title", ""); + weechat_buffer_set(buffer, "title", ""); } -void channel__update_name(struct t_channel *channel, - const char* name) +void weechat::channel::update_name(const char* name) { if (name) - weechat_buffer_set(channel->buffer, "short_name", name); + weechat_buffer_set(buffer, "short_name", name); else - weechat_buffer_set(channel->buffer, "short_name", ""); + weechat_buffer_set(buffer, "short_name", ""); } -struct t_channel_member *channel__add_member(struct t_account *account, - struct t_channel *channel, - const char *id, const char *client) +weechat::channel::member *weechat::channel::add_member(const char *id, const char *client) { - struct t_channel_member *member; - struct t_user *user; + weechat::channel::member *member; + weechat::user *user; - user = user__search(account, id); + user = user::search(&account, id); - if (user && weechat_strcasecmp(user->id, channel->id) == 0 - && channel->type == CHANNEL_TYPE_MUC) + if (user && weechat_strcasecmp(user->id, id) == 0 + && type == weechat::channel::chat_type::MUC) { - weechat_printf_date_tags(channel->buffer, 0, "log2", "%sMUC: %s", - weechat_prefix("network"), - id); - return NULL; + weechat_printf_date_tags(buffer, 0, "log2", "%sMUC: %s", + weechat_prefix("network"), id); + return nullptr; } - if (!(member = channel__member_search(channel, id))) + if (!(member = member_search(id))) { - member = (struct t_channel_member*)malloc(sizeof(struct t_channel_member)); + member = (weechat::channel::member*)malloc(sizeof(weechat::channel::member)); member->id = strdup(id); member->role = NULL; member->affiliation = NULL; - - member->prev_member = channel->last_member; - member->next_member = NULL; - if (channel->last_member) - (channel->last_member)->next_member = member; - else - channel->members = member; - channel->last_member = member; } else if (user) - user__nicklist_remove(account, channel, user); + user->nicklist_remove(&account, this); if (user) - user__nicklist_add(account, channel, user); - - char *jid_bare = xmpp_jid_bare(account->context, user->id); - char *jid_resource = xmpp_jid_resource(account->context, user->id); - if (weechat_strcasecmp(jid_bare, channel->id) == 0 - && channel->type == CHANNEL_TYPE_MUC) - weechat_printf_date_tags(channel->buffer, 0, "xmpp_presence,enter,log4", "%s%s%s%s%s %s%s%s%s %s%s%s%s%s%s%s%s%s%s%s%s%s%s", + user->nicklist_add(&account, this); + else return member; // TODO: !! + + char *jid_bare = xmpp_jid_bare(account.context, user->id); + char *jid_resource = xmpp_jid_resource(account.context, user->id); + if (weechat_strcasecmp(jid_bare, id) == 0 + && type == weechat::channel::chat_type::MUC) + weechat_printf_date_tags(buffer, 0, "xmpp_presence,enter,log4", "%s%s%s%s%s %s%s%s%s %s%s%s%s%s%s%s%s%s%s%s%s%s%s", weechat_prefix("join"), - user__as_prefix_raw(account, jid_resource), + user->as_prefix_raw(), client ? " (" : "", client ? client : "", client ? ")" : "", @@ -957,7 +547,7 @@ struct t_channel_member *channel__add_member(struct t_account *account, weechat_color("irc.color.message_join"), user->profile.status ? user->profile.status : (user->profile.idle ? "idle" : "entered"), weechat_color("reset"), - channel->id, + id, user->profile.status_text ? " [" : "", user->profile.status_text ? user->profile.status_text : "", user->profile.status_text ? "]" : "", @@ -970,10 +560,10 @@ struct t_channel_member *channel__add_member(struct t_account *account, user->profile.pgp_id ? user->profile.pgp_id : "", user->profile.pgp_id ? weechat_color("reset") : ""); else - weechat_printf_date_tags(channel->buffer, 0, "xmpp_presence,enter,log4", "%s%s (%s) %s%s%s%s %s%s%s%s%s%s%s%s%s", + weechat_printf_date_tags(buffer, 0, "xmpp_presence,enter,log4", "%s%s (%s) %s%s%s%s %s%s%s%s%s%s%s%s%s", weechat_prefix("join"), - jid_resource ? user__as_prefix_raw(account, jid_bare) : "You", - jid_resource ? jid_resource : user__as_prefix_raw(account, jid_bare), + jid_resource ? user->as_prefix_raw() : "You", + jid_resource ? jid_resource : user->as_prefix_raw(), user->profile.status ? "is " : "", weechat_color("irc.color.message_join"), user->profile.status ? user->profile.status : (user->profile.idle ? "idle" : "entered"), @@ -994,60 +584,54 @@ struct t_channel_member *channel__add_member(struct t_account *account, return member; } -struct t_channel_member *channel__member_search(struct t_channel *channel, - const char *id) +weechat::channel::member *weechat::channel::member_search(const char *id) { - struct t_channel_member *ptr_member; + if (!id) + return nullptr; - if (!channel || !id) - return NULL; - - for (ptr_member = channel->members; ptr_member; - ptr_member = ptr_member->next_member) + for (auto& ptr_member : members) { - if (weechat_strcasecmp(ptr_member->id, id) == 0) - return ptr_member; + if (weechat_strcasecmp(ptr_member.second.id, id) == 0) + return &ptr_member.second; } - return NULL; + return nullptr; } -struct t_channel_member *channel__remove_member(struct t_account *account, - struct t_channel *channel, - const char *id, const char *reason) +weechat::channel::member *weechat::channel::remove_member(const char *id, const char *reason) { - struct t_channel_member *member; - struct t_user *user; + weechat::channel::member *member; + weechat::user *user; - user = user__search(account, id); + user = user::search(&account, id); if (user) - user__nicklist_remove(account, channel, user); + user->nicklist_remove(&account, this); - member = channel__member_search(channel, id); - if (member) - channel__member_free(channel, member); + member = member_search(id); - char *jid_bare = xmpp_jid_bare(account->context, user->id); - char *jid_resource = xmpp_jid_resource(account->context, user->id); - if (weechat_strcasecmp(jid_bare, channel->id) == 0 - && channel->type == CHANNEL_TYPE_MUC) - weechat_printf_date_tags(channel->buffer, 0, "xmpp_presence,leave,log4", "%s%s %sleft%s %s %s%s%s", + char *jid_bare = xmpp_jid_bare(account.context, user->id); + char *jid_resource = xmpp_jid_resource(account.context, user->id); + if (weechat_strcasecmp(jid_bare, id) == 0 + && type == weechat::channel::chat_type::MUC) + weechat_printf_date_tags(buffer, 0, "xmpp_presence,leave,log4", + "%s%s %sleft%s %s %s%s%s", weechat_prefix("quit"), jid_resource, weechat_color("irc.color.message_quit"), weechat_color("reset"), - channel->id, + id, reason ? "[" : "", reason ? reason : "", reason ? "]" : ""); else - weechat_printf_date_tags(channel->buffer, 0, "xmpp_presence,leave,log4", "%s%s (%s) %sleft%s %s %s%s%s", + weechat_printf_date_tags(buffer, 0, "xmpp_presence,leave,log4", + "%s%s (%s) %sleft%s %s %s%s%s", weechat_prefix("quit"), - xmpp_jid_bare(account->context, user->id), - xmpp_jid_resource(account->context, user->id), + xmpp_jid_bare(account.context, user->id), + xmpp_jid_resource(account.context, user->id), weechat_color("irc.color.message_quit"), weechat_color("reset"), - channel->id, + id, reason ? "[" : "", reason ? reason : "", reason ? "]" : ""); @@ -1055,30 +639,29 @@ struct t_channel_member *channel__remove_member(struct t_account *account, return member; } -int channel__send_message(struct t_account *account, struct t_channel *channel, - std::string to, std::string body, - tl::optional oob = {}) +int weechat::channel::send_message(std::string to, std::string body, + tl::optional oob) { - xmpp_stanza_t *message = xmpp_message_new(account->context, - channel->type == CHANNEL_TYPE_MUC + xmpp_stanza_t *message = xmpp_message_new(account.context, + type == weechat::channel::chat_type::MUC ? "groupchat" : "chat", to.data(), NULL); - char *id = xmpp_uuid_gen(account->context); + char *id = xmpp_uuid_gen(account.context); xmpp_stanza_set_id(message, id); - xmpp_free(account->context, id); + xmpp_free(account.context, id); xmpp_message_set_body(message, body.data()); if (oob) { - xmpp_stanza_t *message__x = xmpp_stanza_new(account->context); + xmpp_stanza_t *message__x = xmpp_stanza_new(account.context); xmpp_stanza_set_name(message__x, "x"); xmpp_stanza_set_ns(message__x, "jabber:x:oob"); - xmpp_stanza_t *message__x__url = xmpp_stanza_new(account->context); + xmpp_stanza_t *message__x__url = xmpp_stanza_new(account.context); xmpp_stanza_set_name(message__x__url, "url"); - xmpp_stanza_t *message__x__url__text = xmpp_stanza_new(account->context); + xmpp_stanza_t *message__x__url__text = xmpp_stanza_new(account.context); xmpp_stanza_set_text(message__x__url__text, oob->data()); xmpp_stanza_add_child(message__x__url, message__x__url__text); xmpp_stanza_release(message__x__url__text); @@ -1090,71 +673,70 @@ int channel__send_message(struct t_account *account, struct t_channel *channel, xmpp_stanza_release(message__x); } - xmpp_stanza_t *message__active = xmpp_stanza_new(account->context); + xmpp_stanza_t *message__active = xmpp_stanza_new(account.context); xmpp_stanza_set_name(message__active, "active"); xmpp_stanza_set_ns(message__active, "http://jabber.org/protocol/chatstates"); xmpp_stanza_add_child(message, message__active); xmpp_stanza_release(message__active); - xmpp_stanza_t *message__request = xmpp_stanza_new(account->context); + xmpp_stanza_t *message__request = xmpp_stanza_new(account.context); xmpp_stanza_set_name(message__request, "request"); xmpp_stanza_set_ns(message__request, "urn:xmpp:receipts"); xmpp_stanza_add_child(message, message__request); xmpp_stanza_release(message__request); - xmpp_stanza_t *message__markable = xmpp_stanza_new(account->context); + xmpp_stanza_t *message__markable = xmpp_stanza_new(account.context); xmpp_stanza_set_name(message__markable, "markable"); xmpp_stanza_set_ns(message__markable, "urn:xmpp:chat-markers:0"); xmpp_stanza_add_child(message, message__markable); xmpp_stanza_release(message__markable); - xmpp_stanza_t *message__store = xmpp_stanza_new(account->context); + xmpp_stanza_t *message__store = xmpp_stanza_new(account.context); xmpp_stanza_set_name(message__store, "store"); xmpp_stanza_set_ns(message__store, "urn:xmpp:hints"); xmpp_stanza_add_child(message, message__store); xmpp_stanza_release(message__store); - xmpp_send(account->connection, message); + xmpp_send(account.connection, message); xmpp_stanza_release(message); - if (channel->type != CHANNEL_TYPE_MUC) - weechat_printf_date_tags(channel->buffer, 0, + if (type != weechat::channel::chat_type::MUC) + weechat_printf_date_tags(buffer, 0, "xmpp_message,message,private,notify_none,self_msg,log1", "%s\t%s", - user__as_prefix_raw(account, account_jid(account)), + user::search(&account, account.jid().data())->as_prefix_raw().data(), body.data()); return WEECHAT_RC_OK; } -int channel__send_message(struct t_account *account, struct t_channel *channel, - const char *to, const char *body) +int weechat::channel::send_message(const char *to, const char *body) { - channel__send_reads(account, channel); + send_reads(); - xmpp_stanza_t *message = xmpp_message_new(account->context, - channel->type == CHANNEL_TYPE_MUC + xmpp_stanza_t *message = xmpp_message_new(account.context, + type == weechat::channel::chat_type::MUC ? "groupchat" : "chat", to, NULL); - char *id = xmpp_uuid_gen(account->context); + char *id = xmpp_uuid_gen(account.context); xmpp_stanza_set_id(message, id); - xmpp_free(account->context, id); + xmpp_free(account.context, id); - if (account->omemo && channel->omemo.enabled) + if (account.omemo && omemo.enabled) { - xmpp_stanza_t *encrypted = account->omemo.encode(account, to, body); + xmpp_stanza_t *encrypted = account.omemo.encode(&account, to, body); if (!encrypted) { - weechat_printf_date_tags(channel->buffer, 0, "notify_none", "%s%s", + weechat_printf_date_tags(buffer, 0, "notify_none", "%s%s", weechat_prefix("error"), "OMEMO Encryption Error"); - channel__set_transport(channel, CHANNEL_TRANSPORT_PLAIN, 1); + set_transport(weechat::channel::transport::PLAIN, 1); xmpp_stanza_release(message); return WEECHAT_RC_ERROR; } xmpp_stanza_add_child(message, encrypted); xmpp_stanza_release(encrypted); - xmpp_stanza_t *message__encryption = xmpp_stanza_new(account->context); + xmpp_stanza_t *message__encryption = xmpp_stanza_new(account.context); xmpp_stanza_set_name(message__encryption, "encryption"); xmpp_stanza_set_ns(message__encryption, "urn:xmpp:eme:0"); xmpp_stanza_set_attribute(message__encryption, "namespace", @@ -1165,27 +747,27 @@ int channel__send_message(struct t_account *account, struct t_channel *channel, xmpp_message_set_body(message, OMEMO_ADVICE); - channel__set_transport(channel, CHANNEL_TRANSPORT_OMEMO, 0); + set_transport(weechat::channel::transport::OMEMO, 0); } - else if (channel->pgp.enabled && channel->pgp.ids) + else if (pgp.enabled && !pgp.ids.empty()) { - xmpp_stanza_t *message__x = xmpp_stanza_new(account->context); + xmpp_stanza_t *message__x = xmpp_stanza_new(account.context); xmpp_stanza_set_name(message__x, "x"); xmpp_stanza_set_ns(message__x, "jabber:x:encrypted"); - xmpp_stanza_t *message__x__text = xmpp_stanza_new(account->context); - char *ciphertext = pgp__encrypt(channel->buffer, account->pgp, account_pgp_keyid(account), std::vector(channel->pgp.ids->begin(), channel->pgp.ids->end()), body); + xmpp_stanza_t *message__x__text = xmpp_stanza_new(account.context); + char *ciphertext = account.pgp.encrypt(buffer, account.pgp_keyid().data(), std::vector(pgp.ids.begin(), pgp.ids.end()), body); if (ciphertext) xmpp_stanza_set_text(message__x__text, ciphertext); else { - weechat_printf_date_tags(channel->buffer, 0, "notify_none", "%s%s", + weechat_printf_date_tags(buffer, 0, "notify_none", "%s%s", weechat_prefix("error"), "PGP Error"); - channel__set_transport(channel, CHANNEL_TRANSPORT_PLAIN, 1); + set_transport(weechat::channel::transport::PLAIN, 1); xmpp_stanza_release(message); return WEECHAT_RC_ERROR; } - free(ciphertext); + ::free(ciphertext); xmpp_stanza_add_child(message__x, message__x__text); xmpp_stanza_release(message__x__text); @@ -1193,7 +775,7 @@ int channel__send_message(struct t_account *account, struct t_channel *channel, xmpp_stanza_add_child(message, message__x); xmpp_stanza_release(message__x); - xmpp_stanza_t *message__encryption = xmpp_stanza_new(account->context); + xmpp_stanza_t *message__encryption = xmpp_stanza_new(account.context); xmpp_stanza_set_name(message__encryption, "encryption"); xmpp_stanza_set_ns(message__encryption, "urn:xmpp:eme:0"); xmpp_stanza_set_attribute(message__encryption, "namespace", "jabber:x:encryption"); @@ -1201,20 +783,20 @@ int channel__send_message(struct t_account *account, struct t_channel *channel, xmpp_stanza_add_child(message, message__encryption); xmpp_stanza_release(message__encryption); - xmpp_message_set_body(message, PGP_ADVICE); + xmpp_message_set_body(message, weechat::xmpp::PGP_ADVICE); - channel__set_transport(channel, CHANNEL_TRANSPORT_PGP, 0); + set_transport(weechat::channel::transport::PGP, 0); } else { xmpp_message_set_body(message, body); - channel__set_transport(channel, CHANNEL_TRANSPORT_PLAIN, 0); + set_transport(weechat::channel::transport::PLAIN, 0); } static const std::regex pattern("https?:[^ ]*"); std::cmatch match; - if (channel->transport == CHANNEL_TRANSPORT_PLAIN && + if (transport == weechat::channel::transport::PLAIN && std::regex_search(body, match, pattern) && match[0].matched && !match.prefix().length()) { @@ -1230,13 +812,12 @@ int channel__send_message(struct t_account *account, struct t_channel *channel, auto command = "url:" + url; const int timeout = 30000; struct message_task { - struct t_account *account; - struct t_channel *channel; + weechat::channel& channel; std::string to; std::string body; std::string url; }; - auto *task = new message_task { account, channel, to, body, url }; + auto *task = new message_task { *this, to, body, url }; auto callback = [](const void *pointer, void *, const char *, int ret, const char *out, const char *err) { auto task = static_cast(pointer); @@ -1257,25 +838,22 @@ int channel__send_message(struct t_account *account, struct t_channel *channel, } if (mime.starts_with("image") || mime.starts_with("video")) { - weechat_printf_date_tags(task->channel->buffer, 0, + weechat_printf_date_tags(task->channel.buffer, 0, "notify_none,no_log", "[oob]\t%s%s", weechat_color("gray"), mime.data()); - channel__send_message(task->account, task->channel, - task->to, task->body, { task->url }); + task->channel.send_message(task->to, task->body, { task->url }); } else { - weechat_printf_date_tags(task->channel->buffer, 0, + weechat_printf_date_tags(task->channel.buffer, 0, "notify_none,no_log", "[curl]\t%s%s", weechat_color("red"), err); - channel__send_message(task->account, task->channel, - task->to, task->body); + task->channel.send_message(task->to.data(), task->body.data()); } } else { - channel__send_message(task->account, task->channel, - task->to, task->body); + task->channel.send_message(task->to.data(), task->body.data()); } delete task; @@ -1290,143 +868,130 @@ int channel__send_message(struct t_account *account, struct t_channel *channel, } while(0); } - xmpp_stanza_t *message__active = xmpp_stanza_new(account->context); + xmpp_stanza_t *message__active = xmpp_stanza_new(account.context); xmpp_stanza_set_name(message__active, "active"); xmpp_stanza_set_ns(message__active, "http://jabber.org/protocol/chatstates"); xmpp_stanza_add_child(message, message__active); xmpp_stanza_release(message__active); - xmpp_stanza_t *message__request = xmpp_stanza_new(account->context); + xmpp_stanza_t *message__request = xmpp_stanza_new(account.context); xmpp_stanza_set_name(message__request, "request"); xmpp_stanza_set_ns(message__request, "urn:xmpp:receipts"); xmpp_stanza_add_child(message, message__request); xmpp_stanza_release(message__request); - xmpp_stanza_t *message__markable = xmpp_stanza_new(account->context); + xmpp_stanza_t *message__markable = xmpp_stanza_new(account.context); xmpp_stanza_set_name(message__markable, "markable"); xmpp_stanza_set_ns(message__markable, "urn:xmpp:chat-markers:0"); xmpp_stanza_add_child(message, message__markable); xmpp_stanza_release(message__markable); - xmpp_stanza_t *message__store = xmpp_stanza_new(account->context); + xmpp_stanza_t *message__store = xmpp_stanza_new(account.context); xmpp_stanza_set_name(message__store, "store"); xmpp_stanza_set_ns(message__store, "urn:xmpp:hints"); xmpp_stanza_add_child(message, message__store); xmpp_stanza_release(message__store); - xmpp_send(account->connection, message); + xmpp_send(account.connection, message); xmpp_stanza_release(message); - if (channel->type != CHANNEL_TYPE_MUC) - weechat_printf_date_tags(channel->buffer, 0, + if (type != weechat::channel::chat_type::MUC) + weechat_printf_date_tags(buffer, 0, "xmpp_message,message,private,notify_none,self_msg,log1", "%s\t%s", - user__as_prefix_raw(account, account_jid(account)), + user::search(&account, account.jid().data())->as_prefix_raw().data(), body); return WEECHAT_RC_OK; } -void channel__send_reads(struct t_account *account, struct t_channel *channel) +void weechat::channel::send_reads() { - if (channel && channel->unreads) - { - int list_size = weechat_list_size(channel->unreads); - - for (int i = 0; i < list_size; i++) - { - struct t_weelist_item *ptr_item = weechat_list_get(channel->unreads, 0); - if (ptr_item) - { - const char *unread_id = weechat_list_string(ptr_item); - struct t_channel_unread *unread = (struct t_channel_unread*)weechat_list_user_data(ptr_item); + auto i = std::begin(unreads); - xmpp_stanza_t *message = xmpp_message_new(account->context, NULL, - channel->id, NULL); + while (i != std::end(unreads)) + { + auto* unread = &*i; - xmpp_stanza_t *message__displayed = xmpp_stanza_new(account->context); - xmpp_stanza_set_name(message__displayed, "displayed"); - xmpp_stanza_set_ns(message__displayed, "urn:xmpp:chat-markers:0"); - xmpp_stanza_set_id(message__displayed, unread->id ? unread->id : unread_id); - if (unread->thread) - { - xmpp_stanza_t *message__thread = xmpp_stanza_new(account->context); - xmpp_stanza_set_name(message__thread, "thread"); + xmpp_stanza_t *message = xmpp_message_new(account.context, NULL, + id.data(), NULL); - xmpp_stanza_t *message__thread__text = xmpp_stanza_new(account->context); - xmpp_stanza_set_text(message__thread__text, unread->thread); - xmpp_stanza_add_child(message__thread, message__thread__text); - xmpp_stanza_release(message__thread__text); + xmpp_stanza_t *message__displayed = xmpp_stanza_new(account.context); + xmpp_stanza_set_name(message__displayed, "displayed"); + xmpp_stanza_set_ns(message__displayed, "urn:xmpp:chat-markers:0"); + xmpp_stanza_set_id(message__displayed, unread->id); + if (unread->thread) + { + xmpp_stanza_t *message__thread = xmpp_stanza_new(account.context); + xmpp_stanza_set_name(message__thread, "thread"); - xmpp_stanza_add_child(message, message__thread); - xmpp_stanza_release(message__thread); - } + xmpp_stanza_t *message__thread__text = xmpp_stanza_new(account.context); + xmpp_stanza_set_text(message__thread__text, unread->thread); + xmpp_stanza_add_child(message__thread, message__thread__text); + xmpp_stanza_release(message__thread__text); - xmpp_stanza_add_child(message, message__displayed); - xmpp_stanza_release(message__displayed); + xmpp_stanza_add_child(message, message__thread); + xmpp_stanza_release(message__thread); + } - xmpp_send(account->connection, message); - xmpp_stanza_release(message); + xmpp_stanza_add_child(message, message__displayed); + xmpp_stanza_release(message__displayed); - channel__unread_free(unread); + xmpp_send(account.connection, message); + xmpp_stanza_release(message); - weechat_list_remove(channel->unreads, ptr_item); - } - } + i = unreads.erase(i); } } -void channel__send_typing(struct t_account *account, struct t_channel *channel, - struct t_user *user) +void weechat::channel::send_typing(weechat::user *user) { - if (channel__add_self_typing(channel, user)) + if (add_self_typing(user)) { - xmpp_stanza_t *message = xmpp_message_new(account->context, - channel->type == CHANNEL_TYPE_MUC + xmpp_stanza_t *message = xmpp_message_new(account.context, + type == weechat::channel::chat_type::MUC ? "groupchat" : "chat", - user ? user->id : channel->id, NULL); + (user ? user->id : id).data(), NULL); - xmpp_stanza_t *message__composing = xmpp_stanza_new(account->context); + xmpp_stanza_t *message__composing = xmpp_stanza_new(account.context); xmpp_stanza_set_name(message__composing, "composing"); xmpp_stanza_set_ns(message__composing, "http://jabber.org/protocol/chatstates"); xmpp_stanza_add_child(message, message__composing); xmpp_stanza_release(message__composing); - xmpp_send(account->connection, message); + xmpp_send(account.connection, message); xmpp_stanza_release(message); } } -void channel__send_paused(struct t_account *account, struct t_channel *channel, - struct t_user *user) +void weechat::channel::send_paused(weechat::user *user) { - xmpp_stanza_t *message = xmpp_message_new(account->context, - channel->type == CHANNEL_TYPE_MUC + xmpp_stanza_t *message = xmpp_message_new(account.context, + type == weechat::channel::chat_type::MUC ? "groupchat" : "chat", - user ? user->id : channel->id, NULL); + (user ? user->id : id).data(), NULL); - xmpp_stanza_t *message__paused = xmpp_stanza_new(account->context); + xmpp_stanza_t *message__paused = xmpp_stanza_new(account.context); xmpp_stanza_set_name(message__paused, "paused"); xmpp_stanza_set_ns(message__paused, "http://jabber.org/protocol/chatstates"); xmpp_stanza_add_child(message, message__paused); xmpp_stanza_release(message__paused); - xmpp_send(account->connection, message); + xmpp_send(account.connection, message); xmpp_stanza_release(message); } -void channel__fetch_mam(struct t_account *account, struct t_channel *channel, - const char *id, time_t *start, time_t *end, const char* after) +void weechat::channel::fetch_mam(const char *id, time_t *start, time_t *end, const char* after) { - xmpp_stanza_t *iq = xmpp_iq_new(account->context, "set", "juliet1"); - xmpp_stanza_set_id(iq, id ? id : xmpp_uuid_gen(account->context)); + xmpp_stanza_t *iq = xmpp_iq_new(account.context, "set", "juliet1"); + xmpp_stanza_set_id(iq, id ? id : xmpp_uuid_gen(account.context)); - xmpp_stanza_t *query = xmpp_stanza_new(account->context); + xmpp_stanza_t *query = xmpp_stanza_new(account.context); xmpp_stanza_set_name(query, "query"); xmpp_stanza_set_ns(query, "urn:xmpp:mam:2"); - xmpp_stanza_t *x = xmpp_stanza_new(account->context); + xmpp_stanza_t *x = xmpp_stanza_new(account.context); xmpp_stanza_set_name(x, "x"); xmpp_stanza_set_ns(x, "jabber:x:data"); xmpp_stanza_set_attribute(x, "type", "result"); @@ -1434,15 +999,15 @@ void channel__fetch_mam(struct t_account *account, struct t_channel *channel, xmpp_stanza_t *field, *value, *text; { - field = xmpp_stanza_new(account->context); + field = xmpp_stanza_new(account.context); xmpp_stanza_set_name(field, "field"); xmpp_stanza_set_attribute(field, "var", "FORM_TYPE"); xmpp_stanza_set_attribute(field, "type", "hidden"); - value = xmpp_stanza_new(account->context); + value = xmpp_stanza_new(account.context); xmpp_stanza_set_name(value, "value"); - text = xmpp_stanza_new(account->context); + text = xmpp_stanza_new(account.context); xmpp_stanza_set_text(text, "urn:xmpp:mam:2"); xmpp_stanza_add_child(value, text); xmpp_stanza_release(text); @@ -1455,15 +1020,15 @@ void channel__fetch_mam(struct t_account *account, struct t_channel *channel, } { - field = xmpp_stanza_new(account->context); + field = xmpp_stanza_new(account.context); xmpp_stanza_set_name(field, "field"); xmpp_stanza_set_attribute(field, "var", "with"); - value = xmpp_stanza_new(account->context); + value = xmpp_stanza_new(account.context); xmpp_stanza_set_name(value, "value"); - text = xmpp_stanza_new(account->context); - xmpp_stanza_set_text(text, channel->id); + text = xmpp_stanza_new(account.context); + xmpp_stanza_set_text(text, id); xmpp_stanza_add_child(value, text); xmpp_stanza_release(text); @@ -1476,14 +1041,14 @@ void channel__fetch_mam(struct t_account *account, struct t_channel *channel, if (start) { - field = xmpp_stanza_new(account->context); + field = xmpp_stanza_new(account.context); xmpp_stanza_set_name(field, "field"); xmpp_stanza_set_attribute(field, "var", "start"); - value = xmpp_stanza_new(account->context); + value = xmpp_stanza_new(account.context); xmpp_stanza_set_name(value, "value"); - text = xmpp_stanza_new(account->context); + text = xmpp_stanza_new(account.context); char time[256] = {0}; strftime(time, sizeof(time), "%Y-%m-%dT%H:%M:%SZ", gmtime(start)); xmpp_stanza_set_text(text, time); @@ -1499,14 +1064,14 @@ void channel__fetch_mam(struct t_account *account, struct t_channel *channel, if (end) { - field = xmpp_stanza_new(account->context); + field = xmpp_stanza_new(account.context); xmpp_stanza_set_name(field, "field"); xmpp_stanza_set_attribute(field, "var", "end"); - value = xmpp_stanza_new(account->context); + value = xmpp_stanza_new(account.context); xmpp_stanza_set_name(value, "value"); - text = xmpp_stanza_new(account->context); + text = xmpp_stanza_new(account.context); char time[256] = {0}; strftime(time, sizeof(time), "%Y-%m-%dT%H:%M:%SZ", gmtime(end)); xmpp_stanza_set_text(text, time); @@ -1527,14 +1092,14 @@ void channel__fetch_mam(struct t_account *account, struct t_channel *channel, { xmpp_stanza_t *set, *set__after, *set__after__text; - set = xmpp_stanza_new(account->context); + set = xmpp_stanza_new(account.context); xmpp_stanza_set_name(set, "set"); xmpp_stanza_set_ns(set, "http://jabber.org/protocol/rsm"); - set__after = xmpp_stanza_new(account->context); + set__after = xmpp_stanza_new(account.context); xmpp_stanza_set_name(set__after, "after"); - set__after__text = xmpp_stanza_new(account->context); + set__after__text = xmpp_stanza_new(account.context); xmpp_stanza_set_text(set__after__text, after); xmpp_stanza_add_child(set__after, set__after__text); xmpp_stanza_release(set__after__text); @@ -1546,12 +1111,11 @@ void channel__fetch_mam(struct t_account *account, struct t_channel *channel, xmpp_stanza_release(set); } else - account__add_mam_query(account, channel, - xmpp_stanza_get_id(iq), start, end); + account.add_mam_query(id, xmpp_stanza_get_id(iq), { *start }, { *end }); xmpp_stanza_add_child(iq, query); xmpp_stanza_release(query); - xmpp_send(account->connection, iq); + xmpp_send(account.connection, iq); xmpp_stanza_release(iq); } diff --git a/channel.hh b/channel.hh index a9b6799..e031495 100644 --- a/channel.hh +++ b/channel.hh @@ -5,212 +5,165 @@ #pragma once #include -#include #include +#include +#include +#include +#include #define CHANNEL_MEMBERS_SPEAKING_LIMIT 128 -enum t_channel_type -{ - CHANNEL_TYPE_MUC, - CHANNEL_TYPE_PM, -}; - -enum t_channel_transport +namespace weechat { - CHANNEL_TRANSPORT_PLAIN, - CHANNEL_TRANSPORT_OMEMO, - CHANNEL_TRANSPORT_PGP, - CHANNEL_TRANSPORT_OTR, - CHANNEL_TRANSPORT_OX, -}; - -struct t_channel_typing -{ - union { - char *id; - struct t_user *user; + 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 { + char *id; + weechat::user *user; + }; + char *name; + time_t ts; + }; + + struct member + { + char *id; + + char *role; + char *affiliation; + }; + + struct topic + { + char *value = nullptr; + char *creator = nullptr; + time_t last_set = 0; + }; + + struct unread + { + char *id; + char *thread; + }; + + private: + topic topic; + + /* mpim */ + char *creator = nullptr; + 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 unreads; + + public: + std::string id; + std::string name; + enum chat_type type; + enum transport transport = weechat::channel::transport::PLAIN; + struct { + int enabled; + struct t_hashtable *devicelist_requests; + struct t_hashtable *bundle_requests; + } omemo; + struct { + int enabled = 1; + std::unordered_set ids; + } pgp; + struct { + int enabled = 0; + } otr; + struct t_weelist *members_speaking[2] = { nullptr }; + std::vector self_typings; + std::vector typings; + std::unordered_map members; + + public: + struct t_gui_buffer *buffer; + + public: + channel(weechat::account& account, enum chat_type type, const char *id, const char *name); + ~channel(); + + void set_transport(enum weechat::channel::transport transport, int force); + + struct t_gui_buffer *search_buffer(weechat::channel::chat_type type, + const char *name); + struct t_gui_buffer *create_buffer(weechat::channel::chat_type type, + const char *name); + + void add_nicklist_groups(); + + void member_speaking_add_to_list(const char *nick, int highlight); + 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); + + static int typing_cb(const void *pointer, void *data, int remaining_calls); + typing *typing_search(const char *id); + int add_typing(weechat::user *user); + + static int self_typing_cb(const void *pointer, void *data, int remaining_calls); + typing *self_typing_search(weechat::user *user); + int add_self_typing(weechat::user *user); + + static int hotlist_update_cb(const void *pointer, void *data, + const char *signal, const char *type_data, + void *signal_data); + + void free(channel *channel); + void free_all(); + + void update_topic(const char* title, const char* creator, int last_set); + void update_name(const char* name); + void update_purpose(const char* purpose, const char* creator, int last_set); + + member *add_member(const char *id, const char *client); + member *member_search(const char *id); + member *remove_member(const char *id, const char *reason); + + int send_message(std::string to, std::string body, + tl::optional oob = {}); + int send_message(const char *to, const char *body); + + void send_reads(); + void send_typing(weechat::user *user); + void send_paused(weechat::user *user); + + void fetch_mam(const char *id, time_t *start, time_t *end, const char *after); + + weechat::account& account; }; - char *name; - time_t ts; - - struct t_channel_typing *prev_typing; - struct t_channel_typing *next_typing; -}; - -struct t_channel_member -{ - char *id; - - char *role; - char *affiliation; - - struct t_channel_member *prev_member; - struct t_channel_member *next_member; -}; - -struct t_channel_topic -{ - char *value; - char *creator; - time_t last_set; -}; - -struct t_channel_unread -{ - char *id; - char *thread; -}; - -struct t_channel -{ - enum t_channel_type type; - char *id; - char *name; - enum t_channel_transport transport; - struct { - int enabled; - struct t_hashtable *devicelist_requests; - struct t_hashtable *bundle_requests; - } omemo; - struct { - int enabled; - std::unordered_set *ids; - } pgp; - struct { - int enabled; - } otr; - - struct t_channel_topic topic; - - /* 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; - char *buffer_as_string; - - struct t_channel *prev_channel; - struct t_channel *next_channel; -}; - -const char *channel__transport_name(enum t_channel_transport transport); - -void channel__set_transport(struct t_channel *channel, - enum t_channel_transport transport, int force); - -struct t_account *channel__account(struct t_channel *channel); - -struct t_channel *channel__search(struct t_account *account, - const char *id); - -void channel__add_nicklist_groups(struct t_account *account, - struct t_channel *channel); - -struct t_channel *channel__new(struct t_account *account, - enum t_channel_type type, - const char *id, const char *name); - -void channel__member_speaking_add(struct t_channel *channel, - 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, - void *signal_data); - -void channel__unread_free(struct t_channel_unread *unread); - -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, - const char* name); - -void channel__update_purpose(struct t_channel *channel, - const char* purpose, - const char* creator, - int last_set); - -struct t_channel_member *channel__add_member(struct t_account *account, - struct t_channel *channel, - const char *id, const char *client); - -struct t_channel_member *channel__member_search(struct t_channel *channel, - const char *id); - -struct t_channel_member *channel__remove_member(struct t_account *account, - struct t_channel *channel, - const char *id, const char *reason); - -int channel__send_message(struct t_account *account, struct t_channel *channel, - 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); +} diff --git a/command.cpp b/command.cpp index 0b603ae..3d6e36a 100644 --- a/command.cpp +++ b/command.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include "plugin.hh" @@ -24,27 +25,27 @@ #define MAM_DEFAULT_DAYS 2 #define STR(X) #X -void command__display_account(struct t_account *account) +void command__display_account(weechat::account *account) { int num_channels, num_pv; - if (account->is_connected) + if (account->connected()) { num_channels = 0;//xmpp_account_get_channel_count(account); num_pv = 0;//xmpp_account_get_pv_count(account); weechat_printf( NULL, " %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"), - account->name, + account->name.data(), weechat_color("reset"), weechat_color("chat_delimiters"), weechat_color("chat_server"), - account_jid(account), + account->jid().data(), weechat_color("chat_delimiters"), weechat_color("reset"), - (account->is_connected) ? _("connected") : _("not connected"), + (account->connected()) ? _("connected") : _("not connected"), weechat_color("chat_delimiters"), weechat_color("reset"), num_channels, @@ -57,11 +58,11 @@ void command__display_account(struct t_account *account) NULL, " %s%s%s %s(%s%s%s)%s", weechat_color("chat_server"), - account->name, + account->name.data(), weechat_color("reset"), weechat_color("chat_delimiters"), weechat_color("chat_server"), - account_jid(account), + account->jid().data(), weechat_color("chat_delimiters"), weechat_color("reset")); } @@ -70,7 +71,6 @@ void command__display_account(struct t_account *account) void command__account_list(int argc, char **argv) { int i, one_account_found; - struct t_account *ptr_account2; char *account_name = NULL; for (i = 2; i < argc; i++) @@ -80,13 +80,13 @@ void command__account_list(int argc, char **argv) } if (!account_name) { - if (!accounts.empty()) + if (!weechat::accounts.empty()) { weechat_printf(NULL, ""); 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 @@ -95,9 +95,9 @@ void command__account_list(int argc, char **argv) else { 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) { @@ -107,7 +107,7 @@ void command__account_list(int argc, char **argv) account_name); } one_account_found = 1; - command__display_account(ptr_account2.second); + command__display_account(&ptr_account2.second); } } 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) { - struct t_account *account; - - account = account__casesearch(name); - if (account) + weechat::account *account = nullptr; + if (weechat::account::search(account, name, true)) { weechat_printf( NULL, @@ -132,7 +130,10 @@ void command__add_account(const char *name, const char *jid, const char *passwor 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) { weechat_printf( @@ -144,19 +145,18 @@ void command__add_account(const char *name, const char *jid, const char *passwor account->name = strdup(name); if (jid) - account_option_set(account, ACCOUNT_OPTION_JID, strdup(jid)); + account->jid(jid); if (password) - account_option_set(account, ACCOUNT_OPTION_PASSWORD, strdup(password)); + account->password(password); if (jid) - account_option_set(account, ACCOUNT_OPTION_NICKNAME, - strdup(xmpp_jid_node(account->context, jid))); + account->nickname(xmpp_jid_node(account->context, jid)); weechat_printf( NULL, _("%s: account %s%s%s %s(%s%s%s)%s added"), WEECHAT_XMPP_PLUGIN_NAME, weechat_color("chat_server"), - account->name, + account->name.data(), weechat_color("reset"), weechat_color("chat_delimiters"), 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) return 0; - if (account->is_connected) + if (account->connected()) { weechat_printf( NULL, _("%s%s: already connected to account \"%s\"!"), weechat_prefix("error"), WEECHAT_XMPP_PLUGIN_NAME, - account->name); + account->name.data()); } - account__connect(account); + account->connect(); 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 i, nb_connect, connect_ok; - struct t_account *ptr_account; + weechat::account *ptr_account = nullptr; (void) buffer; (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++) { nb_connect++; - ptr_account = account__search(argv[i]); - if (ptr_account) + if (weechat::account::search(ptr_account, argv[i])) { 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; } -int command__disconnect_account(struct t_account *account) +int command__disconnect_account(weechat::account *account) { if (!account) return 0; - if (!account->is_connected) + if (!account->connected()) { weechat_printf( NULL, _("%s%s: not connected to account \"%s\"!"), weechat_prefix("error"), WEECHAT_XMPP_PLUGIN_NAME, - account->name); + account->name.data()); } - account__disconnect(account, 0); + account->disconnect(0); 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 i, nb_disconnect, disconnect_ok; - struct t_account *ptr_account; + weechat::account *ptr_account; (void) argc; (void) argv; @@ -277,7 +276,7 @@ int command__account_disconnect(struct t_gui_buffer *buffer, int argc, char **ar nb_disconnect = 0; if (argc < 2) { - struct t_channel *ptr_channel; + weechat::channel *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++) { nb_disconnect++; - ptr_account = account__search(argv[i]); - if (ptr_account) + if (weechat::account::search(ptr_account, argv[i])) { 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; - struct t_account *account; - char *account_name; - if (argc < 3) { weechat_printf( @@ -337,8 +332,9 @@ void command__account_delete(struct t_gui_buffer *buffer, int argc, char **argv) return; } - account = account__search(argv[2]); - if (!account) + weechat::account *account = nullptr; + + if (!weechat::account::search(account, argv[2])) { weechat_printf( NULL, @@ -347,7 +343,7 @@ void command__account_delete(struct t_gui_buffer *buffer, int argc, char **argv) argv[2], "xmpp delete"); return; } - if (account->is_connected) + if (account->connected()) { weechat_printf( NULL, @@ -358,17 +354,15 @@ void command__account_delete(struct t_gui_buffer *buffer, int argc, char **argv) return; } - account_name = strdup(account->name); - account__free(account); + std::string account_name = account->name; + weechat::accounts.erase(account->name); weechat_printf( NULL, _("%s: account %s%s%s has been deleted"), WEECHAT_XMPP_PLUGIN_NAME, weechat_color("chat_server"), - (account_name) ? account_name : "???", + !account_name.empty() ? account_name.data() : "???", weechat_color("reset")); - if (account_name) - free(account_name); } 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, char **argv, char **argv_eol) { - struct t_account *ptr_account = NULL; - struct t_channel *ptr_channel = NULL; + weechat::account *ptr_account = NULL; + weechat::channel *ptr_channel = NULL; xmpp_stanza_t *pres; char *jid, *pres_jid, *text; @@ -442,7 +436,7 @@ int command__enter(const void *pointer, void *data, if (!ptr_account) return WEECHAT_RC_ERROR; - if (!ptr_account->is_connected) + if (!ptr_account->connected()) { weechat_printf(buffer, _("%s%s: you are not connected to server"), @@ -464,19 +458,21 @@ int command__enter(const void *pointer, void *data, ptr_account->context, xmpp_jid_node(ptr_account->context, jid), xmpp_jid_domain(ptr_account->context, jid), - account_nickname(ptr_account) - && strlen(account_nickname(ptr_account)) - ? account_nickname(ptr_account) + ptr_account->nickname().data() + && strlen(ptr_account->nickname().data()) + ? ptr_account->nickname().data() : xmpp_jid_node(ptr_account->context, - account_jid(ptr_account))); + ptr_account->jid().data())); - ptr_channel = channel__search(ptr_account, jid); - if (!ptr_channel) - ptr_channel = channel__new(ptr_account, CHANNEL_TYPE_MUC, jid, jid); + if (!ptr_account->channels.contains(jid)) + ptr_channel = &ptr_account->channels.emplace( + std::make_pair(jid, weechat::channel { + *ptr_account, weechat::channel::chat_type::MUC, jid, jid + })).first->second; pres = xmpp_presence_new(ptr_account->context); 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_set_name(pres__x, "x"); @@ -491,7 +487,7 @@ int command__enter(const void *pointer, void *data, { text = argv_eol[2]; - channel__send_message(ptr_account, ptr_channel, jid, text); + ptr_channel->send_message(jid, text); } char buf[16]; @@ -511,13 +507,15 @@ int command__enter(const void *pointer, void *data, xmpp_jid_domain(ptr_account->context, buffer_jid), weechat_buffer_get_string(buffer, "localvar_nick")); - ptr_channel = channel__search(ptr_account, buffer_jid); - if (!ptr_channel) - ptr_channel = channel__new(ptr_account, CHANNEL_TYPE_MUC, buffer_jid, buffer_jid); + if (!ptr_account->channels.contains(buffer_jid)) + ptr_channel = &ptr_account->channels.emplace( + 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); 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_set_name(pres__x, "x"); @@ -536,8 +534,8 @@ int command__open(const void *pointer, void *data, struct t_gui_buffer *buffer, int argc, char **argv, char **argv_eol) { - struct t_account *ptr_account = NULL; - struct t_channel *ptr_channel = NULL; + weechat::account *ptr_account = NULL; + weechat::channel *ptr_channel = NULL; xmpp_stanza_t *pres; char *jid, *text; @@ -550,7 +548,7 @@ int command__open(const void *pointer, void *data, if (!ptr_account) return WEECHAT_RC_ERROR; - if (!ptr_account->is_connected) + if (!ptr_account->connected()) { weechat_printf(buffer, _("%s%s: you are not connected to server"), @@ -569,30 +567,33 @@ int command__open(const void *pointer, void *data, { jid = xmpp_jid_new( ptr_account->context, - xmpp_jid_node(ptr_account->context, ptr_channel->name), - xmpp_jid_domain(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.data()), jid); } pres = xmpp_presence_new(ptr_account->context); 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_stanza_release(pres); - struct t_channel *channel = channel__search(ptr_account, jid); - if (!channel) - channel = channel__new(ptr_account, CHANNEL_TYPE_PM, jid, jid); + auto channel = ptr_account->channels.find(jid); + if (channel == ptr_account->channels.end()) + channel = ptr_account->channels.emplace( + std::make_pair(jid, weechat::channel { + *ptr_account, weechat::channel::chat_type::PM, jid, jid + })).first; if (argc > 2) { text = argv_eol[2]; - channel__send_message(ptr_account, channel, jid, text); + channel->second.send_message(jid, text); } 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); 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, char **argv, char **argv_eol) { - struct t_account *ptr_account = NULL; - struct t_channel *ptr_channel = NULL; + weechat::account *ptr_account = NULL; + weechat::channel *ptr_channel = NULL; xmpp_stanza_t *message; char *text; @@ -629,7 +630,7 @@ int command__msg(const void *pointer, void *data, return WEECHAT_RC_OK; } - if (!ptr_account->is_connected) + if (!ptr_account->connected()) { weechat_printf(buffer, _("%s%s: you are not connected to server"), @@ -642,16 +643,17 @@ int command__msg(const void *pointer, void *data, text = argv_eol[1]; message = xmpp_message_new(ptr_account->context, - ptr_channel->type == CHANNEL_TYPE_MUC ? "groupchat" : "chat", - ptr_channel->name, NULL); + ptr_channel->type == weechat::channel::chat_type::MUC ? "groupchat" : "chat", + ptr_channel->name.data(), NULL); xmpp_message_set_body(message, text); xmpp_send(ptr_account->connection, 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, "xmpp_message,message,private,notify_none,self_msg,log1", "%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; @@ -661,8 +663,8 @@ int command__me(const void *pointer, void *data, struct t_gui_buffer *buffer, int argc, char **argv, char **argv_eol) { - struct t_account *ptr_account = NULL; - struct t_channel *ptr_channel = NULL; + weechat::account *ptr_account = NULL; + weechat::channel *ptr_channel = NULL; xmpp_stanza_t *message; char *text; @@ -684,7 +686,7 @@ int command__me(const void *pointer, void *data, return WEECHAT_RC_OK; } - if (!ptr_account->is_connected) + if (!ptr_account->connected()) { weechat_printf(buffer, _("%s%s: you are not connected to server"), @@ -697,17 +699,17 @@ int command__me(const void *pointer, void *data, text = argv_eol[0]; message = xmpp_message_new(ptr_account->context, - ptr_channel->type == CHANNEL_TYPE_MUC ? "groupchat" : "chat", - ptr_channel->name, NULL); + ptr_channel->type == weechat::channel::chat_type::MUC ? "groupchat" : "chat", + ptr_channel->name.data(), NULL); xmpp_message_set_body(message, text); xmpp_send(ptr_account->connection, 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, "xmpp_message,message,action,private,notify_none,self_msg,log1", "%s%s %s", 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 : ""); } @@ -718,8 +720,8 @@ int command__mam(const void *pointer, void *data, struct t_gui_buffer *buffer, int argc, char **argv, char **argv_eol) { - struct t_account *ptr_account = NULL; - struct t_channel *ptr_channel = NULL; + weechat::account *ptr_account = NULL; + weechat::channel *ptr_channel = NULL; int days; (void) pointer; @@ -761,7 +763,7 @@ int command__mam(const void *pointer, void *data, else ago->tm_mday -= MAM_DEFAULT_DAYS; 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; } @@ -770,8 +772,8 @@ int command__omemo(const void *pointer, void *data, struct t_gui_buffer *buffer, int argc, char **argv, char **argv_eol) { - struct t_account *ptr_account = NULL; - struct t_channel *ptr_channel = NULL; + weechat::account *ptr_account = NULL; + weechat::channel *ptr_channel = NULL; (void) pointer; (void) data; @@ -796,7 +798,7 @@ int command__omemo(const void *pointer, void *data, ptr_channel->omemo.enabled = 1; 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; } @@ -805,8 +807,8 @@ int command__pgp(const void *pointer, void *data, struct t_gui_buffer *buffer, int argc, char **argv, char **argv_eol) { - struct t_account *ptr_account = NULL; - struct t_channel *ptr_channel = NULL; + weechat::account *ptr_account = NULL; + weechat::channel *ptr_channel = NULL; char *keyid; (void) pointer; @@ -831,12 +833,12 @@ int command__pgp(const void *pointer, void *data, { keyid = argv_eol[1]; - ptr_channel->pgp.ids->emplace(keyid); + ptr_channel->pgp.ids.emplace(keyid); } ptr_channel->omemo.enabled = 0; 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; } @@ -845,8 +847,8 @@ int command__plain(const void *pointer, void *data, struct t_gui_buffer *buffer, int argc, char **argv, char **argv_eol) { - struct t_account *ptr_account = NULL; - struct t_channel *ptr_channel = NULL; + weechat::account *ptr_account = NULL; + weechat::channel *ptr_channel = NULL; (void) pointer; (void) data; @@ -871,7 +873,7 @@ int command__plain(const void *pointer, void *data, ptr_channel->omemo.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; } @@ -880,8 +882,8 @@ int command__xml(const void *pointer, void *data, struct t_gui_buffer *buffer, int argc, char **argv, char **argv_eol) { - struct t_account *ptr_account = NULL; - struct t_channel *ptr_channel = NULL; + weechat::account *ptr_account = NULL; + weechat::channel *ptr_channel = NULL; xmpp_stanza_t *stanza; (void) pointer; @@ -893,7 +895,7 @@ int command__xml(const void *pointer, void *data, if (!ptr_account) return WEECHAT_RC_ERROR; - if (!ptr_account->is_connected) + if (!ptr_account->connected()) { weechat_printf(buffer, _("%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, char **argv, char **argv_eol) { - struct t_account *ptr_account = NULL; - struct t_channel *ptr_channel = NULL; - xmpp_stanza_t *stanza; - (void) pointer; (void) data; + (void) buffer; + (void) argc; (void) argv; + (void) argv_eol; weechat_printf(nullptr, _("%s%s %s [%s]"), diff --git a/completion.cpp b/completion.cpp index 2e78130..39ade4d 100644 --- a/completion.cpp +++ b/completion.cpp @@ -18,11 +18,11 @@ #include "completion.hh" void completion__channel_nicks_add_speakers(struct t_gui_completion *completion, - struct t_account *account, - struct t_channel *channel, + weechat::account *account, + weechat::channel *channel, int highlight) { - struct t_user *user; + weechat::user *user; const char *member; 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)); if (member) { - user = user__search(account, member); + user = weechat::user::search(account, member); if (user) weechat_hook_completion_list_add(completion, 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_completion *completion) { - struct t_account *ptr_account; - struct t_channel *ptr_channel; - struct t_channel_member *ptr_member; - struct t_user *ptr_user; + weechat::account *ptr_account; + weechat::channel *ptr_channel; + weechat::user *ptr_user; /* make C compiler happy */ (void) pointer; @@ -68,30 +67,29 @@ int completion__channel_nicks_cb(const void *pointer, void *data, { switch (ptr_channel->type) { - case CHANNEL_TYPE_MUC: - case CHANNEL_TYPE_PM: - for (ptr_member = ptr_channel->members; ptr_member; - ptr_member = ptr_member->next_member) + case weechat::channel::chat_type::MUC: + case weechat::channel::chat_type::PM: + for (auto& ptr_member : ptr_channel->members) { - ptr_user = user__search(ptr_account, ptr_member->id); + ptr_user = weechat::user::search(ptr_account, ptr_member.second.id); if (ptr_user) weechat_hook_completion_list_add(completion, ptr_user->profile.display_name, 1, WEECHAT_LIST_POS_SORT); } /* 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(weechat::config::nick_completion::SMART_SPEAKERS)) { completion__channel_nicks_add_speakers(completion, ptr_account, ptr_channel, 0); } /* 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(weechat::config::nick_completion::SMART_SPEAKERS_HIGHLIGHTS)) { completion__channel_nicks_add_speakers(completion, ptr_account, ptr_channel, 1); } /* add self member at the end */ weechat_hook_completion_list_add(completion, - ptr_account->name, + ptr_account->name.data(), 1, WEECHAT_LIST_POS_END); break; } @@ -105,17 +103,15 @@ int completion__accounts_cb(const void *pointer, void *data, struct t_gui_buffer *buffer, struct t_gui_completion *completion) { - struct t_account *ptr_account; - /* make C compiler happy */ (void) pointer; (void) data; (void) completion_item; (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); } diff --git a/config.cpp b/config.cpp index 079cd2a..d1e6332 100644 --- a/config.cpp +++ b/config.cpp @@ -5,478 +5,150 @@ #include #include #include -#include +#include #include +#include "strophe.h" #include "plugin.hh" #include "account.hh" #include "config.hh" -struct t_config_file *config_file; - -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) +int account_read_cb(weechat::config_section& section, + const char *option_name, const char *value) { - (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) + if (!option_name) + return WEECHAT_CONFIG_READ_MEMORY_ERROR; + std::istringstream breadcrumbs(option_name); + std::string account_name, option_id; + std::getline(breadcrumbs, account_name, '.'); + std::getline(breadcrumbs, option_id, '.'); + if (account_name.empty()) + return WEECHAT_CONFIG_READ_MEMORY_ERROR; + + int rc = WEECHAT_CONFIG_READ_OK; + weechat::account* account = nullptr; + if (!weechat::account::search(account, account_name)) + account = &weechat::accounts.emplace( + std::piecewise_construct, std::forward_as_tuple(account_name), + std::forward_as_tuple(weechat::config::instance->file, account_name)).first->second; + if (account) { - const char *key = split[1]; - - (void) key; - (void) value; - } - - weechat_string_free_split(split); -} + auto options = { + std::ref(account->option_jid), + std::ref(account->option_password), + std::ref(account->option_tls), + std::ref(account->option_nickname), + std::ref(account->option_autoconnect), + std::ref(account->option_resource), + std::ref(account->option_status), + std::ref(account->option_pgp_path), + std::ref(account->option_pgp_keyid), + }; + + if (!account->reloading_from_config++) + { + for (auto option : options) + option.get().clear(); + } -void config__account_default_change_cb(const void *pointer, void *data, - struct t_config_option *option) -{ - (void) pointer; - (void) data; - (void) option; -} + account->reloading_from_config %= options.size(); -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; + if (option_id == "jid") rc |= (account->option_jid = value) == WEECHAT_CONFIG_OPTION_SET_ERROR; + if (option_id == "password") rc |= (account->option_password = value) == WEECHAT_CONFIG_OPTION_SET_ERROR; + if (option_id == "tls") rc |= (account->option_tls = value) == WEECHAT_CONFIG_OPTION_SET_ERROR; + if (option_id == "nickname") rc |= (account->option_nickname = value) == WEECHAT_CONFIG_OPTION_SET_ERROR; + 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; + if (option_id == "status") rc |= (account->option_status = value) == WEECHAT_CONFIG_OPTION_SET_ERROR; + if (option_id == "pgp_path") rc |= (account->option_pgp_path = value) == WEECHAT_CONFIG_OPTION_SET_ERROR; + if (option_id == "pgp_keyid") rc |= (account->option_pgp_keyid = value) == WEECHAT_CONFIG_OPTION_SET_ERROR; - 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; + if (!account->reloading_from_config) + { + bool ac_global = std::stoul(std::unique_ptr( + weechat_info_get("auto_connect", NULL)).get()); + bool ac_local = account->autoconnect(); + if (ac_local && ac_global) + account->connect(); + } } - - return new_option; -} - -void config__account_create_default_options(struct t_config_section *section) -{ - int i; - - for (i = 0; i < ACCOUNT_NUM_OPTIONS; i++) + else { - 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], + weechat_printf( 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) -{ - struct t_account *ptr_account; - int index_option, rc, i; - char *pos_option, *account_name; - - (void) pointer; - (void) data; - (void) config_file; - (void) section; - - rc = WEECHAT_CONFIG_OPTION_SET_ERROR; - - if (option_name) - { - pos_option = const_cast(strrchr(option_name, '.')); - if (pos_option) - { - account_name = weechat_strndup(option_name, - pos_option - option_name); - pos_option++; - if (account_name) - { - index_option = account__search_option(pos_option); - if (index_option >= 0) - { - ptr_account = account__search(account_name); - if (!ptr_account) - ptr_account = account__alloc(account_name); - if (ptr_account) - { - if (!ptr_account->reloading_from_config++) - { - for (i = 0; i < ACCOUNT_NUM_OPTIONS; i++) - { - weechat_config_option_set( - ptr_account->options[i], NULL, 1); - } - } - ptr_account->reloading_from_config %= - ACCOUNT_NUM_OPTIONS; - rc = weechat_config_option_set( - ptr_account->options[index_option], value, 1); - if (!ptr_account->reloading_from_config) - { - const char *ac_global = weechat_info_get("auto_connect", NULL); - int ac_local = weechat_config_boolean( - ptr_account->options[ACCOUNT_OPTION_AUTOCONNECT]); - if (ac_local && (strcmp(ac_global, "1") == 0)) - account__connect(ptr_account); - } - } - else - { - weechat_printf( - NULL, - _("%s%s: error adding account \"%s\""), - weechat_prefix("error"), WEECHAT_XMPP_PLUGIN_NAME, - account_name); - } - } - free(account_name); - } - } + _("%s%s: error adding account \"%s\""), + weechat_prefix("error"), WEECHAT_XMPP_PLUGIN_NAME, + account_name.data()); } - if (rc == WEECHAT_CONFIG_OPTION_SET_ERROR) + if (rc != WEECHAT_CONFIG_READ_OK) { weechat_printf( NULL, _("%s%s: error creating account option \"%s\""), weechat_prefix("error"), WEECHAT_XMPP_PLUGIN_NAME, option_name); } - return rc; } -int config__account_write_cb(const void *pointer, void *data, - struct t_config_file *config_file, - const char *section_name) +int account_write_cb(weechat::config_section& section, const char *section_name) { - struct t_account *ptr_account; - int i; - - (void) pointer; - (void) data; - - if (!weechat_config_write_line(config_file, section_name, NULL)) + if (!weechat_config_write_line(section.file, section_name, NULL)) 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, - ptr_account.second->options[i])) - return WEECHAT_CONFIG_WRITE_ERROR; - } + if (!account.second.write()) + return WEECHAT_CONFIG_WRITE_ERROR; } return WEECHAT_CONFIG_WRITE_OK; } -int config__reload (const void *pointer, void *data, - struct t_config_file *config_file) +int config_reload(weechat::config_file &file) { - (void) pointer; - (void) data; - - weechat_config_section_free_options(config_section_account_default); - weechat_config_section_free_options(config_section_account); - account__free_all(); + //weechat_config_section_free_options(file.configuration.section_account_default); + //weechat_config_section_free_options(file.configuration.section_account); + weechat::accounts.clear(); - return weechat_config_reload(config_file); + return weechat_config_reload(file); } -int config__init() +bool weechat::config_account::write() { - struct t_config_section *ptr_section; - - config_file = weechat_config_new(WEECHAT_XMPP_CONFIG_NAME, - &config__reload, NULL, NULL); - - if(!config_file) - return 0; - - ptr_section = weechat_config_new_section( - config_file, "look", - 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 ( - config_file, ptr_section, - "nick_completion_smart", "integer", - N_("smart completion for nicks (completes first with last speakers): " - "speakers = all speakers (including highlights), " - "speakers_highlights = only speakers with highlight"), - "off|speakers|speakers_highlights", 0, 0, "speakers", NULL, 0, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); - - 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; + if (!option_jid.write()) return false; + if (!option_password.write()) return false; + if (!option_tls.write()) return false; + if (!option_nickname.write()) return false; + if (!option_autoconnect.write()) return false; + if (!option_resource.write()) return false; + if (!option_status.write()) return false; + if (!option_pgp_path.write()) return false; + if (!option_pgp_keyid.write()) return false; + return true; } -int config__read() +weechat::config::config() + : file{*this, "xmpp", &config_reload} + , section_account_default{file, "account_default", 0, 0, {}, {}, {}, {}, {}} + , 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_highlights = only speakers with highlight"), + "off|speakers|speakers_highlights", 0, 0, + "speakers", nullptr, false, + {}, {}, {}}} { - int rc; - - rc = weechat_config_read(config_file); - - return rc; } -int config__write() -{ - return weechat_config_write(config_file); -} +weechat::config::~config() {} -void config__free() -{ -} +tl::optional 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(); } diff --git a/config.hh b/config.hh index bb33ae7..9b16688 100644 --- a/config.hh +++ b/config.hh @@ -4,52 +4,362 @@ #pragma once -#define WEECHAT_XMPP_CONFIG_NAME "xmpp" +#include +#include +#include +#include +#include +#include +#include +#include "fmt/core.h" +#include "plugin.hh" -enum t_config_nick_completion +using namespace std::placeholders; + +namespace weechat { - CONFIG_NICK_COMPLETION_SMART_OFF = 0, - CONFIG_NICK_COMPLETION_SMART_SPEAKERS, - CONFIG_NICK_COMPLETION_SMART_SPEAKERS_HIGHLIGHTS, -}; - -extern struct t_config_file *config_file; - -extern struct t_config_section *config_section_account_default; -extern struct t_config_section *config_section_account; - -extern struct t_config_option *config_look_nick_completion_smart; - -extern struct t_config_option *config_account_default[]; - -int config__account_check_value_cb(const void *pointer, void *data, - struct t_config_option *option, - const char *value); - -void config__account_change_cb(const void *pointer, void *data, - struct t_config_option *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); - -extern int config__init(); -extern int config__read(); -extern int config__write(); -extern void config__free(); + enum class tls_policy + { + disable = 0, + normal, + trust, + }; + + class config; + struct config_file; + struct config_section; + struct config_option; + + struct config_breadcrumb { + config_breadcrumb(std::string name) + : name(name), parent(tl::nullopt) {} + + config_breadcrumb(std::string name, config_breadcrumb& parent) + : name(name), parent(parent) {} + + std::string name; + tl::optional parent; + }; + + struct config_free { void operator() (struct t_config_file *ptr) { weechat_config_free(ptr); } }; + struct config_file : public std::unique_ptr, public config_breadcrumb { + config_file(struct t_config_file *ptr, config& config, std::string name) + : std::unique_ptr(ptr) + , config_breadcrumb(name) + , configuration(config) { + if (ptr == nullptr) throw std::runtime_error("weechat_config_new"); + } + config_file(config& config, std::string name, std::function cb_reload) + : config_file(weechat_config_new( + name.data(), + [](const void *, void *data, struct t_config_file *config_file) { + auto& file = *reinterpret_cast(data); + if (file != config_file) throw std::invalid_argument("file != config_file"); + if (!file.reload) return 1; + return file.reload() ? 1 : 0; + }, nullptr, this), config, name) { + this->reload = std::bind(cb_reload, std::ref(*this)); + } + operator struct t_config_file *() { return get(); } + std::function reload; + config& configuration; + std::unordered_map 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, public config_breadcrumb { + config_section(struct t_config_section *ptr, config_file& file, std::string name) + : std::unique_ptr(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 cb_read, + std::function cb_write, + std::function cb_write_default, + std::function cb_create_option, + std::function 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(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(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(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(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(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 read; + std::function write; + std::function write_default; + std::function create_option; + std::function delete_option; + config_file& file; + std::unordered_map options; + }; + + struct config_option_free { void operator() (struct t_config_option *ptr) { weechat_config_option_free(ptr); } }; + struct config_option : public std::unique_ptr, public config_breadcrumb { + config_option(struct t_config_option *ptr, config_section& section, std::string name) + : std::unique_ptr(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 cb_check_value, + std::function cb_change, + std::function 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(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(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(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 check_value; + std::function on_changed; + std::function 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 instance; + + public: + static bool init(); + static bool read(); + static bool write(); + }; +} diff --git a/connection.cpp b/connection.cpp index e8d6db8..2e6217b 100644 --- a/connection.cpp +++ b/connection.cpp @@ -1,7 +1,9 @@ -// This Source Code Form is subject to the terms of the Mozilla Public +// 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/. +#include +#include #include #include #include @@ -11,7 +13,6 @@ #include #include #include -#include #include #include "plugin.hh" @@ -29,70 +30,50 @@ extern "C" { #include "diff/diff.h" } -void connection__init() +void weechat::connection::init() { srand(time(NULL)); - xmpp_initialize(); + libstrophe::initialize(); } -int connection__version_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) +bool weechat::connection::version_handler(xmpp_stanza_t *stanza) { - xmpp_stanza_t *reply, *query, *name, *version, *text; - const char *ns; - struct t_account *account = (struct t_account *)userdata; const char *weechat_name = "weechat"; - char *weechat_version = weechat_info_get("version", NULL); + std::unique_ptr weechat_version(weechat_info_get("version", NULL)); weechat_printf(NULL, "Received version request from %s", xmpp_stanza_get_from(stanza)); - reply = xmpp_stanza_reply(stanza); - xmpp_stanza_set_type(reply, "result"); + auto reply = libstrophe::stanza::reply(stanza) + .set_type("result"); - query = xmpp_stanza_new(account->context); - xmpp_stanza_set_name(query, "query"); - ns = xmpp_stanza_get_ns(xmpp_stanza_get_children(stanza)); - if (ns) { - xmpp_stanza_set_ns(query, ns); + auto query = libstrophe::stanza(account.context) + .set_name("query"); + if (const char *ns = xmpp_stanza_get_ns(xmpp_stanza_get_children(stanza)); ns) { + query.set_ns(ns); } - name = xmpp_stanza_new(account->context); - xmpp_stanza_set_name(name, "name"); - xmpp_stanza_add_child(query, name); - xmpp_stanza_release(name); - - text = xmpp_stanza_new(account->context); - xmpp_stanza_set_text(text, weechat_name); - xmpp_stanza_add_child(name, text); - xmpp_stanza_release(text); + query.add_child(libstrophe::stanza(account.context) + .set_name("name") + .add_child(libstrophe::stanza(account.context) + .set_text(weechat_name))); + query.add_child(libstrophe::stanza(account.context) + .set_name("version") + .add_child(libstrophe::stanza(account.context) + .set_text(weechat_version.get()))); - version = xmpp_stanza_new(account->context); - xmpp_stanza_set_name(version, "version"); - xmpp_stanza_add_child(query, version); - xmpp_stanza_release(version); + reply.add_child(query); - text = xmpp_stanza_new(account->context); - xmpp_stanza_set_text(text, weechat_version); - xmpp_stanza_add_child(version, text); - xmpp_stanza_release(text); + account.connection.send(reply); - xmpp_stanza_add_child(reply, query); - xmpp_stanza_release(query); - - xmpp_send(conn, reply); - xmpp_stanza_release(reply); - if (weechat_version) - free(weechat_version); - - return 1; + return true; } -int connection__presence_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) +bool weechat::connection::presence_handler(xmpp_stanza_t *stanza) { - struct t_account *account = reinterpret_cast(userdata); - struct t_user *user; - struct t_channel *channel; + weechat::user *user; + weechat::channel *channel; - auto binding = xml::presence(account->context, stanza); + auto binding = xml::presence(account.context, stanza); if (!binding.from) return 1; @@ -104,23 +85,28 @@ int connection__presence_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void clientid = fmt::format("{}#{}", node, ver); - xmpp_send(conn, stanza::iq() + account.connection.send(stanza::iq() .from(binding.to ? binding.to->full : "") .to(binding.from .transform([](auto& x) { return x.full; }) .value_or(std::string())) .type("get") - .id(stanza::uuid(account->context)) + .id(stanza::uuid(account.context)) .xep0030() .query() - .build(account->context) + .build(account.context) .get()); } - channel = channel__search(account, binding.from->bare.data()); + channel = account.channels.contains(binding.from->bare.data()) + ? &account.channels.find(binding.from->bare.data())->second : nullptr; if (!(binding.type && *binding.type == "unavailable") && !binding.muc_user() && !channel) { - channel = channel__new(account, CHANNEL_TYPE_PM, binding.from->bare.data(), binding.from->bare.data()); + const char* jid = binding.from->bare.data(); + channel = &account.channels.emplace( + std::make_pair(jid, weechat::channel { + account, weechat::channel::chat_type::MUC, jid, jid + })).first->second; } if (binding.type && *binding.type == "error" && channel) @@ -198,9 +184,9 @@ int connection__presence_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void std::string affiliation(item.affiliation ? xep0045::format_affiliation(*item.affiliation) : ""); std::string jid = item.target ? item.target->full : clientid; - user = user__search(account, binding.from->full.data()); + user = weechat::user::search(&account, binding.from->full.data()); if (!user) - user = user__new(account, binding.from->full.data(), + user = new weechat::user(&account, binding.from->full.data(), channel && binding.from->bare.data() == channel->id ? (binding.from->resource.size() ? binding.from->resource.data() : "") : binding.from->full.data()); @@ -218,26 +204,26 @@ int connection__presence_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void { if (auto signature = binding.signature()) { - user->profile.pgp_id = pgp__verify(channel->buffer, account->pgp, signature->data()); - if (channel->type != CHANNEL_TYPE_MUC) - channel->pgp.ids->emplace(user->profile.pgp_id); + user->profile.pgp_id = account.pgp.verify(channel->buffer, signature->data()); + if (channel->type != weechat::channel::chat_type::MUC) + channel->pgp.ids.emplace(user->profile.pgp_id); } if (weechat_strcasecmp(role.data(), "none") == 0) - channel__remove_member(account, channel, binding.from->full.data(), status ? status->data() : nullptr); + channel->remove_member(binding.from->full.data(), status ? status->data() : nullptr); else - channel__add_member(account, channel, binding.from->full.data(), jid.data()); + channel->add_member(binding.from->full.data(), jid.data()); } } } else { - user = user__search(account, binding.from->full.data()); + user = user::search(&account, binding.from->full.data()); if (!user) - user = user__new(account, binding.from->full.data(), - channel && binding.from->bare.data() == channel->id - ? (binding.from->resource.size() ? binding.from->resource.data() : "") - : binding.from->full.data()); + user = new weechat::user(&account, binding.from->full.data(), + channel && binding.from->bare.data() == channel->id + ? (binding.from->resource.size() ? binding.from->resource.data() : "") + : binding.from->full.data()); auto status = binding.status(); auto show = binding.show(); auto idle = binding.idle_since(); @@ -249,34 +235,33 @@ int connection__presence_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void user->profile.affiliation = NULL; if (channel) { - if (auto signature = binding.signature(); signature && account->pgp) + if (auto signature = binding.signature(); signature) { - user->profile.pgp_id = pgp__verify(channel->buffer, account->pgp, signature->data()); - if (channel->type != CHANNEL_TYPE_MUC) - channel->pgp.ids->emplace(user->profile.pgp_id); + user->profile.pgp_id = account.pgp.verify(channel->buffer, signature->data()); + if (channel->type != weechat::channel::chat_type::MUC) + channel->pgp.ids.emplace(user->profile.pgp_id); } if (user->profile.role) - channel__remove_member(account, channel, binding.from->full.data(), status ? status->data() : nullptr); + channel->remove_member(binding.from->full.data(), status ? status->data() : nullptr); else - channel__add_member(account, channel, binding.from->full.data(), clientid.data()); + channel->add_member(binding.from->full.data(), clientid.data()); } } - return 1; + return true; } -int connection__message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) +bool weechat::connection::message_handler(xmpp_stanza_t *stanza) { - struct t_account *account = (struct t_account *)userdata; - struct t_channel *channel, *parent_channel; - xmpp_stanza_t *x, *body, *delay, *topic, *replace, *request, *markable, *composing, *sent, *received, *result, *forwarded, *event, *items, *item, *list, *device, *encrypted, **children; + weechat::channel *channel, *parent_channel; + xmpp_stanza_t *x, *body, *delay, *topic, *replace, *request, *markable, *composing, *sent, *received, *result, *forwarded, *event, *items, *item, *list, *device, *encrypted; const char *type, *from, *nick, *from_bare, *to, *to_bare, *id, *thread, *replace_id, *timestamp; char *text, *intext, *difftext = NULL, *cleartext = NULL; struct tm time = {0}; time_t date = 0; - auto binding = xml::message(account->context, stanza); + auto binding = xml::message(account.context, stanza); body = xmpp_stanza_get_child_by_name(stanza, "body"); if (body == NULL) { @@ -290,19 +275,20 @@ int connection__message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void * from = xmpp_stanza_get_from(stanza); if (from == NULL) return 1; - from_bare = xmpp_jid_bare(account->context, from); - from = xmpp_jid_resource(account->context, from); - channel = channel__search(account, from_bare); + from_bare = xmpp_jid_bare(account.context, from); + from = xmpp_jid_resource(account.context, from); + channel = account.channels.contains(from_bare) + ? &account.channels.find(from_bare)->second : nullptr; if (!channel) { if (weechat_strcasecmp(type, "groupchat") == 0) - channel = channel__new(account, CHANNEL_TYPE_MUC, from_bare, from_bare); + channel = new weechat::channel(account, weechat::channel::chat_type::MUC, from_bare, from_bare); else - channel = channel__new(account, CHANNEL_TYPE_PM, from_bare, from_bare); + channel = new weechat::channel(account, weechat::channel::chat_type::PM, from_bare, from_bare); } - channel__update_topic(channel, intext ? intext : "", from, 0); + channel->update_topic(intext ? intext : "", from, 0); if (intext != NULL) - xmpp_free(account->context, intext); + xmpp_free(account.context, intext); } composing = xmpp_stanza_get_child_by_name_and_ns( @@ -312,20 +298,21 @@ int connection__message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void * from = xmpp_stanza_get_from(stanza); if (from == NULL) return 1; - from_bare = xmpp_jid_bare(account->context, from); - nick = xmpp_jid_resource(account->context, from); - channel = channel__search(account, from_bare); + from_bare = xmpp_jid_bare(account.context, from); + nick = xmpp_jid_resource(account.context, from); + channel = account.channels.contains(from_bare) + ? &account.channels.find(from_bare)->second : nullptr; if (!channel) return 1; - struct t_user *user = user__search(account, from); + auto user = user::search(&account, from); if (!user) - user = user__new(account, from, - weechat_strcasecmp(from_bare, channel->id) == 0 - ? nick : from); - channel__add_typing(channel, user); + user = new weechat::user(&account, from, + weechat_strcasecmp(from_bare, channel->id.data()) == 0 + ? nick : from); + channel->add_typing(user); weechat_printf(channel->buffer, "...\t%s%s typing", weechat_color("gray"), - channel->type == CHANNEL_TYPE_MUC ? nick : from); + channel->type == weechat::channel::chat_type::MUC ? nick : from); } sent = xmpp_stanza_get_child_by_name_and_ns( @@ -341,7 +328,7 @@ int connection__message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void * if ((sent || received) && forwarded != NULL) { xmpp_stanza_t *message = xmpp_stanza_get_children(forwarded); - return connection__message_handler(conn, message, userdata); + return message_handler(message); } result = xmpp_stanza_get_child_by_name_and_ns( @@ -360,7 +347,7 @@ int connection__message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void * forwarded, "delay", "urn:xmpp:delay"); if (delay != NULL) xmpp_stanza_add_child_ex(message, xmpp_stanza_copy(delay), 0); - int ret = connection__message_handler(conn, message, userdata); + int ret = message_handler(message); xmpp_stanza_release(message); return ret; } @@ -388,13 +375,13 @@ int connection__message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void * item, "list", "eu.siacs.conversations.axolotl"); if (list) { - if (account->omemo) + if (account.omemo) { - account->omemo.handle_devicelist( - from ? from : account_jid(account), items); + account.omemo.handle_devicelist( + from ? from : account.jid().data(), items); } - children = (xmpp_stanza_t**)malloc(sizeof(*children) * (3 + 1)); + auto children = std::unique_ptr(new xmpp_stanza_t*[3 + 1]); for (device = xmpp_stanza_get_children(list); device; device = xmpp_stanza_get_next(device)) @@ -412,18 +399,18 @@ int connection__message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void * children[1] = NULL; children[0] = - stanza__iq_pubsub_items(account->context, NULL, + stanza__iq_pubsub_items(account.context, NULL, strdup(bundle_node)); children[0] = - stanza__iq_pubsub(account->context, NULL, children, + stanza__iq_pubsub(account.context, NULL, children.get(), with_noop("http://jabber.org/protocol/pubsub")); - char *uuid = xmpp_uuid_gen(account->context); + char *uuid = xmpp_uuid_gen(account.context); children[0] = - stanza__iq(account->context, NULL, children, NULL, uuid, + stanza__iq(account.context, NULL, children.get(), NULL, uuid, strdup(to), strdup(from), strdup("get")); - xmpp_free(account->context, uuid); + xmpp_free(account.context, uuid); - xmpp_send(conn, children[0]); + account.connection.send(children[0]); xmpp_stanza_release(children[0]); } } @@ -440,11 +427,11 @@ int connection__message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void * from = xmpp_stanza_get_from(stanza); if (from == NULL) return 1; - from_bare = xmpp_jid_bare(account->context, from); + from_bare = xmpp_jid_bare(account.context, from); to = xmpp_stanza_get_to(stanza); if (to == NULL) - to = account_jid(account); - to_bare = to ? xmpp_jid_bare(account->context, to) : NULL; + to = account.jid().data(); + to_bare = to ? xmpp_jid_bare(account.context, to) : NULL; id = xmpp_stanza_get_id(stanza); thread = xmpp_stanza_get_attribute(stanza, "thread"); replace = xmpp_stanza_get_child_by_name_and_ns(stanza, "replace", @@ -455,34 +442,33 @@ int connection__message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void * markable = xmpp_stanza_get_child_by_name_and_ns(stanza, "markable", "urn:xmpp:chat-markers:0"); - const char *channel_id = weechat_strcasecmp(account_jid(account), from_bare) - == 0 ? to_bare : from_bare; - parent_channel = channel__search(account, channel_id); - const char *pm_id = weechat_strcasecmp(account_jid(account), from_bare) - == 0 ? to : from; + const char *channel_id = account.jid() == from_bare ? to_bare : from_bare; + parent_channel = account.channels.contains(channel_id) + ? &account.channels.find(channel_id)->second : nullptr; + const char *pm_id = account.jid() == from_bare ? to : from; channel = parent_channel; if (!channel) - channel = channel__new(account, + channel = new weechat::channel(account, weechat_strcasecmp(type, "groupchat") == 0 - ? CHANNEL_TYPE_MUC : CHANNEL_TYPE_PM, + ? weechat::channel::chat_type::MUC : weechat::channel::chat_type::PM, channel_id, channel_id); - if (channel && channel->type == CHANNEL_TYPE_MUC + if (channel && channel->type == weechat::channel::chat_type::MUC && weechat_strcasecmp(type, "chat") == 0) - channel = channel__new(account, CHANNEL_TYPE_PM, + channel = new weechat::channel(account, weechat::channel::chat_type::PM, pm_id, pm_id); if (id && (markable || request)) { - struct t_channel_unread *unread = (struct t_channel_unread *)malloc(sizeof(struct t_channel_unread)); + auto unread = new weechat::channel::unread(); unread->id = strdup(id); unread->thread = thread ? strdup(thread) : NULL; - xmpp_stanza_t *message = xmpp_message_new(account->context, NULL, - channel->id, NULL); + xmpp_stanza_t *message = xmpp_message_new(account.context, NULL, + channel->id.data(), NULL); if (request) { - xmpp_stanza_t *message__received = xmpp_stanza_new(account->context); + xmpp_stanza_t *message__received = xmpp_stanza_new(account.context); xmpp_stanza_set_name(message__received, "received"); xmpp_stanza_set_ns(message__received, "urn:xmpp:receipts"); xmpp_stanza_set_id(message__received, unread->id); @@ -493,7 +479,7 @@ int connection__message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void * if (markable) { - xmpp_stanza_t *message__received = xmpp_stanza_new(account->context); + xmpp_stanza_t *message__received = xmpp_stanza_new(account.context); xmpp_stanza_set_name(message__received, "received"); xmpp_stanza_set_ns(message__received, "urn:xmpp:chat-markers:0"); xmpp_stanza_set_id(message__received, unread->id); @@ -504,10 +490,10 @@ int connection__message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void * if (unread->thread) { - xmpp_stanza_t *message__thread = xmpp_stanza_new(account->context); + xmpp_stanza_t *message__thread = xmpp_stanza_new(account.context); xmpp_stanza_set_name(message__thread, "thread"); - xmpp_stanza_t *message__thread__text = xmpp_stanza_new(account->context); + xmpp_stanza_t *message__thread__text = xmpp_stanza_new(account.context); xmpp_stanza_set_text(message__thread__text, unread->thread); xmpp_stanza_add_child(message__thread, message__thread__text); xmpp_stanza_release(message__thread__text); @@ -516,21 +502,19 @@ int connection__message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void * xmpp_stanza_release(message__thread); } - xmpp_send(account->connection, message); + xmpp_send(account.connection, message); xmpp_stanza_release(message); - if (!channel->unreads) - channel->unreads = weechat_list_new(); - weechat_list_add(channel->unreads, unread->id, WEECHAT_LIST_POS_END, unread); + channel->unreads.push_back(*unread); } encrypted = xmpp_stanza_get_child_by_name_and_ns(stanza, "encrypted", "eu.siacs.conversations.axolotl"); x = xmpp_stanza_get_child_by_name_and_ns(stanza, "x", "jabber:x:encrypted"); intext = xmpp_stanza_get_text(body); - if (encrypted && account->omemo) + if (encrypted && account.omemo) { - cleartext = account->omemo.decode(account, from_bare, encrypted); + cleartext = account.omemo.decode(&account, from_bare, encrypted); if (!cleartext) { weechat_printf_date_tags(channel->buffer, 0, "notify_none", "%s%s (%s)", @@ -541,8 +525,8 @@ int connection__message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void * if (x) { char *ciphertext = xmpp_stanza_get_text(x); - cleartext = pgp__decrypt(channel->buffer, account->pgp, ciphertext); - xmpp_free(account->context, ciphertext); + cleartext = account.pgp.decrypt(channel->buffer, ciphertext); + xmpp_free(account.context, ciphertext); } text = cleartext ? cleartext : intext; @@ -687,16 +671,14 @@ int connection__message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void * nick = from; if (weechat_strcasecmp(type, "groupchat") == 0) { - nick = weechat_strcasecmp(channel->name, - xmpp_jid_bare(account->context, - from)) == 0 - ? xmpp_jid_resource(account->context, from) + nick = channel->name == xmpp_jid_bare(account.context, from) + ? xmpp_jid_resource(account.context, from) : from; } - else if (parent_channel && parent_channel->type == CHANNEL_TYPE_MUC) + else if (parent_channel && parent_channel->type == weechat::channel::chat_type::MUC) { - nick = weechat_strcasecmp(channel->name, from) == 0 - ? xmpp_jid_resource(account->context, from) + nick = channel->name == from + ? xmpp_jid_resource(account.context, from) : from; } delay = xmpp_stanza_get_child_by_name_and_ns(stanza, "delay", "urn:xmpp:delay"); @@ -723,7 +705,7 @@ int connection__message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void * weechat_string_dyn_concat(dyn_tags, id, -1); } - if (channel->type == CHANNEL_TYPE_PM) + if (channel->type == weechat::channel::chat_type::PM) weechat_string_dyn_concat(dyn_tags, ",private", -1); if (weechat_string_match(text, "/me *", 0)) weechat_string_dyn_concat(dyn_tags, ",xmpp_action", -1); @@ -736,55 +718,55 @@ int connection__message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void * if (date != 0 || encrypted) weechat_string_dyn_concat(dyn_tags, ",notify_none", -1); - else if (channel->type == CHANNEL_TYPE_PM - && weechat_strcasecmp(from_bare, account_jid(account)) != 0) + else if (channel->type == weechat::channel::chat_type::PM + && from_bare != account.jid()) weechat_string_dyn_concat(dyn_tags, ",notify_private", -1); else weechat_string_dyn_concat(dyn_tags, ",notify_message,log1", -1); const char *edit = replace ? "* " : ""; // Losing which message was edited, sadly - if (x && text == cleartext && channel->transport != CHANNEL_TRANSPORT_PGP) + if (x && text == cleartext && channel->transport != weechat::channel::transport::PGP) { - channel->transport = CHANNEL_TRANSPORT_PGP; + channel->transport = weechat::channel::transport::PGP; weechat_printf_date_tags(channel->buffer, date, NULL, "%s%sTransport: %s", weechat_prefix("network"), weechat_color("gray"), - channel__transport_name(channel->transport)); + channel::transport_name(channel->transport)); } - else if (!x && text == intext && channel->transport != CHANNEL_TRANSPORT_PLAIN) + else if (!x && text == intext && channel->transport != weechat::channel::transport::PLAIN) { - channel->transport = CHANNEL_TRANSPORT_PLAIN; + channel->transport = weechat::channel::transport::PLAIN; weechat_printf_date_tags(channel->buffer, date, NULL, "%s%sTransport: %s", weechat_prefix("network"), weechat_color("gray"), - channel__transport_name(channel->transport)); + channel::transport_name(channel->transport)); } - if (channel_id == from_bare && strcmp(to, channel->id) == 0) + if (channel_id == from_bare && to == channel->id) weechat_printf_date_tags(channel->buffer, date, *dyn_tags, "%s%s\t[to %s]: %s", - edit, user__as_prefix_raw(account, nick), + edit, user::as_prefix_raw(&account, nick).data(), to, difftext ? difftext : text ? text : ""); else if (weechat_string_match(text, "/me *", 0)) weechat_printf_date_tags(channel->buffer, date, *dyn_tags, "%s%s\t%s %s", - edit, weechat_prefix("action"), user__as_prefix_raw(account, nick), + edit, weechat_prefix("action"), user::as_prefix_raw(&account, nick).data(), difftext ? difftext+4 : text ? text+4 : ""); else weechat_printf_date_tags(channel->buffer, date, *dyn_tags, "%s%s\t%s", - edit, user__as_prefix_raw(account, nick), + edit, user::as_prefix_raw(&account, nick).data(), difftext ? difftext : text ? text : ""); weechat_string_dyn_free(dyn_tags, 1); if (intext) - xmpp_free(account->context, intext); + xmpp_free(account.context, intext); if (difftext) free(difftext); if (cleartext) free(cleartext); - return 1; + return true; } -xmpp_stanza_t *connection__get_caps(xmpp_stanza_t *reply, struct t_account *account, char **hash) +xmpp_stanza_t *weechat::connection::get_caps(xmpp_stanza_t *reply, char **hash) { - xmpp_stanza_t *query = xmpp_stanza_new(account->context); + xmpp_stanza_t *query = xmpp_stanza_new(account.context); xmpp_stanza_set_name(query, "query"); xmpp_stanza_set_ns(query, "http://jabber.org/protocol/disco#info"); @@ -795,7 +777,7 @@ xmpp_stanza_t *connection__get_caps(xmpp_stanza_t *reply, struct t_account *acco weechat_string_dyn_concat(serial, client_name, -1); weechat_string_dyn_concat(serial, "<", -1); - xmpp_stanza_t *identity = xmpp_stanza_new(account->context); + xmpp_stanza_t *identity = xmpp_stanza_new(account.context); xmpp_stanza_set_name(identity, "identity"); xmpp_stanza_set_attribute(identity, "category", "client"); xmpp_stanza_set_attribute(identity, "name", client_name); @@ -807,7 +789,7 @@ xmpp_stanza_t *connection__get_caps(xmpp_stanza_t *reply, struct t_account *acco xmpp_stanza_t *feature = NULL; #define FEATURE(NS) \ - feature = xmpp_stanza_new(account->context); \ + feature = xmpp_stanza_new(account.context); \ xmpp_stanza_set_name(feature, "feature"); \ xmpp_stanza_set_attribute(feature, "var", NS); \ xmpp_stanza_add_child(query, feature); \ @@ -849,7 +831,7 @@ xmpp_stanza_t *connection__get_caps(xmpp_stanza_t *reply, struct t_account *acco FEATURE("urn:xmpp:time"); #undef FEATURE - xmpp_stanza_t *x = xmpp_stanza_new(account->context); + xmpp_stanza_t *x = xmpp_stanza_new(account.context); xmpp_stanza_set_name(x, "x"); xmpp_stanza_set_ns(x, "jabber:x:data"); xmpp_stanza_set_attribute(x, "type", "result"); @@ -862,15 +844,15 @@ xmpp_stanza_t *connection__get_caps(xmpp_stanza_t *reply, struct t_account *acco } xmpp_stanza_t *field, *value, *text; - // This is utter bullshit, TODO: anything but this. + // This->is utter bullshit, TODO: anything but this-> #define FEATURE1(VAR, TYPE, VALUE) \ - field = xmpp_stanza_new(account->context); \ + field = xmpp_stanza_new(account.context); \ xmpp_stanza_set_name(field, "field"); \ xmpp_stanza_set_attribute(field, "var", VAR); \ if(TYPE) xmpp_stanza_set_attribute(field, "type", TYPE); \ - value = xmpp_stanza_new(account->context); \ + value = xmpp_stanza_new(account.context); \ xmpp_stanza_set_name(value, "value"); \ - text = xmpp_stanza_new(account->context); \ + text = xmpp_stanza_new(account.context); \ xmpp_stanza_set_text(text, VALUE); \ xmpp_stanza_add_child(value, text); \ xmpp_stanza_release(text); \ @@ -885,21 +867,21 @@ xmpp_stanza_t *connection__get_caps(xmpp_stanza_t *reply, struct t_account *acco weechat_string_dyn_concat(serial, VALUE, -1); \ weechat_string_dyn_concat(serial, "<", -1); #define FEATURE2(VAR, TYPE, VALUE1, VALUE2) \ - field = xmpp_stanza_new(account->context); \ + field = xmpp_stanza_new(account.context); \ xmpp_stanza_set_name(field, "field"); \ xmpp_stanza_set_attribute(field, "var", VAR); \ xmpp_stanza_set_attribute(field, "type", TYPE); \ - value = xmpp_stanza_new(account->context); \ + value = xmpp_stanza_new(account.context); \ xmpp_stanza_set_name(value, "value"); \ - text = xmpp_stanza_new(account->context); \ + text = xmpp_stanza_new(account.context); \ xmpp_stanza_set_text(text, VALUE1); \ xmpp_stanza_add_child(value, text); \ xmpp_stanza_release(text); \ xmpp_stanza_add_child(field, value); \ xmpp_stanza_release(value); \ - value = xmpp_stanza_new(account->context); \ + value = xmpp_stanza_new(account.context); \ xmpp_stanza_set_name(value, "value"); \ - text = xmpp_stanza_new(account->context); \ + text = xmpp_stanza_new(account.context); \ xmpp_stanza_set_text(text, VALUE2); \ xmpp_stanza_add_child(value, text); \ xmpp_stanza_release(text); \ @@ -930,7 +912,7 @@ xmpp_stanza_t *connection__get_caps(xmpp_stanza_t *reply, struct t_account *acco xmpp_stanza_add_child(reply, query); unsigned char digest[20]; - xmpp_sha1_t *sha1 = xmpp_sha1_new(account->context); + xmpp_sha1_t *sha1 = xmpp_sha1_new(account.context); xmpp_sha1_update(sha1, (unsigned char*)*serial, strlen(*serial)); xmpp_sha1_final(sha1); weechat_string_dyn_free(serial, 1); @@ -939,22 +921,21 @@ xmpp_stanza_t *connection__get_caps(xmpp_stanza_t *reply, struct t_account *acco if (hash) { - char *cap_hash = xmpp_base64_encode(account->context, digest, 20); + char *cap_hash = xmpp_base64_encode(account.context, digest, 20); *hash = strdup(cap_hash); - xmpp_free(account->context, cap_hash); + xmpp_free(account.context, cap_hash); } return reply; } -int connection__iq_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) +bool weechat::connection::iq_handler(xmpp_stanza_t *stanza) { - struct t_account *account = (struct t_account *)userdata; xmpp_stanza_t *reply, *query, *text, *fin; xmpp_stanza_t *pubsub, *items, *item, *list, *bundle, *device; xmpp_stanza_t *storage, *conference, *nick; - auto binding = xml::iq(account->context, stanza); + auto binding = xml::iq(account.context, stanza); const char *id = xmpp_stanza_get_id(stanza); const char *from = xmpp_stanza_get_from(stanza); const char *to = xmpp_stanza_get_to(stanza); @@ -965,9 +946,9 @@ int connection__iq_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userd { if (weechat_strcasecmp(type, "get") == 0) { - reply = connection__get_caps(xmpp_stanza_reply(stanza), account, NULL); + reply = get_caps(xmpp_stanza_reply(stanza), NULL); - xmpp_send(conn, reply); + account.connection.send(reply); xmpp_stanza_release(reply); } @@ -990,22 +971,21 @@ int connection__iq_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userd if (category == "conference") { - struct t_channel *ptr_channel = channel__search(account, from); - - if (ptr_channel) - channel__update_name(ptr_channel, name.data()); + auto ptr_channel = account.channels.find(from); + if (ptr_channel != account.channels.end()) + ptr_channel->second.update_name(name.data()); } else if (category == "conference") { xmpp_stanza_t *children[2] = {NULL}; - children[0] = stanza__iq_pubsub_items(account->context, NULL, + children[0] = stanza__iq_pubsub_items(account.context, NULL, const_cast("eu.siacs.conversations.axolotl.devicelist")); - children[0] = stanza__iq_pubsub(account->context, NULL, + children[0] = stanza__iq_pubsub(account.context, NULL, children, with_noop("http://jabber.org/protocol/pubsub")); - children[0] = stanza__iq(account->context, NULL, children, NULL, + children[0] = stanza__iq(account.context, NULL, children, NULL, strdup("fetch2"), to ? strdup(to) : NULL, binding.from ? strdup(binding.from->bare.data()) : NULL, strdup("get")); - xmpp_send(conn, children[0]); + account.connection.send(children[0]); xmpp_stanza_release(children[0]); } } @@ -1037,14 +1017,14 @@ int connection__iq_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userd intext = xmpp_stanza_get_text(text); } - xmpp_send(conn, stanza::iq() + account.connection.send(stanza::iq() .from(to) .to(jid) .type("get") - .id(stanza::uuid(account->context)) + .id(stanza::uuid(account.context)) .xep0030() .query() - .build(account->context) + .build(account.context) .get()); if (weechat_strcasecmp(autojoin, "true") == 0) { @@ -1056,11 +1036,11 @@ int connection__iq_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userd weechat_string_dyn_concat(command, "/", -1); weechat_string_dyn_concat(command, intext, -1); } - weechat_command(account->buffer, *command); - struct t_channel *ptr_channel = - channel__search(account, jid); + weechat_command(account.buffer, *command); + auto ptr_channel = account.channels.find(jid); struct t_gui_buffer *ptr_buffer = - ptr_channel ? ptr_channel->buffer : NULL; + ptr_channel != account.channels.end() + ? ptr_channel->second.buffer : NULL; if (ptr_buffer) weechat_buffer_set(ptr_buffer, "short_name", name); weechat_string_dyn_free(command, 1); @@ -1076,7 +1056,7 @@ int connection__iq_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userd stanza, "pubsub", "http://jabber.org/protocol/pubsub"); if (pubsub) { - const char *items_node, *item_id, *device_id; + const char *items_node, *device_id; items = xmpp_stanza_get_child_by_name(pubsub, "items"); if (items) @@ -1089,13 +1069,13 @@ int connection__iq_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userd item = xmpp_stanza_get_child_by_name(items, "item"); if (item) { - item_id = xmpp_stanza_get_id(item); + const char *item_id = xmpp_stanza_get_id(item); list = xmpp_stanza_get_child_by_name_and_ns( item, "list", "eu.siacs.conversations.axolotl"); - if (list && account->omemo) + if (list && account.omemo) { - account->omemo.handle_devicelist( - from ? from : account_jid(account), items); + account.omemo.handle_devicelist( + from ? from : account.jid().data(), items); xmpp_stanza_t *children[2] = {NULL}; for (device = xmpp_stanza_get_children(list); @@ -1114,40 +1094,34 @@ int connection__iq_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userd children[1] = NULL; children[0] = - stanza__iq_pubsub_items(account->context, NULL, + stanza__iq_pubsub_items(account.context, NULL, strdup(bundle_node)); children[0] = - stanza__iq_pubsub(account->context, NULL, children, + stanza__iq_pubsub(account.context, NULL, children, with_noop("http://jabber.org/protocol/pubsub")); - char *uuid = xmpp_uuid_gen(account->context); + char *uuid = xmpp_uuid_gen(account.context); children[0] = - stanza__iq(account->context, NULL, children, NULL, uuid, + stanza__iq(account.context, NULL, children, NULL, uuid, to ? strdup(to) : NULL, from ? strdup(from) : NULL, strdup("get")); - xmpp_free(account->context, uuid); + xmpp_free(account.context, uuid); - xmpp_send(conn, children[0]); + account.connection.send(children[0]); xmpp_stanza_release(children[0]); } - if (weechat_strcasecmp(account_jid(account), from) == 0) + if (account.jid() == from) { - struct t_account_device *dev; + weechat::account::device dev; char id[64] = {0}; - account__free_device_all(account); - - dev = (t_account_device*)malloc(sizeof(struct t_account_device)); - - dev->id = account->omemo.device_id; - snprintf(id, sizeof(id), "%d", dev->id); - dev->name = strdup(id); - dev->label = strdup("weechat"); - account__add_device(account, dev); + account.devices.clear(); - free(dev->label); - free(dev->name); - free(dev); + dev.id = account.omemo.device_id; + snprintf(id, sizeof(id), "%d", dev.id); + dev.name = id; + dev.label = "weechat"; + account.devices.emplace(dev.id, dev); for (device = xmpp_stanza_get_children(list); device; device = xmpp_stanza_get_next(device)) @@ -1158,24 +1132,19 @@ int connection__iq_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userd device_id = xmpp_stanza_get_id(device); - dev = (t_account_device*)malloc(sizeof(struct t_account_device)); - dev->id = atoi(device_id); - dev->name = strdup(device_id); - dev->label = NULL; - account__add_device(account, dev); - - free(dev->label); - free(dev->name); - free(dev); + dev.id = atoi(device_id); + dev.name = device_id; + dev.label = ""; + account.devices.emplace(dev.id, dev); } - reply = account__get_devicelist(account); - char *uuid = xmpp_uuid_gen(account->context); + reply = account.get_devicelist(); + char *uuid = xmpp_uuid_gen(account.context); xmpp_stanza_set_id(reply, uuid); - xmpp_free(account->context, uuid); + xmpp_free(account.context, uuid); xmpp_stanza_set_attribute(reply, "to", from); xmpp_stanza_set_attribute(reply, "from", to); - xmpp_send(conn, reply); + account.connection.send(reply); xmpp_stanza_release(reply); } } @@ -1195,10 +1164,10 @@ int connection__iq_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userd { size_t node_prefix = strlen("eu.siacs.conversations.axolotl.bundles:"); - if (account->omemo && strlen(items_node) > node_prefix) + if (account.omemo && strlen(items_node) > node_prefix) { - account->omemo.handle_bundle( - from ? from : account_jid(account), + account.omemo.handle_bundle( + from ? from : account.jid().data(), strtol(items_node+node_prefix, NULL, 10), items); @@ -1215,100 +1184,108 @@ int connection__iq_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userd { xmpp_stanza_t *set, *set__last; char *set__last__text; - struct t_account_mam_query *mam_query; + weechat::account::mam_query mam_query; set = xmpp_stanza_get_child_by_name_and_ns( fin, "set", "http://jabber.org/protocol/rsm"); - mam_query = account__mam_query_search(account, id); - if (set && mam_query) + if (set && account.mam_query_search(&mam_query, id)) { - struct t_channel *channel = channel__search(account, - mam_query->with); + auto channel = account.channels.find(mam_query.with.data()); set__last = xmpp_stanza_get_child_by_name(set, "last"); set__last__text = set__last ? xmpp_stanza_get_text(set__last) : NULL; - if (channel && set__last__text) + if (channel != account.channels.end() && set__last__text) { - channel__fetch_mam(account, channel, id, - mam_query->has_start ? &mam_query->start : NULL, - mam_query->has_end ? &mam_query->end : NULL, + channel->second.fetch_mam(id, + *mam_query.start.map([](time_t& t){ return &t; }).disjunction(nullptr), + *mam_query.end.map([](time_t& t){ return &t; }).disjunction(nullptr), set__last__text); } else if (!set__last) - account__mam_query_free(account, mam_query); + account.mam_query_remove(mam_query.id); } } - return 1; + return true; } -void connection__handler(xmpp_conn_t *conn, xmpp_conn_event_t status, - int error, xmpp_stream_error_t *stream_error, - void *userdata) +bool weechat::connection::conn_handler(event status, int error, xmpp_stream_error_t *stream_error) { - struct t_account *account = (struct t_account *)userdata; - (void)error; (void)stream_error; - if (status == XMPP_CONN_CONNECT) + if (status == event::connect) { - account->disconnected = 0; + account.disconnected = 0; xmpp_stanza_t *pres__c, *pres__status, *pres__status__text, - *pres__x, *pres__x__text, **children; - - xmpp_handler_add(conn, &connection__version_handler, - "jabber:iq:version", "iq", NULL, account); - xmpp_handler_add(conn, &connection__presence_handler, - NULL, "presence", NULL, account); - xmpp_handler_add(conn, &connection__message_handler, - NULL, "message", /*type*/ NULL, account); - xmpp_handler_add(conn, &connection__iq_handler, - NULL, "iq", NULL, account); - - pgp__init(&account->pgp); + *pres__x, *pres__x__text; + + this->handler_add( + "iq", nullptr, [](xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) { + auto& connection = *reinterpret_cast(userdata); + if (connection != conn) throw std::invalid_argument("connection != conn"); + return connection.version_handler(stanza) ? 1 : 0; + }); + this->handler_add( + "presence", nullptr, [](xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) { + auto& connection = *reinterpret_cast(userdata); + if (connection != conn) throw std::invalid_argument("connection != conn"); + return connection.presence_handler(stanza) ? 1 : 0; + }); + this->handler_add( + "message", /*type*/ nullptr, [](xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) { + auto& connection = *reinterpret_cast(userdata); + if (connection != conn) throw std::invalid_argument("connection != conn"); + return connection.message_handler(stanza) ? 1 : 0; + }); + this->handler_add( + "iq", nullptr, [](xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) { + auto& connection = *reinterpret_cast(userdata); + if (connection != conn) throw std::invalid_argument("connection != conn"); + return connection.iq_handler(stanza) ? 1 : 0; + }); /* Send initial so that we appear online to contacts */ - children = (xmpp_stanza_t**)malloc(sizeof(*children) * (3 + 1)); + auto children = std::unique_ptr(new xmpp_stanza_t*[3 + 1]); - pres__c = xmpp_stanza_new(account->context); + pres__c = xmpp_stanza_new(account.context); xmpp_stanza_set_name(pres__c, "c"); xmpp_stanza_set_ns(pres__c, "http://jabber.org/protocol/caps"); xmpp_stanza_set_attribute(pres__c, "hash", "sha-1"); xmpp_stanza_set_attribute(pres__c, "node", "http://weechat.org"); - xmpp_stanza_t *caps = xmpp_stanza_new(account->context); + xmpp_stanza_t *caps = xmpp_stanza_new(account.context); xmpp_stanza_set_name(caps, "caps"); char *cap_hash; - caps = connection__get_caps(caps, account, &cap_hash); + caps = this->get_caps(caps, &cap_hash); xmpp_stanza_release(caps); xmpp_stanza_set_attribute(pres__c, "ver", cap_hash); free(cap_hash); children[0] = pres__c; - pres__status = xmpp_stanza_new(account->context); + pres__status = xmpp_stanza_new(account.context); xmpp_stanza_set_name(pres__status, "status"); - pres__status__text = xmpp_stanza_new(account->context); - xmpp_stanza_set_text(pres__status__text, account_status(account)); + pres__status__text = xmpp_stanza_new(account.context); + xmpp_stanza_set_text(pres__status__text, account.status().data()); xmpp_stanza_add_child(pres__status, pres__status__text); xmpp_stanza_release(pres__status__text); children[1] = pres__status; children[2] = NULL; - if (account->pgp) + if (true)//account.pgp) { - pres__x = xmpp_stanza_new(account->context); + pres__x = xmpp_stanza_new(account.context); xmpp_stanza_set_name(pres__x, "x"); xmpp_stanza_set_ns(pres__x, "jabber:x:signed"); - pres__x__text = xmpp_stanza_new(account->context); - char *signature = pgp__sign(account->buffer, account->pgp, account_pgp_keyid(account), account_status(account)); + pres__x__text = xmpp_stanza_new(account.context); + char *signature = account.pgp.sign(account.buffer, account.pgp_keyid().data(), account.status().data()); xmpp_stanza_set_text(pres__x__text, signature ? signature : ""); free(signature); xmpp_stanza_add_child(pres__x, pres__x__text); @@ -1318,79 +1295,81 @@ void connection__handler(xmpp_conn_t *conn, xmpp_conn_event_t status, children[3] = NULL; } - xmpp_send(conn, stanza::presence() - .from(account_jid(account)) - .build(account->context) + this->send(stanza::presence() + .from(account.jid()) + .build(account.context) .get()); - xmpp_send(conn, stanza::iq() - .from(account_jid(account)) + this->send(stanza::iq() + .from(account.jid()) .type("set") - .id(stanza::uuid(account->context)) + .id(stanza::uuid(account.context)) .xep0280() .enable() - .build(account->context) + .build(account.context) .get()); - xmpp_send(conn, stanza::iq() - .from(account_jid(account)) - .to(account_jid(account)) + this->send(stanza::iq() + .from(account.jid()) + .to(account.jid()) .type("get") - .id(stanza::uuid(account->context)) + .id(stanza::uuid(account.context)) .rfc6121() .query(stanza::rfc6121::query()) - .build(account->context) + .build(account.context) .get()); - xmpp_send(conn, stanza::iq() - .from(account_jid(account)) - .to(account_jid(account)) + this->send(stanza::iq() + .from(account.jid()) + .to(account.jid()) .type("get") - .id(stanza::uuid(account->context)) + .id(stanza::uuid(account.context)) .xep0049() .query(stanza::xep0049::query().bookmarks()) - .build(account->context) + .build(account.context) .get()); children[1] = NULL; children[0] = - stanza__iq_pubsub_items(account->context, NULL, + stanza__iq_pubsub_items(account.context, NULL, strdup("eu.siacs.conversations.axolotl.devicelist")); children[0] = - stanza__iq_pubsub(account->context, NULL, children, + stanza__iq_pubsub(account.context, NULL, children.get(), with_noop("http://jabber.org/protocol/pubsub")); - char *uuid = xmpp_uuid_gen(account->context); + char *uuid = xmpp_uuid_gen(account.context); children[0] = - stanza__iq(account->context, NULL, children, NULL, uuid, - strdup(account_jid(account)), strdup(account_jid(account)), + stanza__iq(account.context, NULL, children.get(), NULL, uuid, + strdup(account.jid().data()), strdup(account.jid().data()), strdup("get")); - xmpp_free(account->context, uuid); + xmpp_free(account.context, uuid); - xmpp_send(conn, children[0]); + this->send(children[0]); xmpp_stanza_release(children[0]); - account->omemo.init(account->buffer, account->name); + account.omemo.init(account.buffer, account.name.data()); - if (account->omemo) + if (account.omemo) { children[0] = - account->omemo.get_bundle(account->context, - strdup(account_jid(account)), NULL); - xmpp_send(conn, children[0]); + account.omemo.get_bundle(account.context, + strdup(account.jid().data()), NULL); + this->send(children[0]); xmpp_stanza_release(children[0]); } (void) weechat_hook_signal_send("xmpp_account_connected", - WEECHAT_HOOK_SIGNAL_STRING, account->name); + WEECHAT_HOOK_SIGNAL_STRING, account.name.data()); } else { - account__disconnect(account, 1); - //xmpp_stop(account->context); //keep context? + account.disconnect(1); + //xmpp_stop(account.context); //keep context? } + + return true; } -char* connection__rand_string(int length) +char* rand_string(int length) { char *string = (char*)malloc(length); for(int i = 0; i < length; ++i){ @@ -1404,72 +1383,69 @@ char* connection__rand_string(int length) return string; } -int connection__connect(struct t_account *account, xmpp_conn_t **connection, - const char* jid, const char* password, int tls) +int weechat::connection::connect(std::string jid, std::string password, weechat::tls_policy tls) { static const unsigned ka_timeout_sec = 60; static const unsigned ka_timeout_ivl = 1; - *connection = xmpp_conn_new(account->context); + m_conn.set_keepalive(ka_timeout_sec, ka_timeout_ivl); - xmpp_conn_set_keepalive(*connection, ka_timeout_sec, ka_timeout_ivl); - - const char *resource = account_resource(account); + const char *resource = account.resource().data(); if (!(resource && strlen(resource))) { - char *const rand = connection__rand_string(8); + char *const rand = rand_string(8); char ident[64] = {0}; snprintf(ident, sizeof(ident), "weechat.%s", rand); free(rand); - account_option_set(account, ACCOUNT_OPTION_RESOURCE, ident); - resource = account_resource(account); + account.resource(ident); + resource = account.resource().data(); } - xmpp_conn_set_jid(*connection, - xmpp_jid_new(account->context, - xmpp_jid_node(account->context, jid), - xmpp_jid_domain(account->context, jid), - resource)); - xmpp_conn_set_pass(*connection, password); - - int flags = xmpp_conn_get_flags(*connection); + m_conn.set_jid(xmpp_jid_new(account.context, + xmpp_jid_node(account.context, jid.data()), + xmpp_jid_domain(account.context, jid.data()), + resource)); + m_conn.set_pass(password.data()); + + int flags = m_conn.get_flags(); switch (tls) { - case 0: + case weechat::tls_policy::disable: flags |= XMPP_CONN_FLAG_DISABLE_TLS; break; - case 1: + case weechat::tls_policy::normal: flags &= ~XMPP_CONN_FLAG_DISABLE_TLS; flags &= ~XMPP_CONN_FLAG_TRUST_TLS; break; - case 2: + case weechat::tls_policy::trust: flags |= XMPP_CONN_FLAG_TRUST_TLS; break; default: break; } - xmpp_conn_set_flags(*connection, flags); - - if (xmpp_connect_client(*connection, NULL, 0, &connection__handler, account) - != XMPP_EOK) + m_conn.set_flags(flags); + + if (!connect_client( + nullptr, 0, [](xmpp_conn_t *conn, xmpp_conn_event_t status, + int error, xmpp_stream_error_t *stream_error, + void *userdata) { + auto& connection = *reinterpret_cast(userdata); + if (connection != conn) throw std::invalid_argument("connection != conn"); + connection.conn_handler(static_cast(status), error, stream_error); + })) { weechat_printf( - NULL, + nullptr, _("%s%s: error connecting to %s"), weechat_prefix("error"), WEECHAT_XMPP_PLUGIN_NAME, - jid); - return 0; + jid.data()); + return false; } - return 1; + return true; } -void connection__process(xmpp_ctx_t *context, xmpp_conn_t *connection, - const unsigned long timeout) +void weechat::connection::process(xmpp_ctx_t *context, const unsigned long timeout) { - if (connection) - { - xmpp_run_once(context ? context : xmpp_conn_get_context(connection), - timeout); - } + xmpp_run_once(context ? context : this->context(), timeout); } diff --git a/connection.hh b/connection.hh index 01ea84d..ce56255 100644 --- a/connection.hh +++ b/connection.hh @@ -4,12 +4,74 @@ #pragma once +#include +#include +#include #include +#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, - const char* jid, const char* password, int tls); + class connection + { + private: + libstrophe::connection m_conn; -void connection__process(xmpp_ctx_t *context, xmpp_conn_t *connection, - const unsigned long timeout); + enum class event { + 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 ::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); + }; +} diff --git a/input.cpp b/input.cpp index 01377bd..628d429 100644 --- a/input.cpp +++ b/input.cpp @@ -16,8 +16,8 @@ int input__data(struct t_gui_buffer *buffer, const char *text) { - struct t_account *account = NULL; - struct t_channel *channel = NULL; + weechat::account *account = NULL; + weechat::channel *channel = NULL; 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 (!account->is_connected) + if (!account->connected()) { weechat_printf(buffer, _("%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; } - 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; else { @@ -62,15 +62,15 @@ int input__data_cb(const void *pointer, void *data, int input__typing(struct t_gui_buffer *buffer) { - struct t_account *account = NULL; - struct t_channel *channel = NULL; + weechat::account *account = NULL; + weechat::channel *channel = NULL; 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_typing(account, channel, NULL); + channel->send_reads(); + channel->send_typing(NULL); } return WEECHAT_RC_OK; diff --git a/makefile b/makefile index b16c43c..d8a316b 100644 --- a/makefile +++ b/makefile @@ -108,7 +108,7 @@ release: xmpp.so cp xmpp.so .xmpp.so.$(SUFFIX) ln -sf .xmpp.so.$(SUFFIX) .xmpp.so -xmpp.so: $(OBJS) $(DEPS) $(HDRS) +xmpp.so: $(DEPS) $(OBJS) $(HDRS) $(CXX) $(LDFLAGS) -o $@ $(OBJS) $(DEPS) $(LDLIBS) 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 diff --git a/message.cpp b/message.cpp index c21d6a3..8d20e5f 100644 --- a/message.cpp +++ b/message.cpp @@ -19,11 +19,11 @@ static const char format_regex[] = "<([^>]*?)>"; 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) { - struct t_channel *channel; - struct t_user *user; + decltype(account->channels)::iterator channel; + weechat::user *user; size_t resultlen; char *identifier, *alttext, *result, *symbol, *prefix; @@ -42,11 +42,11 @@ char *message__translate_code(struct t_account *account, } else { - channel = channel__search(account, identifier+1); - if (channel) + channel = account->channels.find(identifier+1); + if (channel != account->channels.end()) { prefix = (char*)"#"; - symbol = strdup(channel->name); + symbol = strdup(channel->second.name.data()); } else { @@ -63,7 +63,7 @@ char *message__translate_code(struct t_account *account, } else { - user = user__search(account, identifier+1); + user = weechat::user::search(account, identifier+1); if (user) { prefix = (char*)"@"; @@ -148,7 +148,7 @@ void message__htmldecode(char *dest, const char *src, size_t n) return; } -char *message__decode(struct t_account *account, +char *message__decode(weechat::account *account, const char *text) { int rc; diff --git a/message.hh b/message.hh index 52fb6af..8ab367b 100644 --- a/message.hh +++ b/message.hh @@ -6,5 +6,5 @@ #define MESSAGE_MAX_LENGTH 40000 -char *message__decode(struct t_account *account, +char *message__decode(weechat::account *account, const char *text); diff --git a/omemo.cpp b/omemo.cpp index d4843a8..45cb0e9 100644 --- a/omemo.cpp +++ b/omemo.cpp @@ -2125,7 +2125,7 @@ void omemo::handle_bundle(const char *jid, uint32_t device_id, 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) { auto omemo = &account->omemo; @@ -2267,7 +2267,7 @@ char *omemo::decode(struct t_account *account, const char *jid, 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) { auto omemo = &account->omemo; @@ -2362,7 +2362,7 @@ xmpp_stanza_t *omemo::encode(struct t_account *account, const char *jid, session_cipher_free(cipher); } signal_int_list_free(devicelist); - target = account_jid(account); + target = account->jid().data(); } free(key_and_tag); diff --git a/omemo.hh b/omemo.hh index 703df7c..383d8fc 100644 --- a/omemo.hh +++ b/omemo.hh @@ -13,67 +13,68 @@ #include #include "signal.hh" -struct t_account; extern const char *OMEMO_ADVICE; -namespace weechat::xmpp { +namespace weechat { + class account; -struct t_pre_key { - const char *id; - const char *public_key; -}; + namespace xmpp { + struct t_pre_key { + const char *id; + const char *public_key; + }; -struct omemo -{ - libsignal::context context; - libsignal::store_context store_context; + struct omemo + { + libsignal::context context; + libsignal::store_context store_context; - lmdb::env db_env = nullptr; - struct dbi { - lmdb::dbi omemo; - } dbi; - std::string db_path; + lmdb::env db_env = nullptr; + struct dbi { + lmdb::dbi omemo; + } dbi; + std::string db_path; - libsignal::identity_key_pair identity; + libsignal::identity_key_pair identity; - std::uint32_t device_id; + std::uint32_t device_id; - class bundle_request - { - public: - std::string id; - std::string jid; - std::string device; - std::string message_text; - }; + class bundle_request + { + public: + std::string id; + std::string jid; + std::string device; + std::string message_text; + }; - class devicelist_request - { - public: - std::string id; - bundle_request bundle_req; - }; + class devicelist_request + { + public: + std::string id; + bundle_request bundle_req; + }; - ~omemo(); + ~omemo(); - inline operator bool() { return this->context && this->store_context && - this->identity && this->device_id != 0; } + inline operator bool() { return this->context && this->store_context && + this->identity && this->device_id != 0; } - xmpp_stanza_t *get_bundle(xmpp_ctx_t *context, char *from, char *to); + xmpp_stanza_t *get_bundle(xmpp_ctx_t *context, char *from, char *to); - void init(struct t_gui_buffer *buffer, const char *account_name); + void init(struct t_gui_buffer *buffer, const char *account_name); - void handle_devicelist(const char *jid, xmpp_stanza_t *items); + void handle_devicelist(const char *jid, xmpp_stanza_t *items); - void handle_bundle(const char *jid, std::uint32_t device_id, - xmpp_stanza_t *items); + void handle_bundle(const char *jid, std::uint32_t device_id, + xmpp_stanza_t *items); - char *decode(struct t_account *account, const char *jid, - xmpp_stanza_t *encrypted); - - xmpp_stanza_t *encode(struct t_account *account, const char *jid, - const char *unencrypted); -}; + char *decode(weechat::account *account, const char *jid, + xmpp_stanza_t *encrypted); + xmpp_stanza_t *encode(weechat::account *account, const char *jid, + const char *unencrypted); + }; + } } diff --git a/pgp.cpp b/pgp.cpp index 251f2e9..3545fb5 100644 --- a/pgp.cpp +++ b/pgp.cpp @@ -15,10 +15,10 @@ #include "plugin.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_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) { 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_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_data_t keydata; gpgme_check_version(NULL); - new_pgp = (struct t_pgp*)calloc(1, sizeof(**pgp)); - - err = gpgme_new(&new_pgp->gpgme); + err = gpgme_new(&this->gpgme); if (err) { weechat_printf(nullptr, "gpg (error): %s - %s", 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); //if (err) { // return; //} - //err = gpgme_op_import(new_pgp->gpgme, keydata); + //err = gpgme_op_import(this->gpgme, keydata); //if (err) { // 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); //err = gpgme_data_new_from_file(&keydata, sec, true); @@ -92,28 +89,21 @@ void pgp__init(struct t_pgp **pgp) // return; //} - //err = gpgme_op_import(new_pgp->gpgme, keydata); + //err = gpgme_op_import(this->gpgme, keydata); //if (err) { // 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); - - *pgp = new_pgp; } -void pgp__free(struct t_pgp *pgp) +weechat::xmpp::pgp::~pgp() { - if (pgp) - { - if (pgp->gpgme) - gpgme_release(pgp->gpgme); - free(pgp); - } + gpgme_release(this->gpgme); } -char *pgp__encrypt(struct t_gui_buffer *buffer, struct t_pgp *pgp, const char *source, std::vector&& targets, const char *message) +char *weechat::xmpp::pgp::encrypt(struct t_gui_buffer *buffer, const char *source, std::vector&& targets, const char *message) { std::string encrypted; 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. */ 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) { 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) { 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) { 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) { 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" -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; 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. */ - err = gpgme_op_decrypt(pgp->gpgme, in, out); - if (gpgme_decrypt_result_t dec_result = gpgme_op_decrypt_result(pgp->gpgme); + err = gpgme_op_decrypt(this->gpgme, in, out); + if (gpgme_decrypt_result_t dec_result = gpgme_op_decrypt_result(this->gpgme); dec_result) { for (auto recip = dec_result->recipients; recip; recip = recip->next) { if (!keyids.empty()) keyids += ", "; - keyids += format_key(pgp, recip->keyid); + keyids += format_key(*this, recip->keyid); } if (dec_result->unsupported_algorithm) { @@ -243,7 +233,7 @@ decrypt_finish: 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; 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. */ - err = gpgme_op_verify(pgp->gpgme, in, out, nullptr); + err = gpgme_op_verify(this->gpgme, in, out, nullptr); if (err) { 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)) { //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); - err = gpgme_get_key(pgp->gpgme, result, &key, false); + err = gpgme_get_key(this->gpgme, result, &key, false); if (err) { const char *keyids[2] = { result, nullptr }; - err = gpgme_op_receive_keys(pgp->gpgme, keyids); + err = gpgme_op_receive_keys(this->gpgme, keyids); } verify_finish: @@ -297,7 +287,7 @@ verify_finish: 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; 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. */ { - 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_SIGS; - err = gpgme_set_keylist_mode(pgp->gpgme, kmode); + err = gpgme_set_keylist_mode(this->gpgme, kmode); } if (err) { goto sign_finish; } - err = gpgme_get_key(pgp->gpgme, source, &key, false); + err = gpgme_get_key(this->gpgme, source, &key, false); if (err) { weechat_printf(nullptr, "(gpg) get key fail for %s", source); goto sign_finish; } - err = gpgme_signers_add(pgp->gpgme, key); + err = gpgme_signers_add(this->gpgme, key); if (err) { weechat_printf(nullptr, "(gpg) add key fail for %s", source); goto sign_finish; } /* 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) { weechat_printf(nullptr, "(gpg) sign fail for %s", source); 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) { weechat_printf(nullptr, "(gpg) signature fail for %s", source); diff --git a/pgp.hh b/pgp.hh index fbcb276..b2e4f3f 100644 --- a/pgp.hh +++ b/pgp.hh @@ -7,22 +7,27 @@ #include #include -extern const char *PGP_ADVICE; - -struct t_pgp +namespace weechat::xmpp { - struct gpgme_context *gpgme; - const char *keyid; -}; + extern const char *PGP_ADVICE; + + class pgp + { + public: + struct gpgme_context *gpgme; + 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&& target, const char *message); + char *encrypt(struct t_gui_buffer *buffer, const char *source, std::vector&& 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); + }; +} diff --git a/plugin.cpp b/plugin.cpp index 2f6a501..ee1512d 100644 --- a/plugin.cpp +++ b/plugin.cpp @@ -51,19 +51,19 @@ int weechat_plugin_init(struct t_weechat_plugin *plugin, int argc, char *argv[]) weechat_xmpp_plugin = plugin; - if (!config__init()) + if (!weechat::config::init()) return WEECHAT_RC_ERROR; - config__read(); + weechat::config::read(); - connection__init(); + weechat::connection::init(); command__init(); completion__init(); weechat_xmpp_process_timer = weechat_hook_timer(TIMER_INTERVAL_SEC * 1000, 0, 0, - &account__timer_cb, + &weechat::account::timer_cb, NULL, NULL); if (!weechat_bar_search("typing")) @@ -95,11 +95,11 @@ int weechat_plugin_end(struct t_weechat_plugin *plugin) if (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(); diff --git a/strophe.hh b/strophe.hh new file mode 100644 index 0000000..07d16a4 --- /dev/null +++ b/strophe.hh @@ -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 +#include +#include +#include +#include + +namespace libstrophe { + + template + class type { + private: + T *_ptr; + + protected: + typedef T* pointer_type; + + inline type(T *ptr) : _ptr(ptr) { + } + + template...>>>> + inline void call_checked(Args&&... args) { + int ret = func(*this, std::forward(args)...); + if (ret != success) throw std::runtime_error( + fmt::format("Strophe Error: expected {}, was {}", success, ret)); + } + + template...>>>> + inline void call(Args&&... args) { + func(*this, std::forward(args)...); + } + + template>...>>>> + inline typename std::invoke_result_t>...> + call(Args&&... args) { + return func(*this, std::forward(args)...); + } + + public: + inline explicit type() : _ptr(nullptr) { + } + + template + inline explicit type(Args&&... args) : type() { + _ptr = f_create(std::forward(args)...); + } + + inline ~type() { + if (_ptr) + f_destroy(reinterpret_cast(_ptr)); + _ptr = nullptr; + } + + type(const type &other) = delete; /* no copy construction */ + type(type &&other) = default; + + template + inline void create(Args&&... args) { + if (_ptr) + f_destroy(reinterpret_cast(_ptr)); + _ptr = f_create(std::forward(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 context_type; + class context : public context_type { + public: + using context_type::context_type; + + inline auto set_verbosity(auto &&...args) { + return call(args...); + } + }; + + typedef type 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(args...); + } + + inline auto get_flags(auto &&...args) { + return call(args...); + } + + inline auto set_keepalive(auto &&...args) { +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + return call(args...); +#pragma GCC diagnostic pop + } + + inline auto set_jid(auto &&...args) { + return call(args...); + } + + inline auto set_pass(auto &&...args) { + return call(args...); + } + + inline auto set_flags(auto &&...args) { + return call(args...); + } + + inline auto send(auto &&...args) { + return call(args...); + } + + inline auto connect_client(auto &&...args) { + return call(args...); + } + + inline auto handler_add(auto &&...args) { + return call(args...); + } + }; + + typedef type 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(args...); + } + + inline stanza get_ns(auto &&...args) { + return call(args...); + } + + inline stanza add_child(auto &&...args) { + call(args...); + return std::move(*this); + } + + inline stanza set_name(auto &&...args) { + call(args...); + return std::move(*this); + } + + inline stanza set_ns(auto &&...args) { + call(args...); + return std::move(*this); + } + + inline stanza set_text(auto &&...args) { + call(args...); + return std::move(*this); + } + + inline stanza set_type(auto &&...args) { + call(args...); + return std::move(*this); + } + }; +} diff --git a/tests/plugin.inl b/tests/plugin.inl index 38a6b25..b5e3f8f 100644 --- a/tests/plugin.inl +++ b/tests/plugin.inl @@ -5,8 +5,8 @@ TEST_CASE("weechat") { - std::string current("20211106-01"); - + std::string current("20220312-01"); + SUBCASE("plugin api match") { CHECK(current == WEECHAT_PLUGIN_API_VERSION); diff --git a/user.cpp b/user.cpp index eeb7737..7474cb1 100644 --- a/user.cpp +++ b/user.cpp @@ -14,22 +14,34 @@ #include "user.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, - const char *name) +std::string weechat::user::get_colour_for_nicklist() { - 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", weechat_info_get("nick_color", name), @@ -38,214 +50,126 @@ const char *user__as_prefix_raw(struct t_account *account, return result; } -const char *user__as_prefix(struct t_account *account, - struct t_user *user, - const char *name) +std::string weechat::user::as_prefix() { - 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", - user__get_colour(user), - name ? name : user->profile.display_name); + weechat::user::get_colour(name).data(), name); return result; } -struct t_user *user__bot_search(struct t_account *account, - const char *pgp_id) +weechat::user *weechat::user::bot_search(weechat::account *account, + const char *pgp_id) { - struct t_user *ptr_user; - if (!account || !pgp_id) - return NULL; + return nullptr; - for (ptr_user = account->users; ptr_user; - ptr_user = ptr_user->next_user) + for (auto& ptr_user : account->users) { - if (ptr_user->profile.pgp_id && - weechat_strcasecmp(ptr_user->profile.pgp_id, pgp_id) == 0) - return ptr_user; + if (ptr_user.second.profile.pgp_id && + ptr_user.second.profile.pgp_id == pgp_id) + return &ptr_user.second; } - return NULL; + return nullptr; } -struct t_user *user__search(struct t_account *account, - const char *id) +weechat::user *weechat::user::search(weechat::account *account, + const char *id) { - struct t_user *ptr_user; - if (!account || !id) - return NULL; + return nullptr; - for (ptr_user = account->users; ptr_user; - ptr_user = ptr_user->next_user) - { - if (weechat_strcasecmp(ptr_user->id, id) == 0) - return ptr_user; - } + if (auto user = account->users.find(id); user != account->users.end()) + return &user->second; - return NULL; + return nullptr; } -void user__nicklist_add(struct t_account *account, - struct t_channel *channel, - struct t_user *user) +void weechat::user::nicklist_add(weechat::account *account, + weechat::channel *channel) { struct t_gui_nick_group *ptr_group; 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), - channel->id) == 0) + channel->id.data()) == 0) name = xmpp_jid_resource(account->context, name); ptr_buffer = channel ? channel->buffer : account->buffer; 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*)"!"; - if (weechat_strcasecmp(user->profile.role, (char*)"visitor") == 0) + if (this->profile.role ? this->profile.role == std::string("visitor") : false) group = (char*)"?"; - if (weechat_strcasecmp(user->profile.role, (char*)"participant") == 0) + if (this->profile.role ? this->profile.role == std::string("participant") : false) group = (char*)"+"; - if (weechat_strcasecmp(user->profile.affiliation, (char*)"member") == 0) + if (this->profile.affiliation ? this->profile.affiliation == std::string("member") : false) group = (char*)"%"; - if (weechat_strcasecmp(user->profile.role, (char*)"moderator") == 0) + if (this->profile.role ? this->profile.role == std::string("moderator") : false) group = (char*)"@"; - if (weechat_strcasecmp(user->profile.affiliation, (char*)"admin") == 0) + if (this->profile.affiliation ? this->profile.affiliation == std::string("admin") : false) group = (char*)"&"; - if (weechat_strcasecmp(user->profile.affiliation, (char*)"owner") == 0) + if (this->profile.affiliation ? this->profile.affiliation == std::string("owner") : false) 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, name, - user->is_away ? + this->is_away ? "weechat.color.nicklist_away" : - user__get_colour_for_nicklist(user), + get_colour_for_nicklist().data(), group, "bar_fg", 1); } -void user__nicklist_remove(struct t_account *account, - struct t_channel *channel, - struct t_user *user) +void weechat::user::nicklist_remove(weechat::account *account, + weechat::channel *channel) { struct t_gui_nick *ptr_nick; 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), - channel->id) == 0) + channel->id.data()) == 0) name = xmpp_jid_resource(account->context, name); 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); } -struct t_user *user__new(struct t_account *account, - const char *id, const char *display_name) +weechat::user::user(weechat::account *account, + const char *id, const char *display_name) { - struct t_user *new_user, *ptr_user; - if (!account || !id) { - return NULL; + throw nullptr; } - if (!account->users) - channel__add_nicklist_groups(account, NULL); + //if (account->users.empty()) + // channel::add_nicklist_groups(account, nullptr); - ptr_user = user__search(account, id); + weechat::user *ptr_user = user::search(account, id); if (ptr_user) { - user__nicklist_add(account, NULL, ptr_user); - return ptr_user; + throw nullptr; } - new_user = new struct t_user; - - 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; + //account->users += this; - new_user->id = strdup(id); - new_user->name = NULL; + this->id = strdup(id); - new_user->profile.avatar_hash = NULL; - new_user->profile.status_text = NULL; - new_user->profile.status = NULL; - new_user->profile.display_name = display_name ? + this->profile.display_name = display_name ? 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); - - 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); + nicklist_add(account, nullptr); } diff --git a/user.hh b/user.hh index d477257..d7f2f34 100644 --- a/user.hh +++ b/user.hh @@ -4,60 +4,67 @@ #pragma once -#include +#include #include #include -struct t_user_profile +namespace weechat { - char *avatar_hash; - char *status_text; - char *status; - tl::optional 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; - struct t_user *next_user; -}; + class account; + class channel; -struct t_channel; + class user + { + private: + struct profile + { + char *avatar_hash = nullptr; + char *status_text = nullptr; + char *status = nullptr; + tl::optional 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, - const char *name); + bool updated = false; -const char *user__as_prefix(struct t_account *account, - struct t_user *user, - const char *name); + public: + char *id = nullptr; + bool is_away = false; + struct profile profile; -struct t_user *user__search(struct t_account *account, - const char *id); + public: + user(weechat::account *account, const char *id, const char *display_name); -struct t_user *user__new(struct t_account *account, - const char *id, const char *display_name); + static std::string get_colour(const char *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(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(search(account, id)); + return found ? found->as_prefix() : ""; + } -void user__nicklist_add(struct t_account *account, - struct t_channel *channel, - struct t_user *user); + static weechat::user *bot_search(weechat::account *account, const char *pgp_id); + static weechat::user *search(weechat::account *account, const char *id); -void user__nicklist_remove(struct t_account *account, - struct t_channel *channel, - struct t_user *user); + void nicklist_add(weechat::account *account, weechat::channel *channel); + void nicklist_remove(weechat::account *account, weechat::channel *channel); + }; +} diff --git a/xmpp/node.hh b/xmpp/node.hh index b418205..9a54912 100644 --- a/xmpp/node.hh +++ b/xmpp/node.hh @@ -15,8 +15,8 @@ #include #include #include -#include #include +#include std::string get_name(xmpp_stanza_t *stanza);